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

Reply via email to