[LLVMdev] Is va_arg deprecated?

268 views
Skip to first unread message

Neal N. Wang

unread,
Jul 19, 2010, 2:57:33 PM7/19/10
to llv...@cs.uiuc.edu
Hi folk,

I'm writing a set of small C code to verify whether my pass handle some instruction correctly.   One of the instruction I want to test is "va_arg", but compiling my variadic function does not generate any va_arg instruction. Is va_arg deprecated? Will va_arg instruction ever be generated by any front-end?  The source code and llvm instructions are appended as follows. 

the c code
#include<stdarg.h>
#include<stdio.h>
#include<stdlib.h>

void printValue(char * fmt, ...) {
  va_list args;
  va_start(args, fmt);
  int i;
  double d;
  i = va_arg(args, int);
  d = va_arg(args, double);
  va_end(args);
}

the generated llvm instructions:
; ModuleID = 'i.bc'
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
target triple = "i386-pc-linux-gnu"

define void @printValue(i8* %fmt, ...) nounwind {
entry:
  %fmt_addr = alloca i8*                          ; <i8**> [#uses=1]
  %args.2 = alloca i8*                            ; <i8**> [#uses=3]
  %args.0 = alloca i8*                            ; <i8**> [#uses=3]
  %args = alloca i8*                              ; <i8**> [#uses=6]
  %i = alloca i32                                 ; <i32*> [#uses=1]
  %d = alloca double, align 8                     ; <double*> [#uses=1]
  %"alloca point" = bitcast i32 0 to i32          ; <i32> [#uses=0]
  store i8* %fmt, i8** %fmt_addr
  %args1 = bitcast i8** %args to i8*              ; <i8*> [#uses=1]
  call void @llvm.va_start(i8* %args1)
  %0 = load i8** %args, align 4                   ; <i8*> [#uses=1]
  store i8* %0, i8** %args.0, align 4
  %1 = load i8** %args.0, align 4                 ; <i8*> [#uses=1]
  %2 = getelementptr inbounds i8* %1, i64 4       ; <i8*> [#uses=1]
  store i8* %2, i8** %args, align 4
  %3 = load i8** %args.0, align 4                 ; <i8*> [#uses=1]
  %4 = bitcast i8* %3 to i32*                     ; <i32*> [#uses=1]
  %5 = load i32* %4, align 4                      ; <i32> [#uses=1]
  store i32 %5, i32* %i, align 4
  %6 = load i8** %args, align 4                   ; <i8*> [#uses=1]
  store i8* %6, i8** %args.2, align 4
  %7 = load i8** %args.2, align 4                 ; <i8*> [#uses=1]
  %8 = getelementptr inbounds i8* %7, i64 8       ; <i8*> [#uses=1]
  store i8* %8, i8** %args, align 4
  %9 = load i8** %args.2, align 4                 ; <i8*> [#uses=1]
  %10 = bitcast i8* %9 to double*                 ; <double*> [#uses=1]
  %11 = load double* %10, align 4                 ; <double> [#uses=1]
  store double %11, double* %d, align 8
  %args2 = bitcast i8** %args to i8*              ; <i8*> [#uses=1]
  call void @llvm.va_end(i8* %args2)
  br label %return

return:                                           ; preds = %entry
  ret void
}

declare void @llvm.va_start(i8*) nounwind

declare void @llvm.va_end(i8*) nounwind


David Meyer

unread,
Jul 19, 2010, 5:18:47 PM7/19/10
to Neal N. Wang, llv...@cs.uiuc.edu
Neal,

FYI, my group has added a flag to llvm-gcc for emitting the va_arg
instruction (instead of lowering in the front-end),
and we also have an implementation of the VAARG instruction for
X86-64. (which is currently not implemented in the LLVM backend).

Both of these things will be sent upstream to LLVM soon, pending some
more testing and review.

If you are dire need of these features now, I can point you to the
(public) repository where we have the beta versions.

- David M

> _______________________________________________
> LLVM Developers mailing list
> LLV...@cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
>

_______________________________________________
LLVM Developers mailing list
LLV...@cs.uiuc.edu http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev

Rafael Espindola

unread,
Jul 19, 2010, 8:03:16 PM7/19/10
to Neal N. Wang, llv...@cs.uiuc.edu
On 19 July 2010 14:57, Neal N. Wang <neal...@gmail.com> wrote:
> Hi folk,
>
> I'm writing a set of small C code to verify whether my pass handle some
> instruction correctly.   One of the instruction I want to test is "va_arg",
> but compiling my variadic function does not generate any va_arg instruction.
> Is va_arg deprecated? Will va_arg instruction ever be generated by any
> front-end?  The source code and llvm instructions are appended as follows.

Currently both clang and llvm-gcc lower va_arg. As David mentioned, we
are experimenting with va_arg. Some bits were pushed upstream, some
are in our public svn repo waiting for more testing/cleanup or just
time to send it upstream. With those patches it is possible to use
va_arg, but they are not as tested and the code is not as good (we
load and store the va_list every time for example).

It should be possible to improve the code generated by va_arg and some
optimizations might also be easier to implement with it, but it is not
done yet.

So, there is hope that va_arg will be used, but currently it isn't.

Cheers,
--
Rafael Ávila de Espíndola

Neal N. Wang

unread,
Jul 20, 2010, 3:25:05 AM7/20/10
to David Meyer, llv...@cs.uiuc.edu
Thanks David, I don't want my pass to get any surprise when some front-ends emit va_arg.  Can you please point out the link of your beta versions? Thanks, Neal.

Sergey Yakoushkin

unread,
Feb 18, 2011, 9:42:37 PM2/18/11
to David Meyer, llv...@cs.uiuc.edu, Neal N. Wang
Hi David,

I'm working on source to source transformations and instrumentation.
A flag to disable 'va_arg' lowering in LLVM FEs will be very useful.

Have you sent your modifications upstream to LLVM?
If not, could you please share link to your public repository.

Thanks,
Sergey Yakoushkin

On Mon, Jul 19, 2010 at 11:18 PM, David Meyer <pd...@google.com> wrote:
> Neal,
>
> FYI, my group has added a flag to llvm-gcc for emitting the va_arg
> instruction (instead of lowering in the front-end),
> and we also have an implementation of the VAARG instruction for
> X86-64. (which is currently not implemented in the LLVM backend).
>
> Both of these things will be sent upstream to LLVM soon, pending some
> more testing and review.
>
> If you are dire need of these features now, I can point you to the
> (public) repository where we have the beta versions.
>
> - David M

Renato Golin

unread,
Feb 19, 2011, 1:49:03 PM2/19/11
to Sergey Yakoushkin, Neal N. Wang, llv...@cs.uiuc.edu
On 19 February 2011 02:42, Sergey Yakoushkin

<sergey.y...@gmail.com> wrote:
> I'm working on source to source transformations and instrumentation.
> A flag to disable 'va_arg' lowering in LLVM FEs will be very useful.

Hi,

For the sake of simplicity, if types are simple, we emit va_arg
directly, otherwise we do like Clang and lower it in the front-end.

Would be nice to keep va_arg for the simple cases...

cheers,
--renato

David Meyer

unread,
Feb 20, 2011, 2:54:04 PM2/20/11
to Renato Golin, Neal N. Wang, llv...@cs.uiuc.edu
Sergey,

Here's a patch on llvm-gcc which adds a flag "-fuse-llvm-va-arg".

(Note that this patch won't ever be part of llvm-gcc upstream. It will most likely be deprecated by later changes.)

- pdox

llvm-gcc-va-arg-2.patch

Arushi Aggarwal

unread,
May 12, 2011, 1:29:32 PM5/12/11
to David Meyer, llv...@cs.uiuc.edu, Renato Golin, Neal N. Wang
Have these changes made it to mainline? Is there a way to get a patch for the
backend, which does the actual lowering?

Thanks,
Arushi

Will Dietz

unread,
Aug 17, 2011, 2:53:32 PM8/17/11
to Arushi Aggarwal, Neal N. Wang, Renato Golin, llv...@cs.uiuc.edu
FWIW, attached is a similar patch that adds a -falways-use-llvm-vaarg
flag to Clang.

Applies against mainline.

(As discussed, va_arg isn't really supported well so this probably
doesn't work well on anything other than simple code, YMMV, etc)

~Will

0001-Add-option-to-force-emitting-va_arg-instruction.patch

Eric Christopher

unread,
Aug 17, 2011, 3:41:58 PM8/17/11
to wil...@gmail.com, llv...@cs.uiuc.edu, Renato Golin, Neal N. Wang

> <0001-Add-option-to-force-emitting-va_arg-instruction.patch>_______________________________________________

So, what's the point of this one?

-eric

Will Dietz

unread,
Aug 17, 2011, 6:02:28 PM8/17/11
to Eric Christopher, llv...@cs.uiuc.edu, Renato Golin, Neal N. Wang
To get clang to emit va_arg instructions for va_arg() calls, as
opposed to manually lowering it in the frontend, same as the llvm-gcc
patch sent earlier does.

~Will

Eric Christopher

unread,
Aug 17, 2011, 6:08:08 PM8/17/11
to wil...@gmail.com, llv...@cs.uiuc.edu, Renato Golin, Neal N. Wang
I should have been more specific:

"Why do we want this as an option? Do we want it on all the time? Why or why not?"

-eric

Will Dietz

unread,
Aug 18, 2011, 1:13:36 AM8/18/11
to Eric Christopher, llv...@cs.uiuc.edu, Renato Golin, Neal N. Wang
Oh, sorry about that, and thanks for the clarification as to what you
were looking for.

Here you go:

** Why do we want this option? **

Presently clang will manually lower va_arg() in the frontend to the
equivalent (relatively complicated!) IR, as opposed to making use of
the LLVM va_arg instruction directly. IR that contains the va_arg
instruction is much easier to analyze because it is concise and clear
in its semantics. The lowered version IR is target-specific pointer
manipulation from a magic struct, that can expand to multiple BB's and
introduce conditional branches. Therefore, this option helps make the
IR significantly easier to analyze and is probably also rather useful
for source-to-source transformations.

** Do we want it on all the time? Why or why not? **

No, certainly not. Not until the various backends fully support the
va_arg instruction*, and even then there might be ABI issues**.
Furthermore, the existing clang code seems to suggest emitting va_arg
instructions for complex and aggregate values doesn't work***, and my
limited testing agrees with this. It's also possible that lowering it
later rather than earlier has an effect on optimizations and the like,
but I don't know how significant that is.

For those reasons I'd say this option should default to off (as done
in the patch), as va_arg doesn't seem suitable for general use at this
time.

**************
Attached is updated version of the patch that gives a neat unsupported
error (same code path as when the target doesn't implement EmitVAArg)
when attempting to emit va_arg instruction for complex or aggregate
types, instead of an ugly assertion failure.

Let me know if you have any further comments or questions, I'm happy
to help as I can.

Thanks!

~Will

* = See http://llvm.org/bugs/show_bug.cgi?id=1740 and related
** = http://lists.cs.uiuc.edu/pipermail/cfe-dev/2010-February/007799.html
*** = Not the best reference, but
http://lists.cs.uiuc.edu/pipermail/cfe-dev/2010-February/007784.html
shows the relevant code, and as mentioned my testing shows these
unsupported errors are for good reason (surprise!).

0001-Add-option-to-force-emitting-va_arg-instruction.patch

Renato Golin

unread,
Aug 18, 2011, 4:58:12 AM8/18/11
to wil...@gmail.com, Neal N. Wang, llv...@cs.uiuc.edu
On 18 August 2011 06:13, Will Dietz <wil...@gmail.com> wrote:
> For those reasons I'd say this option should default to off (as done
> in the patch), as va_arg doesn't seem suitable for general use at this
> time.

Hi Will,

I think that was a great summary. There is, however, one question that
is hovering this issue:

If not all back-ends support, and we don't want it all the time, is it
worth to keep it half-way through just for the sake of simplicity in
some analysis?

Other features (like union types) got removed for the same reason, and
as much as I liked the idea of having them, I didn't have a strong
case to keep them in the trunk.

To have a flag that will enable it only in special cases is the
quickest way to decommission in the near future, especially near major
releases (like 3.0).

There is a way to work around it that was touched last year when we
were discussing about union types, bitfields and C++ ABI: to have an
IR lowering pass.

The idea is that front-ends can create a reasonably simple IR by using
special constructs (va_arg, bitfield semantics, union types) but not
all back-ends can understand them and, most importantly, those that
do, do it at different levels. So, this pass could be run after all
the passes that need the extra semantics, (lowering all constructs
into simpler, messier IR), and before the other passes that need the
lower IR. Specific targets could have special lowering passes, if
there is a feature they don't support.

For example, at that time, the ARM back-end couldn't deal with struct
by-val, but it could with array by-val. So Clang had to cast all
structures being returned to arrays to pass it by-val. Now that is a
complication that Clang didn't have to know! So, to completely
de-couple front-ends from back-ends, we need those smart passes in the
middle-end.

But that's a long road...

cheers,
--renato

Reply all
Reply to author
Forward
0 new messages