summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp34
-rw-r--r--llvm/test/Instrumentation/AddressSanitizer/basic-myriad.ll84
2 files changed, 117 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index eadc9ce50a8..488cbd33adc 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -112,6 +112,13 @@ static const uint64_t kNetBSD_ShadowOffset64 = 1ULL << 46;
static const uint64_t kPS4CPU_ShadowOffset64 = 1ULL << 40;
static const uint64_t kWindowsShadowOffset32 = 3ULL << 28;
+static const uint64_t kMyriadShadowScale = 5;
+static const uint64_t kMyriadMemoryOffset32 = 0x80000000ULL;
+static const uint64_t kMyriadMemorySize32 = 0x20000000ULL;
+static const uint64_t kMyriadTagShift = 29;
+static const uint64_t kMyriadDDRTag = 4;
+static const uint64_t kMyriadCacheBitMask32 = 0x40000000ULL;
+
// The shadow memory space is dynamically allocated.
static const uint64_t kWindowsShadowOffset64 = kDynamicShadowSentinel;
@@ -494,10 +501,11 @@ static ShadowMapping getShadowMapping(Triple &TargetTriple, int LongSize,
bool IsAArch64 = TargetTriple.getArch() == Triple::aarch64;
bool IsWindows = TargetTriple.isOSWindows();
bool IsFuchsia = TargetTriple.isOSFuchsia();
+ bool IsMyriad = TargetTriple.getVendor() == llvm::Triple::Myriad;
ShadowMapping Mapping;
- Mapping.Scale = kDefaultShadowScale;
+ Mapping.Scale = IsMyriad ? kMyriadShadowScale : kDefaultShadowScale;
if (ClMappingScale.getNumOccurrences() > 0) {
Mapping.Scale = ClMappingScale;
}
@@ -516,6 +524,11 @@ static ShadowMapping getShadowMapping(Triple &TargetTriple, int LongSize,
Mapping.Offset = IsX86 ? kIOSSimShadowOffset32 : kIOSShadowOffset32;
else if (IsWindows)
Mapping.Offset = kWindowsShadowOffset32;
+ else if (IsMyriad) {
+ uint64_t ShadowOffset = (kMyriadMemoryOffset32 + kMyriadMemorySize32 -
+ (kMyriadMemorySize32 >> Mapping.Scale));
+ Mapping.Offset = ShadowOffset - (kMyriadMemoryOffset32 >> Mapping.Scale);
+ }
else
Mapping.Offset = kDefaultShadowOffset32;
} else { // LongSize == 64
@@ -1495,6 +1508,8 @@ void AddressSanitizer::instrumentAddress(Instruction *OrigIns,
uint32_t TypeSize, bool IsWrite,
Value *SizeArgument, bool UseCalls,
uint32_t Exp) {
+ bool IsMyriad = TargetTriple.getVendor() == llvm::Triple::Myriad;
+
IRBuilder<> IRB(InsertBefore);
Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
size_t AccessSizeIndex = TypeSizeToSizeIndex(TypeSize);
@@ -1509,6 +1524,23 @@ void AddressSanitizer::instrumentAddress(Instruction *OrigIns,
return;
}
+ if (IsMyriad) {
+ // Strip the cache bit and do range check.
+ // AddrLong &= ~kMyriadCacheBitMask32
+ AddrLong = IRB.CreateAnd(AddrLong, ~kMyriadCacheBitMask32);
+ // Tag = AddrLong >> kMyriadTagShift
+ Value *Tag = IRB.CreateLShr(AddrLong, kMyriadTagShift);
+ // Tag == kMyriadDDRTag
+ Value *TagCheck =
+ IRB.CreateICmpEQ(Tag, ConstantInt::get(IntptrTy, kMyriadDDRTag));
+
+ TerminatorInst *TagCheckTerm = SplitBlockAndInsertIfThen(
+ TagCheck, InsertBefore, false, MDBuilder(*C).createBranchWeights(1, 100000));
+ assert(cast<BranchInst>(TagCheckTerm)->isUnconditional());
+ IRB.SetInsertPoint(TagCheckTerm);
+ InsertBefore = TagCheckTerm;
+ }
+
Type *ShadowTy =
IntegerType::get(*C, std::max(8U, TypeSize >> Mapping.Scale));
Type *ShadowPtrTy = PointerType::get(ShadowTy, 0);
diff --git a/llvm/test/Instrumentation/AddressSanitizer/basic-myriad.ll b/llvm/test/Instrumentation/AddressSanitizer/basic-myriad.ll
new file mode 100644
index 00000000000..9ece86e66f9
--- /dev/null
+++ b/llvm/test/Instrumentation/AddressSanitizer/basic-myriad.ll
@@ -0,0 +1,84 @@
+; Test basic address sanitizer instrumentation for Myriad.
+;
+; RUN: opt -asan -asan-module -S < %s | FileCheck %s
+
+target triple = "sparc-myriad-rtems"
+target datalayout = "E-m:e-p:32:32-i64:64-f128:64-n32-S64"
+; CHECK: @llvm.global_ctors = {{.*}}@asan.module_ctor
+
+define i32 @test_load(i32* %a) sanitize_address {
+; CHECK-LABEL: @test_load
+; CHECK-NOT: load
+; CHECK: ptrtoint i32* %a to i32
+; CHECK: %[[LOAD_ADDR:[^ ]*]] = and i32 %{{.*}}, -1073741825
+; CHECK: lshr i32 %{{.*}}, 29
+; CHECK: icmp eq i32 %{{.*}}, 4
+; CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}!prof ![[PROF:[0-9]+]]
+;
+; This block checks whether the shadow byte is 0.
+; CHECK: lshr i32 %[[LOAD_ADDR]], 5
+; CHECK: add i32 %{{.*}}, -1694498816
+; CHECK: %[[LOAD_SHADOW_PTR:[^ ]*]] = inttoptr
+; CHECK: %[[LOAD_SHADOW:[^ ]*]] = load i8, i8* %[[LOAD_SHADOW_PTR]]
+; CHECK: icmp ne i8
+; CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}!prof ![[PROF:[0-9]+]]
+;
+; This block refines the shadow test.
+; CHECK: and i32 %[[LOAD_ADDR]], 31
+; CHECK: add i32 %{{.*}}, 3
+; CHECK: trunc i32 %{{.*}} to i8
+; CHECK: icmp sge i8 %{{.*}}, %[[LOAD_SHADOW]]
+; CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
+;
+; The crash block reports the error.
+; CHECK: call void @__asan_report_load4(i32 %[[LOAD_ADDR]])
+; CHECK: unreachable
+;
+; The actual load.
+; CHECK: %tmp1 = load i32, i32* %a
+; CHECK: ret i32 %tmp1
+
+entry:
+ %tmp1 = load i32, i32* %a, align 4
+ ret i32 %tmp1
+}
+
+define void @test_store(i32* %a) sanitize_address {
+; CHECK-LABEL: @test_store
+; CHECK-NOT: store
+; CHECK: ptrtoint i32* %a to i32
+; CHECK: %[[STORE_ADDR:[^ ]*]] = and i32 %{{.*}}, -1073741825
+; CHECK: lshr i32 %{{.*}}, 29
+; CHECK: icmp eq i32 %{{.*}}, 4
+; CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}!prof ![[PROF:[0-9]+]]
+;
+; This block checks whether the shadow byte is 0.
+; CHECK: lshr i32 %[[STORE_ADDR]], 5
+; CHECK: add i32 %{{.*}}, -1694498816
+; CHECK: %[[STORE_SHADOW_PTR:[^ ]*]] = inttoptr
+; CHECK: %[[STORE_SHADOW:[^ ]*]] = load i8, i8* %[[STORE_SHADOW_PTR]]
+; CHECK: icmp ne i8
+; CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
+;
+; This block refines the shadow test.
+; CHECK: and i32 %[[STORE_ADDR]], 31
+; CHECK: add i32 %{{.*}}, 3
+; CHECK: trunc i32 %{{.*}} to i8
+; CHECK: icmp sge i8 %{{.*}}, %[[STORE_SHADOW]]
+; CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
+;
+; The crash block reports the error.
+; CHECK: call void @__asan_report_store4(i32 %[[STORE_ADDR]])
+; CHECK: unreachable
+; The actual store.
+; CHECK: store i32 42, i32* %a
+; CHECK: ret void
+;
+
+entry:
+ store i32 42, i32* %a, align 4
+ ret void
+}
+
+; CHECK: define internal void @asan.module_ctor()
+; CHECK: call void @__asan_init()
OpenPOWER on IntegriCloud