2016-11-23 22 views
2

所以我創建了一個結構類型與此:如何獲取LLVM中結構成員的值?

llvm::StructType* llvm_struct = llvm::StructType::create(llvm_context, struct_name); 
std::vector<llvm::Type*> members; 

for(size_t j = 0; j != struct_data.members.size(); j++){ 
    llvm::Type* member_type = /*get member type*/; 
    members.push_back(member_type); 
} 

llvm_struct->setBody(members) 

,我想知道如何在結構內訪問的成員。

我使用getelementptr沒有運氣到目前爲止已經試過:

llvm::Value* member_index = llvm::ConstantInt::get(llvm_context, llvm::APInt(32, /*structure member index*/, true)); 
llvm::Value* indices[2] = {llvm::ConstantInt::get(member_index->getType(), 0), member_index}; 
llvm::Value* data = /*expression value*/; 

return irbuilder.CreateInBoundsGEP(data, llvm::ArrayRef<llvm::Value*>(indices, 2), "membtmp"); 

感謝您的任何反饋!

編輯:

好了,所以的llvm::Value* data類型是將其從堆棧上的指針加載的%a_struct。從文檔看來,irbuilder.CreateInBoundsGEP(llvm::Value*, llvm::ArrayRef<llvm::Value*>, llvm::Twine)要求第一個參數是指向結構的指針,而不是結構本身的值。

將結構體的值複製到堆棧中的變量時,將引發此錯誤:Expression: getOperand(0)->getType() == cast<PointerType>(getOperand(1)->getType())->getElementType(‌​‌​) && "Ptr must be a pointer to Val type!"。當拋出該錯誤時,粘貼到irbuidler.CreateInBoundsGEP(...)的指針是llvm::AllocaInst*,該堆棧新分配到堆棧並且包含複製到其中的值llvm::Value* data(類型%a_struct)。

的IR所產生的呼叫irbuilder.CreateInBoundsGEP(...)與複製到一個變量堆棧上的值之前右:

define i32 @main() { 
entry: 
    %calltmp = call %a_struct @new_a_struct() 
    %a_var = alloca %a_struct 
    store %a_struct %calltmp, %a_struct* %a_var 
    %a_var1 = load %a_struct, %a_struct* %a_var 
    %memballoctmp = alloca %a_struct 
    store %a_struct %a_var1, %a_struct* %memballoctmp 
} 

而且應該有更好的方式來訪問的%a_var成員,而無需複製它(同時仍在語言中支持表達式如a_struct_var1.member + a_struct_var2.member)。

+0

當你說你已經使用getelementptr沒有運氣嘗試過,你是什麼意思?生成的LLVM IR看起來像什麼? –

+0

@FrankC。當調用irbuilder.CreateInBoundsGEP(...)時,斷言失敗並打印此消息:「Expression:isa (Val)&&」cast ()argument of incompatible type!「'。我嘗試將llvm :: Value *複製到堆棧中的一個變量上,但是接着另一個斷言失敗:'Expression:getOperand(0) - > getType()== cast (getOperand(1) - > getType()) - > getElementType()&&「Ptr必須是一個指向Val類型的指針!'我在考慮對'llvm :: Value * data =/* expression * /'做錯了什麼,所以我我會研究它的類型數據。 –

回答

0

我找到了解決方案。我認爲我錯誤地傳遞了索引或其他東西。

注:我還沒有與具有不同的數據類型成員測試了這個還沒有,但它似乎工作

llvm::Value* member_index = llvm::ConstantInt::get(llvm_context, llvm::APInt(32, index /*The index of the member*/, true)); 
llvm::Value* data = /*A structure value*/; 

llvm::AllocaInst* alloc = irbuilder.CreateAlloca(struct_type, 0, "alloctmp"); 
irbuilder.CreateStore(data, alloc); 

std::vector<llvm::Value*> indices(2); 
indices[0] = llvm::ConstantInt::get(llvm_context, llvm::APInt(32, 0, true)); 
indices[1] = member_index; 

llvm::Value* member_ptr = irbuilder.CreateGEP(struct_type, alloc, indices, "memberptr"); 
llvm::Value* loaded_member = irbuilder.CreateLoad(member_ptr, "loadtmp");