[PATCH v2] LangRef: clarify that va_arg doesn't work on x86_64

Ramkumar Ramachandra artagnon at gmail.com
Wed Oct 29 13:10:48 PDT 2014


Hi Tim,

Tim Northover wrote:
> I'm actually still unconvinced by the need to call out x86_64
> specifically (especially having discovered that there *is* partial
> support for "va_arg"). I'd just go for something like "Note that not
> all targets support the va_arg instruction".

The example in LangRef actually crashes on my x86_64 machine, and this
is the problem I'm trying to fix for others. Should we replace it with
a working example on x86_64 like:

-- 8< --
%struct.__va_list_tag = type { i32, i32, i8*, i8* }

define i32 @test(i32 %X, ...) {
  ; Initialize variable argument processing
  %ap = alloca %struct.__va_list_tag
  %ap2 = bitcast %struct.__va_list_tag* %ap to i8*
  call void @llvm.va_start(i8* %ap2)

  ; Read a single integer argument
  %tmp = va_arg %struct.__va_list_tag* %ap, i32

  ; Demonstrate usage of llvm.va_copy and llvm.va_end
  %aq = alloca %struct.__va_list_tag
  %aq2 = bitcast %struct.__va_list_tag* %aq to i8*
  call void @llvm.va_copy(i8* %aq2, i8* %ap2)
  call void @llvm.va_end(i8* %aq2)

  ; Stop processing of arguments.
  call void @llvm.va_end(i8* %ap2)
  ret i32 %tmp
}

define i32 @main() {
  %call = call i32 (i32, ...)* @test(i32 1, i32 3)
  ret i32 %call
}

declare void @llvm.va_start(i8*)
declare void @llvm.va_copy(i8*, i8*)
declare void @llvm.va_end(i8*)
-- 8< --

If the user tries to read anything other than a builtin type, LLVM
will error out. Are we okay with a minimal working example?

> On 29 October 2014 12:21, Ramkumar Ramachandra <artagnon at gmail.com> wrote:
>> -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 :ref:`va_arg <i_va_arg>` instruction and
>> +the variable argument handling intrinsic functions are used. Note that
>> +this is for platforms where ``va_list`` is an ``i8**``, most notably
>> +not x86_64.
>
> This isn't quite right. As far as I know (x86, ARM, AArch64) all
> in-tree targets that accept va_arg use it with an i8**, but with
> certain caveats (around type lowering & alignment in particular) even
> the x86_64 ABI could be supported. In fact, X86 actually seems to
> support certain common cases.

Do you mean that the va_list on those platforms is something other
than i8**, but the varargs mechanism exposes a pseudo i8** interface?

> It's just rather easier and more efficient to do it in Clang -- the
> optimisation passes can be rather useful for simplifying the special
> cases.

True, but wouldn't it be nice to support the common cases for people
starting out?

In any case, it would be nice to have the vaarg intricacies of x86_64
documented somewhere (like "look in the other i8* if reading over 40
bits").

Cheers.

Ram



More information about the llvm-commits mailing list