1
+ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
1
2
; RUN: opt < %s -S -passes=msan 2>&1 | FileCheck %s
2
3
3
4
target datalayout = "E-m:m-i8:8:32-i16:16:32-i64:64-n32:64-S128"
4
5
target triple = "mips64--linux"
5
6
6
7
define i32 @foo (i32 %guard , ...) {
8
+ ; CHECK-LABEL: define i32 @foo(
9
+ ; CHECK-SAME: i32 [[GUARD:%.*]], ...) {
10
+ ; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr @__msan_va_arg_overflow_size_tls, align 8
11
+ ; CHECK-NEXT: [[TMP2:%.*]] = alloca i8, i64 [[TMP1]], align 8
12
+ ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP2]], i8 0, i64 [[TMP1]], i1 false)
13
+ ; CHECK-NEXT: [[TMP3:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP1]], i64 800)
14
+ ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP2]], ptr align 8 @__msan_va_arg_tls, i64 [[TMP3]], i1 false)
15
+ ; CHECK-NEXT: call void @llvm.donothing()
16
+ ; CHECK-NEXT: [[VL:%.*]] = alloca ptr, align 8
17
+ ; CHECK-NEXT: [[TMP4:%.*]] = ptrtoint ptr [[VL]] to i64
18
+ ; CHECK-NEXT: [[TMP5:%.*]] = xor i64 [[TMP4]], 549755813888
19
+ ; CHECK-NEXT: [[TMP6:%.*]] = inttoptr i64 [[TMP5]] to ptr
20
+ ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP6]], i8 0, i64 8, i1 false)
21
+ ; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[VL]])
22
+ ; CHECK-NEXT: [[TMP7:%.*]] = ptrtoint ptr [[VL]] to i64
23
+ ; CHECK-NEXT: [[TMP8:%.*]] = xor i64 [[TMP7]], 549755813888
24
+ ; CHECK-NEXT: [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr
25
+ ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 8, i1 false)
26
+ ; CHECK-NEXT: call void @llvm.va_start.p0(ptr [[VL]])
27
+ ; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[VL]] to i64
28
+ ; CHECK-NEXT: [[TMP11:%.*]] = inttoptr i64 [[TMP10]] to ptr
29
+ ; CHECK-NEXT: [[TMP12:%.*]] = load ptr, ptr [[TMP11]], align 8
30
+ ; CHECK-NEXT: [[TMP13:%.*]] = ptrtoint ptr [[TMP12]] to i64
31
+ ; CHECK-NEXT: [[TMP14:%.*]] = xor i64 [[TMP13]], 549755813888
32
+ ; CHECK-NEXT: [[TMP15:%.*]] = inttoptr i64 [[TMP14]] to ptr
33
+ ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP15]], ptr align 8 [[TMP2]], i64 [[TMP1]], i1 false)
34
+ ; CHECK-NEXT: call void @llvm.va_end.p0(ptr [[VL]])
35
+ ; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[VL]])
36
+ ; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8
37
+ ; CHECK-NEXT: ret i32 0
38
+ ;
7
39
%vl = alloca ptr , align 8
8
40
call void @llvm.lifetime.start.p0 (ptr %vl )
9
41
call void @llvm.va_start (ptr %vl )
@@ -12,47 +44,62 @@ define i32 @foo(i32 %guard, ...) {
12
44
ret i32 0
13
45
}
14
46
15
- ; First, check allocation of the save area.
16
-
17
- ; CHECK-LABEL: @foo
18
- ; CHECK: [[A:%.*]] = load {{.*}} @__msan_va_arg_overflow_size_tls
19
- ; CHECK: [[C:%.*]] = alloca {{.*}} [[A]]
20
-
21
- ; CHECK: call void @llvm.memset.p0.i64(ptr align 8 [[C]], i8 0, i64 [[A]], i1 false)
22
-
23
- ; CHECK: [[D:%.*]] = call i64 @llvm.umin.i64(i64 [[A]], i64 800)
24
- ; CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[C]], ptr align 8 @__msan_va_arg_tls, i64 [[D]], i1 false)
25
-
26
47
declare void @llvm.lifetime.start.p0 (ptr nocapture ) #1
27
48
declare void @llvm.va_start (ptr ) #2
28
49
declare void @llvm.va_end (ptr ) #2
29
50
declare void @llvm.lifetime.end.p0 (ptr nocapture ) #1
30
51
31
52
define i32 @bar () {
53
+ ; CHECK-LABEL: define i32 @bar() {
54
+ ; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr @__msan_va_arg_overflow_size_tls, align 8
55
+ ; CHECK-NEXT: call void @llvm.donothing()
56
+ ; CHECK-NEXT: store i32 0, ptr @__msan_param_tls, align 8
57
+ ; CHECK-NEXT: store i32 0, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 8) to ptr), align 8
58
+ ; CHECK-NEXT: store i64 0, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 16) to ptr), align 8
59
+ ; CHECK-NEXT: store i64 0, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 24) to ptr), align 8
60
+ ; CHECK-NEXT: store i32 0, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_va_arg_tls to i64), i64 4) to ptr), align 8
61
+ ; CHECK-NEXT: store i64 0, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_va_arg_tls to i64), i64 8) to ptr), align 8
62
+ ; CHECK-NEXT: store i64 0, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_va_arg_tls to i64), i64 16) to ptr), align 8
63
+ ; CHECK-NEXT: store i64 24, ptr @__msan_va_arg_overflow_size_tls, align 8
64
+ ; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8
65
+ ; CHECK-NEXT: [[TMP2:%.*]] = call i32 (i32, ...) @foo(i32 0, i32 1, i64 2, double 3.000000e+00)
66
+ ; CHECK-NEXT: [[_MSRET:%.*]] = load i32, ptr @__msan_retval_tls, align 8
67
+ ; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8
68
+ ; CHECK-NEXT: ret i32 [[TMP2]]
69
+ ;
32
70
%1 = call i32 (i32 , ...) @foo (i32 0 , i32 1 , i64 2 , double 3 .000000e+00 )
33
71
ret i32 %1
34
72
}
35
73
36
74
; Save the incoming shadow value from the arguments in the __msan_va_arg_tls
37
75
; array. The first argument is stored at position 4, since it's right
38
76
; justified.
39
- ; CHECK-LABEL: @bar
40
- ; CHECK: store i32 0, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_va_arg_tls to i64), i64 4) to ptr), align 8
41
- ; CHECK: store i64 0, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_va_arg_tls to i64), i64 8) to ptr), align 8
42
- ; CHECK: store i64 0, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_va_arg_tls to i64), i64 16) to ptr), align 8
43
- ; CHECK: store {{.*}} 24, {{.*}} @__msan_va_arg_overflow_size_tls
44
77
45
78
; Check multiple fixed arguments.
46
79
declare i32 @foo2 (i32 %g1 , i32 %g2 , ...)
47
80
define i32 @bar2 () {
81
+ ; CHECK-LABEL: define i32 @bar2() {
82
+ ; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr @__msan_va_arg_overflow_size_tls, align 8
83
+ ; CHECK-NEXT: call void @llvm.donothing()
84
+ ; CHECK-NEXT: store i32 0, ptr @__msan_param_tls, align 8
85
+ ; CHECK-NEXT: store i32 0, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 8) to ptr), align 8
86
+ ; CHECK-NEXT: store i64 0, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 16) to ptr), align 8
87
+ ; CHECK-NEXT: store i64 0, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 24) to ptr), align 8
88
+ ; CHECK-NEXT: store i64 0, ptr @__msan_va_arg_tls, align 8
89
+ ; CHECK-NEXT: store i64 0, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_va_arg_tls to i64), i64 8) to ptr), align 8
90
+ ; CHECK-NEXT: store i64 16, ptr @__msan_va_arg_overflow_size_tls, align 8
91
+ ; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8
92
+ ; CHECK-NEXT: [[TMP2:%.*]] = call i32 (i32, i32, ...) @foo2(i32 0, i32 1, i64 2, double 3.000000e+00)
93
+ ; CHECK-NEXT: [[_MSRET:%.*]] = load i32, ptr @__msan_retval_tls, align 8
94
+ ; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8
95
+ ; CHECK-NEXT: ret i32 [[TMP2]]
96
+ ;
48
97
%1 = call i32 (i32 , i32 , ...) @foo2 (i32 0 , i32 1 , i64 2 , double 3 .000000e+00 )
49
98
ret i32 %1
50
99
}
51
100
52
- ; CHECK-LABEL: @bar2
53
- ; CHECK: store i64 0, ptr @__msan_va_arg_tls, align 8
54
- ; CHECK: store i64 0, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_va_arg_tls to i64), i64 8) to ptr), align 8
55
- ; CHECK: store {{.*}} 16, {{.*}} @__msan_va_arg_overflow_size_tls
101
+
102
+ ; UTC_ARGS: --disable
56
103
57
104
; Test that MSan doesn't generate code overflowing __msan_va_arg_tls when too many arguments are
58
105
; passed to a variadic function.
0 commit comments