mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-08 19:25:47 +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:
@@ -89,12 +89,12 @@ looks like:
|
|||||||
|
|
||||||
void %munge(%struct.munger_struct* %P) {
|
void %munge(%struct.munger_struct* %P) {
|
||||||
entry:
|
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
|
%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
|
%tmp7 = load i32* %tmp6
|
||||||
%tmp8 = add i32 %tmp7, %tmp
|
%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
|
store i32 %tmp8, i32* %tmp9
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
@@ -109,9 +109,9 @@ To make this clear, let's consider a more obtuse example:
|
|||||||
|
|
||||||
%MyVar = uninitialized global i32
|
%MyVar = uninitialized global i32
|
||||||
...
|
...
|
||||||
%idx1 = getelementptr i32* %MyVar, i64 0
|
%idx1 = getelementptr i32, i32* %MyVar, i64 0
|
||||||
%idx2 = getelementptr i32* %MyVar, i64 1
|
%idx2 = getelementptr i32, i32* %MyVar, i64 1
|
||||||
%idx3 = getelementptr i32* %MyVar, i64 2
|
%idx3 = getelementptr i32, i32* %MyVar, i64 2
|
||||||
|
|
||||||
These GEP instructions are simply making address computations from the base
|
These GEP instructions are simply making address computations from the base
|
||||||
address of ``MyVar``. They compute, as follows (using C syntax):
|
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 }
|
%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
|
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
|
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 ]* }
|
%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
|
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
|
structure containing a pointer to an array of 40 ints. The GEP instruction seems
|
||||||
@@ -197,9 +197,9 @@ following:
|
|||||||
|
|
||||||
.. code-block:: llvm
|
.. 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
|
%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
|
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:
|
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 ] }
|
%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
|
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
|
pointer and the GEP instruction can index through the global variable, into the
|
||||||
@@ -225,9 +225,9 @@ index. Consider this example:
|
|||||||
|
|
||||||
.. code-block:: llvm
|
.. code-block:: llvm
|
||||||
|
|
||||||
%MyVar = global { [10 x i32 ] }
|
%MyVar = global { [10 x i32] }
|
||||||
%idx1 = getelementptr { [10 x i32 ] }* %MyVar, i64 0, i32 0, i64 1
|
%idx1 = getelementptr { [10 x i32] }, { [10 x i32] }* %MyVar, i64 0, i32 0, i64 1
|
||||||
%idx2 = getelementptr { [10 x i32 ] }* %MyVar, 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
|
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
|
array that is in the structure in ``%MyVar``, that is ``MyVar+4``. The type of
|
||||||
@@ -248,9 +248,9 @@ type. Consider this example:
|
|||||||
|
|
||||||
.. code-block:: llvm
|
.. code-block:: llvm
|
||||||
|
|
||||||
%MyVar = global { [10 x i32 ] }
|
%MyVar = global { [10 x i32] }
|
||||||
%idx1 = getelementptr { [10 x i32 ] }* %MyVar, i64 1, i32 0, i64 0
|
%idx1 = getelementptr { [10 x i32] }, { [10 x i32] }* %MyVar, i64 1, i32 0, i64 0
|
||||||
%idx2 = getelementptr { [10 x i32 ] }* %MyVar, i64 1
|
%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
|
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
|
``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
|
; Definition of main function
|
||||||
define i32 @main() { ; i32()*
|
define i32 @main() { ; i32()*
|
||||||
; Convert [13 x i8]* to i8 *...
|
; 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 puts function to write out the string to stdout.
|
||||||
call i32 @puts(i8* %cast210)
|
call i32 @puts(i8* %cast210)
|
||||||
@@ -1057,8 +1057,8 @@ The prefix data can be referenced as,
|
|||||||
|
|
||||||
.. code-block:: llvm
|
.. code-block:: llvm
|
||||||
|
|
||||||
%0 = bitcast *void () @f to *i32
|
%0 = bitcast void* () @f to i32*
|
||||||
%a = getelementptr inbounds *i32 %0, i32 -1
|
%a = getelementptr inbounds i32, i32* %0, i32 -1
|
||||||
%b = load i32* %a
|
%b = load i32* %a
|
||||||
|
|
||||||
Prefix data is laid out as if it were an initializer for a global variable
|
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:
|
following rules:
|
||||||
|
|
||||||
- A pointer value formed from a ``getelementptr`` operation is *based*
|
- 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
|
- The result value of a ``bitcast`` is *based* on the operand of the
|
||||||
``bitcast``.
|
``bitcast``.
|
||||||
- A pointer value formed by an ``inttoptr`` is *based* on all pointer
|
- A pointer value formed by an ``inttoptr`` is *based* on all pointer
|
||||||
@@ -2567,7 +2567,7 @@ Here are some examples:
|
|||||||
entry:
|
entry:
|
||||||
%poison = sub nuw i32 0, 1 ; Results in a poison value.
|
%poison = sub nuw i32 0, 1 ; Results in a poison value.
|
||||||
%still_poison = and i32 %poison, 0 ; 0, but also poison.
|
%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 0, i32* %poison_yet_again ; memory at @h[0] is poisoned
|
||||||
|
|
||||||
store i32 %poison, i32* @g ; Poison value stored to memory.
|
store i32 %poison, i32* @g ; Poison value stored to memory.
|
||||||
@@ -5930,9 +5930,9 @@ Syntax:
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
<result> = getelementptr <pty>* <ptrval>{, <ty> <idx>}*
|
<result> = getelementptr <ty>, <ty>* <ptrval>{, <ty> <idx>}*
|
||||||
<result> = getelementptr inbounds <pty>* <ptrval>{, <ty> <idx>}*
|
<result> = getelementptr inbounds <ty>, <ty>* <ptrval>{, <ty> <idx>}*
|
||||||
<result> = getelementptr <ptr vector> ptrval, <vector index type> idx
|
<result> = getelementptr <ty>, <ptr vector> <ptrval>, <vector index type> <idx>
|
||||||
|
|
||||||
Overview:
|
Overview:
|
||||||
"""""""""
|
"""""""""
|
||||||
@@ -5944,8 +5944,9 @@ address calculation only and does not access memory.
|
|||||||
Arguments:
|
Arguments:
|
||||||
""""""""""
|
""""""""""
|
||||||
|
|
||||||
The first argument is always a pointer or a vector of pointers, and
|
The first argument is always a type used as the basis for the calculations.
|
||||||
forms the basis of the calculation. The remaining arguments are indices
|
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.
|
that indicate which of the elements of the aggregate object are indexed.
|
||||||
The interpretation of each index is dependent on the type being 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
|
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 {
|
define i32* @foo(%struct.ST* %s) nounwind uwtable readnone optsize ssp {
|
||||||
entry:
|
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
|
ret i32* %arrayidx
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6018,11 +6019,11 @@ for the given testcase is equivalent to:
|
|||||||
.. code-block:: llvm
|
.. code-block:: llvm
|
||||||
|
|
||||||
define i32* @foo(%struct.ST* %s) {
|
define i32* @foo(%struct.ST* %s) {
|
||||||
%t1 = getelementptr %struct.ST* %s, i32 1 ; yields %struct.ST*:%t1
|
%t1 = getelementptr %struct.ST, %struct.ST* %s, i32 1 ; yields %struct.ST*:%t1
|
||||||
%t2 = getelementptr %struct.ST* %t1, i32 0, i32 2 ; yields %struct.RT*:%t2
|
%t2 = getelementptr %struct.ST, %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
|
%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]]* %t3, i32 0, i32 5 ; yields [20 x i32]*:%t4
|
%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]* %t4, i32 0, i32 13 ; yields i32*:%t5
|
%t5 = getelementptr [20 x i32], [20 x i32]* %t4, i32 0, i32 13 ; yields i32*:%t5
|
||||||
ret i32* %t5
|
ret i32* %t5
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6056,20 +6057,20 @@ Example:
|
|||||||
.. code-block:: llvm
|
.. code-block:: llvm
|
||||||
|
|
||||||
; yields [12 x i8]*:aptr
|
; 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
|
; 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
|
; 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
|
; 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
|
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:
|
must be a vector with the same number of elements. For example:
|
||||||
|
|
||||||
.. code-block:: llvm
|
.. 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
|
Conversion Operations
|
||||||
---------------------
|
---------------------
|
||||||
@@ -9546,7 +9547,7 @@ It can be created as follows:
|
|||||||
.. code-block:: llvm
|
.. code-block:: llvm
|
||||||
|
|
||||||
%tramp = alloca [10 x i8], align 4 ; size and alignment only correct for X86
|
%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)
|
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)
|
%p = call i8* @llvm.adjust.trampoline(i8* %tramp1)
|
||||||
%fp = bitcast i8* %p to i32 (i32, i32)*
|
%fp = bitcast i8* %p to i32 (i32, i32)*
|
||||||
|
Reference in New Issue
Block a user