2016-11-23 198 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");