LLVM - проблема связывания - PullRequest
       7

LLVM - проблема связывания

11 голосов
/ 14 сентября 2009

Я пишу генератор кода LLVM для языка Timber, текущий компилятор испускает C-код. Моя проблема в том, что мне нужно вызывать функции C из сгенерированных файлов LLVM, например, компилятор имеет сборщик мусора в реальном времени, и мне нужно вызывать функции, чтобы уведомлять, когда новые объекты размещаются в куче. Я понятия не имею, как связать эти функции с моими сгенерированными файлами LLVM.

Генерация кода производится путем генерации .ll-файлов и последующей их компиляции вручную.

Я пытаюсь вызвать внешнюю функцию из LLVM, но мне не повезло. В примерах, которые я> нашел, вызываются только стандартные функции языка Си, такие как "put" и "printf", но я хочу вызвать> самодельную функцию. Я застрял.

Ответы [ 3 ]

12 голосов
/ 23 октября 2009

Я предполагаю, что вы пишете преобразование LLVM и хотите добавить вызовы внешних функций в преобразованный код. Если это не так, отредактируйте свой вопрос и включите дополнительную информацию.

Прежде чем вы сможете вызвать внешнюю функцию из кода LLVM, вам нужно вставить объявление для нее. Например:

virtual bool runOnModule(Module &m) {
    Constant *log_func = m.getOrInsertFunction("log_func",
                                               Type::VoidTy,
                                               PointerType::getUnqual(Type::Int8Ty),
                                               Type::Int32Ty,
                                               Type::Int32Ty,
                                               NULL);
    ...
}

Код выше объявляет функцию log_func, которая возвращает void и принимает три аргумента: указатель байта (строка) и два 32-разрядных целых числа. getOrInsertFunction - это метод Module.

Для фактического вызова функции необходимо вставить CallInst. Для этого есть несколько статических Create методов.

5 голосов
/ 01 января 2010

Скомпилируйте ваши файлы сборки LLVM обычно с помощью llvm-as:

llvm-as *.ll

Скомпилируйте файлы битового кода в файлы на языке ассемблера .s:

llc *.bc

GCC их с библиотекой времени выполнения:

gcc *.s runtime.c -o executable

Заменить в реальных make-файлах, общих библиотеках и т. Д., Если необходимо. Вы поняли идею.

3 голосов
/ 27 января 2010

Я интерпретирую ваш вопрос как «как мне реализовать библиотеку времени выполнения на C или C ++ для моего языка, который компилируется в LLVM?»

Один из подходов, как подробно описал Джонатан Танг, преобразует вывод вашего компилятора из LLVM IR в битовый код в сборку, и ванильный gcc связывает сборку с источником времени выполнения (или объектными файлами).

Альтернативный, возможно, более гибкий подход состоит в том, чтобы использовать llvm-gcc для компиляции самой среды выполнения в битовый код LLVM, а затем использовать llvm-ld, чтобы связать битовый код вашего компилятора с битовым кодом вашей среды выполнения. Этот битовый код затем может быть повторно оптимизирован с помощью opt, преобразован обратно в IR с помощью llvm-dis, интерпретирован непосредственно с помощью lli (это будет, на самом деле, работает, только если LLVM был построен против libffi), или скомпилирован в сборку с llc (а затем в собственный двоичный файл с ванилью gcc).

...