mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 13:11:39 +01:00
[msan] Implement sanitize_memory attribute.
Shadow checks are disabled and memory loads always produce fully initialized values in functions that don't have a sanitize_memory attribute. Value and argument shadow is propagated as usual. This change also updates blacklist behaviour to match the above. llvm-svn: 176247
This commit is contained in:
parent
86c3e15702
commit
caac73e5ea
@ -418,6 +418,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
||||
SmallVector<PHINode *, 16> ShadowPHINodes, OriginPHINodes;
|
||||
ValueMap<Value*, Value*> ShadowMap, OriginMap;
|
||||
bool InsertChecks;
|
||||
bool LoadShadow;
|
||||
OwningPtr<VarArgHelper> VAHelper;
|
||||
|
||||
struct ShadowOriginAndInsertPoint {
|
||||
@ -432,11 +433,15 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
||||
SmallVector<Instruction*, 16> StoreList;
|
||||
|
||||
MemorySanitizerVisitor(Function &F, MemorySanitizer &MS)
|
||||
: F(F), MS(MS), VAHelper(CreateVarArgHelper(F, MS, *this)) {
|
||||
InsertChecks = !MS.BL->isIn(F);
|
||||
: F(F), MS(MS), VAHelper(CreateVarArgHelper(F, MS, *this)) {
|
||||
LoadShadow = InsertChecks =
|
||||
!MS.BL->isIn(F) &&
|
||||
F.getAttributes().hasAttribute(AttributeSet::FunctionIndex,
|
||||
Attribute::SanitizeMemory);
|
||||
|
||||
DEBUG(if (!InsertChecks)
|
||||
dbgs() << "MemorySanitizer is not inserting checks into '"
|
||||
<< F.getName() << "'\n");
|
||||
dbgs() << "MemorySanitizer is not inserting checks into '"
|
||||
<< F.getName() << "'\n");
|
||||
}
|
||||
|
||||
void materializeStores() {
|
||||
@ -831,15 +836,25 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
||||
IRBuilder<> IRB(&I);
|
||||
Type *ShadowTy = getShadowTy(&I);
|
||||
Value *Addr = I.getPointerOperand();
|
||||
Value *ShadowPtr = getShadowPtr(Addr, ShadowTy, IRB);
|
||||
setShadow(&I, IRB.CreateAlignedLoad(ShadowPtr, I.getAlignment(), "_msld"));
|
||||
if (LoadShadow) {
|
||||
Value *ShadowPtr = getShadowPtr(Addr, ShadowTy, IRB);
|
||||
setShadow(&I,
|
||||
IRB.CreateAlignedLoad(ShadowPtr, I.getAlignment(), "_msld"));
|
||||
} else {
|
||||
setShadow(&I, getCleanShadow(&I));
|
||||
}
|
||||
|
||||
if (ClCheckAccessAddress)
|
||||
insertCheck(I.getPointerOperand(), &I);
|
||||
|
||||
if (MS.TrackOrigins) {
|
||||
unsigned Alignment = std::max(kMinOriginAlignment, I.getAlignment());
|
||||
setOrigin(&I, IRB.CreateAlignedLoad(getOriginPtr(Addr, IRB), Alignment));
|
||||
if (LoadShadow) {
|
||||
unsigned Alignment = std::max(kMinOriginAlignment, I.getAlignment());
|
||||
setOrigin(&I,
|
||||
IRB.CreateAlignedLoad(getOriginPtr(Addr, IRB), Alignment));
|
||||
} else {
|
||||
setOrigin(&I, getCleanOrigin());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1405,16 +1420,25 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
||||
Value *Addr = I.getArgOperand(0);
|
||||
|
||||
Type *ShadowTy = getShadowTy(&I);
|
||||
Value *ShadowPtr = getShadowPtr(Addr, ShadowTy, IRB);
|
||||
// We don't know the pointer alignment (could be unaligned SSE load!).
|
||||
// Have to assume to worst case.
|
||||
setShadow(&I, IRB.CreateAlignedLoad(ShadowPtr, 1, "_msld"));
|
||||
if (LoadShadow) {
|
||||
Value *ShadowPtr = getShadowPtr(Addr, ShadowTy, IRB);
|
||||
// We don't know the pointer alignment (could be unaligned SSE load!).
|
||||
// Have to assume to worst case.
|
||||
setShadow(&I, IRB.CreateAlignedLoad(ShadowPtr, 1, "_msld"));
|
||||
} else {
|
||||
setShadow(&I, getCleanShadow(&I));
|
||||
}
|
||||
|
||||
|
||||
if (ClCheckAccessAddress)
|
||||
insertCheck(Addr, &I);
|
||||
|
||||
if (MS.TrackOrigins)
|
||||
setOrigin(&I, IRB.CreateLoad(getOriginPtr(Addr, IRB)));
|
||||
if (MS.TrackOrigins) {
|
||||
if (LoadShadow)
|
||||
setOrigin(&I, IRB.CreateLoad(getOriginPtr(Addr, IRB)));
|
||||
else
|
||||
setOrigin(&I, getCleanOrigin());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3
|
||||
|
||||
; Check instrumentation of stores
|
||||
|
||||
define void @Store(i32* nocapture %p, i32 %x) nounwind uwtable {
|
||||
define void @Store(i32* nocapture %p, i32 %x) nounwind uwtable sanitize_memory {
|
||||
entry:
|
||||
store i32 %x, i32* %p, align 4
|
||||
ret void
|
||||
@ -39,7 +39,7 @@ entry:
|
||||
; Shadow store has the same alignment as the original store; origin store
|
||||
; does not specify explicit alignment.
|
||||
|
||||
define void @AlignedStore(i32* nocapture %p, i32 %x) nounwind uwtable {
|
||||
define void @AlignedStore(i32* nocapture %p, i32 %x) nounwind uwtable sanitize_memory {
|
||||
entry:
|
||||
store i32 %x, i32* %p, align 32
|
||||
ret void
|
||||
@ -64,7 +64,7 @@ entry:
|
||||
|
||||
|
||||
; load followed by cmp: check that we load the shadow and call __msan_warning.
|
||||
define void @LoadAndCmp(i32* nocapture %a) nounwind uwtable {
|
||||
define void @LoadAndCmp(i32* nocapture %a) nounwind uwtable sanitize_memory {
|
||||
entry:
|
||||
%0 = load i32* %a, align 4
|
||||
%tobool = icmp eq i32 %0, 0
|
||||
@ -89,7 +89,7 @@ declare void @foo(...)
|
||||
; CHECK: ret void
|
||||
|
||||
; Check that we store the shadow for the retval.
|
||||
define i32 @ReturnInt() nounwind uwtable readnone {
|
||||
define i32 @ReturnInt() nounwind uwtable readnone sanitize_memory {
|
||||
entry:
|
||||
ret i32 123
|
||||
}
|
||||
@ -99,7 +99,7 @@ entry:
|
||||
; CHECK: ret i32
|
||||
|
||||
; Check that we get the shadow for the retval.
|
||||
define void @CopyRetVal(i32* nocapture %a) nounwind uwtable {
|
||||
define void @CopyRetVal(i32* nocapture %a) nounwind uwtable sanitize_memory {
|
||||
entry:
|
||||
%call = tail call i32 @ReturnInt() nounwind
|
||||
store i32 %call, i32* %a, align 4
|
||||
@ -114,7 +114,7 @@ entry:
|
||||
|
||||
|
||||
; Check that we generate PHIs for shadow.
|
||||
define void @FuncWithPhi(i32* nocapture %a, i32* %b, i32* nocapture %c) nounwind uwtable {
|
||||
define void @FuncWithPhi(i32* nocapture %a, i32* %b, i32* nocapture %c) nounwind uwtable sanitize_memory {
|
||||
entry:
|
||||
%tobool = icmp eq i32* %b, null
|
||||
br i1 %tobool, label %if.else, label %if.then
|
||||
@ -141,7 +141,7 @@ entry:
|
||||
; CHECK: ret void
|
||||
|
||||
; Compute shadow for "x << 10"
|
||||
define void @ShlConst(i32* nocapture %x) nounwind uwtable {
|
||||
define void @ShlConst(i32* nocapture %x) nounwind uwtable sanitize_memory {
|
||||
entry:
|
||||
%0 = load i32* %x, align 4
|
||||
%1 = shl i32 %0, 10
|
||||
@ -159,7 +159,7 @@ entry:
|
||||
; CHECK: ret void
|
||||
|
||||
; Compute shadow for "10 << x": it should have 'sext i1'.
|
||||
define void @ShlNonConst(i32* nocapture %x) nounwind uwtable {
|
||||
define void @ShlNonConst(i32* nocapture %x) nounwind uwtable sanitize_memory {
|
||||
entry:
|
||||
%0 = load i32* %x, align 4
|
||||
%1 = shl i32 10, %0
|
||||
@ -176,7 +176,7 @@ entry:
|
||||
; CHECK: ret void
|
||||
|
||||
; SExt
|
||||
define void @SExt(i32* nocapture %a, i16* nocapture %b) nounwind uwtable {
|
||||
define void @SExt(i32* nocapture %a, i16* nocapture %b) nounwind uwtable sanitize_memory {
|
||||
entry:
|
||||
%0 = load i16* %b, align 2
|
||||
%1 = sext i16 %0 to i32
|
||||
@ -195,7 +195,7 @@ entry:
|
||||
|
||||
|
||||
; memset
|
||||
define void @MemSet(i8* nocapture %x) nounwind uwtable {
|
||||
define void @MemSet(i8* nocapture %x) nounwind uwtable sanitize_memory {
|
||||
entry:
|
||||
call void @llvm.memset.p0i8.i64(i8* %x, i8 42, i64 10, i32 1, i1 false)
|
||||
ret void
|
||||
@ -209,7 +209,7 @@ declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
|
||||
|
||||
|
||||
; memcpy
|
||||
define void @MemCpy(i8* nocapture %x, i8* nocapture %y) nounwind uwtable {
|
||||
define void @MemCpy(i8* nocapture %x, i8* nocapture %y) nounwind uwtable sanitize_memory {
|
||||
entry:
|
||||
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %x, i8* %y, i64 10, i32 1, i1 false)
|
||||
ret void
|
||||
@ -223,7 +223,7 @@ declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32,
|
||||
|
||||
|
||||
; memmove is lowered to a call
|
||||
define void @MemMove(i8* nocapture %x, i8* nocapture %y) nounwind uwtable {
|
||||
define void @MemMove(i8* nocapture %x, i8* nocapture %y) nounwind uwtable sanitize_memory {
|
||||
entry:
|
||||
call void @llvm.memmove.p0i8.p0i8.i64(i8* %x, i8* %y, i64 10, i32 1, i1 false)
|
||||
ret void
|
||||
@ -238,7 +238,7 @@ declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32,
|
||||
|
||||
; Check that we propagate shadow for "select"
|
||||
|
||||
define i32 @Select(i32 %a, i32 %b, i32 %c) nounwind uwtable readnone {
|
||||
define i32 @Select(i32 %a, i32 %b, i32 %c) nounwind uwtable readnone sanitize_memory {
|
||||
entry:
|
||||
%tobool = icmp ne i32 %c, 0
|
||||
%cond = select i1 %tobool, i32 %a, i32 %b
|
||||
@ -255,7 +255,7 @@ entry:
|
||||
; Select condition is flattened to i1, which is then used to select one of the
|
||||
; argument origins.
|
||||
|
||||
define <8 x i16> @SelectVector(<8 x i16> %a, <8 x i16> %b, <8 x i1> %c) nounwind uwtable readnone {
|
||||
define <8 x i16> @SelectVector(<8 x i16> %a, <8 x i16> %b, <8 x i1> %c) nounwind uwtable readnone sanitize_memory {
|
||||
entry:
|
||||
%cond = select <8 x i1> %c, <8 x i16> %a, <8 x i16> %b
|
||||
ret <8 x i16> %cond
|
||||
@ -268,7 +268,7 @@ entry:
|
||||
; CHECK-ORIGINS: ret <8 x i16>
|
||||
|
||||
|
||||
define i8* @IntToPtr(i64 %x) nounwind uwtable readnone {
|
||||
define i8* @IntToPtr(i64 %x) nounwind uwtable readnone sanitize_memory {
|
||||
entry:
|
||||
%0 = inttoptr i64 %x to i8*
|
||||
ret i8* %0
|
||||
@ -281,7 +281,7 @@ entry:
|
||||
; CHECK: ret i8
|
||||
|
||||
|
||||
define i8* @IntToPtr_ZExt(i16 %x) nounwind uwtable readnone {
|
||||
define i8* @IntToPtr_ZExt(i16 %x) nounwind uwtable readnone sanitize_memory {
|
||||
entry:
|
||||
%0 = inttoptr i16 %x to i8*
|
||||
ret i8* %0
|
||||
@ -296,7 +296,7 @@ entry:
|
||||
; Check that we insert exactly one check on udiv
|
||||
; (2nd arg shadow is checked, 1st arg shadow is propagated)
|
||||
|
||||
define i32 @Div(i32 %a, i32 %b) nounwind uwtable readnone {
|
||||
define i32 @Div(i32 %a, i32 %b) nounwind uwtable readnone sanitize_memory {
|
||||
entry:
|
||||
%div = udiv i32 %a, %b
|
||||
ret i32 %div
|
||||
@ -313,7 +313,7 @@ entry:
|
||||
|
||||
; Check that we propagate shadow for x<0, x>=0, etc (i.e. sign bit tests)
|
||||
|
||||
define zeroext i1 @ICmpSLT(i32 %x) nounwind uwtable readnone {
|
||||
define zeroext i1 @ICmpSLT(i32 %x) nounwind uwtable readnone sanitize_memory {
|
||||
%1 = icmp slt i32 %x, 0
|
||||
ret i1 %1
|
||||
}
|
||||
@ -325,7 +325,7 @@ define zeroext i1 @ICmpSLT(i32 %x) nounwind uwtable readnone {
|
||||
; CHECK-NOT: call void @__msan_warning
|
||||
; CHECK: ret i1
|
||||
|
||||
define zeroext i1 @ICmpSGE(i32 %x) nounwind uwtable readnone {
|
||||
define zeroext i1 @ICmpSGE(i32 %x) nounwind uwtable readnone sanitize_memory {
|
||||
%1 = icmp sge i32 %x, 0
|
||||
ret i1 %1
|
||||
}
|
||||
@ -337,7 +337,7 @@ define zeroext i1 @ICmpSGE(i32 %x) nounwind uwtable readnone {
|
||||
; CHECK-NOT: call void @__msan_warning
|
||||
; CHECK: ret i1
|
||||
|
||||
define zeroext i1 @ICmpSGT(i32 %x) nounwind uwtable readnone {
|
||||
define zeroext i1 @ICmpSGT(i32 %x) nounwind uwtable readnone sanitize_memory {
|
||||
%1 = icmp sgt i32 0, %x
|
||||
ret i1 %1
|
||||
}
|
||||
@ -349,7 +349,7 @@ define zeroext i1 @ICmpSGT(i32 %x) nounwind uwtable readnone {
|
||||
; CHECK-NOT: call void @__msan_warning
|
||||
; CHECK: ret i1
|
||||
|
||||
define zeroext i1 @ICmpSLE(i32 %x) nounwind uwtable readnone {
|
||||
define zeroext i1 @ICmpSLE(i32 %x) nounwind uwtable readnone sanitize_memory {
|
||||
%1 = icmp sle i32 0, %x
|
||||
ret i1 %1
|
||||
}
|
||||
@ -365,7 +365,7 @@ define zeroext i1 @ICmpSLE(i32 %x) nounwind uwtable readnone {
|
||||
; Check that we propagate shadow for x<0, x>=0, etc (i.e. sign bit tests)
|
||||
; of the vector arguments.
|
||||
|
||||
define <2 x i1> @ICmpSLT_vector(<2 x i32*> %x) nounwind uwtable readnone {
|
||||
define <2 x i1> @ICmpSLT_vector(<2 x i32*> %x) nounwind uwtable readnone sanitize_memory {
|
||||
%1 = icmp slt <2 x i32*> %x, zeroinitializer
|
||||
ret <2 x i1> %1
|
||||
}
|
||||
@ -381,7 +381,7 @@ define <2 x i1> @ICmpSLT_vector(<2 x i32*> %x) nounwind uwtable readnone {
|
||||
; Check that we propagate shadow for unsigned relational comparisons with
|
||||
; constants
|
||||
|
||||
define zeroext i1 @ICmpUGTConst(i32 %x) nounwind uwtable readnone {
|
||||
define zeroext i1 @ICmpUGTConst(i32 %x) nounwind uwtable readnone sanitize_memory {
|
||||
entry:
|
||||
%cmp = icmp ugt i32 %x, 7
|
||||
ret i1 %cmp
|
||||
@ -400,7 +400,7 @@ entry:
|
||||
; Check that loads of shadow have the same aligment as the original loads.
|
||||
; Check that loads of origin have the aligment of max(4, original alignment).
|
||||
|
||||
define i32 @ShadowLoadAlignmentLarge() nounwind uwtable {
|
||||
define i32 @ShadowLoadAlignmentLarge() nounwind uwtable sanitize_memory {
|
||||
%y = alloca i32, align 64
|
||||
%1 = load volatile i32* %y, align 64
|
||||
ret i32 %1
|
||||
@ -411,7 +411,7 @@ define i32 @ShadowLoadAlignmentLarge() nounwind uwtable {
|
||||
; CHECK: load volatile i32* {{.*}} align 64
|
||||
; CHECK: ret i32
|
||||
|
||||
define i32 @ShadowLoadAlignmentSmall() nounwind uwtable {
|
||||
define i32 @ShadowLoadAlignmentSmall() nounwind uwtable sanitize_memory {
|
||||
%y = alloca i32, align 2
|
||||
%1 = load volatile i32* %y, align 2
|
||||
ret i32 %1
|
||||
@ -433,7 +433,7 @@ define i32 @ShadowLoadAlignmentSmall() nounwind uwtable {
|
||||
; Check that the same bit manipulation is applied to the shadow values.
|
||||
; Check that there is a zero test of the shadow of %idx argument, where present.
|
||||
|
||||
define i32 @ExtractElement(<4 x i32> %vec, i32 %idx) {
|
||||
define i32 @ExtractElement(<4 x i32> %vec, i32 %idx) sanitize_memory {
|
||||
%x = extractelement <4 x i32> %vec, i32 %idx
|
||||
ret i32 %x
|
||||
}
|
||||
@ -444,7 +444,7 @@ define i32 @ExtractElement(<4 x i32> %vec, i32 %idx) {
|
||||
; CHECK: extractelement
|
||||
; CHECK: ret i32
|
||||
|
||||
define <4 x i32> @InsertElement(<4 x i32> %vec, i32 %idx, i32 %x) {
|
||||
define <4 x i32> @InsertElement(<4 x i32> %vec, i32 %idx, i32 %x) sanitize_memory {
|
||||
%vec1 = insertelement <4 x i32> %vec, i32 %x, i32 %idx
|
||||
ret <4 x i32> %vec1
|
||||
}
|
||||
@ -455,7 +455,7 @@ define <4 x i32> @InsertElement(<4 x i32> %vec, i32 %idx, i32 %x) {
|
||||
; CHECK: insertelement
|
||||
; CHECK: ret <4 x i32>
|
||||
|
||||
define <4 x i32> @ShuffleVector(<4 x i32> %vec, <4 x i32> %vec1) {
|
||||
define <4 x i32> @ShuffleVector(<4 x i32> %vec, <4 x i32> %vec1) sanitize_memory {
|
||||
%vec2 = shufflevector <4 x i32> %vec, <4 x i32> %vec1,
|
||||
<4 x i32> <i32 0, i32 4, i32 1, i32 5>
|
||||
ret <4 x i32> %vec2
|
||||
@ -469,7 +469,7 @@ define <4 x i32> @ShuffleVector(<4 x i32> %vec, <4 x i32> %vec1) {
|
||||
|
||||
|
||||
; Test bswap intrinsic instrumentation
|
||||
define i32 @BSwap(i32 %x) nounwind uwtable readnone {
|
||||
define i32 @BSwap(i32 %x) nounwind uwtable readnone sanitize_memory {
|
||||
%y = tail call i32 @llvm.bswap.i32(i32 %x)
|
||||
ret i32 %y
|
||||
}
|
||||
@ -487,7 +487,7 @@ declare i32 @llvm.bswap.i32(i32) nounwind readnone
|
||||
|
||||
; Store intrinsic.
|
||||
|
||||
define void @StoreIntrinsic(i8* %p, <4 x float> %x) nounwind uwtable {
|
||||
define void @StoreIntrinsic(i8* %p, <4 x float> %x) nounwind uwtable sanitize_memory {
|
||||
call void @llvm.x86.sse.storeu.ps(i8* %p, <4 x float> %x)
|
||||
ret void
|
||||
}
|
||||
@ -504,7 +504,7 @@ declare void @llvm.x86.sse.storeu.ps(i8*, <4 x float>) nounwind
|
||||
|
||||
; Load intrinsic.
|
||||
|
||||
define <16 x i8> @LoadIntrinsic(i8* %p) nounwind uwtable {
|
||||
define <16 x i8> @LoadIntrinsic(i8* %p) nounwind uwtable sanitize_memory {
|
||||
%call = call <16 x i8> @llvm.x86.sse3.ldu.dq(i8* %p)
|
||||
ret <16 x i8> %call
|
||||
}
|
||||
@ -530,7 +530,7 @@ declare <16 x i8> @llvm.x86.sse3.ldu.dq(i8* %p) nounwind
|
||||
; Check that shadow is OR'ed, and origin is Select'ed
|
||||
; And no shadow checks!
|
||||
|
||||
define <8 x i16> @Paddsw128(<8 x i16> %a, <8 x i16> %b) nounwind uwtable {
|
||||
define <8 x i16> @Paddsw128(<8 x i16> %a, <8 x i16> %b) nounwind uwtable sanitize_memory {
|
||||
%call = call <8 x i16> @llvm.x86.sse2.padds.w(<8 x i16> %a, <8 x i16> %b)
|
||||
ret <8 x i16> %call
|
||||
}
|
||||
@ -559,7 +559,7 @@ declare <8 x i16> @llvm.x86.sse2.padds.w(<8 x i16> %a, <8 x i16> %b) nounwind
|
||||
; Test handling of vectors of pointers.
|
||||
; Check that shadow of such vector is a vector of integers.
|
||||
|
||||
define <8 x i8*> @VectorOfPointers(<8 x i8*>* %p) nounwind uwtable {
|
||||
define <8 x i8*> @VectorOfPointers(<8 x i8*>* %p) nounwind uwtable sanitize_memory {
|
||||
%x = load <8 x i8*>* %p
|
||||
ret <8 x i8*> %x
|
||||
}
|
||||
@ -574,7 +574,7 @@ define <8 x i8*> @VectorOfPointers(<8 x i8*>* %p) nounwind uwtable {
|
||||
|
||||
declare void @llvm.va_copy(i8*, i8*) nounwind
|
||||
|
||||
define void @VACopy(i8* %p1, i8* %p2) nounwind uwtable {
|
||||
define void @VACopy(i8* %p1, i8* %p2) nounwind uwtable sanitize_memory {
|
||||
call void @llvm.va_copy(i8* %p1, i8* %p2) nounwind
|
||||
ret void
|
||||
}
|
||||
@ -587,7 +587,7 @@ define void @VACopy(i8* %p1, i8* %p2) nounwind uwtable {
|
||||
; Test handling of volatile stores.
|
||||
; Check that MemorySanitizer does not add a check of the value being stored.
|
||||
|
||||
define void @VolatileStore(i32* nocapture %p, i32 %x) nounwind uwtable {
|
||||
define void @VolatileStore(i32* nocapture %p, i32 %x) nounwind uwtable sanitize_memory {
|
||||
entry:
|
||||
store volatile i32 %x, i32* %p, align 4
|
||||
ret void
|
||||
@ -596,3 +596,30 @@ entry:
|
||||
; CHECK: @VolatileStore
|
||||
; CHECK-NOT: @__msan_warning
|
||||
; CHECK: ret void
|
||||
|
||||
|
||||
; Test that checks are omitted but shadow propagation is kept if
|
||||
; sanitize_memory attribute is missing.
|
||||
|
||||
define i32 @NoSanitizeMemory(i32 %x) uwtable {
|
||||
entry:
|
||||
%tobool = icmp eq i32 %x, 0
|
||||
br i1 %tobool, label %if.end, label %if.then
|
||||
|
||||
if.then: ; preds = %entry
|
||||
tail call void @bar()
|
||||
br label %if.end
|
||||
|
||||
if.end: ; preds = %entry, %if.then
|
||||
ret i32 %x
|
||||
}
|
||||
|
||||
declare void @bar()
|
||||
|
||||
; CHECK: @NoSanitizeMemory
|
||||
; CHECK-NOT: @__msan_warning
|
||||
; CHECK: load i32* {{.*}} @__msan_param_tls
|
||||
; CHECK-NOT: @__msan_warning
|
||||
; CHECK: store {{.*}} @__msan_retval_tls
|
||||
; CHECK-NOT: @__msan_warning
|
||||
; CHECK: ret i32
|
||||
|
Loading…
x
Reference in New Issue
Block a user