我想在運行時在現有的C/C++程序中JIT編譯一些函數,但我遇到了全局變量初始化的一些麻煩。具體來說,我採用的方法是使用Clang將程序預編譯爲除可執行文件之外的IR位模塊模塊。在運行時,程序加載模塊,轉換它們(程序特化),編譯並執行它們。事實證明,我有一些全局變量在執行「主機」程序期間被初始化和修改。目前,這些全局變量也在JIT編譯代碼中初始化,而我希望它們映射到主機全局變量。有人可以幫我弄這個嗎?在MCJIT中使用全局變量
下面摘錄了一個小的轉載。完整的源代碼是here。文件somefunc.cpp在構建期間被預編譯,並被加載到testCompile.cpp中的main()函數中。全局變量xyz在somefunc.cpp中被初始化爲指向25,但我希望它在main()中指向10。換句話說,main()中的斷言應該成功。
我嘗試了幾種不同的方法來解決這個問題。 ChangeGlobal()函數嘗試(不成功)實現此updateGlobalMapping()。第二種更加冒險的方法是使用一個新的全局變量進行適當的初始化。我可以使用後一種方法來處理某些類型的全局變量,但是有沒有比這更優雅的方法?
//————— 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());
}