[llvm-dev] [RFC] The future of the va_arg instruction

Alex Bradbury via llvm-dev llvm-dev at lists.llvm.org
Wed Aug 9 09:11:00 PDT 2017


# The future of the va_arg instruction

## Summary
LLVM IR currently defines a va_arg instruction, which can be used to access
a vararg. Few Clang targets make use of it, and it has a number of
limitations. This RFC hopes to promote discussion on its future - how 'smart'
should va_arg be? Should we be aiming to transition all targets and LLVM
frontends to using it?

## Background on va_arg
The va_arg instruction is described in the language reference here
<http://llvm.org/docs/LangRef.html#int-varargs> and here
<http://llvm.org/docs/LangRef.html#i-va-arg>. When it's possible to use
va_arg, it frees the frontend from worrying about manipulation of the
target-specific va_list struct. This also has the potential to make analysis
of the IR more straight-forward. However, va_arg can't currently be used
with an aggregate type (such as a struct). The difficulty of adding support
for aggregates is discussed later in this email.

Which Clang targets generate va_arg?
* PNaCl always uses va_arg, even for aggregates. Their ExpandVarArgs pass
replaces it with appropriate loads and stors.
* AArch64/Darwin generates va_arg if possible. When not possible, as for
aggregates or illegal vector types, it generates the usual va_list
manipulation code. It is not used for other AARch64 platforms.
* A few other targets such as MSP430, Lanai and AVR seem to use it due to
DefaultABIInfo

Which in-tree backends support va_arg?
* AArch64, ARM, Hexagon, Lanai, MSP430, Mips, PPC, Sparc, WebAssembly, X86,
XCore

It's worth nothing there has been some relevant prior discussion, see these
messages from Will Dietz and Renato Golin
<http://lists.llvm.org/pipermail/llvm-dev/2011-August/042505.html>
<http://lists.llvm.org/pipermail/llvm-dev/2011-August/042509.html>.

## Options for the future of va_arg

Option 1: Discourage use of va_arg and aim to remove it in the future
  * Most targets frontends have to directly manipulate va_list in at least
  some cases. You could argue we'd be better off by having varargs
  handled in a uniform manner, even if va_list manipulation is more explicit
  and target specific?

Option 2: Status quo
  * va_arg is there. Most backends can at least expand it, though it's not
  clear how heavily tested this is.
  * There's still a question of what the reccomendation should be for
  frontends. If we keep va_arg as-is, would it be beneficial to
  modify Clang to use it when possible, while falling back to explicit
  manipulation if necessary like on Darwin/AArch64? Alternatively, casting may
  allow va_arg to be used for a wider variety of types.

Option 3: Teach va_arg to handle aggregates
  * In this option, va_arg might reasonably be expected to handle a struct,
  but would not be expected to have detailed ABI-specific knowledge. e.g. it
  won't automagically know whether a value of a certain size/type is passed
  indirectly or not. In a sense, this would put support for aggregates passed
  as varargs on par with aggregates passed in named arguments.
  * Casting would be necessary in the same cases casting is required
for named args
  * Support for aggregates could be implemented via a new module-level
pass, much like PNaCl.
  * Alternatively, the conversion from the va_arg instruction to
  SelectionDAG could be modified. It might be desirable to convert the vaarg
  instruction to a number of loads and a new node that is responsible only for
  manipulating the va_list struct.

Option 4: Expect va_arg to handle all ABI details
  * In this more extreme option, va_arg with any type would expected to
  generate ABI-compliant code. e.g. a va_arg with i128 would "do the right
  thing", regardless of whether an i128 is passed indirectly or not for the
  given ABI.
  * This would be nice, but probably only makes sense as part of a larger
  effort to reduce the ABI lowering burden on frontends. This sort of effort
  has been discussed many times, and is not a small project.

## Next steps
I'd really appreciate any input on the issues here. Do people have strong
feelings about the future direction of va_arg? Will GlobalISel have any effect
on the relative difficulty or desirability of these options?

Thanks,

Alex


More information about the llvm-dev mailing list