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>