Как сгенерировать машинный код с llvm
В настоящее время я работаю над проектом компилятора с использованием llvm. Я следил за различными учебниками до того момента, когда у меня есть синтаксический анализатор для создания дерева синтаксиса, а затем дерево преобразуется в модуль llvm, используя предоставленный IRBuilder.
Моя цель - создать исполняемый файл, и я смущен как что делать дальше. Все обучающие материалы, которые я нашел, просто создают модуль llvm и распечатывают сборку с помощью Module.dump(). Кроме того, единственная документация, которую я могу найти, предназначена для разработчиков llvm, а не для конечных пользователей проекта.
Если я хочу сгенерировать машинный код, каковы следующие шаги? Проект llvm-mc выглядит так, как будто он может делать то, что я хочу, но я не могу найти на нем никакой документации.
Возможно, я ожидаю, что llvm сделает что-то, чего нет. Я ожидаю, что я смогу создать модуль, тогда будет API, который я могу вызвать с помощью модуля и целевой тройки, и будет создан объектный файл. Я нашел документацию и примеры по созданию JIT, и меня это не интересует. Я ищу, как создавать скомпилированные двоичные файлы.
Я работаю над OS X, если это имеет какое-то влияние.
Ответы
Ответ 1
Используйте llc -filetype=obj
, чтобы испускать связанный объектный файл с вашего IR. Вы можете посмотреть код llc
, чтобы увидеть вызовы API LLVM, которые он делает, чтобы испускать такой код. По крайней мере, для Mac OS X и Linux объекты, испущенные таким образом, должны быть довольно хорошими (т.е. Это уже не "качество альфа-качества" ).
LLVM не содержит компоновщика (пока!). Поэтому, чтобы связать этот объектный файл с какой-либо исполняемой или разделяемой библиотекой, вам нужно будет использовать системный компоновщик. Обратите внимание, что даже если у вас есть исполняемый файл, состоящий из одного объектного файла, последний должен быть привязан в любом случае. Разработчики сообщества LLVM работают над реальным компоновщиком LLVM, который называется lld
. Вы можете посетить его страницу или выполнить поиск в архивах списков рассылки, чтобы следить за его прогрессом.
Ответ 2
Как вы можете прочитать в руководстве llc, это действительно предназначено только для сборки сборки, а затем "Выход языка ассемблера затем может быть передан через собственный сборщик и компоновщик для генерации собственного исполняемого файла" - например, ассемблер gnu (as
) и компоновщик (ld
).
Итак, главный ответ здесь - использовать собственные инструменты для сборки и компоновки.
Однако существует экспериментальная поддержка для создания собственного объекта непосредственно из IR файла через llc
:
-filetype - Choose a file type (not all types are supported by all targets):
=asm - Emit an assembly ('.s') file
=obj - Emit a native object ('.o') file [experimental]
Или вы можете использовать llvm-mc
для сборки из файла .s
:
-filetype - Choose an output file type:
=asm - Emit an assembly ('.s') file
=null - Don't emit anything (for timing purposes)
=obj - Emit a native object ('.o') file
Я не знаю о линкерах.
Кроме того, я рекомендую проверить файл tools/bugpoint/ToolRunner.h
, в котором представлена оболочка, объединяющая llc
и корневую ссылку на платформу C для генерации машинного кода. Из комментария заголовка:
Этот файл предоставляет абстракцию вокруг компилятора платформы C, используемого для компиляции кода C и сборки.
Ответ 3
Проверьте эти функции в llvm-c/TargetMachine.h
:
/** Emits an asm or object file for the given module to the filename. This
wraps several c++ only classes (among them a file stream). Returns any
error in ErrorMessage. Use LLVMDisposeMessage to dispose the message. */
LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M,
char *Filename, LLVMCodeGenFileType codegen, char **ErrorMessage);
/** Compile the LLVM IR stored in \p M and store the result in \p OutMemBuf. */
LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T, LLVMModuleRef M,
LLVMCodeGenFileType codegen, char** ErrorMessage, LLVMMemoryBufferRef *OutMemBuf);
Ответ 4
Чтобы запустить пример программы BrainF
, скомпилируйте его и запустите:
echo ,. > test.bf
./BrainF test.bf -o test.bc
llc -filetype=obj test.bc
gcc test.o -o a.out
./a.out
затем введите одну букву и нажмите Enter. Он должен повторить это письмо к вам. (Что делает ,.
).
Выше была протестирована версия LLVM версии 3.5.0.