c – 如何在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 *数据的类型是从堆栈上的指针加载的%a_struct.从文档中可以看出irbuilder.CreateInBoundsGEP(llvm :: Value *,llvm :: ArrayRef< llvm :: Value *>,llvm :: Twine)要求第一个参数是指向结构的指针,而不是值结构本身.

将结构的值复制到堆栈中的变量时,会抛出此错误:Expression:getOperand(0) – > getType()== cast< PointerType>(getOperand(1) – > getType()) – > getElementType()&& “Ptr必须是指向Val类型的指针!”.抛出此错误时粘贴到irbuidler.CreateInBoundsGEP(…)的指针是llvm :: AllocaInst *,它是在堆栈上新分配的并包含复制到的llvm :: Value * data(%a_struct类型)的值它.

在调用irbuilder.CreateInBoundsGEP(…)之前生成的IR,其值复制到堆栈上的变量:

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这样的表达式).

最佳答案 我找到了解决方案.我想我正在错误地传递索引或其他东西.

注意:我还没有对具有不同数据类型的成员进行测试,但它似乎有效

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");
点赞