2015-07-17 14 views
5

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:

  1. Bu doğru mu? İstediğimi yapabilir miyim, yani JIT'd koduyla ham C++ işaretçisini paylaşabilir miyim?
  2. Ç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ş.

+0

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 –

+0

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. –

+0

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. –

cevap

1

daha lcc ile çok etrafında oynayan (ve onun içine beslemek için daha iyi C++ kodu kullanarak) sonra, bunun çalışma var: JIT'd fonksiyonu olduğunda

llvm::Value* pointerToPointer(void *ptr, llvm::BasicBlock *block) { 
    using namespace llvm; 
    LLVMContext &ctx = block->getContext(); 
    ConstantInt *const ptrAsInt = 
     ConstantInt::get(IntegerType::get(ctx, 64), (uint64_t)ptr); 
    PointerType *const Int8Ptr_type = Type::getInt8PtrTy(ctx); 
    PointerType *const Int8PtrPtr_type = PointerType::getUnqual(Int8Ptr_type); 
    return new IntToPtrInst(ptrAsInt, Int8PtrPtr_type, "pptr", block); 
} 

void pointerInc(llvm::Value *pptr, llvm::ConstantInt *sizeof_T, 
       llvm::BasicBlock *block) { 
    using namespace llvm; 
    LLVMContext &ctx = block->getContext(); 

    LoadInst *const ptr = new LoadInst(pptr, "ptr", block); 
    ptr->setAlignment(sizeof(void*)); 

    GetElementPtrInst *const inc = 
     GetElementPtrInst::Create(ptr, sizeof_T, "inc", block); 

    StoreInst *const store = new StoreInst(inc, pptr, block); 
    store->setAlignment(sizeof(void*)); 
} 

template<typename T> 
inline void pointerInc(T **pptr, llvm::BasicBlock *block) { 
    using namespace llvm; 
    LLVMContext &ctx = block->getContext(); 
    ConstantInt *const sizeof_T = ConstantInt::get(
     IntegerType::get(ctx, 64), (uint64_t)sizeof(T) 
    ); 
    pointerInc(pointerToPointer(pptr, block), sizeof_T, block); 
} 

Ancak program sadece başarılı bir şekilde çalıştığını ya getFunctionAddress() veya getPointerToFunction() çekirdek dökümlerini kullanarak

vector<GenericValue> noargs; 
exec->runFunction(func, noargs); 

: üzerinden çağrılabilir. Buna hala bir cevabım yok.