2015-07-17 14 views
5

Tôi muốn có hầu hết chương trình của mình là chương trình C++ được biên dịch thông thường. Chương trình cho biết sử dụng một đoạn bộ nhớ tiếp giáp cho một chồng. Phía trên cùng của ngăn xếp được duy trì bởi một con trỏ bình thường.Chia sẻ con trỏ C++ với mã LLVM JIT'd

Tôi muốn chia sẻ con trỏ đó với mã được tạo qua LLVM JIT. Ví dụ, đưa ra:

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 

nơi pointerInc() sẽ chèn mã JIT'd vào hiện tại BasicBlock để tăng top. Mã pointerInc() là:

// 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); 
} 

Thật không may, điều này không hiệu quả. Đó là cơ thể của (lớn hơn) pointerInc() đó là sai. Mã thực sự được lấy từ mã API LLVM C++ được tạo bởi llc trên một chương trình C++ thông thường làm tăng một con trỏ.

Khi chạy, chương trình in:

&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) 

Có hai câu hỏi:

  1. Đây có phải là đúng? Tôi thậm chí có thể làm những gì tôi muốn, tức là, chia sẻ một con trỏ C++ nguyên với mã JIT'd?
  2. Tại sao nó bán phá giá lõi?

Ngay cả khi tôi đã thực hiện chức năng JIT'd, thì mã vẫn còn các khối lõi tại dòng gọi hàm đó. Mã thiết lập LLVM JIT trông giống như tất cả các ví dụ tôi đã thấy, vì vậy tôi cũng không thấy có vấn đề gì với nó.

Trợ giúp một chút?


Cập nhật

Nếu tôi thay đổi dòng bị phản đối:

void *const func_ptr = exec->getPointerToFunction(func); 

vào dòng mới:

uint64_t const func_ptr = exec->getFunctionAddress("func"); 

sau đó func_ptr là null.

+0

Tôi đã viết về một cái gì đó tương tự ở đây: http://eli.thegreenplace.net/2015/calling-back-into-python-from-llvmlite-jited-code - nó sử dụng bindings Python cho LLVM, nhưng ý tưởng chính là như nhau - làm cho mã JIT nhận thức được điều gì đó trong chương trình máy chủ –

+0

Tôi không nghĩ nó tương tự như vậy. Dường như bạn đang gọi một hàm từ mã JIT'd.Tôi chỉ muốn tăng một con trỏ từ mã JIT'd. –

+0

Bạn có thể yêu cầu một số danh sách gửi thư [LLVM-dev] (http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev) hoặc trên một số [kênh LLVM IRC] (http://llvm.org/docs/# irc). Bạn cũng có thể sử dụng một số công nghệ khác: [GCCJIT] (https://gcc.gnu.org/onlinedocs/jit/), 'libjit',' asmjit' v.v. và bạn có thể liệt kê mã lắp ráp được sản xuất để hiểu thêm về nó. –

Trả lời

1

Sau khi chơi đùa nhiều hơn với lcc (và sử dụng tốt hơn C++ để nuôi vào nó), tôi có nó làm việc:

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); 
} 

Tuy nhiên, chương trình chạy thành công chỉ khi chức năng JIT'd là gọi qua:

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

Sử dụng một trong hai getFunctionAddress() hoặc getPointerToFunction() bãi lõi. Tôi vẫn không có câu trả lời cho điều đó.

Các vấn đề liên quan