Programımın çoğunu normal derlenmiş C++ programına sahip olmak istiyorum. Söz konusu program, bir yığın için bir bitişik bellek yığını kullanır. Yığının üst kısmı sıradan bir işaretçi tarafından korunur.LLVM ile bir C++ işaretçisini paylaşma JIT'd kodu
Bu işaretçiyi LLVM JIT ile oluşturulan kod ile paylaşmak istiyorum. Örneğin, belirli bir: pointerInc()
mevcut BasicBlock
içine JIT'd kodu ekler
llvm::InitializeNativeTarget();
llvm::LLVMContext ctx;
std::unique_ptr<llvm::Module> uptr_module = llvm::make_unique<llvm::Module>("lt", ctx);
llvm::Module *const module = uptr_module.get();
int *const stack = new int[100];
int *top = stack; // I want this pointer to be shared with JIT'd code
llvm::Function *const func = llvm::cast<llvm::Function>(
module->getOrInsertFunction("func", llvm::Type::getVoidTy(ctx), (llvm::Type*)0)
);
llvm::BasicBlock *const block = llvm::BasicBlock::Create(ctx, "entry", func);
pointerInc(&top, block); // Increment the pointer in JIT'd code
llvm::ReturnInst::Create(ctx, block);
llvm::verifyFunction(*func, &llvm::outs());
llvm::verifyModule(*module, &llvm::outs());
module->dump();
llvm::EngineBuilder eb(std::move(uptr_module));
llvm::ExecutionEngine *const exec = eb.create();
assert(exec);
void *const func_ptr = exec->getPointerToFunction(func);
assert(func_ptr);
typedef void (*PFv_v)();
(*(PFv_v)func_ptr)(); // Call JIT'd function
top
artırmak için. pointerInc()
kodudur:
// Convert a raw C++ pointer into an LLVM Constant*.
template<typename T>
inline llvm::Value* ptrToValue(T **pptr, llvm::LLVMContext &ctx) {
return return llvm::ConstantInt::get(llvm::Type::getInt64Ty(ctx), (uint64_t)pptr);
}
void pointerInc(llvm::Constant *pptrAsInt64, llvm::ConstantInt *sizeof_T,
llvm::BasicBlock *block) {
llvm::LLVMContext &ctx = block->getContext();
llvm::Constant *const intToPtr8 = llvm::ConstantExpr::getIntToPtr(
pptrAsInt64, llvm::PointerType::getUnqual(llvm::Type::getInt8Ty(ctx))
);
llvm::GetElementPtrInst *const inc =
llvm::GetElementPtrInst::Create(intToPtr8, sizeof_T, "inc", block);
llvm::CastInst *const cast = llvm::CastInst::CreatePointerCast(
inc, llvm::Type::getInt64Ty(ctx), "cast", block
);
llvm::Constant *const intToPtr64 = llvm::ConstantExpr::getIntToPtr(
pptrAsInt64, llvm::PointerType::getUnqual(llvm::Type::getInt64Ty(ctx))
);
llvm::StoreInst *const store = new llvm::StoreInst(cast, intToPtr64, false, block);
store->setAlignment(8);
}
template<typename T>
inline void pointerInc(T **pptr, llvm::BasicBlock *block) {
llvm::LLVMContext &ctx = block->getContext();
llvm::ConstantInt *const sizeof_T =
llvm::ConstantInt::get(llvm::Type::getInt64Ty(ctx), sizeof(T));
pointerInc(ptrToValue(pptr, ctx), sizeof_T, block);
}
Maalesef bu işe yaramaz. Bu (büyük) pointerInc()
yanlıştır. Kod aslında, bir işaretçi artıran sıradan bir C++ programında llc
tarafından oluşturulan LLVM C++ API kodundan türetilmiştir.
çalıştırın Program yazdırır:
&p = 140734551679784
--------------------
; ModuleID = 'lt'
define void @func() {
entry:
%inc = getelementptr i8* inttoptr (i64 140734551679784 to i8*), i64 4
%cast = ptrtoint i8* %inc to i64
store i64 %cast, i64* inttoptr (i64 140734551679784 to i64*), align 8
ret void
}
Segmentation fault: 11 (core dumped)
iki soru vardır:
- Bu doğru mu? İstediğimi yapabilir miyim, yani JIT'd koduyla ham C++ işaretçisini paylaşabilir miyim?
- Çekirdek neden biriktiriyor? Ben JIT'd işlevi boş etse bile
, hala çekirdek işlevini çağırır çizgisinde döker kodu. LLVM JIT kurulum kodu, gördüğüm tüm örneklere benziyor, bu yüzden neyin yanlış olduğunu da göremiyorum.
Biraz yardım? Yeni hattına
void *const func_ptr = exec->getPointerToFunction(func);
: Ben kaldırılmış çizgiyi değiştirirseniz
Güncelleme
uint64_t const func_ptr = exec->getFunctionAddress("func");
sonra func_ptr
boş.
Burada benzer bir şey hakkında yazdım: http://eli.thegreenplace.net/2015/calling-back-into-python-from-llvmlite-jited-code - LLVM için Python bağlamaları kullanıyor, ancak ana fikir aynıdır - ana programda –
JIT kodunun bir şeyden haberdar olmasını yeterli görmüyorum. JIT'd kodundan bir işlevi çağırıyor gibi görünüyorsunuz.Sadece JIT'd kodundan bir işaretçi arttırmak istiyorum. –
Bazı [LLVM-dev] (http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev) e-posta listesinden veya bazı [LLVM IRC kanalı] 'dan (http://llvm.org/docs) isteyebilirsiniz./# irc). Başka bir teknoloji de kullanabilirsiniz: [GCCJIT] (https://gcc.gnu.org/onlinedocs/jit/), 'libjit', asmjit' vb. ve daha fazlasını anlamak için üretilen assembler kodunu listeleyebilirsiniz. –