Если вы удалите из этой схемы своё промежуточное представление, вы существенно упростите себе жизнь.
Свой язык программирования можно реализовать в Clang-е, есть хорошие примеры, описания и т.д.
написать бэкенд для x86 для меня проще, чем для LLVM
Бэкенд для x86 уже написан, и он входит в состав LLVM. Я не знаю точно, что вы хотите сделать, но вам нужно внести изменения в Clang, наверное.
Вы хотите реализовать какой-то свой язык программирования?
У нас на факультете тоже была СМ-ка. Спирт на неё выдавался (начало 1990-х) и использовался для очевидных целей. Поэтому её и не списывали долго, наверное.
Конечно, после вставки нативного кода универсальность теряется.
Вы говорили, что вам нужно только под платформу x86.
Если нужно всё-таки для разных, можно вставлять разный код для разных архитектур.
из IR-кода надо ещё как-то воспользоваться этой модификацией.
Так часто практикуется. Clang может генерировать разный IR-код для разных аппаратных платформ, в расчёте на то, что конкретный бэкенд умеет оптимизировать определённые структуры в IR-коде.
Хотелось бы, чтобы были не только виртуальные регистры, но и виртуальный стек.
Зачем? IR обходится без этого.
На каком этапе существует IR
Код IR поступает в бэкенд и там преобразуется в SelectionDAG, который уже зависит от таргета. IR не зависит от таргета (если на вдаваться в тонкости).
Притягательная сила LLVM состоит в том, чтобы сделать только то, что вам нужно, а остальное сделает LLVM. Если вы хотите сделать компилятор для нового языка программирования, то вам не нужно писать множество бэкендов, достаточно сгенерировать правильный IR-код. Если вы хотите сделать оптимизации нативного кода для конкретной архитектуры, то вам не нужно заниматься формированием IR-кода, нужно написать только бэкенд (или модифицировать существующий).
Нет, не так. На уровне IR (промежуточного кода) никакого стека нет, он работает только с виртуальными (не физическими) регистрами.
Дальше генерируются другие промежуточные представления, где действительно есть стек (точнее, Frame Index, индексы в кадре стека). Их обработка и преобразование в конкретные машинные инструкции остаётся целиком за разработчиком бэкенда. При этом процессор может иметь отдельно регистр стека и регистр фрейма, или только регистр стека, например (хотя при этом будет нельзя работать со стеком, динамически изменяющим размер в run-time).
В командах Selection DAG (которое является следующим за IR промежуточным представлением) операнды работы со стеком имеют вид, например FI+1, где FI — текущий кадр стека. Его значение не определено, команды оперируют только относительным смещением.
Указатель стека вы можете изменять, как и любой другой физический регистр, соответствующими командами таргета.
Зачем нужно собственное промежуточное представление, и генерировать из него LLVM IR? Чем вас не устраивает clang, который просто генерирует LLVM IR?
нужно переписать соответствующий бэкенд?
Вероятно, да.
Т.е. сейчас в LLVM указатель стека не может быть загружен новым значением по ходу работы?
Давайте различать LLVM и конкретный бэкенд LLVM. Я не знаю устройство именно бэкенда x86, и не знаю, как он работает со стеком.
Это не так. Все современные компиляторы, включая LLVM, работают по варианту 1. Более точно это показано на рисунке 1.
Далее я буду писать только про бэкенд, т.е. преобразование из промежуточного кода в код таректа.
По поводу преимуществ:
LLVM имеет возможность быстрой компиляции, в основном для работы в режиме JIT.
Насколько полно и эффективно будут использованы возможности процессора, зависит только от разработчика бэкенда. LLVM не ограничивает его ни в чём.
Разумеется, нужно писать кодогенератор под каждую платформу (если под кодогенератором вы понимаете бэкенд).
В LLVM есть возможность генерации любых машинных инструкций.
Не совсем уловил суть вопроса. У вас есть какой-то процессор, в нём есть регистр указателя стека, и есть команды, которые изменяют его содержимое. Вы разрабатываете для этого процессора бэкенд LLVM. В нём вы можете генерировать нужные вам команды, для этого есть множество способов.
А в самом по себе LLVM никакого указателя стека нет.
Защёлки приводят к разным труднопрогнозируемым багам (glitches и т.п.), поэтому лучше просто так не делать вообще никогда. Синтезатор должен, кстати, выдавать предупреждение об этом. Вы в Quartus II делали?
Ничего хорошего. Пользуйтесь в синхронных always только неблокирующими присваиваниями, иначе будут образовываться защёлки (latch), что ведёт к куче негативных последствий.
Хорошие курсовые, у нас таких не было. Трансляция из блок-схемы в С, это же очень полезная вещь для различных визуальных сред разработки. Программируемые логические контроллеры так и программируются, в целом, например IsaGraf перегоняет разные блоковые диаграммы в С, потом компилирует обычным компилятором, чуть ли не Turbo C.
Описание взять здесь: llvm.org.
Если вы удалите из этой схемы своё промежуточное представление, вы существенно упростите себе жизнь.
Свой язык программирования можно реализовать в Clang-е, есть хорошие примеры, описания и т.д.
Бэкенд для x86 уже написан, и он входит в состав LLVM. Я не знаю точно, что вы хотите сделать, но вам нужно внести изменения в Clang, наверное.
Вы хотите реализовать какой-то свой язык программирования?
Вы говорили, что вам нужно только под платформу x86.
Если нужно всё-таки для разных, можно вставлять разный код для разных архитектур.
Так часто практикуется. Clang может генерировать разный IR-код для разных аппаратных платформ, в расчёте на то, что конкретный бэкенд умеет оптимизировать определённые структуры в IR-коде.
Зачем? IR обходится без этого.
Код IR поступает в бэкенд и там преобразуется в SelectionDAG, который уже зависит от таргета. IR не зависит от таргета (если на вдаваться в тонкости).
Притягательная сила LLVM состоит в том, чтобы сделать только то, что вам нужно, а остальное сделает LLVM. Если вы хотите сделать компилятор для нового языка программирования, то вам не нужно писать множество бэкендов, достаточно сгенерировать правильный IR-код. Если вы хотите сделать оптимизации нативного кода для конкретной архитектуры, то вам не нужно заниматься формированием IR-кода, нужно написать только бэкенд (или модифицировать существующий).
Нет, не так. На уровне IR (промежуточного кода) никакого стека нет, он работает только с виртуальными (не физическими) регистрами.
Дальше генерируются другие промежуточные представления, где действительно есть стек (точнее, Frame Index, индексы в кадре стека). Их обработка и преобразование в конкретные машинные инструкции остаётся целиком за разработчиком бэкенда. При этом процессор может иметь отдельно регистр стека и регистр фрейма, или только регистр стека, например (хотя при этом будет нельзя работать со стеком, динамически изменяющим размер в run-time).
В командах Selection DAG (которое является следующим за IR промежуточным представлением) операнды работы со стеком имеют вид, например FI+1, где FI — текущий кадр стека. Его значение не определено, команды оперируют только относительным смещением.
Указатель стека вы можете изменять, как и любой другой физический регистр, соответствующими командами таргета.
Вероятно, да.
Давайте различать LLVM и конкретный бэкенд LLVM. Я не знаю устройство именно бэкенда x86, и не знаю, как он работает со стеком.
Далее я буду писать только про бэкенд, т.е. преобразование из промежуточного кода в код таректа.
По поводу преимуществ:
А в самом по себе LLVM никакого указателя стека нет.
Во-первых: output wire — это не есть хорошо. Выходы настоятельно рекомендуется делать reg-ами.
Ничего хорошего. Пользуйтесь в синхронных always только неблокирующими присваиваниями, иначе будут образовываться защёлки (latch), что ведёт к куче негативных последствий.