StephenFan updated this revision to Diff 445420. StephenFan added a comment. Herald added a project: LLVM. Herald added a subscriber: llvm-commits.
1. Rebase. 2. Add a test case of goto_bypass. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D129448/new/ https://reviews.llvm.org/D129448 Files: clang/lib/CodeGen/CGDecl.cpp clang/lib/CodeGen/CGStmt.cpp clang/lib/CodeGen/CodeGenFunction.cpp clang/lib/CodeGen/CodeGenFunction.h clang/test/CodeGen/lifetime2.c llvm/test/Instrumentation/MemorySanitizer/alloca.ll
Index: llvm/test/Instrumentation/MemorySanitizer/alloca.ll =================================================================== --- llvm/test/Instrumentation/MemorySanitizer/alloca.ll +++ llvm/test/Instrumentation/MemorySanitizer/alloca.ll @@ -209,7 +209,42 @@ ; KMSAN-NOT: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: call void @llvm.lifetime.end +define void @goto_bypass() sanitize_memory { +entry: + %x = alloca i8, align 1 + call void @llvm.lifetime.start.p0i8(i64 1, i8* %x) + br label %l1 + +l1: + call void @llvm.lifetime.start.p0i8(i64 1, i8* %x) + call void @bar(i8* noundef %x, i32 noundef 1) + %0 = load i8, i8* %x + %tobool = icmp ne i8 %0, 0 + br i1 %tobool, label %if.then, label %if.end + +if.then: + br label %l1 + +if.end: + call void @llvm.lifetime.end.p0i8(i64 1, i8* %x) + br label %l1 +} - +; CHECK-LABEL: define void @goto_bypass( +; CHECK-LABEL: entry: +; CHECK: %x = alloca i8 +; INLINE: call void @llvm.memset.p0i8.i64(i8* align 1 {{.*}}, i8 -1, i64 1, i1 false) +; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 1) +; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 1, +; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 1, + +; FIXME: It is invalid to instrument here Since variable x may be initialized by callee bar. +; CHECK-LABEL: l1: +; INLINE: call void @llvm.memset.p0i8.i64(i8* align 1 {{.*}}, i8 -1, i64 1, i1 false) +; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 1) +; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 1, +; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 1, + +declare void @bar(i8* noundef, i32 noundef) declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) Index: clang/test/CodeGen/lifetime2.c =================================================================== --- clang/test/CodeGen/lifetime2.c +++ clang/test/CodeGen/lifetime2.c @@ -35,8 +35,11 @@ void goto_bypass(void) { { char x; + // O2: @llvm.lifetime.start.p0i8(i64 1 l1: + // O2: @llvm.lifetime.start.p0i8(i64 1 bar(&x, 1); + // O2: @llvm.lifetime.end.p0i8(i64 1 } goto l1; } @@ -67,21 +70,30 @@ case 1: n = n; char x; + // O2: @llvm.lifetime.start.p0i8(i64 1 bar(&x, 1); break; case 2: + // O2: @llvm.lifetime.start.p0i8(i64 1 bar(&x, 1); break; + // O2: @llvm.lifetime.end.p0i8(i64 1 } } // CHECK-LABEL: @indirect_jump void indirect_jump(int n) { char x; + // O2: @llvm.lifetime.start.p0i8(i64 1 void *T[] = {&&L}; + // O2: @llvm.lifetime.start.p0i8(i64 8 goto *T[n]; L: + // O2: @llvm.lifetime.start.p0i8(i64 1 + // O2: @llvm.lifetime.start.p0i8(i64 8 bar(&x, 1); + // O2: @llvm.lifetime.end.p0i8(i64 8 + // O2: @llvm.lifetime.end.p0i8(i64 1 } extern void foo2(int p); Index: clang/lib/CodeGen/CodeGenFunction.h =================================================================== --- clang/lib/CodeGen/CodeGenFunction.h +++ clang/lib/CodeGen/CodeGenFunction.h @@ -38,6 +38,7 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/Debug.h" #include "llvm/Transforms/Utils/SanitizerStats.h" @@ -1926,6 +1927,14 @@ /// The current lexical scope. LexicalScope *CurLexicalScope = nullptr; + /// Map from lexical socpe to vector of bypassed lifetime start markers. + /// NOTE: If a lifetime start marker isn't defined in any lexical scope( + /// defining while CurLexicalScope is nullptr), its key is nullptr; + std::map<const LexicalScope *, llvm::SmallVector<llvm::CallInst *, 8>> + BypassedLifetimeStartMarkers; + + void restartBypassedVariable(); + /// The current source location that should be used for exception /// handling code. SourceLocation CurEHLocation; @@ -2922,7 +2931,8 @@ void EmitSehTryScopeBegin(); void EmitSehTryScopeEnd(); - llvm::Value *EmitLifetimeStart(llvm::TypeSize Size, llvm::Value *Addr); + llvm::Value *EmitLifetimeStart(llvm::TypeSize Size, llvm::Value *Addr, + bool isBypassed = false); void EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr); llvm::Value *EmitCXXNewExpr(const CXXNewExpr *E); Index: clang/lib/CodeGen/CodeGenFunction.cpp =================================================================== --- clang/lib/CodeGen/CodeGenFunction.cpp +++ clang/lib/CodeGen/CodeGenFunction.cpp @@ -1247,6 +1247,8 @@ EmitBranch(SkipCountBB); } EmitBlock(BB); + restartBypassedVariable(); + uint64_t CurrentCount = getCurrentProfileCount(); incrementProfileCounter(S); setCurrentProfileCount(getCurrentProfileCount() + CurrentCount); @@ -1313,6 +1315,14 @@ return ResTy; } +void CodeGenFunction::restartBypassedVariable() { + if (BypassedLifetimeStartMarkers.count(CurLexicalScope)) + llvm::for_each(BypassedLifetimeStartMarkers[CurLexicalScope], + [this](const llvm::CallInst *LifetimeStartMarker) { + Builder.Insert(LifetimeStartMarker->clone()); + }); +} + void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, const CGFunctionInfo &FnInfo) { assert(Fn && "generating code for null Function"); @@ -1468,6 +1478,8 @@ // a quick pass now to see if we can. if (!CurFn->doesNotThrow()) TryMarkNoThrow(CurFn); + + BypassedLifetimeStartMarkers.clear(); } /// ContainsLabel - Return true if the statement contains a label in it. If Index: clang/lib/CodeGen/CGStmt.cpp =================================================================== --- clang/lib/CodeGen/CGStmt.cpp +++ clang/lib/CodeGen/CGStmt.cpp @@ -646,6 +646,7 @@ } EmitBlock(Dest.getBlock()); + restartBypassedVariable(); // Emit debug info for labels. if (CGDebugInfo *DI = getDebugInfo()) { Index: clang/lib/CodeGen/CGDecl.cpp =================================================================== --- clang/lib/CodeGen/CGDecl.cpp +++ clang/lib/CodeGen/CGDecl.cpp @@ -1330,7 +1330,8 @@ /// \return a pointer to the temporary size Value if a marker was emitted, null /// otherwise llvm::Value *CodeGenFunction::EmitLifetimeStart(llvm::TypeSize Size, - llvm::Value *Addr) { + llvm::Value *Addr, + bool isBypassed) { if (!ShouldEmitLifetimeMarkers) return nullptr; @@ -1342,6 +1343,8 @@ Addr = Builder.CreateBitCast(Addr, AllocaInt8PtrTy); llvm::CallInst *C = Builder.CreateCall(CGM.getLLVMLifetimeStartFn(), {SizeV, Addr}); + if (isBypassed) + BypassedLifetimeStartMarkers[CurLexicalScope].push_back(C); C->setDoesNotThrow(); return SizeV; } @@ -1551,24 +1554,10 @@ // Emit a lifetime intrinsic if meaningful. There's no point in doing this // if we don't have a valid insertion point (?). if (HaveInsertPoint() && !IsMSCatchParam) { - // If there's a jump into the lifetime of this variable, its lifetime - // gets broken up into several regions in IR, which requires more work - // to handle correctly. For now, just omit the intrinsics; this is a - // rare case, and it's better to just be conservatively correct. - // PR28267. - // - // We have to do this in all language modes if there's a jump past the - // declaration. We also have to do it in C if there's a jump to an - // earlier point in the current block because non-VLA lifetimes begin as - // soon as the containing block is entered, not when its variables - // actually come into scope; suppressing the lifetime annotations - // completely in this case is unnecessarily pessimistic, but again, this - // is rare. - if (!Bypasses.IsBypassed(&D) && - !(!getLangOpts().CPlusPlus && hasLabelBeenSeenInCurrentScope())) { + if (!(!getLangOpts().CPlusPlus && hasLabelBeenSeenInCurrentScope())) { llvm::TypeSize Size = CGM.getDataLayout().getTypeAllocSize(allocaTy); - emission.SizeForLifetimeMarkers = - EmitLifetimeStart(Size, AllocaAddr.getPointer()); + emission.SizeForLifetimeMarkers = EmitLifetimeStart( + Size, AllocaAddr.getPointer(), Bypasses.IsBypassed(&D)); } } else { assert(!emission.useLifetimeMarkers());
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits