1 // REQUIRES: hexagon-registered-target
2 // RUN: %clang_cc1 -no-opaque-pointers -emit-llvm -triple hexagon-unknown-linux-musl %s -o - | FileCheck %s
3 #include <stdarg.h>
4 
5 struct AAA {
6   int x;
7   int y;
8   int z;
9   int d;
10 };
11 
12 // CHECK:   call void @llvm.va_start(i8* %arraydecay1)
13 // CHECK:   %arraydecay2 = getelementptr inbounds [1 x %struct.__va_list_tag],
14 // [1 x %struct.__va_list_tag]* %ap, i32 0, i32 0
15 // CHECK:   br label %vaarg.maybe_reg
16 
17 // CHECK: vaarg.maybe_reg:                                  ; preds = %entry
18 // CHECK:   %__current_saved_reg_area_pointer_p = getelementptr inbounds
19 // %struct.__va_list_tag, %struct.__va_list_tag* %arraydecay2, i32 0, i32 0
20 // CHECK:   %__current_saved_reg_area_pointer = load i8*, i8**
21 // %__current_saved_reg_area_pointer_p
22 // CHECK:   %__saved_reg_area_end_pointer_p = getelementptr inbounds
23 // %struct.__va_list_tag, %struct.__va_list_tag* %arraydecay2, i32 0, i32 1
24 // CHECK:   %__saved_reg_area_end_pointer = load i8*, i8**
25 // %__saved_reg_area_end_pointer_p
26 // CHECK:   %__new_saved_reg_area_pointer = getelementptr i8, i8*
27 // %__current_saved_reg_area_pointer, i32 4
28 // CHECK:   %0 = icmp sgt i8* %__new_saved_reg_area_pointer,
29 // %__saved_reg_area_end_pointer
30 // CHECK:   br i1 %0, label %vaarg.on_stack, label %vaarg.in_reg
31 
32 // CHECK: vaarg.in_reg:                                     ; preds =
33 // %vaarg.maybe_reg
34 // CHECK:   %1 = bitcast i8* %__current_saved_reg_area_pointer to i32*
35 // CHECK:   store i8* %__new_saved_reg_area_pointer, i8**
36 // %__current_saved_reg_area_pointer_p
37 // CHECK:   br label %vaarg.end
38 
39 // CHECK: vaarg.on_stack:                                   ; preds =
40 // %vaarg.maybe_reg
41 // CHECK:   %__overflow_area_pointer_p = getelementptr inbounds
42 // %struct.__va_list_tag, %struct.__va_list_tag* %arraydecay2, i32 0, i32 2
43 // CHECK:   %__overflow_area_pointer = load i8*, i8** %__overflow_area_pointer_p
44 // CHECK:   %__overflow_area_pointer.next = getelementptr i8, i8*
45 // %__overflow_area_pointer, i32 4
46 // CHECK:   store i8* %__overflow_area_pointer.next, i8**
47 // %__overflow_area_pointer_p
48 // CHECK:   store i8* %__overflow_area_pointer.next, i8**
49 // %__current_saved_reg_area_pointer_p
50 // CHECK:   %2 = bitcast i8* %__overflow_area_pointer to i32*
51 // CHECK:   br label %vaarg.end
52 
53 // CHECK: vaarg.end:                                        ; preds =
54 // %vaarg.on_stack, %vaarg.in_reg
55 // CHECK:   %vaarg.addr = phi i32* [ %1, %vaarg.in_reg ], [ %2, %vaarg.on_stack
56 // ]
57 // CHECK:   %3 = load i32, i32* %vaarg.addr
58 
59 struct AAA aaa = {100, 200, 300, 400};
60 
61 int foo(int xx, ...) {
62   va_list ap;
63   int d;
64   int ret = 0;
65   struct AAA bbb;
66   va_start(ap, xx);
67   d = va_arg(ap, int);
68   ret += d;
69   bbb = va_arg(ap, struct AAA);
70   ret += bbb.d;
71   d = va_arg(ap, int);
72   ret += d;
73   va_end(ap);
74   return ret;
75 }
76 
77 int main(void) {
78   int x;
79   x = foo(1, 2, aaa, 4);
80   return x;
81 }
82