Ramkumar Ramachandra
2014-Oct-29 01:32 UTC
[LLVMdev] [PATCH] LangRef: va_arg doesn't work on X86_64; update example
Provide a full-fledged example of working variable arguments on X86_64,
since it's easily the most popular platform.
Cc: Reid Kleckner <rnk at google.com>
Signed-off-by: Ramkumar Ramachandra <artagnon at gmail.com>
---
docs/LangRef.rst | 44 ++++++++++++++++++++++++++++++--------------
1 file changed, 30 insertions(+), 14 deletions(-)
diff --git a/docs/LangRef.rst b/docs/LangRef.rst
index ddef803..f429062 100644
--- a/docs/LangRef.rst
+++ b/docs/LangRef.rst
@@ -6695,7 +6695,8 @@ Overview:
The '``va_arg``' instruction is used to access arguments passed through
the "variable argument" area of a function call. It is used to
implement
-the ``va_arg`` macro in C.
+the ``va_arg`` macro in C. Note that ``va_arg`` does not work on
+platforms that have a non-builtin ``va_list`` type, like x86_64.
Arguments:
""""""""""
@@ -6879,29 +6880,44 @@ value type "``va_list``". The LLVM assembly
language reference manual
does not define what this type is, so all transformations should be
prepared to handle these functions regardless of the type used.
-This example shows how the :ref:`va_arg <i_va_arg>` instruction and the
-variable argument handling intrinsic functions are used.
+This example shows how the variable argument handling is done on
+x86_64. The complexity arises from the fact that ``va_arg`` does not
+work on this type of ``va_list``.
.. code-block:: llvm
+ %struct.__va_list_tag = type { i32, i32, i8*, i8* }
+
define i32 @test(i32 %X, ...) {
; Initialize variable argument processing
- %ap = alloca i8*
- %ap2 = bitcast i8** %ap to i8*
+ %ap = alloca %struct.__va_list_tag
+ %ap2 = bitcast %struct.__va_list_tag* %ap to i8*
+ %retptr = alloca i32
call void @llvm.va_start(i8* %ap2)
; Read a single integer argument
- %tmp = va_arg i8** %ap, i32
-
- ; Demonstrate usage of llvm.va_copy and llvm.va_end
- %aq = alloca i8*
- %aq2 = bitcast i8** %aq to i8*
- call void @llvm.va_copy(i8* %aq2, i8* %ap2)
- call void @llvm.va_end(i8* %aq2)
-
+ %idxptr = getelementptr inbounds %struct.__va_list_tag* %ap, i32 0, i32 0
+ %idx = load i32* %idxptr
+ %tmp = getelementptr inbounds %struct.__va_list_tag* %ap, i32 0, i32 3
+ %extract = load i8** %tmp
+ %rawel = getelementptr i8* %extract, i32 %idx
+ %elptr = bitcast i8* %rawel to i32*
+ %newidx = add i32 %idx, 8
+ store i32 %idx, i32* %idxptr
+
+ ; Store that argument in el
+ %el = load i32* %elptr
+ store i32 %el, i32* %retptr
+ %ret = load i32* %retptr
+
; Stop processing of arguments.
call void @llvm.va_end(i8* %ap2)
- ret i32 %tmp
+ ret i32 %ret
+ }
+
+ define i32 @main() {
+ %call = call i32 (i32, ...)* @test(i32 1, i32 3)
+ ret i32 %call
}
declare void @llvm.va_start(i8*)
--
1.9.3 (Apple Git-50)
Tim Northover
2014-Oct-29 18:21 UTC
[LLVMdev] [PATCH] LangRef: va_arg doesn't work on X86_64; update example
Hi Ramkumar, On 28 October 2014 18:32, Ramkumar Ramachandra <artagnon at gmail.com> wrote:> Provide a full-fledged example of working variable arguments on X86_64, > since it's easily the most popular platform.I don't think this is a good idea. The section is about all the varargs intrinsics and instructions, so the example should use all of them even if it does have to use a target other than x86_64. Also, a single example of x86's va_arg handling isn't going to be very enlightening for anyone: either you know the ABI and it's just the "obvious" LLVM IR, or you don't and you won't have a clue what's going on. It's a rather complex and initially confusing topic, and would probably deserve its own article if it's going to be documented. Cheers. Tim.
Sean Silva
2014-Oct-30 21:11 UTC
[LLVMdev] [PATCH] LangRef: va_arg doesn't work on X86_64; update example
On Wed, Oct 29, 2014 at 11:21 AM, Tim Northover <t.p.northover at gmail.com> wrote:> Hi Ramkumar, > > On 28 October 2014 18:32, Ramkumar Ramachandra <artagnon at gmail.com> wrote: > > Provide a full-fledged example of working variable arguments on X86_64, > > since it's easily the most popular platform. > > I don't think this is a good idea. The section is about all the > varargs intrinsics and instructions, so the example should use all of > them even if it does have to use a target other than x86_64. > > Also, a single example of x86's va_arg handling isn't going to be very > enlightening for anyone: either you know the ABI and it's just the > "obvious" LLVM IR, or you don't and you won't have a clue what's going > on. It's a rather complex and initially confusing topic, and would > probably deserve its own article if it's going to be documented. >I agree. -- Sean Silva> > Cheers. > > Tim. > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20141030/2c70c9a9/attachment.html>