[LLVMdev] va_arg

Scott Ricketts sricketts at maxentric.com
Fri Aug 28 15:07:13 PDT 2009


I would like to be able to instrument va_arg, but when I generate a bc
file for a test case using:

llvm-gcc -O3 -emit-llvm vararg.c -c -o vararg.bc

I do not see va_arg. Instead, it seems the args are accessed through
%struct.__va_list_tag, which makes things a bit trickier to
instrument. Is there a way to force llvm-gcc to use va_arg?

Perhaps there is some documentation about va_list_tag or llvm's use of
stdarg that would help me understand what is going on?

Here is the C code...

int sum(int n, ...) {
  int sum = 0;

  va_list list;
  va_start(list, n);
  int i;
  for (i=0; i<n; ++i) {
    sum += va_arg(list, int);
  }
  va_end(list);

  return sum;
}


And the snippet from vararg.ll:

; ModuleID = 'vararg.bc'
target datalayout =
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
target triple = "x86_64-unknown-linux-gnu"
        %struct.__va_list_tag = type { i32, i32, i8*, i8* }

define i32 @sum(i32 %n, ...) nounwind {
entry:
        %list = alloca [1 x %struct.__va_list_tag], align 8
 ; <[1 x %struct.__va_list_tag]*> [#uses=4]
        %list12 = bitcast [1 x %struct.__va_list_tag]* %list to i8*
        ; <i8*> [#uses=2]
        call void @llvm.va_start(i8* %list12)
        %0 = icmp sgt i32 %n, 0         ; <i1> [#uses=1]
        br i1 %0, label %bb.nph, label %bb7

bb.nph:         ; preds = %entry
        %1 = getelementptr [1 x %struct.__va_list_tag]* %list, i64 0,
i64 0, i32 0              ; <i32*> [#uses=2]
        %2 = getelementptr [1 x %struct.__va_list_tag]* %list, i64 0,
i64 0, i32 3              ; <i8**> [#uses=1]
        %3 = getelementptr [1 x %struct.__va_list_tag]* %list, i64 0,
i64 0, i32 2              ; <i8**> [#uses=2]
        br label %bb

bb:             ; preds = %bb5, %bb.nph
        %i.011 = phi i32 [ 0, %bb.nph ], [ %indvar.next, %bb5 ]
 ; <i32> [#uses=1]
        %sum.012 = phi i32 [ 0, %bb.nph ], [ %14, %bb5 ]
 ; <i32> [#uses=1]
        %4 = load i32* %1, align 8              ; <i32> [#uses=3]
        %5 = icmp ult i32 %4, 48                ; <i1> [#uses=1]
        br i1 %5, label %bb3, label %bb4

bb3:            ; preds = %bb
        %6 = load i8** %2, align 8              ; <i8*> [#uses=1]
        %7 = inttoptr i32 %4 to i8*             ; <i8*> [#uses=1]
        %8 = ptrtoint i8* %7 to i64             ; <i64> [#uses=1]
        %ctg2 = getelementptr i8* %6, i64 %8            ; <i8*> [#uses=1]
        %9 = add i32 %4, 8              ; <i32> [#uses=1]
        store i32 %9, i32* %1, align 8
        br label %bb5

bb4:            ; preds = %bb
        %10 = load i8** %3, align 8             ; <i8*> [#uses=2]
        %11 = getelementptr i8* %10, i64 8              ; <i8*> [#uses=1]
        store i8* %11, i8** %3, align 8
        br label %bb5

bb5:            ; preds = %bb4, %bb3
        %addr.0.0 = phi i8* [ %10, %bb4 ], [ %ctg2, %bb3 ]
 ; <i8*> [#uses=1]
        %12 = bitcast i8* %addr.0.0 to i32*             ; <i32*> [#uses=1]
        %13 = load i32* %12, align 4            ; <i32> [#uses=1]
        %14 = add i32 %13, %sum.012             ; <i32> [#uses=2]
        %indvar.next = add i32 %i.011, 1                ; <i32> [#uses=2]
        %exitcond = icmp eq i32 %indvar.next, %n                ; <i1> [#uses=1]
        br i1 %exitcond, label %bb7, label %bb

bb7:            ; preds = %bb5, %entry
        %sum.0.lcssa = phi i32 [ 0, %entry ], [ %14, %bb5 ]
 ; <i32> [#uses=1]
        call void @llvm.va_end(i8* %list12)
        ret i32 %sum.0.lcssa
}



More information about the llvm-dev mailing list