1 ; RUN: opt < %s -msan-check-access-address=0 -S -passes='module(msan)' 2>&1 | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CHECK,NOORIGINS --implicit-check-not="call void @__msan_warning"
2 ; RUN: opt < %s --passes='module(msan)' -msan-check-access-address=0 -S | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CHECK,NOORIGINS --implicit-check-not="call void @__msan_warning"
3 ; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -S -passes='module(msan)' 2>&1 | FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK,ORIGINS %s --implicit-check-not="call void @__msan_warning"
4 ; RUN: opt < %s -passes='module(msan)' -msan-check-access-address=0 -msan-track-origins=1 -S | FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK,ORIGINS %s --implicit-check-not="call void @__msan_warning"
5 ; RUN: opt < %s -passes='module(msan)' -msan-instrumentation-with-call-threshold=0 -msan-track-origins=1 -S | FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK-CALLS %s --implicit-check-not="call void @__msan_warning"
7 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-n8:16:32:64-S128"
8 target triple = "x86_64-unknown-linux-gnu"
10 ; CHECK: @llvm.used = appending global [1 x ptr] [ptr @msan.module_ctor]
11 ; CHECK: @llvm.global_ctors {{.*}} { i32 0, ptr @msan.module_ctor, ptr null }
13 ; Check the presence and the linkage type of __msan_track_origins and
14 ; other interface symbols.
15 ; CHECK-NOT: @__msan_track_origins
16 ; ORIGINS: @__msan_track_origins = weak_odr constant i32 1
17 ; CHECK-NOT: @__msan_keep_going = weak_odr constant i32 0
18 ; CHECK: @__msan_retval_tls = external thread_local(initialexec) global [{{.*}}]
19 ; CHECK: @__msan_retval_origin_tls = external thread_local(initialexec) global i32
20 ; CHECK: @__msan_param_tls = external thread_local(initialexec) global [{{.*}}]
21 ; CHECK: @__msan_param_origin_tls = external thread_local(initialexec) global [{{.*}}]
22 ; CHECK: @__msan_va_arg_tls = external thread_local(initialexec) global [{{.*}}]
23 ; CHECK: @__msan_va_arg_overflow_size_tls = external thread_local(initialexec) global i64
26 ; Check instrumentation of stores
28 define void @Store(ptr nocapture %p, i32 %x) nounwind uwtable sanitize_memory {
30 store i32 %x, ptr %p, align 4
35 ; CHECK: load {{.*}} @__msan_param_tls
36 ; ORIGINS: load {{.*}} @__msan_param_origin_tls
40 ; ORIGINS: {{^[0-9]+}}:
43 ; ORIGINS: {{^[0-9]+}}:
48 ; Check instrumentation of aligned stores
49 ; Shadow store has the same alignment as the original store; origin store
50 ; does not specify explicit alignment.
52 define void @AlignedStore(ptr nocapture %p, i32 %x) nounwind uwtable sanitize_memory {
54 store i32 %x, ptr %p, align 32
58 ; CHECK-LABEL: @AlignedStore
59 ; CHECK: load {{.*}} @__msan_param_tls
60 ; ORIGINS: load {{.*}} @__msan_param_origin_tls
61 ; CHECK: store {{.*}} align 32
64 ; ORIGINS: {{^[0-9]+}}:
65 ; ORIGINS: store {{.*}} align 32
67 ; ORIGINS: {{^[0-9]+}}:
68 ; CHECK: store {{.*}} align 32
72 ; load followed by cmp: check that we load the shadow and call __msan_warning_with_origin.
73 define void @LoadAndCmp(ptr nocapture %a) nounwind uwtable sanitize_memory {
75 %0 = load i32, ptr %a, align 4
76 %tobool = icmp eq i32 %0, 0
77 br i1 %tobool, label %if.end, label %if.then
79 if.then: ; preds = %entry
80 tail call void (...) @foo() nounwind
83 if.end: ; preds = %entry, %if.then
87 declare void @foo(...)
89 ; CHECK-LABEL: @LoadAndCmp
90 ; CHECK: %0 = load i32,
92 ; ORIGINS: %[[ORIGIN:.*]] = load
93 ; NOORIGINS: call void @__msan_warning_noreturn()
94 ; ORIGINS: call void @__msan_warning_with_origin_noreturn(i32 %[[ORIGIN]])
96 ; CHECK-NEXT: unreachable
97 ; CHECK: br i1 %tobool
100 ; Check that we store the shadow for the retval.
101 define i32 @ReturnInt() nounwind uwtable readnone sanitize_memory {
106 ; CHECK-LABEL: @ReturnInt
107 ; CHECK: store i32 0,{{.*}}__msan_retval_tls
110 ; Check that we get the shadow for the retval.
111 define void @CopyRetVal(ptr nocapture %a) nounwind uwtable sanitize_memory {
113 %call = tail call i32 @ReturnInt() nounwind
114 store i32 %call, ptr %a, align 4
118 ; CHECK-LABEL: @CopyRetVal
119 ; CHECK: load{{.*}}__msan_retval_tls
125 ; Check that we generate PHIs for shadow.
126 define void @FuncWithPhi(ptr nocapture %a, ptr %b, ptr nocapture %c) nounwind uwtable sanitize_memory {
128 %tobool = icmp eq ptr %b, null
129 br i1 %tobool, label %if.else, label %if.then
131 if.then: ; preds = %entry
132 %0 = load i32, ptr %b, align 4
135 if.else: ; preds = %entry
136 %1 = load i32, ptr %c, align 4
139 if.end: ; preds = %if.else, %if.then
140 %t.0 = phi i32 [ %0, %if.then ], [ %1, %if.else ]
141 store i32 %t.0, ptr %a, align 4
145 ; CHECK-LABEL: @FuncWithPhi
146 ; NOORIGINS: call void @__msan_warning_noreturn()
147 ; ORIGINS: call void @__msan_warning_with_origin_noreturn(i32
154 ; Compute shadow for "x << 10"
155 define void @ShlConst(ptr nocapture %x) nounwind uwtable sanitize_memory {
157 %0 = load i32, ptr %x, align 4
159 store i32 %1, ptr %x, align 4
163 ; CHECK-LABEL: @ShlConst
172 ; Compute shadow for "10 << x": it should have 'sext i1'.
173 define void @ShlNonConst(ptr nocapture %x) nounwind uwtable sanitize_memory {
175 %0 = load i32, ptr %x, align 4
177 store i32 %1, ptr %x, align 4
181 ; CHECK-LABEL: @ShlNonConst
190 define void @SExt(ptr nocapture %a, ptr nocapture %b) nounwind uwtable sanitize_memory {
192 %0 = load i16, ptr %b, align 2
193 %1 = sext i16 %0 to i32
194 store i32 %1, ptr %a, align 4
209 define void @MemSet(ptr nocapture %x) nounwind uwtable sanitize_memory {
211 call void @llvm.memset.p0.i64(ptr %x, i8 42, i64 10, i1 false)
215 declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1) nounwind
217 ; CHECK-LABEL: @MemSet
218 ; CHECK: call ptr @__msan_memset
223 define void @MemCpy(ptr nocapture %x, ptr nocapture %y) nounwind uwtable sanitize_memory {
225 call void @llvm.memcpy.p0.p0.i64(ptr %x, ptr %y, i64 10, i1 false)
229 declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) nounwind
231 ; CHECK-LABEL: @MemCpy
232 ; CHECK: call ptr @__msan_memcpy
236 define void @MemSetInline(ptr nocapture %x) nounwind uwtable sanitize_memory {
238 call void @llvm.memset.inline.p0.i64(ptr %x, i8 42, i64 10, i1 false)
242 declare void @llvm.memset.inline.p0.i64(ptr nocapture, i8, i64, i1) nounwind
244 ; CHECK-LABEL: @MemSetInline
245 ; CHECK: call ptr @__msan_memset
249 define void @MemCpyInline(ptr nocapture %x, ptr nocapture %y) nounwind uwtable sanitize_memory {
251 call void @llvm.memcpy.inline.p0.p0.i64(ptr %x, ptr %y, i64 10, i1 false)
255 declare void @llvm.memcpy.inline.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) nounwind
257 ; CHECK-LABEL: @MemCpyInline
258 ; CHECK: call ptr @__msan_memcpy
261 ; memmove is lowered to a call
262 define void @MemMove(ptr nocapture %x, ptr nocapture %y) nounwind uwtable sanitize_memory {
264 call void @llvm.memmove.p0.p0.i64(ptr %x, ptr %y, i64 10, i1 false)
268 declare void @llvm.memmove.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) nounwind
270 ; CHECK-LABEL: @MemMove
271 ; CHECK: call ptr @__msan_memmove
275 ;; Placeholder tests that will fail once element atomic @llvm.mem[cpy|move|set] intrinsics have
276 ;; been added to the MemIntrinsic class hierarchy. These will act as a reminder to
277 ;; verify that MSAN handles these intrinsics properly once they have been
278 ;; added to that class hierarchy.
279 declare void @llvm.memset.element.unordered.atomic.p0.i64(ptr nocapture writeonly, i8, i64, i32) nounwind
280 declare void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i32) nounwind
281 declare void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i32) nounwind
283 define void @atomic_memcpy(ptr nocapture %x, ptr nocapture %y) nounwind {
284 ; CHECK-LABEL: atomic_memcpy
285 ; CHECK-NEXT: call void @llvm.donothing
286 ; CHECK-NEXT: call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 %x, ptr align 2 %y, i64 16, i32 1)
287 ; CHECK-NEXT: ret void
288 call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 %x, ptr align 2 %y, i64 16, i32 1)
292 define void @atomic_memmove(ptr nocapture %x, ptr nocapture %y) nounwind {
293 ; CHECK-LABEL: atomic_memmove
294 ; CHECK-NEXT: call void @llvm.donothing
295 ; CHECK-NEXT: call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 %x, ptr align 2 %y, i64 16, i32 1)
296 ; CHECK-NEXT: ret void
297 call void @llvm.memmove.element.unordered.atomic.p0.p0.i64(ptr align 1 %x, ptr align 2 %y, i64 16, i32 1)
301 define void @atomic_memset(ptr nocapture %x) nounwind {
302 ; CHECK-LABEL: atomic_memset
303 ; CHECK-NEXT: call void @llvm.donothing
304 ; CHECK-NEXT: call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 1 %x, i8 88, i64 16, i32 1)
305 ; CHECK-NEXT: ret void
306 call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 1 %x, i8 88, i64 16, i32 1)
313 ; Check that we propagate shadow for "select"
315 define i32 @Select(i32 %a, i32 %b, i1 %c) nounwind uwtable readnone sanitize_memory {
317 %cond = select i1 %c, i32 %a, i32 %b
321 ; CHECK-LABEL: @Select
326 ; CHECK-DAG: select i1
327 ; ORIGINS-DAG: select
328 ; ORIGINS-DAG: select
329 ; CHECK-DAG: select i1
330 ; CHECK: store i32{{.*}}@__msan_retval_tls
331 ; ORIGINS: store i32{{.*}}@__msan_retval_origin_tls
335 ; Check that we propagate origin for "select" with vector condition.
336 ; Select condition is flattened to i1, which is then used to select one of the
339 define <8 x i16> @SelectVector(<8 x i16> %a, <8 x i16> %b, <8 x i1> %c) nounwind uwtable readnone sanitize_memory {
341 %cond = select <8 x i1> %c, <8 x i16> %a, <8 x i16> %b
345 ; CHECK-LABEL: @SelectVector
346 ; CHECK: select <8 x i1>
347 ; CHECK-DAG: or <8 x i16>
348 ; CHECK-DAG: xor <8 x i16>
349 ; CHECK: or <8 x i16>
350 ; CHECK-DAG: select <8 x i1>
351 ; ORIGINS-DAG: select
352 ; ORIGINS-DAG: select
353 ; CHECK-DAG: select <8 x i1>
354 ; CHECK: store <8 x i16>{{.*}}@__msan_retval_tls
355 ; ORIGINS: store i32{{.*}}@__msan_retval_origin_tls
356 ; CHECK: ret <8 x i16>
359 ; Check that we propagate origin for "select" with scalar condition and vector
360 ; arguments. Select condition shadow is sign-extended to the vector type and
361 ; mixed into the result shadow.
363 define <8 x i16> @SelectVector2(<8 x i16> %a, <8 x i16> %b, i1 %c) nounwind uwtable readnone sanitize_memory {
365 %cond = select i1 %c, <8 x i16> %a, <8 x i16> %b
369 ; CHECK-LABEL: @SelectVector2
371 ; CHECK-DAG: or <8 x i16>
372 ; CHECK-DAG: xor <8 x i16>
373 ; CHECK: or <8 x i16>
374 ; CHECK-DAG: select i1
375 ; ORIGINS-DAG: select i1
376 ; ORIGINS-DAG: select i1
377 ; CHECK-DAG: select i1
378 ; CHECK: ret <8 x i16>
381 define { i64, i64 } @SelectStruct(i1 zeroext %x, { i64, i64 } %a, { i64, i64 } %b) readnone sanitize_memory {
383 %c = select i1 %x, { i64, i64 } %a, { i64, i64 } %b
387 ; CHECK-LABEL: @SelectStruct
388 ; CHECK: select i1 {{.*}}, { i64, i64 }
389 ; CHECK-NEXT: select i1 {{.*}}, { i64, i64 } { i64 -1, i64 -1 }, { i64, i64 }
392 ; CHECK-NEXT: select i1 {{.*}}, { i64, i64 }
393 ; CHECK: ret { i64, i64 }
396 define { ptr, double } @SelectStruct2(i1 zeroext %x, { ptr, double } %a, { ptr, double } %b) readnone sanitize_memory {
398 %c = select i1 %x, { ptr, double } %a, { ptr, double } %b
399 ret { ptr, double } %c
402 ; CHECK-LABEL: @SelectStruct2
403 ; CHECK: select i1 {{.*}}, { i64, i64 }
404 ; CHECK-NEXT: select i1 {{.*}}, { i64, i64 } { i64 -1, i64 -1 }, { i64, i64 }
407 ; CHECK-NEXT: select i1 {{.*}}, { ptr, double }
408 ; CHECK: ret { ptr, double }
411 define ptr @IntToPtr(i64 %x) nounwind uwtable readnone sanitize_memory {
413 %0 = inttoptr i64 %x to ptr
417 ; CHECK-LABEL: @IntToPtr
418 ; CHECK: load i64, ptr{{.*}}__msan_param_tls
419 ; ORIGINS-NEXT: load i32, ptr{{.*}}__msan_param_origin_tls
420 ; CHECK-NEXT: call void @llvm.donothing
421 ; CHECK-NEXT: inttoptr
422 ; CHECK-NEXT: store i64{{.*}}__msan_retval_tls
426 define ptr @IntToPtr_ZExt(i16 %x) nounwind uwtable readnone sanitize_memory {
428 %0 = inttoptr i16 %x to ptr
432 ; CHECK-LABEL: @IntToPtr_ZExt
433 ; CHECK: load i16, ptr{{.*}}__msan_param_tls
435 ; CHECK-NEXT: inttoptr
436 ; CHECK-NEXT: store i64{{.*}}__msan_retval_tls
440 ; Check that we insert exactly one check on udiv
441 ; (2nd arg shadow is checked, 1st arg shadow is propagated)
443 define i32 @Div(i32 %a, i32 %b) nounwind uwtable readnone sanitize_memory {
445 %div = udiv i32 %a, %b
451 ; NOORIGINS: call void @__msan_warning_noreturn()
452 ; ORIGINS: call void @__msan_warning_with_origin_noreturn(i32
458 ; Check that fdiv, unlike udiv, simply propagates shadow.
460 define float @FDiv(float %a, float %b) nounwind uwtable readnone sanitize_memory {
462 %c = fdiv float %a, %b
467 ; CHECK: %[[SA:.*]] = load i32,{{.*}}@__msan_param_tls
468 ; CHECK: %[[SB:.*]] = load i32,{{.*}}@__msan_param_tls
469 ; CHECK: %[[SC:.*]] = or i32 %[[SA]], %[[SB]]
470 ; CHECK: = fdiv float
471 ; CHECK: store i32 %[[SC]], ptr {{.*}}@__msan_retval_tls
474 ; Check that fneg simply propagates shadow.
476 define float @FNeg(float %a) nounwind uwtable readnone sanitize_memory {
483 ; CHECK: %[[SA:.*]] = load i32,{{.*}}@__msan_param_tls
484 ; ORIGINS: %[[SB:.*]] = load i32,{{.*}}@__msan_param_origin_tls
485 ; CHECK: = fneg float
486 ; CHECK: store i32 %[[SA]], ptr {{.*}}@__msan_retval_tls
487 ; ORIGINS: store i32{{.*}}@__msan_retval_origin_tls
490 ; Check that we propagate shadow for x<0, x>=0, etc (i.e. sign bit tests)
492 define zeroext i1 @ICmpSLTZero(i32 %x) nounwind uwtable readnone sanitize_memory {
493 %1 = icmp slt i32 %x, 0
497 ; CHECK-LABEL: @ICmpSLTZero
499 ; CHECK-NOT: call void @__msan_warning
501 ; CHECK-NOT: call void @__msan_warning
504 define zeroext i1 @ICmpSGEZero(i32 %x) nounwind uwtable readnone sanitize_memory {
505 %1 = icmp sge i32 %x, 0
509 ; CHECK-LABEL: @ICmpSGEZero
511 ; CHECK-NOT: call void @__msan_warning
513 ; CHECK-NOT: call void @__msan_warning
516 define zeroext i1 @ICmpSGTZero(i32 %x) nounwind uwtable readnone sanitize_memory {
517 %1 = icmp sgt i32 0, %x
521 ; CHECK-LABEL: @ICmpSGTZero
523 ; CHECK-NOT: call void @__msan_warning
525 ; CHECK-NOT: call void @__msan_warning
528 define zeroext i1 @ICmpSLEZero(i32 %x) nounwind uwtable readnone sanitize_memory {
529 %1 = icmp sle i32 0, %x
533 ; CHECK-LABEL: @ICmpSLEZero
535 ; CHECK-NOT: call void @__msan_warning
537 ; CHECK-NOT: call void @__msan_warning
541 ; Check that we propagate shadow for x<=-1, x>-1, etc (i.e. sign bit tests)
543 define zeroext i1 @ICmpSLTAllOnes(i32 %x) nounwind uwtable readnone sanitize_memory {
544 %1 = icmp slt i32 -1, %x
548 ; CHECK-LABEL: @ICmpSLTAllOnes
550 ; CHECK-NOT: call void @__msan_warning
552 ; CHECK-NOT: call void @__msan_warning
555 define zeroext i1 @ICmpSGEAllOnes(i32 %x) nounwind uwtable readnone sanitize_memory {
556 %1 = icmp sge i32 -1, %x
560 ; CHECK-LABEL: @ICmpSGEAllOnes
562 ; CHECK-NOT: call void @__msan_warning
564 ; CHECK-NOT: call void @__msan_warning
567 define zeroext i1 @ICmpSGTAllOnes(i32 %x) nounwind uwtable readnone sanitize_memory {
568 %1 = icmp sgt i32 %x, -1
572 ; CHECK-LABEL: @ICmpSGTAllOnes
574 ; CHECK-NOT: call void @__msan_warning
576 ; CHECK-NOT: call void @__msan_warning
579 define zeroext i1 @ICmpSLEAllOnes(i32 %x) nounwind uwtable readnone sanitize_memory {
580 %1 = icmp sle i32 %x, -1
584 ; CHECK-LABEL: @ICmpSLEAllOnes
586 ; CHECK-NOT: call void @__msan_warning
588 ; CHECK-NOT: call void @__msan_warning
592 ; Check that we propagate shadow for x<0, x>=0, etc (i.e. sign bit tests)
593 ; of the vector arguments.
595 define <2 x i1> @ICmpSLT_vector_Zero(<2 x ptr> %x) nounwind uwtable readnone sanitize_memory {
596 %1 = icmp slt <2 x ptr> %x, zeroinitializer
600 ; CHECK-LABEL: @ICmpSLT_vector_Zero
601 ; CHECK: icmp slt <2 x i64>
602 ; CHECK-NOT: call void @__msan_warning
603 ; CHECK: icmp slt <2 x ptr>
604 ; CHECK-NOT: call void @__msan_warning
605 ; CHECK: ret <2 x i1>
607 ; Check that we propagate shadow for x<=-1, x>0, etc (i.e. sign bit tests)
608 ; of the vector arguments.
610 define <2 x i1> @ICmpSLT_vector_AllOnes(<2 x i32> %x) nounwind uwtable readnone sanitize_memory {
611 %1 = icmp slt <2 x i32> <i32 -1, i32 -1>, %x
615 ; CHECK-LABEL: @ICmpSLT_vector_AllOnes
616 ; CHECK: icmp slt <2 x i32>
617 ; CHECK-NOT: call void @__msan_warning
618 ; CHECK: icmp slt <2 x i32>
619 ; CHECK-NOT: call void @__msan_warning
620 ; CHECK: ret <2 x i1>
623 ; Check that we propagate shadow for unsigned relational comparisons with
626 define zeroext i1 @ICmpUGTConst(i32 %x) nounwind uwtable readnone sanitize_memory {
628 %cmp = icmp ugt i32 %x, 7
632 ; CHECK-LABEL: @ICmpUGTConst
633 ; CHECK: icmp ugt i32
634 ; CHECK-NOT: call void @__msan_warning
635 ; CHECK: icmp ugt i32
636 ; CHECK-NOT: call void @__msan_warning
637 ; CHECK: icmp ugt i32
638 ; CHECK-NOT: call void @__msan_warning
642 ; Check that loads of shadow have the same alignment as the original loads.
643 ; Check that loads of origin have the alignment of max(4, original alignment).
645 define i32 @ShadowLoadAlignmentLarge() nounwind uwtable sanitize_memory {
646 %y = alloca i32, align 64
647 %1 = load volatile i32, ptr %y, align 64
651 ; CHECK-LABEL: @ShadowLoadAlignmentLarge
652 ; CHECK: load volatile i32, ptr {{.*}} align 64
653 ; CHECK: load i32, ptr {{.*}} align 64
656 define i32 @ShadowLoadAlignmentSmall() nounwind uwtable sanitize_memory {
657 %y = alloca i32, align 2
658 %1 = load volatile i32, ptr %y, align 2
662 ; CHECK-LABEL: @ShadowLoadAlignmentSmall
663 ; CHECK: load volatile i32, ptr {{.*}} align 2
664 ; CHECK: load i32, ptr {{.*}} align 2
665 ; ORIGINS: load i32, ptr {{.*}} align 4
669 ; Test vector manipulation instructions.
670 ; Check that the same bit manipulation is applied to the shadow values.
671 ; Check that there is a zero test of the shadow of %idx argument, where present.
673 define i32 @ExtractElement(<4 x i32> %vec, i32 %idx) sanitize_memory {
674 %x = extractelement <4 x i32> %vec, i32 %idx
678 ; CHECK-LABEL: @ExtractElement
679 ; CHECK: extractelement
680 ; NOORIGINS: call void @__msan_warning_noreturn()
681 ; ORIGINS: call void @__msan_warning_with_origin_noreturn(i32
682 ; CHECK: extractelement
685 define <4 x i32> @InsertElement(<4 x i32> %vec, i32 %idx, i32 %x) sanitize_memory {
686 %vec1 = insertelement <4 x i32> %vec, i32 %x, i32 %idx
690 ; CHECK-LABEL: @InsertElement
691 ; CHECK: insertelement
692 ; NOORIGINS: call void @__msan_warning_noreturn()
693 ; ORIGINS: call void @__msan_warning_with_origin_noreturn(i32
694 ; CHECK: insertelement
695 ; CHECK: ret <4 x i32>
697 define <4 x i32> @ShuffleVector(<4 x i32> %vec, <4 x i32> %vec1) sanitize_memory {
698 %vec2 = shufflevector <4 x i32> %vec, <4 x i32> %vec1,
699 <4 x i32> <i32 0, i32 4, i32 1, i32 5>
703 ; CHECK-LABEL: @ShuffleVector
704 ; CHECK: shufflevector
705 ; CHECK-NOT: call void @__msan_warning
706 ; CHECK: shufflevector
707 ; CHECK: ret <4 x i32>
710 ; Test bswap intrinsic instrumentation
711 define i32 @BSwap(i32 %x) nounwind uwtable readnone sanitize_memory {
712 %y = tail call i32 @llvm.bswap.i32(i32 %x)
716 declare i32 @llvm.bswap.i32(i32) nounwind readnone
718 ; CHECK-LABEL: @BSwap
719 ; CHECK-NOT: call void @__msan_warning
720 ; CHECK: @llvm.bswap.i32
721 ; CHECK-NOT: call void @__msan_warning
722 ; CHECK: @llvm.bswap.i32
723 ; CHECK-NOT: call void @__msan_warning
726 ; Test handling of vectors of pointers.
727 ; Check that shadow of such vector is a vector of integers.
729 define <8 x ptr> @VectorOfPointers(ptr %p) nounwind uwtable sanitize_memory {
730 %x = load <8 x ptr>, ptr %p
734 ; CHECK-LABEL: @VectorOfPointers
735 ; CHECK: load <8 x ptr>, ptr
736 ; CHECK: load <8 x i64>, ptr
737 ; CHECK: store <8 x i64> {{.*}} @__msan_retval_tls
738 ; CHECK: ret <8 x ptr>
740 ; Test handling of va_copy.
742 declare void @llvm.va_copy(ptr, ptr) nounwind
744 define void @VACopy(ptr %p1, ptr %p2) nounwind uwtable sanitize_memory {
745 call void @llvm.va_copy(ptr %p1, ptr %p2) nounwind
749 ; CHECK-LABEL: @VACopy
750 ; CHECK: call void @llvm.memset.p0.i64({{.*}}, i8 0, i64 24, i1 false)
754 ; Test that va_start instrumentation does not use va_arg_tls*.
755 ; It should work with a local stack copy instead.
757 %struct.__va_list_tag = type { i32, i32, ptr, ptr }
758 declare void @llvm.va_start(ptr) nounwind
760 ; Function Attrs: nounwind uwtable
761 define void @VAStart(i32 %x, ...) sanitize_memory {
763 %x.addr = alloca i32, align 4
764 %va = alloca [1 x %struct.__va_list_tag], align 16
765 store i32 %x, ptr %x.addr, align 4
766 call void @llvm.va_start(ptr %va)
770 ; CHECK-LABEL: @VAStart
771 ; CHECK: call void @llvm.va_start
772 ; CHECK-NOT: @__msan_va_arg_tls
773 ; CHECK-NOT: @__msan_va_arg_overflow_size_tls
777 ; Test handling of volatile stores.
778 ; Check that MemorySanitizer does not add a check of the value being stored.
780 define void @VolatileStore(ptr nocapture %p, i32 %x) nounwind uwtable sanitize_memory {
782 store volatile i32 %x, ptr %p, align 4
786 ; CHECK-LABEL: @VolatileStore
787 ; CHECK-NOT: @__msan_warning_with_origin
791 ; Test that checks are omitted and returned value is always initialized if
792 ; sanitize_memory attribute is missing.
794 define i32 @NoSanitizeMemory(i32 %x) uwtable {
796 %tobool = icmp eq i32 %x, 0
797 br i1 %tobool, label %if.end, label %if.then
799 if.then: ; preds = %entry
800 tail call void @bar()
803 if.end: ; preds = %entry, %if.then
809 ; CHECK-LABEL: @NoSanitizeMemory
810 ; CHECK-NOT: @__msan_warning_with_origin
811 ; CHECK: store i32 0, {{.*}} @__msan_retval_tls
812 ; CHECK-NOT: @__msan_warning_with_origin
816 ; Test that stack allocations are unpoisoned in functions missing
817 ; sanitize_memory attribute
819 define i32 @NoSanitizeMemoryAlloca() {
821 %p = alloca i32, align 4
822 %x = call i32 @NoSanitizeMemoryAllocaHelper(ptr %p)
826 declare i32 @NoSanitizeMemoryAllocaHelper(ptr %p)
828 ; CHECK-LABEL: @NoSanitizeMemoryAlloca
829 ; CHECK: call void @llvm.memset.p0.i64(ptr align 4 {{.*}}, i8 0, i64 4, i1 false)
830 ; CHECK: call i32 @NoSanitizeMemoryAllocaHelper(ptr
834 ; Test that undef is unpoisoned in functions missing
835 ; sanitize_memory attribute
837 define i32 @NoSanitizeMemoryUndef() {
839 %x = call i32 @NoSanitizeMemoryUndefHelper(i32 undef)
843 declare i32 @NoSanitizeMemoryUndefHelper(i32 %x)
845 ; CHECK-LABEL: @NoSanitizeMemoryUndef
846 ; CHECK: store i32 0, ptr @__msan_param_tls
847 ; CHECK: call i32 @NoSanitizeMemoryUndefHelper(i32 undef)
851 ; Test PHINode instrumentation in ignorelisted functions
853 define i32 @NoSanitizeMemoryPHI(i32 %x) {
855 %tobool = icmp ne i32 %x, 0
856 br i1 %tobool, label %cond.true, label %cond.false
858 cond.true: ; preds = %entry
861 cond.false: ; preds = %entry
864 cond.end: ; preds = %cond.false, %cond.true
865 %cond = phi i32 [ undef, %cond.true ], [ undef, %cond.false ]
869 ; CHECK: [[A:%.*]] = phi i32 [ undef, %cond.true ], [ undef, %cond.false ]
870 ; CHECK: store i32 0, ptr @__msan_retval_tls
871 ; CHECK: ret i32 [[A]]
874 ; Test that there are no __msan_param_origin_tls stores when
875 ; argument shadow is a compile-time zero constant (which is always the case
876 ; in functions missing sanitize_memory attribute).
878 define i32 @NoSanitizeMemoryParamTLS(ptr nocapture readonly %x) {
880 %0 = load i32, ptr %x, align 4
881 %call = tail call i32 @NoSanitizeMemoryParamTLSHelper(i32 %0)
885 declare i32 @NoSanitizeMemoryParamTLSHelper(i32 %x)
887 ; CHECK-LABEL: define i32 @NoSanitizeMemoryParamTLS(
888 ; CHECK-NOT: __msan_param_origin_tls
892 ; Test argument shadow alignment
894 define <2 x i64> @ArgumentShadowAlignment(i64 %a, <2 x i64> %b) sanitize_memory {
899 ; CHECK-LABEL: @ArgumentShadowAlignment
900 ; CHECK: load <2 x i64>, ptr {{.*}} @__msan_param_tls {{.*}}, align 8
901 ; CHECK: store <2 x i64> {{.*}}, ptr @__msan_retval_tls, align 8
902 ; CHECK: ret <2 x i64>
905 ; Test origin propagation for insertvalue
907 define { i64, i32 } @make_pair_64_32(i64 %x, i32 %y) sanitize_memory {
909 %a = insertvalue { i64, i32 } undef, i64 %x, 0
910 %b = insertvalue { i64, i32 } %a, i32 %y, 1
914 ; ORIGINS: @make_pair_64_32
915 ; First element shadow
916 ; ORIGINS: insertvalue { i64, i32 } { i64 -1, i32 -1 }, i64 {{.*}}, 0
917 ; First element origin
918 ; ORIGINS: icmp ne i64
920 ; First element app value
921 ; ORIGINS: insertvalue { i64, i32 } undef, i64 {{.*}}, 0
922 ; Second element shadow
923 ; ORIGINS: insertvalue { i64, i32 } {{.*}}, i32 {{.*}}, 1
924 ; Second element origin
925 ; ORIGINS: icmp ne i32
927 ; Second element app value
928 ; ORIGINS: insertvalue { i64, i32 } {{.*}}, i32 {{.*}}, 1
929 ; ORIGINS: ret { i64, i32 }
932 ; Test shadow propagation for aggregates passed through ellipsis.
934 %struct.StructByVal = type { i32, i32, i32, i32 }
936 declare void @VAArgStructFn(i32 %guard, ...)
938 define void @VAArgStruct(ptr nocapture %s) sanitize_memory {
940 %agg.tmp2 = alloca %struct.StructByVal, align 8
941 %agg.tmp.sroa.0.0.copyload = load i64, ptr %s, align 4
942 %agg.tmp.sroa.2.0..sroa_idx = getelementptr inbounds %struct.StructByVal, ptr %s, i64 0, i32 2
943 %agg.tmp.sroa.2.0.copyload = load i64, ptr %agg.tmp.sroa.2.0..sroa_idx, align 4
944 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp2, ptr align 4 %s, i64 16, i1 false)
945 call void (i32, ...) @VAArgStructFn(i32 undef, i64 %agg.tmp.sroa.0.0.copyload, i64 %agg.tmp.sroa.2.0.copyload, i64 %agg.tmp.sroa.0.0.copyload, i64 %agg.tmp.sroa.2.0.copyload, ptr byval(%struct.StructByVal) align 8 %agg.tmp2)
949 ; "undef" and the first 2 structs go to general purpose registers;
950 ; the third struct goes to the overflow area byval
952 ; CHECK-LABEL: @VAArgStruct
953 ; undef not stored to __msan_va_arg_tls - it's a fixed argument
954 ; first struct through general purpose registers
955 ; CHECK: store i64 {{.*}}, ptr {{.*}}@__msan_va_arg_tls{{.*}}, i64 8){{.*}}, align 8
956 ; CHECK: store i64 {{.*}}, ptr {{.*}}@__msan_va_arg_tls{{.*}}, i64 16){{.*}}, align 8
957 ; second struct through general purpose registers
958 ; CHECK: store i64 {{.*}}, ptr {{.*}}@__msan_va_arg_tls{{.*}}, i64 24){{.*}}, align 8
959 ; CHECK: store i64 {{.*}}, ptr {{.*}}@__msan_va_arg_tls{{.*}}, i64 32){{.*}}, align 8
960 ; third struct through the overflow area byval
961 ; CHECK: ptrtoint ptr {{.*}} to i64
962 ; CHECK: call void @llvm.memcpy.p0.p0.i64{{.*}}@__msan_va_arg_tls {{.*}}, i64 176
963 ; CHECK: store i64 16, ptr @__msan_va_arg_overflow_size_tls
964 ; CHECK: call void (i32, ...) @VAArgStructFn
967 ; Same code compiled without SSE (see attributes below).
968 ; The register save area is only 48 bytes instead of 176.
969 define void @VAArgStructNoSSE(ptr nocapture %s) sanitize_memory #0 {
971 %agg.tmp2 = alloca %struct.StructByVal, align 8
972 %agg.tmp.sroa.0.0.copyload = load i64, ptr %s, align 4
973 %agg.tmp.sroa.2.0..sroa_idx = getelementptr inbounds %struct.StructByVal, ptr %s, i64 0, i32 2
974 %agg.tmp.sroa.2.0.copyload = load i64, ptr %agg.tmp.sroa.2.0..sroa_idx, align 4
975 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp2, ptr align 4 %s, i64 16, i1 false)
976 call void (i32, ...) @VAArgStructFn(i32 undef, i64 %agg.tmp.sroa.0.0.copyload, i64 %agg.tmp.sroa.2.0.copyload, i64 %agg.tmp.sroa.0.0.copyload, i64 %agg.tmp.sroa.2.0.copyload, ptr byval(%struct.StructByVal) align 8 %agg.tmp2)
980 attributes #0 = { "target-features"="+fxsr,+x87,-sse" }
982 ; CHECK: call void @llvm.memcpy.p0.p0.i64{{.*}}@__msan_va_arg_tls {{.*}}, i64 48
984 declare i32 @InnerTailCall(i32 %a)
986 define void @MismatchedReturnTypeTailCall(i32 %a) sanitize_memory {
987 %b = tail call i32 @InnerTailCall(i32 %a)
991 ; We used to strip off the 'tail' modifier, but now that we unpoison return slot
992 ; shadow before the call, we don't need to anymore.
994 ; CHECK-LABEL: define void @MismatchedReturnTypeTailCall
995 ; CHECK: tail call i32 @InnerTailCall
999 declare i32 @MustTailCall(i32 %a)
1001 define i32 @CallMustTailCall(i32 %a) sanitize_memory {
1002 %b = musttail call i32 @MustTailCall(i32 %a)
1006 ; For "musttail" calls we can not insert any shadow manipulating code between
1007 ; call and the return instruction. And we don't need to, because everything is
1008 ; taken care of in the callee.
1010 ; CHECK-LABEL: define i32 @CallMustTailCall
1011 ; CHECK: musttail call i32 @MustTailCall
1012 ; No instrumentation between call and ret.
1013 ; CHECK-NEXT: ret i32
1015 declare ptr @MismatchingMustTailCall(i32 %a)
1017 define ptr @MismatchingCallMustTailCall(i32 %a) sanitize_memory {
1018 %b = musttail call ptr @MismatchingMustTailCall(i32 %a)
1022 ; For "musttail" calls we can not insert any shadow manipulating code between
1023 ; call and the return instruction. And we don't need to, because everything is
1024 ; taken care of in the callee.
1026 ; CHECK-LABEL: define ptr @MismatchingCallMustTailCall
1027 ; CHECK: musttail call ptr @MismatchingMustTailCall
1028 ; No instrumentation between call and ret.
1029 ; CHECK-NEXT: ret ptr
1032 ; CHECK-LABEL: define internal void @msan.module_ctor() #[[#ATTR:]] {
1033 ; CHECK: call void @__msan_init()
1035 ; CHECK-CALLS: declare void @__msan_maybe_warning_1(i8, i32)
1036 ; CHECK-CALLS: declare void @__msan_maybe_store_origin_1(i8, ptr, i32)
1037 ; CHECK-CALLS: declare void @__msan_maybe_warning_2(i16, i32)
1038 ; CHECK-CALLS: declare void @__msan_maybe_store_origin_2(i16, ptr, i32)
1039 ; CHECK-CALLS: declare void @__msan_maybe_warning_4(i32, i32)
1040 ; CHECK-CALLS: declare void @__msan_maybe_store_origin_4(i32, ptr, i32)
1041 ; CHECK-CALLS: declare void @__msan_maybe_warning_8(i64, i32)
1042 ; CHECK-CALLS: declare void @__msan_maybe_store_origin_8(i64, ptr, i32)
1044 ; CHECK: attributes #[[#ATTR]] = { nounwind }