mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-28 22:20:43 +00:00
Update LangRef for getelementptr explicit type changes
Here's a rough/first draft - it at least hits the actual textual IR examples and some of the phrasing. It's probably worth a full pass over, but I'm not sure how much these docs should reflect the strange intermediate state we're in anyway. Totally open to lots of review/feedback/suggestions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@231294 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
198cef7d7a
commit
af9251f66b
@ -89,12 +89,12 @@ looks like:
|
||||
|
||||
void %munge(%struct.munger_struct* %P) {
|
||||
entry:
|
||||
%tmp = getelementptr %struct.munger_struct* %P, i32 1, i32 0
|
||||
%tmp = getelementptr %struct.munger_struct, %struct.munger_struct* %P, i32 1, i32 0
|
||||
%tmp = load i32* %tmp
|
||||
%tmp6 = getelementptr %struct.munger_struct* %P, i32 2, i32 1
|
||||
%tmp6 = getelementptr %struct.munger_struct, %struct.munger_struct* %P, i32 2, i32 1
|
||||
%tmp7 = load i32* %tmp6
|
||||
%tmp8 = add i32 %tmp7, %tmp
|
||||
%tmp9 = getelementptr %struct.munger_struct* %P, i32 0, i32 0
|
||||
%tmp9 = getelementptr %struct.munger_struct, %struct.munger_struct* %P, i32 0, i32 0
|
||||
store i32 %tmp8, i32* %tmp9
|
||||
ret void
|
||||
}
|
||||
@ -109,9 +109,9 @@ To make this clear, let's consider a more obtuse example:
|
||||
|
||||
%MyVar = uninitialized global i32
|
||||
...
|
||||
%idx1 = getelementptr i32* %MyVar, i64 0
|
||||
%idx2 = getelementptr i32* %MyVar, i64 1
|
||||
%idx3 = getelementptr i32* %MyVar, i64 2
|
||||
%idx1 = getelementptr i32, i32* %MyVar, i64 0
|
||||
%idx2 = getelementptr i32, i32* %MyVar, i64 1
|
||||
%idx3 = getelementptr i32, i32* %MyVar, i64 2
|
||||
|
||||
These GEP instructions are simply making address computations from the base
|
||||
address of ``MyVar``. They compute, as follows (using C syntax):
|
||||
@ -146,7 +146,7 @@ variable which is always a pointer type. For example, consider this:
|
||||
|
||||
%MyStruct = uninitialized global { float*, i32 }
|
||||
...
|
||||
%idx = getelementptr { float*, i32 }* %MyStruct, i64 0, i32 1
|
||||
%idx = getelementptr { float*, i32 }, { float*, i32 }* %MyStruct, i64 0, i32 1
|
||||
|
||||
The GEP above yields an ``i32*`` by indexing the ``i32`` typed field of the
|
||||
structure ``%MyStruct``. When people first look at it, they wonder why the ``i64
|
||||
@ -182,7 +182,7 @@ only involved in the computation of addresses. For example, consider this:
|
||||
|
||||
%MyVar = uninitialized global { [40 x i32 ]* }
|
||||
...
|
||||
%idx = getelementptr { [40 x i32]* }* %MyVar, i64 0, i32 0, i64 0, i64 17
|
||||
%idx = getelementptr { [40 x i32]* }, { [40 x i32]* }* %MyVar, i64 0, i32 0, i64 0, i64 17
|
||||
|
||||
In this example, we have a global variable, ``%MyVar`` that is a pointer to a
|
||||
structure containing a pointer to an array of 40 ints. The GEP instruction seems
|
||||
@ -197,9 +197,9 @@ following:
|
||||
|
||||
.. code-block:: llvm
|
||||
|
||||
%idx = getelementptr { [40 x i32]* }* %, i64 0, i32 0
|
||||
%idx = getelementptr { [40 x i32]* }, { [40 x i32]* }* %, i64 0, i32 0
|
||||
%arr = load [40 x i32]** %idx
|
||||
%idx = getelementptr [40 x i32]* %arr, i64 0, i64 17
|
||||
%idx = getelementptr [40 x i32], [40 x i32]* %arr, i64 0, i64 17
|
||||
|
||||
In this case, we have to load the pointer in the structure with a load
|
||||
instruction before we can index into the array. If the example was changed to:
|
||||
@ -208,7 +208,7 @@ instruction before we can index into the array. If the example was changed to:
|
||||
|
||||
%MyVar = uninitialized global { [40 x i32 ] }
|
||||
...
|
||||
%idx = getelementptr { [40 x i32] }*, i64 0, i32 0, i64 17
|
||||
%idx = getelementptr { [40 x i32] }, { [40 x i32] }*, i64 0, i32 0, i64 17
|
||||
|
||||
then everything works fine. In this case, the structure does not contain a
|
||||
pointer and the GEP instruction can index through the global variable, into the
|
||||
@ -226,8 +226,8 @@ index. Consider this example:
|
||||
.. code-block:: llvm
|
||||
|
||||
%MyVar = global { [10 x i32] }
|
||||
%idx1 = getelementptr { [10 x i32 ] }* %MyVar, i64 0, i32 0, i64 1
|
||||
%idx2 = getelementptr { [10 x i32 ] }* %MyVar, i64 1
|
||||
%idx1 = getelementptr { [10 x i32] }, { [10 x i32] }* %MyVar, i64 0, i32 0, i64 1
|
||||
%idx2 = getelementptr { [10 x i32] }, { [10 x i32] }* %MyVar, i64 1
|
||||
|
||||
In this example, ``idx1`` computes the address of the second integer in the
|
||||
array that is in the structure in ``%MyVar``, that is ``MyVar+4``. The type of
|
||||
@ -249,8 +249,8 @@ type. Consider this example:
|
||||
.. code-block:: llvm
|
||||
|
||||
%MyVar = global { [10 x i32] }
|
||||
%idx1 = getelementptr { [10 x i32 ] }* %MyVar, i64 1, i32 0, i64 0
|
||||
%idx2 = getelementptr { [10 x i32 ] }* %MyVar, i64 1
|
||||
%idx1 = getelementptr { [10 x i32] }, { [10 x i32] }* %MyVar, i64 1, i32 0, i64 0
|
||||
%idx2 = getelementptr { [10 x i32] }, { [10 x i32] }* %MyVar, i64 1
|
||||
|
||||
In this example, the value of ``%idx1`` is ``%MyVar+40`` and its type is
|
||||
``i32*``. The value of ``%idx2`` is also ``MyVar+40`` but its type is ``{ [10 x
|
||||
|
@ -162,7 +162,7 @@ symbol table entries. Here is an example of the "hello world" module:
|
||||
; Definition of main function
|
||||
define i32 @main() { ; i32()*
|
||||
; Convert [13 x i8]* to i8 *...
|
||||
%cast210 = getelementptr [13 x i8]* @.str, i64 0, i64 0
|
||||
%cast210 = getelementptr [13 x i8], [13 x i8]* @.str, i64 0, i64 0
|
||||
|
||||
; Call puts function to write out the string to stdout.
|
||||
call i32 @puts(i8* %cast210)
|
||||
@ -1057,8 +1057,8 @@ The prefix data can be referenced as,
|
||||
|
||||
.. code-block:: llvm
|
||||
|
||||
%0 = bitcast *void () @f to *i32
|
||||
%a = getelementptr inbounds *i32 %0, i32 -1
|
||||
%0 = bitcast void* () @f to i32*
|
||||
%a = getelementptr inbounds i32, i32* %0, i32 -1
|
||||
%b = load i32* %a
|
||||
|
||||
Prefix data is laid out as if it were an initializer for a global variable
|
||||
@ -1584,7 +1584,7 @@ A pointer value is *based* on another pointer value according to the
|
||||
following rules:
|
||||
|
||||
- A pointer value formed from a ``getelementptr`` operation is *based*
|
||||
on the first operand of the ``getelementptr``.
|
||||
on the first value operand of the ``getelementptr``.
|
||||
- The result value of a ``bitcast`` is *based* on the operand of the
|
||||
``bitcast``.
|
||||
- A pointer value formed by an ``inttoptr`` is *based* on all pointer
|
||||
@ -2567,7 +2567,7 @@ Here are some examples:
|
||||
entry:
|
||||
%poison = sub nuw i32 0, 1 ; Results in a poison value.
|
||||
%still_poison = and i32 %poison, 0 ; 0, but also poison.
|
||||
%poison_yet_again = getelementptr i32* @h, i32 %still_poison
|
||||
%poison_yet_again = getelementptr i32, i32* @h, i32 %still_poison
|
||||
store i32 0, i32* %poison_yet_again ; memory at @h[0] is poisoned
|
||||
|
||||
store i32 %poison, i32* @g ; Poison value stored to memory.
|
||||
@ -5930,9 +5930,9 @@ Syntax:
|
||||
|
||||
::
|
||||
|
||||
<result> = getelementptr <pty>* <ptrval>{, <ty> <idx>}*
|
||||
<result> = getelementptr inbounds <pty>* <ptrval>{, <ty> <idx>}*
|
||||
<result> = getelementptr <ptr vector> ptrval, <vector index type> idx
|
||||
<result> = getelementptr <ty>, <ty>* <ptrval>{, <ty> <idx>}*
|
||||
<result> = getelementptr inbounds <ty>, <ty>* <ptrval>{, <ty> <idx>}*
|
||||
<result> = getelementptr <ty>, <ptr vector> <ptrval>, <vector index type> <idx>
|
||||
|
||||
Overview:
|
||||
"""""""""
|
||||
@ -5944,8 +5944,9 @@ address calculation only and does not access memory.
|
||||
Arguments:
|
||||
""""""""""
|
||||
|
||||
The first argument is always a pointer or a vector of pointers, and
|
||||
forms the basis of the calculation. The remaining arguments are indices
|
||||
The first argument is always a type used as the basis for the calculations.
|
||||
The second argument is always a pointer or a vector of pointers, and is the
|
||||
base address to start from. The remaining arguments are indices
|
||||
that indicate which of the elements of the aggregate object are indexed.
|
||||
The interpretation of each index is dependent on the type being indexed
|
||||
into. The first index always indexes the pointer value given as the
|
||||
@ -5993,7 +5994,7 @@ The LLVM code generated by Clang is:
|
||||
|
||||
define i32* @foo(%struct.ST* %s) nounwind uwtable readnone optsize ssp {
|
||||
entry:
|
||||
%arrayidx = getelementptr inbounds %struct.ST* %s, i64 1, i32 2, i32 1, i64 5, i64 13
|
||||
%arrayidx = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 1, i32 2, i32 1, i64 5, i64 13
|
||||
ret i32* %arrayidx
|
||||
}
|
||||
|
||||
@ -6018,11 +6019,11 @@ for the given testcase is equivalent to:
|
||||
.. code-block:: llvm
|
||||
|
||||
define i32* @foo(%struct.ST* %s) {
|
||||
%t1 = getelementptr %struct.ST* %s, i32 1 ; yields %struct.ST*:%t1
|
||||
%t2 = getelementptr %struct.ST* %t1, i32 0, i32 2 ; yields %struct.RT*:%t2
|
||||
%t3 = getelementptr %struct.RT* %t2, i32 0, i32 1 ; yields [10 x [20 x i32]]*:%t3
|
||||
%t4 = getelementptr [10 x [20 x i32]]* %t3, i32 0, i32 5 ; yields [20 x i32]*:%t4
|
||||
%t5 = getelementptr [20 x i32]* %t4, i32 0, i32 13 ; yields i32*:%t5
|
||||
%t1 = getelementptr %struct.ST, %struct.ST* %s, i32 1 ; yields %struct.ST*:%t1
|
||||
%t2 = getelementptr %struct.ST, %struct.ST* %t1, i32 0, i32 2 ; yields %struct.RT*:%t2
|
||||
%t3 = getelementptr %struct.RT, %struct.RT* %t2, i32 0, i32 1 ; yields [10 x [20 x i32]]*:%t3
|
||||
%t4 = getelementptr [10 x [20 x i32]], [10 x [20 x i32]]* %t3, i32 0, i32 5 ; yields [20 x i32]*:%t4
|
||||
%t5 = getelementptr [20 x i32], [20 x i32]* %t4, i32 0, i32 13 ; yields i32*:%t5
|
||||
ret i32* %t5
|
||||
}
|
||||
|
||||
@ -6056,20 +6057,20 @@ Example:
|
||||
.. code-block:: llvm
|
||||
|
||||
; yields [12 x i8]*:aptr
|
||||
%aptr = getelementptr {i32, [12 x i8]}* %saptr, i64 0, i32 1
|
||||
%aptr = getelementptr {i32, [12 x i8]}, {i32, [12 x i8]}* %saptr, i64 0, i32 1
|
||||
; yields i8*:vptr
|
||||
%vptr = getelementptr {i32, <2 x i8>}* %svptr, i64 0, i32 1, i32 1
|
||||
%vptr = getelementptr {i32, <2 x i8>}, {i32, <2 x i8>}* %svptr, i64 0, i32 1, i32 1
|
||||
; yields i8*:eptr
|
||||
%eptr = getelementptr [12 x i8]* %aptr, i64 0, i32 1
|
||||
%eptr = getelementptr [12 x i8], [12 x i8]* %aptr, i64 0, i32 1
|
||||
; yields i32*:iptr
|
||||
%iptr = getelementptr [10 x i32]* @arr, i16 0, i16 0
|
||||
%iptr = getelementptr [10 x i32], [10 x i32]* @arr, i16 0, i16 0
|
||||
|
||||
In cases where the pointer argument is a vector of pointers, each index
|
||||
must be a vector with the same number of elements. For example:
|
||||
|
||||
.. code-block:: llvm
|
||||
|
||||
%A = getelementptr <4 x i8*> %ptrs, <4 x i64> %offsets,
|
||||
%A = getelementptr i8, <4 x i8*> %ptrs, <4 x i64> %offsets,
|
||||
|
||||
Conversion Operations
|
||||
---------------------
|
||||
@ -9546,7 +9547,7 @@ It can be created as follows:
|
||||
.. code-block:: llvm
|
||||
|
||||
%tramp = alloca [10 x i8], align 4 ; size and alignment only correct for X86
|
||||
%tramp1 = getelementptr [10 x i8]* %tramp, i32 0, i32 0
|
||||
%tramp1 = getelementptr [10 x i8], [10 x i8]* %tramp, i32 0, i32 0
|
||||
call i8* @llvm.init.trampoline(i8* %tramp1, i8* bitcast (i32 (i8*, i32, i32)* @f to i8*), i8* %nval)
|
||||
%p = call i8* @llvm.adjust.trampoline(i8* %tramp1)
|
||||
%fp = bitcast i8* %p to i32 (i32, i32)*
|
||||
|
Loading…
Reference in New Issue
Block a user