From 262af8c7d8ce7265f4dee4c9b08186fb1a8030b3 Mon Sep 17 00:00:00 2001
From: Chris Lattner
<result> = getelementptr <ty>* <ptrval>{, long <aidx>|, ubyte <sidx>}*+
+ <result> = getelementptr <ty>* <ptrval>{, <ty> <idx>}* ++
The 'getelementptr' instruction is used to get the address -of a subelement of an aggregate data structure.
+ ++The 'getelementptr' instruction is used to get the address of a +subelement of an aggregate data structure.
+This instruction takes a list of long values and ubyte -constants that indicate what form of addressing to perform. The actual -types of the arguments provided depend on the type of the first pointer -argument. The 'getelementptr' instruction is used to index -down through the type levels of a structure.
+ +This instruction takes a list of integer constants that indicate what +elements of the aggregate object to index to. The actual types of the arguments +provided depend on the type of the first pointer argument. The +'getelementptr' instruction is used to index down through the type +levels of a structure. When indexing into a structure, only uint +integer constants are allowed. When indexing into an array or pointer +int and long indexes are allowed of any sign.
+For example, let's consider a C code fragment and how it gets compiled to LLVM:
-struct RT {+ +
char A;
int B[10][20];
char C;
};
struct ST {
int X;
double Y;
struct RT Z;
};
int *foo(struct ST *s) {
return &s[1].Z.B[5][13];
}
+ struct RT { + char A; + int B[10][20]; + char C; + }; + struct ST { + int X; + double Y; + struct RT Z; + }; + + int *foo(struct ST *s) { + return &s[1].Z.B[5][13]; + } ++
The LLVM code generated by the GCC frontend is:
-%RT = type { sbyte, [10 x [20 x int]], sbyte }+ +
%ST = type { int, double, %RT }
int* "foo"(%ST* %s) {
%reg = getelementptr %ST* %s, long 1, ubyte 2, ubyte 1, long 5, long 13
ret int* %reg
}
+ %RT = type { sbyte, [10 x [20 x int]], sbyte } + %ST = type { int, double, %RT } + + int* "foo"(%ST* %s) { + %reg = getelementptr %ST* %s, int 1, uint 2, uint 1, int 5, int 13+
+ ret int* %reg + } +
The index types specified for the 'getelementptr' -instruction depend on the pointer type that is being index into. Pointer and array types -require 'long' values, and structure -types require 'ubyte' constants.
+ +The index types specified for the 'getelementptr' instruction depend +on the pointer type that is being index into. Pointer +and array types require uint, int, +ulong, or long values, and structure +types require uint constants.
+In the example above, the first index is indexing into the '%ST*' -type, which is a pointer, yielding a '%ST' = '{ int, -double, %RT }' type, a structure. The second index indexes into -the third element of the structure, yielding a '%RT' = '{ -sbyte, [10 x [20 x int]], sbyte }' type, another structure. The -third index indexes into the second element of the structure, yielding -a '[10 x [20 x int]]' type, an array. The two dimensions of -the array are subscripted into, yielding an 'int' type. The 'getelementptr' -instruction return a pointer to this element, thus yielding a 'int*' -type.
+type, which is a pointer, yielding a '%ST' = '{ int, double, %RT +}' type, a structure. The second index indexes into the third element of +the structure, yielding a '%RT' = '{ sbyte, [10 x [20 x int]], +sbyte }' type, another structure. The third index indexes into the second +element of the structure, yielding a '[10 x [20 x int]]' type, an +array. The two dimensions of the array are subscripted into, yielding an +'int' type. The 'getelementptr' instruction return a pointer +to this element, thus computing a value of 'int*' type. +Note that it is perfectly legal to index partially through a structure, returning a pointer to an inner element. Because of this, the LLVM code for the given testcase is equivalent to:
-int* "foo"(%ST* %s) {
%t1 = getelementptr %ST* %s , long 1 ; yields %ST*:%t1 - %t2 = getelementptr %ST* %t1, long 0, ubyte 2 ; yields %RT*:%t2 - %t3 = getelementptr %RT* %t2, long 0, ubyte 1 ; yields [10 x [20 x int]]*:%t3 - %t4 = getelementptr [10 x [20 x int]]* %t3, long 0, long 5 ; yields [20 x int]*:%t4 - %t5 = getelementptr [20 x int]* %t4, long 0, long 13 ; yields int*:%t5 - ret int* %t5 -} + ++ int* "foo"(%ST* %s) { + %t1 = getelementptr %ST* %s, int 1 ; yields %ST*:%t1 + %t2 = getelementptr %ST* %t1, int 0, uint 2 ; yields %RT*:%t2 + %t3 = getelementptr %RT* %t2, int 0, uint 1 ; yields [10 x [20 x int]]*:%t3 + %t4 = getelementptr [10 x [20 x int]]* %t3, int 0, int 5 ; yields [20 x int]*:%t4 + %t5 = getelementptr [20 x int]* %t4, int 0, int 13 ; yields int*:%t5 + ret int* %t5 + }Example:
-; yields [12 x ubyte]*:aptr - %aptr = getelementptr {int, [12 x ubyte]}* %sptr, long 0, ubyte 1-Note To The Novice:
-When using indexing into global arrays with the 'getelementptr' -instruction, you must remember that the
+ ; yields [12 x ubyte]*:aptr + %aptr = getelementptr {int, [12 x ubyte]}* %sptr, long 0, uint 1 ++ +