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

Ramkumar Ramachandra artagnon at gmail.com
Wed Oct 29 15:04:10 PDT 2014


Tim Northover wrote:
>> The example in LangRef actually crashes on my x86_64 machine, and this
>> is the problem I'm trying to fix for others.
>
> It works for me, with both Linux and OS X triples. What platform are
> you on and what version of LLVM?

You mean the *current* LangRef example? I'm on OS X, running LLVM
3.4.2. I tried adding:

  target triple = "x86_64-apple-darwin"

to the .ll, but it still segfaults when run with lli.

> I don't think we should, it adds more obfuscating target-specific
> detail. Maybe add a target triple to the example, if we really want it
> to run with no extra effort?

In any case, I think the segfault is a bug that should be fixed with
an assert or similar. We should do _something_ to make sure that the
example actually works atleast on x86_64.

>> If the user tries to read anything other than a builtin type, LLVM
>> will error out. Are we okay with a minimal working example?
>
> What do you mean here? I'm personally OK with an example that works,
> but goes wrong in more complicated cases. It's the nature of va_arg on
> x86_64.

>From what I understood from what Reid said in a previous email, va_arg
only works on integers, floats, pointers etc, but not on a struct on
x86_64. Relevant code:

  // Decide which area this value should be read from.
  // TODO: Implement the AMD64 ABI in its entirety. This simple
  // selection mechanism works only for the basic types.
  if (ArgVT == MVT::f80) {
    llvm_unreachable("va_arg for f80 not yet implemented");
  } else if (ArgVT.isFloatingPoint() && ArgSize <= 16 /*bytes*/) {
    ArgMode = 2;  // Argument passed in XMM register. Use fp_offset.
  } else if (ArgVT.isInteger() && ArgSize <= 32 /*bytes*/) {
    ArgMode = 1;  // Argument passed in GPR64 register(s). Use gp_offset.
  } else {
    llvm_unreachable("Unhandled argument type in LowerVAARG");
  }

>> Do you mean that the va_list on those platforms is something other
>> than i8**, but the varargs mechanism exposes a pseudo i8** interface?
>
> [...]
>
> x86_64 is a struct but appears to pretend
> to be an i8** (in reality it probably doesn't matter).

Can you point me to the LLVM code that reads the i8** or struct?

>> 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").
>
> http://www.x86-64.org/documentation/abi.pdf documents what's needed.
> I'm not sure we could add much to that except some kind of tutorial on
> how to implement generic C in LLVM IR.

Thanks for the link. That should be sufficient for anyone.



More information about the llvm-commits mailing list