Связывание кода 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, а не то, что вы хотите сделать.