Understanding GEP Instruction when accessing members of type

Hello!

I am struggling wtih implementing accesses to members of a type. My compiler generates this code:

%testtype = type { double, i8* }

@0 = private unnamed_addr constant [5 x i8] c"test\00", align 1

define double @entry() {
entry:
  %test = alloca %testtype, i0 1, align 8
  store %testtype zeroinitializer, %testtype* %test, align 8
  %0 = getelementptr %testtype, %testtype* %test, i32 1
  store i8* getelementptr inbounds ([5 x i8], [5 x i8]* @0, i32 0, i32 0), %testtype* %0, align 8
  ret double 0.000000e+00
}

I am trying to access the second member of the type, so the member of type i8*. I don’t get why the result of the getelementptr is of type %testtype* instead of i8*. I have tried specifying, that it should be of type i8*, but then the compiler tells me that that doesn’t work as the types have to be the same in the GEP instruction. How can I make that the result of GEP instruction is a pointer to the subtype of my defined structure, instead of a pointer to the structure? Anything else doesn’t make sense to me. I have tried reading the language reference for getelementpointer and the ar

If you need more details, please tell me.

Any help is greatly appreciated!
Tom

Hi Tom,

The first index in a GEP is based on the pointer of the second argument (a testtype pointer in your case). So you would want to do

%0 = getelementptr %testtype, %testtype* %test, i32 0, i32 1

if you want to access the second element in the testtype element pointed to by %test. Hope that makes sense. Best regards,

Thomas

1 Like

I found these resources very helpful when I was getting to grips with the GEP instruction:

In your case, the i8* is at (0, 1), not at (1). If you have a pointer to struct with two members, you first have to ‘pierce through’ the pointer (the ‘0’), then get the second member (the ‘1’).

This LLVM IR seems to do what you want:

%testtype = type { double, i8* }

@0 = private unnamed_addr constant [5 x i8] c"test\00", align 1

define double @entry() {
entry:
  %test = alloca %testtype, align 8
  store %testtype zeroinitializer, %testtype* %test, align 8
  %0 = getelementptr %testtype, %testtype* %test, i32 0, i32 1
  store i8* getelementptr inbounds ([5 x i8], [5 x i8]* @0, i32 0, i32 0), i8** %0, align 8
  ret double 0.000000e+00
}
1 Like

Thanks to both of you this really helped me!