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>