将LLVM JIT代码链接到外部C++函数

19
我正在编写一个 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);

运行我的脚本并使用 erft(0.0) 时,出现以下错误消息:

LLVM 错误:程序使用了无法解析的外部函数 'erft'!

需要手动进行映射。

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

会得到以下错误:

`void llvm::ExecutionEngine::addGlobalMapping(const llvm::GlobalValue*, void*)'的声明超出了类定义

显然我做错了什么。非常感谢您的帮助。


2
提醒未来的访客:这些答案正在引用已废弃的方法。 - antipattern
1
这个问题的答案展示了如何使用非废弃的方法来实现。链接 - James Allingham
3个回答

14

假设你没有禁用它(通过调用EE->DisableSymbolSearching()),LLVM将使用dlsym()在JIT程序本身中查找符号。根据您的平台,这可能意味着您需要使用-fPIC构建JIT,或者它可能根本不可用(例如在Windows上)。

除了自动符号搜索外,您始终可以使用EE->addGlobalMapping(GV, &function)注册每个函数本身,其中GV = llvm::Function*函数声明,与您调用的本地函数相匹配。对于ertf(),您可以使用以下代码:

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

请注意,您将全局函数命名为erft(),并将本地变量命名为erft,因此需要使用“::”。下次请选择不同的名称!


2
这可能是因为您忘记添加“libm”依赖项,尝试使用以下方法:
[your module]->addLibrary("m");

更多关于Module::addLibrary()的信息,请参见此处


0

我不了解 LLVM,但这没有意义:

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

这定义了一个新的C++函数。你需要做的是以某种方式将你的函数注册到LLVM。定义该函数就像尝试向LLVM类添加新方法一样,这不是你想要做的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接