Подтвердить что ты не робот

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

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

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

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

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

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

4b9b3361

Ответ 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.