1 ; RUN: opt < %s -S -passes=msan 2>&1 | FileCheck %s
2 ; RUN: opt < %s -msan -S | FileCheck %s
4 target datalayout = "E-m:e-i64:64-n32:64"
5 target triple = "powerpc64--linux"
7 define i32 @foo(i32 %guard, ...) {
8 %vl = alloca i8*, align 8
9 %1 = bitcast i8** %vl to i8*
10 call void @llvm.lifetime.start.p0i8(i64 32, i8* %1)
11 call void @llvm.va_start(i8* %1)
12 call void @llvm.va_end(i8* %1)
13 call void @llvm.lifetime.end.p0i8(i64 32, i8* %1)
17 ; First, check allocation of the save area.
20 ; CHECK: [[A:%.*]] = load {{.*}} @__msan_va_arg_overflow_size_tls
21 ; CHECK: [[B:%.*]] = add i64 0, [[A]]
22 ; CHECK: [[C:%.*]] = alloca {{.*}} [[B]]
24 ; CHECK: [[STACK:%.*]] = bitcast {{.*}} @__msan_va_arg_tls to i8*
25 ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[C]], i8* align 8 [[STACK]], i64 [[B]], i1 false)
27 declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
28 declare void @llvm.va_start(i8*) #2
29 declare void @llvm.va_end(i8*) #2
30 declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #1
33 %1 = call i32 (i32, ...) @foo(i32 0, i32 1, i64 2, double 3.000000e+00)
37 ; Save the incoming shadow value from the arguments in the __msan_va_arg_tls
38 ; array. The first argument is stored at position 4, since it's right
41 ; CHECK: store i32 0, i32* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 4) to i32*), align 8
42 ; CHECK: store i64 0, i64* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 8) to i64*), align 8
43 ; CHECK: store i64 0, i64* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 16) to i64*), align 8
44 ; CHECK: store {{.*}} 24, {{.*}} @__msan_va_arg_overflow_size_tls
46 ; Check vector argument.
48 %1 = call i32 (i32, ...) @foo(i32 0, <2 x i64> <i64 1, i64 2>)
52 ; The vector is at offset 16 of parameter save area, but __msan_va_arg_tls
53 ; corresponds to offset 8+ of parameter save area - so the offset from
54 ; __msan_va_arg_tls is actually misaligned.
56 ; CHECK: store <2 x i64> zeroinitializer, <2 x i64>* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 8) to <2 x i64>*), align 8
57 ; CHECK: store {{.*}} 24, {{.*}} @__msan_va_arg_overflow_size_tls
59 ; Check QPX vector argument.
60 define i32 @bar3() "target-features"="+qpx" {
61 %1 = call i32 (i32, ...) @foo(i32 0, i32 1, i32 2, <4 x double> <double 1.0, double 2.0, double 3.0, double 4.0>)
65 ; That one is even stranger: the parameter save area starts at offset 48 from
66 ; (32-byte aligned) stack pointer, the vector parameter is at 96 bytes from
67 ; the stack pointer, so its offset from parameter save area is misaligned.
69 ; CHECK: store i32 0, i32* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 4) to i32*), align 8
70 ; CHECK: store i32 0, i32* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 12) to i32*), align 8
71 ; CHECK: store <4 x i64> zeroinitializer, <4 x i64>* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 40) to <4 x i64>*), align 8
72 ; CHECK: store {{.*}} 72, {{.*}} @__msan_va_arg_overflow_size_tls
76 %1 = call i32 (i32, ...) @foo(i32 0, [2 x i64] [i64 1, i64 2])
81 ; CHECK: store [2 x i64] zeroinitializer, [2 x i64]* bitcast ([100 x i64]* @__msan_va_arg_tls to [2 x i64]*), align 8
82 ; CHECK: store {{.*}} 16, {{.*}} @__msan_va_arg_overflow_size_tls
86 %1 = call i32 (i32, ...) @foo(i32 0, [2 x i128] [i128 1, i128 2])
91 ; CHECK: store [2 x i128] zeroinitializer, [2 x i128]* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 8) to [2 x i128]*), align 8
92 ; CHECK: store {{.*}} 40, {{.*}} @__msan_va_arg_overflow_size_tls
94 ; Check 8-aligned byval.
95 define i32 @bar6([2 x i64]* %arg) {
96 %1 = call i32 (i32, ...) @foo(i32 0, [2 x i64]* byval align 8 %arg)
101 ; CHECK: [[SHADOW:%[0-9]+]] = bitcast [2 x i64]* bitcast ([100 x i64]* @__msan_va_arg_tls to [2 x i64]*) to i8*
102 ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[SHADOW]], i8* align 8 {{.*}}, i64 16, i1 false)
103 ; CHECK: store {{.*}} 16, {{.*}} @__msan_va_arg_overflow_size_tls
105 ; Check 16-aligned byval.
106 define i32 @bar7([4 x i64]* %arg) {
107 %1 = call i32 (i32, ...) @foo(i32 0, [4 x i64]* byval align 16 %arg)
112 ; CHECK: [[SHADOW:%[0-9]+]] = bitcast [4 x i64]* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 8) to [4 x i64]*)
113 ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 [[SHADOW]], i8* align 8 {{.*}}, i64 32, i1 false)
114 ; CHECK: store {{.*}} 40, {{.*}} @__msan_va_arg_overflow_size_tls
117 ; Test that MSan doesn't generate code overflowing __msan_va_arg_tls when too many arguments are
118 ; passed to a variadic function.
119 define dso_local i64 @many_args() {
121 %ret = call i64 (i64, ...) @sum(i64 120,
122 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
123 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
124 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
125 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
126 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
127 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
128 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
129 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
130 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
131 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
132 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1,
133 i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1, i64 1
138 ; If the size of __msan_va_arg_tls changes the second argument of `add` must also be changed.
139 ; CHECK-LABEL: @many_args
140 ; CHECK: i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 792)
141 ; CHECK-NOT: i64 add (i64 ptrtoint ([100 x i64]* @__msan_va_arg_tls to i64), i64 800)
142 declare i64 @sum(i64 %n, ...)