I have a type defined as %Colour = type { { i32, i32, i32 }, %RED*, %GREEN*, %BLUE*, %RGB* }
, I use the first field to store RTTI, I load the field at Colour*.0.0.2
and have it in a variable "arity" but when I try to do a GEP on the object again to get the RGB*
with builder.CreateInBoundsGEP(valType, val, {builder.getInt32(0), arity})
I'm getting a "Invalid GetElementPtrInst indices for type!". Dumping the type of arity I get i32 as I expected, what am I doing wrong?
Can I not use a runtime value in a GEP? I ask because, after I ran into this, I tried changing it to builder.CreateInBoundsGEP(valType, val, {builder.getInt32(0), builder.getInt32(4)})
which produce the expected result of %2 = getelementptr inbounds %Colour, %Colour* %0, i32 0, i32 4
so I could then load it %3 = load %RGB*, %RGB** %2
Can I not use a runtime value in a GEP?
You have to use constant indices when indexing into struct components of the type. Otherwise it's impossible to statically know the type of the GEP instruction.
In other words, since getelementptr inbounds %Colour, %Colour* %0, i32 0, i32 4
is %RGB**
and %y = getelementptr inbounds %Colour, %Colour* %0, i32 0, i32 3
is %BLUE**
, and the type of GEP must be known statically, that last index must be a constant.
GEP indices into arrays do not have to be constants.
This is all written explicitly in the langref:
The type of each index argument depends on the type it is indexing into. When indexing into a (optionally packed) structure, only i32 integer constants are allowed (when using a vector of indices they must all be the same i32 integer constant). When indexing into an array, pointer or vector, integers of any width are allowed, and they are not required to be constant. These integers are treated as signed values where relevant.
(emphasis mine)