簡體   English   中英

使用 LLVM 分配和訪問堆 arrays

[英]Allocation and access of heap arrays with LLVM

從萬花筒教程和堆棧交換問題( 問題)開始,我嘗試使用 LLVM output 一些數組創建和訪問代碼。 這個想法是有一個“alloca”堆棧變量“a”,它持有一個指向分配有 malloc 的數組的雙*。生成的代碼失敗,我相信主要問題是我在 C++ 中對“CreateInBoundsGEP”的調用。

所以我一句話中的主要問題是“如何調用 CreateInBoundsGEP 以便它輸出正確的 IR 代碼?”

我嘗試的是以下內容:

我的分配代碼創建為 llvm c++ 接口的“CreateMalloc”調用的 output 來自上面提到的問題。

%a = alloca double*, align 8
%malloccall = tail call i8* @malloc(i32 48)
%0 = bitcast i8* %malloccall to double*
store double* %0, double** %a, align 8

這段代碼對我來說看起來不錯,但在使用 verifyFunction() 檢查時它已經導致錯誤/警告。

Call parameter type does not match function signature!
i32 48

遺憾的是它沒有告訴我正確的參數類型是什么(i64?)。 IR 參考根本沒有提到“malloc”函數調用,而是提到了“malloc”IR 操作(參考)!

我的主要問題(如果之前沒有發現,也會導致 memory 錯誤)發生在對數組的寫訪問中。

我的第一次嘗試是直接從引用的堆棧交換問題1中復制(或多或少):

//ret is the base adress of the pointer, ie "a"
//rhs is the Value* to the right hand side that is assigned
//index is the Value* to the array index 
auto element_ptr = Builder->CreateInBoundsGEP(ret, index, "acc_tmp");
Builder->CreateStore(rhs, element_ptr);

哪些輸出(對於 a[1]=5 作為輸入代碼)

%acc_tmp = getelementptr inbounds double*, double** %a, i32 1
store double 5.000000e+00, double** %acc_tmp, align 8

這會產生“verifyFunction”錯誤,我可以看到“double**”可能應該是“double*”。 由於我也收到了棄用警告,因此我決定嘗試使用類型參數的 CreateInBoundsGEP。 由於文檔沒有告訴我“類型”應該是元素類型還是指針類型,所以我都嘗試了

auto element_ptr = Builder->CreateInBoundsGEP(rhs->getType()->getPointerTo(), ret, index, "acc_tmp");

或者

auto element_ptr = Builder->CreateInBoundsGEP(rhs->getType(), ret, index, "acc_tmp");

兩者都不起作用,第一個版本輸出與不傳遞類型相同的代碼,第二個版本導致

static llvm::GetElementPtrInst *llvm::GetElementPtrInst::Create(llvm::Type *, llvm::Value *, ArrayRef<llvm::Value *>, const llvm::Twine &, llvm::Instruction *): Assertion `cast<PointerType>(Ptr->getType()->getScalarType()) ->isOpaqueOrPointeeTypeMatches(PointeeType)' failed.

正如我在最初的問題中注意到的那樣,我的指令中有一個指針*太多了。 起初我不明白為什么會這樣,但后來我在一個看似無關的問題1中找到了我的問題的答案:

如果您直接使用“CreateMalloc”的返回值作為“CreateInBoundsGEP”的參數,我最初從2復制的代碼將起作用。

然而,在我的例子中,還涉及一個步驟:我將“CreateMalloc”返回值存儲在一個局部變量中,該變量又由分配有“alloca”的指針引用。 因此,與原始代碼片段相比,我需要一個額外的取消引用步驟來訪問我的數組元素。

1中所述,LLVM-IR 中的取消引用只是一個“負載”。 所以正確的數組訪問代碼看起來像

//ret is the pointer to(!) the base adress of the array, ie "a"
//rhs is the Value* to the right hand side that is assigned
//index is the Value* holding the array index 
llvm::Value* index = visit(ctx->index).as<llvm::Value*>();
llvm::Value* ret_deref =   Builder->CreateLoad(llvm::Type::getDoubleTy(*TheContext)->getPointerTo(),ret,"deref_tmp");
auto element_ptr = Builder->CreateInBoundsGEP(rhs->getType(), ret_deref, index, "acc_tmp");
Builder->CreateStore(rhs, element_ptr);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM