Моя программа, которая JIT компилирует модуль LLVM IR и вызывает функцию foo
определенный в нем сбой во время выполнения, если foo
использует внешне определенную функцию:
LLVM ERROR: Program used external function 'glutInit' which could not be resolved!
Моя программа:
// foo1.cpp
#include <GL/glut.h>
extern "C" void foo()
{
glutInit(0,0);
}
// foo2.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <llvm/Support/raw_ostream.h>
#include <llvm/LLVMContext.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/IRReader.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/ExecutionEngine/JIT.h>
#include <llvm/ExecutionEngine/RuntimeDyld.h>
int main(int argc, char **argv)
{
using namespace llvm;
InitializeNativeTarget();
LLVMContext context;
SMDiagnostic error;
std::ifstream ir_file("foo1.s");
std::string ir((std::istreambuf_iterator<char>(ir_file)),
(std::istreambuf_iterator<char>()));
Module *m = ParseIR(MemoryBuffer::getMemBuffer(StringRef(ir)), error, context);
if(!m)
{
error.print(argv[0], errs());
}
ExecutionEngine *ee = ExecutionEngine::create(m);
Function *func = ee->FindFunctionNamed("foo");
if(func == 0)
{
std::cerr << "Couldn't find Function foo" << std::endl;
std::exit(-1);
}
typedef void (*fcn_ptr)();
fcn_ptr foo = reinterpret_cast<fcn_ptr>(ee->getPointerToFunction(func));
foo();
delete ee;
return 0;
}
Вот как я строю свою программу:
$ clang -S -emit-llvm foo1.cpp
$ g++ -rdynamic foo2.cpp `llvm-config --cxxflags` `llvm-config --libs` `llvm-config --ldflags` -lglut
Выход:
$ ./a.out
LLVM ERROR: Program used external function 'glutInit' which could not be resolved!
Он завершается с подобной ошибкой каждый раз, когда я пытаюсь использовать внешне определенную функцию, которая отсутствует в стандартной библиотеке C ++ (например, printf
, malloc
, & free
нет проблем). Что я делаю неправильно?
Удостоверься что glutInit
был связан с a.out
, Если ваш хост-код (то, что выполняет JIT) не вызывал его, он мог быть удален компоновщиком. Если это так, вы должны добавить фиктивную ссылку или использовать скрипты / флаги компоновщика.
Добавление параметра командной строки -Wl,-no-as-needed
непосредственно перед -lglut
предотвратит падение компоновщика glut
библиотека, которая в противном случае считает ненужной:
$ g++ -rdynamic foo2.cpp `llvm-config --cxxflags` `llvm-config --libs` `llvm-config --ldflags` -Wl,-no-as-needed -lglut