2016-11-23 5 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), скопированное в нее.

ИК генерируется непосредственно перед вызовом 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 () аргумент несовместимого типа! "'. Я попытался скопировать llvm :: Value * в переменную в стеке, но затем не выполняется другое утверждение: 'Expression: getOperand (0) -> getType() == cast (getOperand (1) -> getType()) -> getElementType() && "Ptr должен быть указателем на тип Val!". Я думаю, что я делаю что-то не так с выражением 'llvm :: Value * data =/* * /', поэтому я «Посмотрим на данные типа для него. –

ответ

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