Связывание кода LLVM JIT с внешними функциями С++

Я пишу LLVM скриптовый движок, который JIT компилирует код сценария на пользовательском языке. Моя проблема в том, что я не могу вызывать внешние функции (даже функция C99 erf() не работает).

Например, если я extern "C" выполняет функцию erf,

extern "C" double erft(double x){
return erf(x);
}

и создать функцию с внешней связью

std::vector<const Type*> Double1(1,Type::getDoubleTy(getGlobalContext()));
FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),Double1,false);
Function *erft = Function::Create(FT,Function::ExternalLinkage,"erft",TheModule);

получить следующее сообщение об ошибке при запуске my script с помощью erft (0.0):

LLVM ERROR: программа использует внешнюю функцию 'erft', которая не может быть решена!

Выполнение сопоставления вручную,

void ExecutionEngine::addGlobalMapping( const GlobalValue *  erfF, void *  erft); 

получит следующую ошибку:

Объявление `void llvm:: ExecutionEngine:: addGlobalMapping (const llvm:: GlobalValue *, void *) 'вне класса не является определением

Очевидно, я делаю что-то очень плохое. Любая помощь будет высоко оценена

Ответы

Ответ 1

Предполагая, что вы его не отключили (вызывая EE->DisableSymbolSearching()), тогда LLVM будет использовать dlsym() для поиска символов в самой программе JIT. В зависимости от вашей платформы это может означать, что вам нужно создать свой JIT с помощью -fPIC или что он может быть недоступен вообще (например, в Windows).

Помимо автоматического поиска символа, вы всегда можете самостоятельно регистрировать отдельные функции, используя EE->addGlobalMapping(GV, &function), где GV = объявление функции llvm:: Function *, которое соответствует нативной функции, которую вы вызываете. В вашем случае с ertf() это:

EE->addGlobalMapping(erft, &::erft);

Обратите внимание, что вы назвали глобальную функцию erft() и локальную переменную erft, следовательно, "::". В следующий раз выберите разные имена!

Ответ 2

Это может происходить, потому что вы забыли добавить "libm", попробуйте использовать:

[your module]->addLibrary("m");

Смотрите здесь для получения дополнительной информации о Module::addLibrary().

Ответ 3

Я не знаю llvm, но это не имеет смысла:

void ExecutionEngine::addGlobalMapping( const GlobalValue *  erfF, void *  erft); 

Это определяет новую функцию в С++. Что вам нужно сделать, так это зарегистрировать свою функцию с помощью LLVM. Определение этой функции похоже на попытку добавить новые методы в классы LLVM, а не то, что вы хотите сделать.