From: Evgeniy Stepanov Date: Fri, 14 Aug 2015 22:03:50 +0000 (+0000) Subject: [msan] Fix handling of musttail calls. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=fa995560c20aa25436340d7bd3bce2a818dd9314;p=oota-llvm.git [msan] Fix handling of musttail calls. MSan instrumentation for return values of musttail calls is not allowed by the IR constraints, and not needed at the same time. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@245106 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/lib/Transforms/Instrumentation/MemorySanitizer.cpp index 226876d407c..46593ca7233 100644 --- a/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -1339,6 +1339,12 @@ struct MemorySanitizerVisitor : public InstVisitor { } void visitBitCastInst(BitCastInst &I) { + // Special case: if this is the bitcast (there is exactly 1 allowed) between + // a musttail call and a ret, don't instrument. New instructions are not + // allowed after a musttail call. + if (auto *CI = dyn_cast(I.getOperand(0))) + if (CI->isMustTailCall()) + return; IRBuilder<> IRB(&I); setShadow(&I, IRB.CreateBitCast(getShadow(&I, 0), getShadowTy(&I))); setOrigin(&I, getOrigin(&I, 0)); @@ -2493,6 +2499,8 @@ struct MemorySanitizerVisitor : public InstVisitor { // Now, get the shadow for the RetVal. if (!I.getType()->isSized()) return; + // Don't emit the epilogue for musttail call returns. + if (CS.isCall() && cast(&I)->isMustTailCall()) return; IRBuilder<> IRBBefore(&I); // Until we have full dynamic coverage, make sure the retval shadow is 0. Value *Base = getShadowPtrForRetval(&I, IRBBefore); @@ -2523,10 +2531,22 @@ struct MemorySanitizerVisitor : public InstVisitor { setOrigin(&I, IRBAfter.CreateLoad(getOriginPtrForRetval(IRBAfter))); } + bool isAMustTailRetVal(Value *RetVal) { + if (auto *I = dyn_cast(RetVal)) { + RetVal = I->getOperand(0); + } + if (auto *I = dyn_cast(RetVal)) { + return I->isMustTailCall(); + } + return false; + } + void visitReturnInst(ReturnInst &I) { IRBuilder<> IRB(&I); Value *RetVal = I.getReturnValue(); if (!RetVal) return; + // Don't emit the epilogue for musttail call returns. + if (isAMustTailRetVal(RetVal)) return; Value *ShadowPtr = getShadowPtrForRetval(RetVal, IRB); if (CheckReturnValue) { insertShadowCheck(RetVal, &I); diff --git a/test/Instrumentation/MemorySanitizer/msan_basic.ll b/test/Instrumentation/MemorySanitizer/msan_basic.ll index 8b8e2970959..73e2c7ac120 100644 --- a/test/Instrumentation/MemorySanitizer/msan_basic.ll +++ b/test/Instrumentation/MemorySanitizer/msan_basic.ll @@ -864,6 +864,7 @@ entry: ; CHECK: call void (i32, ...) @VAArgStructFn ; CHECK: ret void + declare i32 @InnerTailCall(i32 %a) define void @MismatchedReturnTypeTailCall(i32 %a) sanitize_memory { @@ -878,5 +879,41 @@ define void @MismatchedReturnTypeTailCall(i32 %a) sanitize_memory { ; CHECK: tail call i32 @InnerTailCall ; CHECK: ret void + +declare i32 @MustTailCall(i32 %a) + +define i32 @CallMustTailCall(i32 %a) sanitize_memory { + %b = musttail call i32 @MustTailCall(i32 %a) + ret i32 %b +} + +; For "musttail" calls we can not insert any shadow manipulating code between +; call and the return instruction. And we don't need to, because everything is +; taken care of in the callee. + +; CHECK-LABEL: define i32 @CallMustTailCall +; CHECK: musttail call i32 @MustTailCall +; No instrumentation between call and ret. +; CHECK-NEXT: ret i32 + +declare i32* @MismatchingMustTailCall(i32 %a) + +define i8* @MismatchingCallMustTailCall(i32 %a) sanitize_memory { + %b = musttail call i32* @MismatchingMustTailCall(i32 %a) + %c = bitcast i32* %b to i8* + ret i8* %c +} + +; For "musttail" calls we can not insert any shadow manipulating code between +; call and the return instruction. And we don't need to, because everything is +; taken care of in the callee. + +; CHECK-LABEL: define i8* @MismatchingCallMustTailCall +; CHECK: musttail call i32* @MismatchingMustTailCall +; No instrumentation between call and ret. +; CHECK-NEXT: bitcast i32* {{.*}} to i8* +; CHECK-NEXT: ret i8* + + ; CHECK-LABEL: define internal void @msan.module_ctor ; CHECK: call void @__msan_init()