OSDN Git Service

Update aosp/master LLVM for rebase to r256229
[android-x86/external-llvm.git] / test / Instrumentation / MemorySanitizer / AArch64 / vararg.ll
1 ; RUN: opt < %s -msan -S | FileCheck %s
2
3 target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
4 target triple = "aarch64-unknown-linux-gnu"
5
6 %struct.__va_list = type { i8*, i8*, i8*, i32, i32 }
7
8 define i32 @foo(i32 %guard, ...) {
9   %vl = alloca %struct.__va_list, align 8
10   %1 = bitcast %struct.__va_list* %vl to i8*
11   call void @llvm.lifetime.start(i64 32, i8* %1)
12   call void @llvm.va_start(i8* %1)
13   call void @llvm.va_end(i8* %1)
14   call void @llvm.lifetime.end(i64 32, i8* %1)
15   ret i32 0
16 }
17
18 ; First check if the variadic shadow values are saved in stack with correct
19 ; size (192 is total of general purpose registers size, 56, rounded to 16
20 ; plus total of floating-point registers size, 128).
21
22 ; CHECK-LABEL: @foo
23 ; CHECK: [[A:%.*]] = load {{.*}} @__msan_va_arg_overflow_size_tls
24 ; CHECK: [[B:%.*]] = add i64 192, [[A]]
25 ; CHECK: alloca {{.*}} [[B]]
26
27 ; We expect three memcpy operations: one for the general purpose registers,
28 ; one for floating-point/SIMD ones, and one for thre remaining arguments.
29
30 ; Propagate the GR shadow values on for the va_list::__gp_top, adjust the 
31 ; offset in the __msan_va_arg_tls based on va_list:__gp_off, and finally
32 ; issue the memcpy.
33 ; CHECK: [[GRP:%.*]] = getelementptr inbounds i8, i8* {{%.*}}, i64 {{%.*}}
34 ; CHECK: [[GRSIZE:%.*]] = sub i64 56, {{%.*}}
35 ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{%.*}}, i8* [[GRP]], i64 [[GRSIZE]], i32 8, i1 false)
36
37 ; Propagate the VR shadow values on for the va_list::__vr_top, adjust the 
38 ; offset in the __msan_va_arg_tls based on va_list:__vr_off, and finally
39 ; issue the memcpy.
40 ; CHECK: [[VRP:%.*]] = getelementptr inbounds i8, i8* {{%.*}}, i64 {{%.*}}
41 ; CHECK: [[VRSIZE:%.*]] = sub i64 128, {{%.*}}
42 ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{%.*}}, i8* [[VRP]], i64 [[VRSIZE]], i32 8, i1 false)
43
44 ; Copy the remaining shadow values on the va_list::__stack position (it is
45 ; on the constant offset of 192 from __msan_va_arg_tls).
46 ; CHECK: [[STACK:%.*]] = getelementptr inbounds i8, i8* {{%.*}}, i32 192
47 ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{%.*}}, i8* [[STACK]], i64 {{%.*}}, i32 16, i1 false)
48
49 declare void @llvm.lifetime.start(i64, i8* nocapture) #1
50 declare void @llvm.va_start(i8*) #2
51 declare void @llvm.va_end(i8*) #2
52 declare void @llvm.lifetime.end(i64, i8* nocapture) #1
53
54 define i32 @bar() {
55   %1 = call i32 (i32, ...) @foo(i32 0, i32 1, i32 2, double 3.000000e+00, 
56                                 double 4.000000e+00, i32 5, i32 6,
57                                 double 7.000000e+00, i32 8, i32 9, i32 10, i32 11)
58   ret i32 %1
59 }
60
61 ; Save the incoming shadow value from the arguments in the __msan_va_arg_tls
62 ; array.  General purpose registers are saved at positions from 0 to 56, Floating
63 ; point and SIMD are saved from 64 to 192, and the remaining from 192.
64 ; CHECK-LABEL: @bar
65 ; CHECK: store {{.*}} @__msan_va_arg_tls {{.*}} 8
66 ; CHECK: store {{.*}} @__msan_va_arg_tls {{.*}} 64
67 ; CHECK: store {{.*}} @__msan_va_arg_tls {{.*}} 80
68 ; CHECK: store {{.*}} @__msan_va_arg_tls {{.*}} 16
69 ; CHECK: store {{.*}} @__msan_va_arg_tls {{.*}} 24
70 ; CHECK: store {{.*}} @__msan_va_arg_tls {{.*}} 96
71 ; CHECK: store {{.*}} @__msan_va_arg_tls {{.*}} 32
72 ; CHECK: store {{.*}} @__msan_va_arg_tls {{.*}} 40
73 ; CHECK: store {{.*}} @__msan_va_arg_tls {{.*}} 48
74 ; CHECK: store {{.*}} @__msan_va_arg_tls {{.*}} 192
75 ; CHECK: store {{.*}} 8, {{.*}} @__msan_va_arg_overflow_size_tls