Как сгенерировать машинный код с помощью llvm

В настоящее время я работаю над проектом компилятора, используя llvm. Я следовал различным учебникам до того момента, когда у меня есть парсер для создания синтаксического дерева, а затем дерево преобразуется в модуль llvm с использованием предоставленного IRBuilder.

Моя цель — создать исполняемый файл, и я не понимаю, что делать дальше. Все учебники, которые я нашел, просто создают модуль llvm и распечатывают сборку с помощью Module.dump (). Кроме того, единственная документация, которую я могу найти, предназначена для разработчиков llvm, а не для конечных пользователей проекта.

Если я хочу сгенерировать машинный код, каковы следующие шаги? Похоже, проект llvm-mc может делать то, что я хочу, но я не могу найти какую-либо документацию по нему.

Возможно, я ожидаю, что llvm сделает что-то, чего нет. Я ожидаю, что я смогу построить модуль, тогда будет API, который я могу вызвать с модулем, и будет получена целевая тройка и объектный файл. Я нашел документацию и примеры по созданию JIT, и я не заинтересован в этом. Я ищу, как создавать скомпилированные двоичные файлы.

Я работаю над OS X, если это как-то повлияет.

18

Решение

использование llc -filetype=obj испустить связываемый объектный файл с вашего IR. Вы можете посмотреть на код llc чтобы увидеть вызовы API LLVM, он создает такой код. По крайней мере, для Mac OS X и Linux объекты, излучаемые таким образом, должны быть довольно хорошими (то есть, это пока не вариант «альфа-качества»).

Однако LLVM не содержит компоновщика (пока!). Таким образом, чтобы фактически связать этот объектный файл с некоторой исполняемой или общей библиотекой, вам нужно использовать системный компоновщик. Обратите внимание, что даже если у вас есть исполняемый файл, состоящий из одного объектного файла, последний все равно должен быть связан. Разработчики в сообществе LLVM работают над реальным компоновщиком для LLVM, который называется lld, Вы можете посетить его страница или искать в архивах списка рассылки, чтобы следить за его ходом.

15

Другие решения

Как вы можете читать дальше руководство ООО, он действительно предназначен просто для генерации сборки, а затем «Выходные данные на языке ассемблера могут затем передаваться через собственный ассемблер и компоновщик для генерации собственного исполняемого файла» — например, Гну ассемблер (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 и ассемблера.

14

Проверьте эти функции в 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.

1
По вопросам рекламы [email protected]