Я пытаюсь поэкспериментировать с llvm прямо сейчас. Я хотел бы использовать языки, которые могут быть скомпилированы в LLVM битовый код для сценариев. До сих пор мне удавалось загрузить модуль битового кода llvm и вызвать функцию, определенную в нем, из моего «внутреннего» кода C ++. Затем я попытался представить функцию c ++ из своего внутреннего кода jit’d-коду — до сих пор в этих усилиях мне не удалось получить ничего, кроме SEGFAULT.
Мой код выглядит следующим образом. Я попытался создать функцию и глобальное отображение в моем механизме выполнения, которое указывает на функцию, которую я хотел бы вызвать.
extern "C" void externGuy()
{
cout << "I'm the extern guy" << endl;
}
void ExposeFunction()
{
std::vector<Type*> NoArgs(0);
FunctionType* FT = FunctionType::get(Type::getVoidTy(getGlobalContext()), NoArgs, false);
Function* fnc = Function::Create(FT, Function::ExternalLinkage, "externGuy", StartModule);
JIT->addGlobalMapping(fnc, (void*)externGuy);
}
// ... Create module, create execution engine
ExposeFunction();
Проблема в том, что я не могу добавить функцию в модуль после ее загрузки из файла битового кода?
Обновить:
Я реорганизовал свой код так, чтобы он читался так:
// ... Create module, create execution engine
std::vector<Type*> NoArgs(0);
FunctionType* FT = FunctionType::get(Type::getVoidTy(getGlobalContext()), NoArgs, false);
Function* fnc = Function::Create(FT, Function::ExternalLinkage, "externGuy", m);
fnc->dump();
JIT->addGlobalMapping(fnc, (void*)externGuy);
Так что вместо segfault я получаю:
Program used external function 'externGuy' which could not be resolved
Кроме того, результат dump () печатает:
declare void @externGuy1()
Если я изменю свой битовый код сценария c ++, чтобы вызвать externGuy1()
вместо externGuy()
это предложит мне, что я хотел использовать externGuy
, addGlobalMapping
просто, похоже, не работает для меня. Я не уверен, что мне здесь не хватает. Я также добавил -fPIC
к моей команде компиляции, как я видел, предложено в другом вопросе — я честно не уверен, помогло ли это что-нибудь, но без вреда при попытке.
Я наконец получил это, чтобы работать. Я подозреваю, что, возможно, создание функции, а также ее определение в скрипте вызывает, возможно, более 1 объявления имени функции, и сопоставление просто не сработало. Что я сделал, так это определил функцию в скрипте и затем использовал getFunction
использовать для сопоставления вместо. С использованием dump()
метод на выходе функции:
declare void @externGuy() #1
Вот почему я думаю, что это как-то связано с тем, что отображение не работает изначально. Я также помню учебник Калейдоскопа, говорящий, что getPointerToFunction
будет делать JIT-компиляцию, когда он вызывается, если это еще не сделано, поэтому я подумал, что мне придется сделать отображение перед этим вызовом.
В общем, чтобы все это работало, это было следующим:
// Get the function and map it
Function* extrn = m->getFunction("externGuy");
extrn->dump();
JIT->addGlobalMapping(extrn, (void*)&::externGuy);
// Get a pointer to the jit compiled function
Function* mane = m->getFunction("hello");
void* fptr = JIT->getPointerToFunction(mane);
// Make a call to the jit compiled function which contains a call to externGuy
void (*FP)() = (void(*)())(intptr_t)fptr;
FP();