我正在尝试在运行时JIT编译现有C / C ++程序中的某些函数,但是我遇到了全局变量初始化的问题。具体来说,我采用的方法是使用Clang将程序预编译为IR bitcode模块以及可执行文件。在运行时,程序加载模块,转换它们(程序专门化),编译并执行它们。事实证明,我有一些全局变量在执行“主机”程序时被初始化和修改。目前,这些全局变量也在JIT编译代码中初始化,而我希望它们映射到主机全局变量。有人可以帮我这个吗?
下面摘录了一个小的复制品。完整的源代码是here。 somefunc.cpp文件在构建期间被预编译,并加载到testCompile.cpp中的main()函数中。全局变量xyz在somefunc.cpp中被初始化为指向25,但是我希望它指向10而不是main()。换句话说,main()中的断言应该成功。
我尝试了几种不同的方法来解决这个问题。 ChangeGlobal()函数尝试(不成功)实现此updateGlobalMapping()。第二种更为hacky的方法是使用适当初始化的新全局变量。我可以让后一种方法适用于某些类型的全局变量,但有没有比这更优雅的方法?
//————— somefunc.h ————————
extern int *xyz;
//—————— somefunc.cpp ——————
int abc = 25;
int *xyz = &abc;
int somefunc() {
return *xyz;
}
//—————— testCompile.cpp ——————
class JitCompiler {
public:
JitCompiler(const std::string module_file);
void LoadModule(const std::string& file);
template <typename FnType>
FnType CompileFunc(FnType fn, const std::string& fn_name);
void ChangeGlobal();
private:
std::unique_ptr<LLVMContext> context_;
Module *module_;
std::unique_ptr<ExecutionEngine> engine_;
};
void JitCompiler::ChangeGlobal() {
// ----------------- #1: UpdateGlobalMapping -----------------
//auto g = engine_->FindGlobalVariableNamed("xyz");
//engine_->updateGlobalMapping(g, &xyz);
//assert(engine_->getGlobalValueAddress("xyz") == (uint64_t) &xyz);
// ----------------- #2: Replace with new global ————————
// ------- Ugly hack that works for globals of type T** ----------
auto g = engine_->FindGlobalVariableNamed("xyz");
Constant *addr_i = ConstantInt::get(*context_, APInt(64, (uint64_t) xyz));
auto addr = ConstantExpr::getIntToPtr(
addr_i, g->getType()->getPointerElementType());
GlobalVariable *n = new GlobalVariable(
*module_,
g->getType()->getPointerElementType(),
g->isConstant(),
g->getLinkage(),
addr,
g->getName() + "_new");
g->replaceAllUsesWith(n);
n->takeName(g);
g->eraseFromParent();
}
int main() {
xyz = new int (10);
JitCompiler jit("somefunc.bc");
jit.ChangeGlobal();
auto fn = jit.CompileFunc(&somefunc, "somefunc");
assert(somefunc() == fn());
}
答案 0 :(得分:0)
更好的方法是将两者结合起来,即创建一个新的全局,其外部链接映射到&xyz
并将其替换为原始:
auto g = engine_->FindGlobalVariableNamed("xyz");
GlobalVariable *n = new GlobalVariable(
g->getType()->getPointerElementType(),
g->isConstant(),
ExternalLinkage
nullptr,
g->getName() + "_new");
engine_->updateGlobalMapping(n, &xyz);
g->replaceAllUsesWith(n);
n->takeName(g);
g->eraseFromParent();