[llvm] r279984 - Use store operation to poison allocas for lifetime analysis.

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 29 11:17:21 PDT 2016


Author: vitalybuka
Date: Mon Aug 29 13:17:21 2016
New Revision: 279984

URL: http://llvm.org/viewvc/llvm-project?rev=279984&view=rev
Log:
Use store operation to poison allocas for lifetime analysis.

Summary:
Calling __asan_poison_stack_memory and __asan_unpoison_stack_memory for small
variables is too expensive.

Code is disabled by default and can be enabled by -asan-experimental-poisoning.

PR27453

Reviewers: eugenis

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D23947

Added:
    llvm/trunk/test/Instrumentation/AddressSanitizer/stack-poisoning-experimental-be.ll
Modified:
    llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp
    llvm/trunk/test/Instrumentation/AddressSanitizer/stack-poisoning-experimental.ll

Modified: llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp?rev=279984&r1=279983&r2=279984&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp (original)
+++ llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp Mon Aug 29 13:17:21 2016
@@ -55,6 +55,7 @@
 #include "llvm/Transforms/Utils/PromoteMemToReg.h"
 #include <algorithm>
 #include <iomanip>
+#include <limits>
 #include <sstream>
 #include <string>
 #include <system_error>
@@ -811,11 +812,19 @@ struct FunctionStackPoisoner : public In
 
   /// Finds alloca where the value comes from.
   AllocaInst *findAllocaForValue(Value *V);
-  void poisonStackFrameInline(ArrayRef<uint8_t> ShadowBytes, size_t Begin,
-                              size_t End, IRBuilder<> &IRB, Value *ShadowBase,
-                              bool DoPoison);
-  void poisonStackFrame(ArrayRef<uint8_t> ShadowBytes, IRBuilder<> &IRB,
-                        Value *ShadowBase, bool DoPoison);
+
+  // Copies bytes from ShadowBytes into shadow memory for indexes where
+  // ShadowMask is not zero. If ShadowMask[i] is zero, we assume that
+  // ShadowBytes[i] is constantly zero and doesn't need to be overwritten.
+  void copyToShadow(ArrayRef<uint8_t> ShadowMask, ArrayRef<uint8_t> ShadowBytes,
+                    IRBuilder<> &IRB, Value *ShadowBase);
+  void copyToShadow(ArrayRef<uint8_t> ShadowMask, ArrayRef<uint8_t> ShadowBytes,
+                    size_t Begin, size_t End, IRBuilder<> &IRB,
+                    Value *ShadowBase);
+  void copyToShadowInline(ArrayRef<uint8_t> ShadowMask,
+                          ArrayRef<uint8_t> ShadowBytes, size_t Begin,
+                          size_t End, IRBuilder<> &IRB, Value *ShadowBase);
+
   void poisonAlloca(Value *V, uint64_t Size, IRBuilder<> &IRB, bool DoPoison);
 
   Value *createAllocaForLayout(IRBuilder<> &IRB, const ASanStackFrameLayout &L,
@@ -1958,15 +1967,11 @@ void FunctionStackPoisoner::initializeCa
           kAsanAllocasUnpoison, IRB.getVoidTy(), IntptrTy, IntptrTy, nullptr));
 }
 
-// If DoPoison is true function copies ShadowBytes into shadow memory.
-// If DoPoison is false function sets 0s into shadow memory.
-// Function assumes that if ShadowBytes[i] is 0, then corresponding shadow
-// memory is constant for duration of the function and it contains 0s. So we
-// will try to minimize writes into corresponding addresses of the real shadow
-// memory.
-void FunctionStackPoisoner::poisonStackFrameInline(
-    ArrayRef<uint8_t> ShadowBytes, size_t Begin, size_t End, IRBuilder<> &IRB,
-    Value *ShadowBase, bool DoPoison) {
+void FunctionStackPoisoner::copyToShadowInline(ArrayRef<uint8_t> ShadowMask,
+                                               ArrayRef<uint8_t> ShadowBytes,
+                                               size_t Begin, size_t End,
+                                               IRBuilder<> &IRB,
+                                               Value *ShadowBase) {
   if (Begin >= End)
     return;
 
@@ -1976,11 +1981,12 @@ void FunctionStackPoisoner::poisonStackF
   const bool IsLittleEndian = F.getParent()->getDataLayout().isLittleEndian();
 
   // Poison given range in shadow using larges store size with out leading and
-  // trailing zeros. Zeros never change, so they need neither poisoning nor
-  // up-poisoning, but we don't mind if some of them get into a middle of a
-  // store.
+  // trailing zeros in ShadowMask. Zeros never change, so they need neither
+  // poisoning nor up-poisoning. Still we don't mind if some of them get into a
+  // middle of a store.
   for (size_t i = Begin; i < End;) {
-    if (!ShadowBytes[i]) {
+    if (!ShadowMask[i]) {
+      assert(!ShadowBytes[i]);
       ++i;
       continue;
     }
@@ -1991,22 +1997,17 @@ void FunctionStackPoisoner::poisonStackF
       StoreSizeInBytes /= 2;
 
     // Minimize store size by trimming trailing zeros.
-    for (size_t j = StoreSizeInBytes - 1; j && !ShadowBytes[i + j]; --j) {
+    for (size_t j = StoreSizeInBytes - 1; j && !ShadowMask[i + j]; --j) {
       while (j <= StoreSizeInBytes / 2)
         StoreSizeInBytes /= 2;
     }
 
     uint64_t Val = 0;
-    if (DoPoison) {
-      for (size_t j = 0; j < StoreSizeInBytes; j++) {
-        if (IsLittleEndian)
-          Val |= (uint64_t)ShadowBytes[i + j] << (8 * j);
-        else
-          Val = (Val << 8) | ShadowBytes[i + j];
-      }
-      assert(Val); // Impossible because ShadowBytes[i] != 0
-    } else {
-      Val = 0;
+    for (size_t j = 0; j < StoreSizeInBytes; j++) {
+      if (IsLittleEndian)
+        Val |= (uint64_t)ShadowBytes[i + j] << (8 * j);
+      else
+        Val = (Val << 8) | ShadowBytes[i + j];
     }
 
     Value *Ptr = IRB.CreateAdd(ShadowBase, ConstantInt::get(IntptrTy, i));
@@ -2018,30 +2019,33 @@ void FunctionStackPoisoner::poisonStackF
   }
 }
 
-void FunctionStackPoisoner::poisonStackFrame(ArrayRef<uint8_t> ShadowBytes,
-                                             IRBuilder<> &IRB,
-                                             Value *ShadowBase, bool DoPoison) {
-  auto ValueToWrite = [&](size_t i) {
-    if (DoPoison)
-      return ShadowBytes[i];
-    return static_cast<uint8_t>(0);
-  };
+void FunctionStackPoisoner::copyToShadow(ArrayRef<uint8_t> ShadowMask,
+                                         ArrayRef<uint8_t> ShadowBytes,
+                                         IRBuilder<> &IRB, Value *ShadowBase) {
+  copyToShadow(ShadowMask, ShadowBytes, 0, ShadowMask.size(), IRB, ShadowBase);
+}
 
-  const size_t End = ShadowBytes.size();
-  size_t Done = 0;
-  for (size_t i = 0, j = 1; i < End; i = j++) {
-    if (!ShadowBytes[i])
+void FunctionStackPoisoner::copyToShadow(ArrayRef<uint8_t> ShadowMask,
+                                         ArrayRef<uint8_t> ShadowBytes,
+                                         size_t Begin, size_t End,
+                                         IRBuilder<> &IRB, Value *ShadowBase) {
+  assert(ShadowMask.size() == ShadowBytes.size());
+  size_t Done = Begin;
+  for (size_t i = Begin, j = Begin + 1; i < End; i = j++) {
+    if (!ShadowMask[i]) {
+      assert(!ShadowBytes[i]);
       continue;
-    uint8_t Val = ValueToWrite(i);
+    }
+    uint8_t Val = ShadowBytes[i];
     if (!AsanSetShadowFunc[Val])
       continue;
 
     // Skip same values.
-    for (; j < End && ShadowBytes[j] && Val == ValueToWrite(j); ++j) {
+    for (; j < End && ShadowMask[j] && Val == ShadowBytes[j]; ++j) {
     }
 
     if (j - i >= ClMaxInlinePoisoningSize) {
-      poisonStackFrameInline(ShadowBytes, Done, i, IRB, ShadowBase, DoPoison);
+      copyToShadowInline(ShadowMask, ShadowBytes, Done, i, IRB, ShadowBase);
       IRB.CreateCall(AsanSetShadowFunc[Val],
                      {IRB.CreateAdd(ShadowBase, ConstantInt::get(IntptrTy, i)),
                       ConstantInt::get(IntptrTy, j - i)});
@@ -2049,7 +2053,7 @@ void FunctionStackPoisoner::poisonStackF
     }
   }
 
-  poisonStackFrameInline(ShadowBytes, Done, End, IRB, ShadowBase, DoPoison);
+  copyToShadowInline(ShadowMask, ShadowBytes, Done, End, IRB, ShadowBase);
 }
 
 // Fake stack allocator (asan_fake_stack.h) has 11 size classes
@@ -2155,23 +2159,33 @@ void FunctionStackPoisoner::processStati
   // If we have a call to llvm.localescape, keep it in the entry block.
   if (LocalEscapeCall) LocalEscapeCall->moveBefore(InsBefore);
 
-  // Insert poison calls for lifetime intrinsics for static allocas.
+  // Find static allocas with lifetime analysis.
+  DenseMap<const AllocaInst *, const ASanStackVariableDescription *>
+      AllocaToSVDMap;
   for (const auto &APC : StaticAllocaPoisonCallVec) {
     assert(APC.InsBefore);
     assert(APC.AI);
     assert(ASan.isInterestingAlloca(*APC.AI));
     assert(APC.AI->isStaticAlloca());
 
-    IRBuilder<> IRB(APC.InsBefore);
-    poisonAlloca(APC.AI, APC.Size, IRB, APC.DoPoison);
+    if (ClExperimentalPoisoning) {
+      AllocaToSVDMap[APC.AI] = nullptr;
+    } else {
+      IRBuilder<> IRB(APC.InsBefore);
+      poisonAlloca(APC.AI, APC.Size, IRB, APC.DoPoison);
+    }
   }
 
   SmallVector<ASanStackVariableDescription, 16> SVD;
   SVD.reserve(AllocaVec.size());
   for (AllocaInst *AI : AllocaVec) {
+    size_t UseAfterScopePoisonSize =
+        AllocaToSVDMap.find(AI) != AllocaToSVDMap.end()
+            ? ASan.getAllocaSizeInBytes(*AI)
+            : 0;
     ASanStackVariableDescription D = {AI->getName().data(),
                                       ASan.getAllocaSizeInBytes(*AI),
-                                      0,
+                                      UseAfterScopePoisonSize,
                                       AI->getAlignment(),
                                       AI,
                                       0};
@@ -2182,8 +2196,7 @@ void FunctionStackPoisoner::processStati
   size_t MinHeaderSize = ASan.LongSize / 2;
   const ASanStackFrameLayout &L =
       ComputeASanStackFrameLayout(SVD, 1ULL << Mapping.Scale, MinHeaderSize);
-  const SmallVector<uint8_t, 64> &ShadowBytes =
-      GetShadowBytesAfterScope(SVD, L);
+
   DEBUG(dbgs() << L.DescriptionString << " --- " << L.FrameSize << "\n");
   uint64_t LocalStackSize = L.FrameSize;
   bool DoStackMalloc = ClUseAfterReturn && !ASan.CompileKernel &&
@@ -2278,22 +2291,55 @@ void FunctionStackPoisoner::processStati
       IntptrPtrTy);
   IRB.CreateStore(IRB.CreatePointerCast(&F, IntptrTy), BasePlus2);
 
-  // Poison the stack redzones at the entry.
+  const auto &ShadowAfterScope = GetShadowBytesAfterScope(SVD, L);
+
+  // Poison the stack red zones at the entry.
   Value *ShadowBase = ASan.memToShadow(LocalStackBase, IRB);
-  poisonStackFrame(ShadowBytes, IRB, ShadowBase, true);
+  // As mask we must use most poisoned case: red zones and after scope.
+  // As bytes we can use either the same or just red zones only.
+  copyToShadow(ShadowAfterScope, ShadowAfterScope, IRB, ShadowBase);
+
+  if (ClExperimentalPoisoning && !StaticAllocaPoisonCallVec.empty()) {
+    // Complete AllocaToSVDMap
+    for (const auto &Desc : SVD) {
+      auto It = AllocaToSVDMap.find(Desc.AI);
+      if (It != AllocaToSVDMap.end()) {
+        It->second = &Desc;
+      }
+    }
+
+    const auto &ShadowInScope = GetShadowBytes(SVD, L);
+
+    // Poison static allocas near lifetime intrinsics.
+    for (const auto &APC : StaticAllocaPoisonCallVec) {
+      // Must be already set.
+      assert(AllocaToSVDMap[APC.AI]);
+      const auto &Desc = *AllocaToSVDMap[APC.AI];
+      assert(Desc.Offset % L.Granularity == 0);
+      size_t Begin = Desc.Offset / L.Granularity;
+      size_t End = Begin + (APC.Size + L.Granularity - 1) / L.Granularity;
+
+      IRBuilder<> IRB(APC.InsBefore);
+      copyToShadow(ShadowAfterScope,
+                   APC.DoPoison ? ShadowAfterScope : ShadowInScope, Begin, End,
+                   IRB, ShadowBase);
+    }
+  }
+
+  SmallVector<uint8_t, 64> ShadowClean(ShadowAfterScope.size(), 0);
 
   auto UnpoisonStack = [&](IRBuilder<> &IRB) {
     // Do this always as poisonAlloca can be disabled with
     // detect_stack_use_after_scope=0.
-    poisonStackFrame(ShadowBytes, IRB, ShadowBase, false);
-    if (!StaticAllocaPoisonCallVec.empty()) {
+    copyToShadow(ShadowAfterScope, ShadowClean, IRB, ShadowBase);
+    if (!ClExperimentalPoisoning && !StaticAllocaPoisonCallVec.empty()) {
       // If we poisoned some allocas in llvm.lifetime analysis,
       // unpoison whole stack frame now.
       poisonAlloca(LocalStackBase, LocalStackSize, IRB, false);
     }
   };
 
-  SmallVector<uint8_t, 64> ShadowBytesAfterReturn;
+  SmallVector<uint8_t, 64> ShadowAfterReturn;
 
   // (Un)poison the stack before all ret instructions.
   for (auto Ret : RetVec) {
@@ -2321,9 +2367,10 @@ void FunctionStackPoisoner::processStati
       IRBuilder<> IRBPoison(ThenTerm);
       if (StackMallocIdx <= 4) {
         int ClassSize = kMinStackMallocSize << StackMallocIdx;
-        ShadowBytesAfterReturn.resize(ClassSize >> Mapping.Scale,
-                                      kAsanStackUseAfterReturnMagic);
-        poisonStackFrame(ShadowBytesAfterReturn, IRBPoison, ShadowBase, true);
+        ShadowAfterReturn.resize(ClassSize / L.Granularity,
+                                 kAsanStackUseAfterReturnMagic);
+        copyToShadow(ShadowAfterReturn, ShadowAfterReturn, IRBPoison,
+                     ShadowBase);
         Value *SavedFlagPtrPtr = IRBPoison.CreateAdd(
             FakeStack,
             ConstantInt::get(IntptrTy, ClassSize - ASan.LongSize / 8));

Added: llvm/trunk/test/Instrumentation/AddressSanitizer/stack-poisoning-experimental-be.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrumentation/AddressSanitizer/stack-poisoning-experimental-be.ll?rev=279984&view=auto
==============================================================================
--- llvm/trunk/test/Instrumentation/AddressSanitizer/stack-poisoning-experimental-be.ll (added)
+++ llvm/trunk/test/Instrumentation/AddressSanitizer/stack-poisoning-experimental-be.ll Mon Aug 29 13:17:21 2016
@@ -0,0 +1,324 @@
+; Test check the following function parts: ENTRY, LIFE (lifetime), FAKE (fake stack) and EXIT.
+; Test each part can have prefix: no prefix (regular), UAS (use-after-scope), EXP (new poisoning) and UAS-EXP (use-after-scope with new poisoning)
+
+; Regular stack poisoning.
+; RUN: opt < %s -asan -asan-module -asan-experimental-poisoning=0 -asan-use-after-scope=0 -S | FileCheck --check-prefixes=CHECK,ENTRY,LIFE,FAKE,EXIT %s
+
+; Optimized poisoning. Only fake stack part is different from the first test.
+; RUN: opt < %s -asan -asan-module -asan-experimental-poisoning=1 -asan-use-after-scope=0 -S | FileCheck --check-prefixes=CHECK,ENTRY,LIFE,FAKE-EXP,EXIT %s
+
+; Regular stack poisoning with stack-use-after-scope. Only lifetime checks are different from the first test.
+; RUN: opt < %s -asan -asan-module -asan-experimental-poisoning=0 -asan-use-after-scope=1 -S | FileCheck --check-prefixes=CHECK,ENTRY,LIFE-UAS,FAKE,EXIT %s
+
+; Optimized poisoning with stack-use-after-scope.
+; RUN: opt < %s -asan -asan-module -asan-experimental-poisoning=1 -asan-use-after-scope=1 -S | FileCheck --check-prefixes=CHECK,ENTRY-UAS-EXP,LIFE-UAS-EXP,FAKE-EXP,EXIT-EXP %s
+
+target datalayout = "E-m:e-i64:64-n32:64"
+target triple = "powerpc64-unknown-linux-gnu"
+
+declare void @Foo(i8*)
+
+define void @Bar() uwtable sanitize_address {
+entry:
+  %x = alloca [650 x i8], align 16
+  %xx = getelementptr inbounds [650 x i8], [650 x i8]* %x, i64 0, i64 0
+
+  %y = alloca [13 x i8], align 1
+  %yy = getelementptr inbounds [13 x i8], [13 x i8]* %y, i64 0, i64 0
+
+  %z = alloca [40 x i8], align 1
+  %zz = getelementptr inbounds [40 x i8], [40 x i8]* %z, i64 0, i64 0
+
+  ; CHECK: [[SHADOW_BASE:%[0-9]+]] = add i64 %{{[0-9]+}}, 2199023255552
+
+  ; F1F1F1F1
+  ; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
+  ; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
+  ; ENTRY-NEXT: store [[TYPE]] -235802127, [[TYPE]]* [[PTR]], align 1
+
+  ; 02F2F2F2F2F2F2F2
+  ; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 85
+  ; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; ENTRY-NEXT: store [[TYPE]] 212499257711850226, [[TYPE]]* [[PTR]], align 1
+
+  ; F2F2F2F2F2F2F2F2
+  ; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 93
+  ; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; ENTRY-NEXT: store [[TYPE]] -940422246894996750, [[TYPE]]* [[PTR]], align 1
+
+  ; F20005F2F2000000
+  ; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 101
+  ; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; ENTRY-NEXT: store [[TYPE]] -1008799775530680320, [[TYPE]]* [[PTR]], align 1
+
+  ; F3F3F3F3
+  ; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 111
+  ; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
+  ; ENTRY-NEXT: store [[TYPE]] -202116109, [[TYPE]]* [[PTR]], align 1
+
+  ; F3
+  ; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 115
+  ; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i8]]*
+  ; ENTRY-NEXT: store [[TYPE]] -13, [[TYPE]]* [[PTR]], align 1
+
+  ; F1F1F1F1
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -235802127, [[TYPE]]* [[PTR]], align 1
+
+  ; F8F8F8...
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 4
+  ; ENTRY-UAS-EXP-NEXT: call void @__asan_set_shadow_f8(i64 [[OFFSET]], i64 82)
+
+  ; F2F2F2F2F2F2F2F2
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 86
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -940422246894996750, [[TYPE]]* [[PTR]], align 1
+
+  ; F2F2F2F2F2F2F2F2
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 94
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -940422246894996750, [[TYPE]]* [[PTR]], align 1
+
+  ; F8F8F2F2F8F8F8F8
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 102
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -506387832706107144, [[TYPE]]* [[PTR]], align 1
+
+  ; F8F3F3F3
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 110
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -118230029, [[TYPE]]* [[PTR]], align 1
+
+  ; F3F3
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 114
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i16]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -3085, [[TYPE]]* [[PTR]], align 1
+
+  ; CHECK-LABEL: %xx = getelementptr inbounds
+  ; CHECK-NEXT: %yy = getelementptr inbounds
+  ; CHECK-NEXT: %zz = getelementptr inbounds
+
+
+  call void @llvm.lifetime.start(i64 650, i8* %xx)
+  ; LIFE-UAS: call void @__asan_unpoison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE:650]])
+
+  ; 0000...
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 4
+  ; ENTRY-UAS-EXP-NEXT: call void @__asan_set_shadow_00(i64 [[OFFSET]], i64 81)
+  ; 02
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 85
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i8]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] 2, [[TYPE]]* [[PTR]], align 1
+
+  ; CHECK-NEXT: call void @llvm.lifetime.start(i64 650, i8* %xx)
+
+  call void @Foo(i8* %xx)
+  ; CHECK-NEXT: call void @Foo(i8* %xx)
+
+  call void @llvm.lifetime.end(i64 650, i8* %xx)
+  ; LIFE-UAS: call void @__asan_poison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE]])
+
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 4
+  ; ENTRY-UAS-EXP-NEXT: call void @__asan_set_shadow_f8(i64 [[OFFSET]], i64 82)
+
+  ; CHECK-NEXT: call void @llvm.lifetime.end(i64 650, i8* %xx)
+
+
+  call void @llvm.lifetime.start(i64 13, i8* %yy)
+  ; LIFE-UAS: call void @__asan_unpoison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE:13]])
+
+  ; 0005
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 102
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i16]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] 5, [[TYPE]]* [[PTR]], align 1
+
+  ; CHECK-NEXT: call void @llvm.lifetime.start(i64 13, i8* %yy)
+
+  call void @Foo(i8* %yy)
+  ; CHECK-NEXT: call void @Foo(i8* %yy)
+
+  call void @llvm.lifetime.end(i64 13, i8* %yy)
+  ; LIFE-UAS: call void @__asan_poison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE]])
+
+  ; F8F8
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 102
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i16]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -1800, [[TYPE]]* [[PTR]], align 1
+
+  ; CHECK-NEXT: call void @llvm.lifetime.end(i64 13, i8* %yy)
+
+
+  call void @llvm.lifetime.start(i64 40, i8* %zz)
+  ; LIFE-UAS: call void @__asan_unpoison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE:40]])
+
+  ; 00000000
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 106
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
+  ; 00
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 110
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i8]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
+
+  ; CHECK-NEXT: call void @llvm.lifetime.start(i64 40, i8* %zz)
+
+  call void @Foo(i8* %zz)
+  ; CHECK-NEXT: call void @Foo(i8* %zz)
+
+  call void @llvm.lifetime.end(i64 40, i8* %zz)
+  ; LIFE-UAS: call void @__asan_poison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE]])
+
+  ; F8F8F8F8
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 106
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -117901064, [[TYPE]]* [[PTR]], align 1
+  ; F8
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 110
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i8]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -8, [[TYPE]]* [[PTR]], align 1
+
+  ; CHECK-NEXT: call void @llvm.lifetime.end(i64 40, i8* %zz)
+
+
+  ; CHECK-LABEL: <label>
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 8
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 16
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 24
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 32
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 40
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 48
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 56
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 64
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 72
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 80
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 88
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 96
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 104
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 112
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 120
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; FAKE-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
+  ; FAKE-EXP-NEXT: call void @__asan_set_shadow_f5(i64 [[OFFSET]], i64 128)
+
+  ; CHECK-NOT: add i64 [[SHADOW_BASE]]
+
+  ; CHECK-LABEL: <label>
+
+  ; 00000000
+  ; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
+  ; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
+  ; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
+
+  ; 0000000000000000
+  ; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 85
+  ; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
+
+  ; 0000000000000000
+  ; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 93
+  ; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
+
+  ; 0000000000000000
+  ; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 101
+  ; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
+
+  ; 00000000
+  ; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 111
+  ; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
+  ; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
+
+  ; 00
+  ; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 115
+  ; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i8]]*
+  ; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
+
+  ; 0000...
+  ; EXIT-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
+  ; EXIT-EXP-NEXT: call void @__asan_set_shadow_00(i64 [[OFFSET]], i64 116)
+
+  ; CHECK-NOT: add i64 [[SHADOW_BASE]]
+
+  ret void
+  ; CHECK-LABEL: <label>
+  ; CHECK: ret void
+}
+
+declare void @llvm.lifetime.start(i64, i8* nocapture)
+declare void @llvm.lifetime.end(i64, i8* nocapture)
+
+; CHECK-ON: declare void @__asan_set_shadow_00(i64, i64)
+; CHECK-ON: declare void @__asan_set_shadow_f1(i64, i64)
+; CHECK-ON: declare void @__asan_set_shadow_f2(i64, i64)
+; CHECK-ON: declare void @__asan_set_shadow_f3(i64, i64)
+; CHECK-ON: declare void @__asan_set_shadow_f5(i64, i64)
+; CHECK-ON: declare void @__asan_set_shadow_f8(i64, i64)
+
+; CHECK-OFF-NOT: declare void @__asan_set_shadow_

Modified: llvm/trunk/test/Instrumentation/AddressSanitizer/stack-poisoning-experimental.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrumentation/AddressSanitizer/stack-poisoning-experimental.ll?rev=279984&r1=279983&r2=279984&view=diff
==============================================================================
--- llvm/trunk/test/Instrumentation/AddressSanitizer/stack-poisoning-experimental.ll (original)
+++ llvm/trunk/test/Instrumentation/AddressSanitizer/stack-poisoning-experimental.ll Mon Aug 29 13:17:21 2016
@@ -1,5 +1,17 @@
-; RUN: opt < %s -asan -asan-module -asan-experimental-poisoning -S | FileCheck --check-prefixes=CHECK-ON,CHECK %s
-; RUN: opt < %s -asan -asan-module -S | FileCheck --check-prefixes=CHECK-OFF,CHECK %s
+; Test check the following function parts: ENTRY, LIFE (lifetime), FAKE (fake stack) and EXIT.
+; Test each part can have prefix: no prefix (regular), UAS (use-after-scope), EXP (new poisoning) and UAS-EXP (use-after-scope with new poisoning)
+
+; Regular stack poisoning.
+; RUN: opt < %s -asan -asan-module -asan-experimental-poisoning=0 -asan-use-after-scope=0 -S | FileCheck --check-prefixes=CHECK,ENTRY,LIFE,FAKE,EXIT %s
+
+; Optimized poisoning. Only fake stack part is different from the first test.
+; RUN: opt < %s -asan -asan-module -asan-experimental-poisoning=1 -asan-use-after-scope=0 -S | FileCheck --check-prefixes=CHECK,ENTRY,LIFE,FAKE-EXP,EXIT %s
+
+; Regular stack poisoning with stack-use-after-scope. Only lifetime checks are different from the first test.
+; RUN: opt < %s -asan -asan-module -asan-experimental-poisoning=0 -asan-use-after-scope=1 -S | FileCheck --check-prefixes=CHECK,ENTRY,LIFE-UAS,FAKE,EXIT %s
+
+; Optimized poisoning with stack-use-after-scope.
+; RUN: opt < %s -asan -asan-module -asan-experimental-poisoning=1 -asan-use-after-scope=1 -S | FileCheck --check-prefixes=CHECK,ENTRY-UAS-EXP,LIFE-UAS-EXP,FAKE-EXP,EXIT-EXP %s
 
 target datalayout = "e-i64:64-f80:128-s:64-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
@@ -8,47 +20,300 @@ declare void @Foo(i8*)
 
 define void @Bar() uwtable sanitize_address {
 entry:
-  ; CHECK: store i32 -235802127
-  ; CHECK: store i64 -868082074056920318
-  ; CHECK: store i64 -868082074056920077
-  ; CHECK: store i16 -3085
-  ; CHECK: store i8 -13
-  ; CHECK-LABEL: call void @Foo
-  
-  ; CHECK-LABEL: <label>
-  ; CHECK-ON-NOT: store i64
-  ; CHECK-ON: call void @__asan_set_shadow_f5(i64 %{{[0-9]+}}, i64 128)
- 
-  ; CHECK-OFF-NOT: call void @__asan_set_shadow_f5
-  ; CHECK-OFF: store i64 -723401728380766731
-  ; CHECK-OFF: store i64 -723401728380766731
-  ; CHECK-OFF: store i64 -723401728380766731
-  ; CHECK-OFF: store i64 -723401728380766731
-  ; CHECK-OFF: store i64 -723401728380766731
-  ; CHECK-OFF: store i64 -723401728380766731
-  ; CHECK-OFF: store i64 -723401728380766731
-  ; CHECK-OFF: store i64 -723401728380766731
-  ; CHECK-OFF: store i64 -723401728380766731
-  ; CHECK-OFF: store i64 -723401728380766731
-  ; And more...
+  %x = alloca [650 x i8], align 16
+  %xx = getelementptr inbounds [650 x i8], [650 x i8]* %x, i64 0, i64 0
+
+  %y = alloca [13 x i8], align 1
+  %yy = getelementptr inbounds [13 x i8], [13 x i8]* %y, i64 0, i64 0
+
+  %z = alloca [40 x i8], align 1
+  %zz = getelementptr inbounds [40 x i8], [40 x i8]* %z, i64 0, i64 0
+
+  ; CHECK: [[SHADOW_BASE:%[0-9]+]] = add i64 %{{[0-9]+}}, 2147450880
+
+  ; F1F1F1F1
+  ; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
+  ; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
+  ; ENTRY-NEXT: store [[TYPE]] -235802127, [[TYPE]]* [[PTR]], align 1
+
+  ; 02F2F2F2F2F2F2F2
+  ; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 85
+  ; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; ENTRY-NEXT: store [[TYPE]] -940422246894996990, [[TYPE]]* [[PTR]], align 1
+
+  ; F2F2F2F2F2F2F2F2
+  ; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 93
+  ; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; ENTRY-NEXT: store [[TYPE]] -940422246894996750, [[TYPE]]* [[PTR]], align 1
+
+  ; F20005F2F2000000
+  ; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 101
+  ; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; ENTRY-NEXT: store [[TYPE]] 1043442499826, [[TYPE]]* [[PTR]], align 1
+
+  ; F3F3F3F3
+  ; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 111
+  ; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
+  ; ENTRY-NEXT: store [[TYPE]] -202116109, [[TYPE]]* [[PTR]], align 1
+
+  ; F3
+  ; ENTRY-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 115
+  ; ENTRY-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i8]]*
+  ; ENTRY-NEXT: store [[TYPE]] -13, [[TYPE]]* [[PTR]], align 1
+
+  ; F1F1F1F1
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -235802127, [[TYPE]]* [[PTR]], align 1
+
+  ; F8F8F8...
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 4
+  ; ENTRY-UAS-EXP-NEXT: call void @__asan_set_shadow_f8(i64 [[OFFSET]], i64 82)
+
+  ; F2F2F2F2F2F2F2F2
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 86
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -940422246894996750, [[TYPE]]* [[PTR]], align 1
+
+  ; F2F2F2F2F2F2F2F2
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 94
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -940422246894996750, [[TYPE]]* [[PTR]], align 1
+
+  ; F8F8F2F2F8F8F8F8
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 102
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -506381209967593224, [[TYPE]]* [[PTR]], align 1
+
+  ; F8F3F3F3
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 110
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -202116104, [[TYPE]]* [[PTR]], align 1
+
+  ; F3F3
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 114
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i16]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -3085, [[TYPE]]* [[PTR]], align 1
+
+  ; CHECK-LABEL: %xx = getelementptr inbounds
+  ; CHECK-NEXT: %yy = getelementptr inbounds
+  ; CHECK-NEXT: %zz = getelementptr inbounds
+
+
+  call void @llvm.lifetime.start(i64 650, i8* %xx)
+  ; LIFE-UAS: call void @__asan_unpoison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE:650]])
+
+  ; 0000...
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 4
+  ; ENTRY-UAS-EXP-NEXT: call void @__asan_set_shadow_00(i64 [[OFFSET]], i64 81)
+  ; 02
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 85
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i8]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] 2, [[TYPE]]* [[PTR]], align 1
+
+  ; CHECK-NEXT: call void @llvm.lifetime.start(i64 650, i8* %xx)
+
+  call void @Foo(i8* %xx)
+  ; CHECK-NEXT: call void @Foo(i8* %xx)
+
+  call void @llvm.lifetime.end(i64 650, i8* %xx)
+  ; LIFE-UAS: call void @__asan_poison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE]])
+
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 4
+  ; ENTRY-UAS-EXP-NEXT: call void @__asan_set_shadow_f8(i64 [[OFFSET]], i64 82)
+
+  ; CHECK-NEXT: call void @llvm.lifetime.end(i64 650, i8* %xx)
+
+
+  call void @llvm.lifetime.start(i64 13, i8* %yy)
+  ; LIFE-UAS: call void @__asan_unpoison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE:13]])
+
+  ; 0005
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 102
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i16]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] 1280, [[TYPE]]* [[PTR]], align 1
+
+  ; CHECK-NEXT: call void @llvm.lifetime.start(i64 13, i8* %yy)
+
+  call void @Foo(i8* %yy)
+  ; CHECK-NEXT: call void @Foo(i8* %yy)
+
+  call void @llvm.lifetime.end(i64 13, i8* %yy)
+  ; LIFE-UAS: call void @__asan_poison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE]])
+
+  ; F8F8
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 102
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i16]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -1800, [[TYPE]]* [[PTR]], align 1
+
+  ; CHECK-NEXT: call void @llvm.lifetime.end(i64 13, i8* %yy)
+
+
+  call void @llvm.lifetime.start(i64 40, i8* %zz)
+  ; LIFE-UAS: call void @__asan_unpoison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE:40]])
+
+  ; 00000000
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 106
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
+  ; 00
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 110
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i8]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
+
+  ; CHECK-NEXT: call void @llvm.lifetime.start(i64 40, i8* %zz)
+
+  call void @Foo(i8* %zz)
+  ; CHECK-NEXT: call void @Foo(i8* %zz)
+
+  call void @llvm.lifetime.end(i64 40, i8* %zz)
+  ; LIFE-UAS: call void @__asan_poison_stack_memory(i64 %{{[0-9]+}}, i64 [[SIZE]])
+
+  ; F8F8F8F8
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 106
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -117901064, [[TYPE]]* [[PTR]], align 1
+  ; F8
+  ; ENTRY-UAS-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 110
+  ; ENTRY-UAS-EXP-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i8]]*
+  ; ENTRY-UAS-EXP-NEXT: store [[TYPE]] -8, [[TYPE]]* [[PTR]], align 1
+
+  ; CHECK-NEXT: call void @llvm.lifetime.end(i64 40, i8* %zz)
+
 
   ; CHECK-LABEL: <label>
-  ; CHECK-NOT: call void @__asan_set_shadow_00
-  ; CHECK: store i32 0
-  ; CHECK: store i64 0
-  ; CHECK: store i64 0
-  ; CHECK: store i16 0
-  ; CHECK: store i8 0
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 8
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 16
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 24
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 32
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 40
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 48
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 56
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 64
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 72
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 80
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 88
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 96
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 104
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 112
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; F5F5F5F5F5F5F5F5
+  ; FAKE-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 120
+  ; FAKE-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; FAKE-NEXT: store [[TYPE]] -723401728380766731, [[TYPE]]* [[PTR]], align 1
+
+  ; FAKE-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
+  ; FAKE-EXP-NEXT: call void @__asan_set_shadow_f5(i64 [[OFFSET]], i64 128)
+
+  ; CHECK-NOT: add i64 [[SHADOW_BASE]]
 
   ; CHECK-LABEL: <label>
-  ; CHECK: ret void
 
-  %x = alloca [650 x i8], align 16
-  %arraydecay = getelementptr inbounds [650 x i8], [650 x i8]* %x, i64 0, i64 0
-  call void @Foo(i8* %arraydecay)
+  ; 00000000
+  ; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
+  ; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
+  ; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
+
+  ; 0000000000000000
+  ; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 85
+  ; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
+
+  ; 0000000000000000
+  ; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 93
+  ; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
+
+  ; 0000000000000000
+  ; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 101
+  ; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i64]]*
+  ; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
+
+  ; 00000000
+  ; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 111
+  ; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i32]]*
+  ; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
+
+  ; 00
+  ; EXIT-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 115
+  ; EXIT-NEXT: [[PTR:%[0-9]+]] = inttoptr i64 [[OFFSET]] to [[TYPE:i8]]*
+  ; EXIT-NEXT: store [[TYPE]] 0, [[TYPE]]* [[PTR]], align 1
+
+  ; 0000...
+  ; EXIT-EXP-NEXT: [[OFFSET:%[0-9]+]] = add i64 [[SHADOW_BASE]], 0
+  ; EXIT-EXP-NEXT: call void @__asan_set_shadow_00(i64 [[OFFSET]], i64 116)
+
+  ; CHECK-NOT: add i64 [[SHADOW_BASE]]
+
   ret void
+  ; CHECK-LABEL: <label>
+  ; CHECK: ret void
 }
 
+declare void @llvm.lifetime.start(i64, i8* nocapture)
+declare void @llvm.lifetime.end(i64, i8* nocapture)
+
 ; CHECK-ON: declare void @__asan_set_shadow_00(i64, i64)
 ; CHECK-ON: declare void @__asan_set_shadow_f1(i64, i64)
 ; CHECK-ON: declare void @__asan_set_shadow_f2(i64, i64)




More information about the llvm-commits mailing list