Вызовите функции C/С++ из ExecutionEngine

Я изучаю llvm и хочу сделать доказательство концепции идеи, которую я имею.

В принципе, я хочу разбить мой компилятор и мое время выполнения. Компилятор предоставит .bc, и среда выполнения загрузит его через ParseBitcodeFile и использует ExecutionEngine для ее запуска. Эта часть работает.

Теперь, чтобы легко сделать системные вызовы, я хочу иметь возможность реализовать в своих функциях C/С++ во время выполнения, которые выполняют все системные вызовы (файл io, stdout printing и т.д.). Мой вопрос: как я могу назвать эти функции из кода моего компилятора игрушек, который скомпилирован на другом шаге llvm и позволяет использовать его при выполнении.

Ответ 1

Хорошие новости: при использовании JIT ExecutionEngine это будет работать. Когда JIT-er находит внешний символ, используемый IR, который не найден в самом IR, он смотрит в самом JIT-процессе, поэтому любые символы, видимые из вашей основной программы, могут быть вызваны.

Это объясняется непосредственно в часть 4 учебника LLVM:

Кто знает, как JIT знает о грехе и о косе? Ответ удивительно просто: в этом примере JIT начал выполнение и получил вызов функции. Он понял, что функция еще JIT не скомпилировал и не вызвал стандартный набор подпрограмм для разрешить эту функцию. В этом случае тела, определенного для функции, поэтому JIT закончил тем, что вызвал "dlsym (" sin ")" на Сам процесс калейдоскопа. Поскольку "sin" определяется в JIT адресное пространство, он просто разбивает вызовы в модуле для вызова libm версия греха напрямую.

В деталях посмотрите на lib/ExecutionEngine/JIT/JIT.cpp - в частности, его использование DynamicLibrary.

Ответ 2

Эли ответ велик, и вы должны его принять. Однако существует еще одна альтернатива, заключающаяся в том, чтобы отдельно скомпилировать исходные файлы времени выполнения для модулей LLVM (например, с помощью Clang) и использовать ExecutionEngine::addModule() для их добавления.

Это менее удобно, и это означает, что необходимо скомпилировать одни и те же файлы дважды (один раз для вашей хост-программы, а другой - получить от них Module), но преимущество в том, что оно позволяет выполнять встроенную и другую перекрестную оптимизацию из вашего JIT-кода.