const char kAsanAllocaPoison[] = "__asan_alloca_poison";
const char kAsanAllocasUnpoison[] = "__asan_allocas_unpoison";
+const char kAMDGPUAddressSharedName[] = "llvm.amdgcn.is.shared";
+const char kAMDGPUAddressPrivateName[] = "llvm.amdgcn.is.private";
+
// Accesses sizes are powers of two: 1, 2, 4, 8, 16.
static const size_t kNumberOfAccessSizes = 5;
bool IsFuchsia = TargetTriple.isOSFuchsia();
bool IsMyriad = TargetTriple.getVendor() == llvm::Triple::Myriad;
bool IsEmscripten = TargetTriple.isOSEmscripten();
+ bool IsAMDGPU = TargetTriple.isAMDGPU();
+
+ // Asan support for AMDGPU assumes X86 as the host right now.
+ if (IsAMDGPU)
+ IsX86_64 = true;
ShadowMapping Mapping;
void instrumentAddress(Instruction *OrigIns, Instruction *InsertBefore,
Value *Addr, uint32_t TypeSize, bool IsWrite,
Value *SizeArgument, bool UseCalls, uint32_t Exp);
+ Instruction *instrumentAMDGPUAddress(Instruction *OrigIns,
+ Instruction *InsertBefore, Value *Addr,
+ uint32_t TypeSize, bool IsWrite,
+ Value *SizeArgument);
void instrumentUnusualSizeOrAlignment(Instruction *I,
Instruction *InsertBefore, Value *Addr,
uint32_t TypeSize, bool IsWrite,
Value *LocalDynamicShadow = nullptr;
const GlobalsMetadata &GlobalsMD;
DenseMap<const AllocaInst *, bool> ProcessedAllocas;
+
+ FunctionCallee AMDGPUAddressShared;
+ FunctionCallee AMDGPUAddressPrivate;
};
class AddressSanitizerLegacyPass : public FunctionPass {
bool HasInlineAsm = false;
bool HasReturnsTwiceCall = false;
+ bool PoisonStack;
FunctionStackPoisoner(Function &F, AddressSanitizer &ASan)
: F(F), ASan(ASan), DIB(*F.getParent(), /*AllowUnresolved*/ false),
C(ASan.C), IntptrTy(ASan.IntptrTy),
IntptrPtrTy(PointerType::get(IntptrTy, 0)), Mapping(ASan.Mapping),
- StackAlignment(1 << Mapping.Scale) {}
+ StackAlignment(1 << Mapping.Scale),
+ PoisonStack(ClStack &&
+ !Triple(F.getParent()->getTargetTriple()).isAMDGPU()) {}
bool runOnFunction() {
- if (!ClStack) return false;
+ if (!PoisonStack)
+ return false;
if (ClRedzoneByvalArgs)
copyArgsPassedByValToAllocas();
return false;
}
+static bool isUnsupportedAMDGPUAddrspace(Value *Addr) {
+ Type *PtrTy = cast<PointerType>(Addr->getType()->getScalarType());
+ unsigned int AddrSpace = PtrTy->getPointerAddressSpace();
+ if (AddrSpace == 3 || AddrSpace == 5)
+ return true;
+ return false;
+}
+
Value *AddressSanitizer::memToShadow(Value *Shadow, IRBuilder<> &IRB) {
// Shadow >> scale
Shadow = IRB.CreateLShr(Shadow, Mapping.Scale);
}
bool AddressSanitizer::ignoreAccess(Value *Ptr) {
- // Do not instrument acesses from different address spaces; we cannot deal
- // with them.
+ // Instrument acesses from different address spaces only for AMDGPU.
Type *PtrTy = cast<PointerType>(Ptr->getType()->getScalarType());
- if (PtrTy->getPointerAddressSpace() != 0)
+ if (PtrTy->getPointerAddressSpace() != 0 &&
+ !(TargetTriple.isAMDGPU() && !isUnsupportedAMDGPUAddrspace(Ptr)))
return true;
// Ignore swifterror addresses.
return IRB.CreateICmpSGE(LastAccessedByte, ShadowValue);
}
+Instruction *AddressSanitizer::instrumentAMDGPUAddress(
+ Instruction *OrigIns, Instruction *InsertBefore, Value *Addr,
+ uint32_t TypeSize, bool IsWrite, Value *SizeArgument) {
+ // Do not instrument unsupported addrspaces.
+ if (isUnsupportedAMDGPUAddrspace(Addr))
+ return nullptr;
+ Type *PtrTy = cast<PointerType>(Addr->getType()->getScalarType());
+ // Follow host instrumentation for global and constant addresses.
+ if (PtrTy->getPointerAddressSpace() != 0)
+ return InsertBefore;
+ // Instrument generic addresses in supported addressspaces.
+ IRBuilder<> IRB(InsertBefore);
+ Value *AddrLong = IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy());
+ Value *IsShared = IRB.CreateCall(AMDGPUAddressShared, {AddrLong});
+ Value *IsPrivate = IRB.CreateCall(AMDGPUAddressPrivate, {AddrLong});
+ Value *IsSharedOrPrivate = IRB.CreateOr(IsShared, IsPrivate);
+ Value *Cmp = IRB.CreateICmpNE(IRB.getTrue(), IsSharedOrPrivate);
+ Value *AddrSpaceZeroLanding =
+ SplitBlockAndInsertIfThen(Cmp, InsertBefore, false);
+ InsertBefore = cast<Instruction>(AddrSpaceZeroLanding);
+ return InsertBefore;
+}
+
void AddressSanitizer::instrumentAddress(Instruction *OrigIns,
Instruction *InsertBefore, Value *Addr,
uint32_t TypeSize, bool IsWrite,
uint32_t Exp) {
bool IsMyriad = TargetTriple.getVendor() == llvm::Triple::Myriad;
+ if (TargetTriple.isAMDGPU()) {
+ InsertBefore = instrumentAMDGPUAddress(OrigIns, InsertBefore, Addr,
+ TypeSize, IsWrite, SizeArgument);
+ if (!InsertBefore)
+ return;
+ }
+
IRBuilder<> IRB(InsertBefore);
Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
size_t AccessSizeIndex = TypeSizeToSizeIndex(TypeSize);
if (GlobalsMD.get(G).IsExcluded) return false;
if (!Ty->isSized()) return false;
if (!G->hasInitializer()) return false;
- // Only instrument globals of default address spaces
- if (G->getAddressSpace()) return false;
+ // Globals in address space 1 and 4 are supported for AMDGPU.
+ if (G->getAddressSpace() &&
+ !(TargetTriple.isAMDGPU() && !isUnsupportedAMDGPUAddrspace(G)))
+ return false;
if (GlobalWasGeneratedByCompiler(G)) return false; // Our own globals.
// Two problems with thread-locals:
// - The address of the main thread's copy can't be computed at link-time.
if (Mapping.InGlobal)
AsanShadowGlobal = M.getOrInsertGlobal("__asan_shadow",
ArrayType::get(IRB.getInt8Ty(), 0));
+
+ AMDGPUAddressShared = M.getOrInsertFunction(
+ kAMDGPUAddressSharedName, IRB.getInt1Ty(), IRB.getInt8PtrTy());
+ AMDGPUAddressPrivate = M.getOrInsertFunction(
+ kAMDGPUAddressPrivateName, IRB.getInt1Ty(), IRB.getInt8PtrTy());
}
bool AddressSanitizer::maybeInsertAsanInitAtFunctionEntry(Function &F) {
--- /dev/null
+; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s
+; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s
+target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7"
+target triple = "amdgcn-amd-amdhsa"
+
+; Here we check that the global redzone sizes grow with the object size
+; for objects in constant address space.
+
+@G10 = addrspace(4) global [10 x i8] zeroinitializer, align 1
+; CHECK: @G10 = addrspace(4) global { [10 x i8], [54 x i8] }
+
+@G31 = addrspace(4) global [31 x i8] zeroinitializer, align 1
+@G32 = addrspace(4) global [32 x i8] zeroinitializer, align 1
+@G33 = addrspace(4) global [33 x i8] zeroinitializer, align 1
+; CHECK: @G31 = addrspace(4) global { [31 x i8], [33 x i8] }
+; CHECK: @G32 = addrspace(4) global { [32 x i8], [32 x i8] }
+; CHECK: @G33 = addrspace(4) global { [33 x i8], [63 x i8] }
+
+@G63 = addrspace(4) global [63 x i8] zeroinitializer, align 1
+@G64 = addrspace(4) global [64 x i8] zeroinitializer, align 1
+@G65 = addrspace(4) global [65 x i8] zeroinitializer, align 1
+; CHECK: @G63 = addrspace(4) global { [63 x i8], [33 x i8] }
+; CHECK: @G64 = addrspace(4) global { [64 x i8], [32 x i8] }
+; CHECK: @G65 = addrspace(4) global { [65 x i8], [63 x i8] }
+
+@G127 = addrspace(4) global [127 x i8] zeroinitializer, align 1
+@G128 = addrspace(4) global [128 x i8] zeroinitializer, align 1
+@G129 = addrspace(4) global [129 x i8] zeroinitializer, align 1
+; CHECK: @G127 = addrspace(4) global { [127 x i8], [33 x i8] }
+; CHECK: @G128 = addrspace(4) global { [128 x i8], [32 x i8] }
+; CHECK: @G129 = addrspace(4) global { [129 x i8], [63 x i8] }
+
+@G255 = addrspace(4) global [255 x i8] zeroinitializer, align 1
+@G256 = addrspace(4) global [256 x i8] zeroinitializer, align 1
+@G257 = addrspace(4) global [257 x i8] zeroinitializer, align 1
+; CHECK: @G255 = addrspace(4) global { [255 x i8], [33 x i8] }
+; CHECK: @G256 = addrspace(4) global { [256 x i8], [64 x i8] }
+; CHECK: @G257 = addrspace(4) global { [257 x i8], [95 x i8] }
+
+@G511 = addrspace(4) global [511 x i8] zeroinitializer, align 1
+@G512 = addrspace(4) global [512 x i8] zeroinitializer, align 1
+@G513 = addrspace(4) global [513 x i8] zeroinitializer, align 1
+; CHECK: @G511 = addrspace(4) global { [511 x i8], [97 x i8] }
+; CHECK: @G512 = addrspace(4) global { [512 x i8], [128 x i8] }
+; CHECK: @G513 = addrspace(4) global { [513 x i8], [159 x i8] }
+
+@G1023 = addrspace(4) global [1023 x i8] zeroinitializer, align 1
+@G1024 = addrspace(4) global [1024 x i8] zeroinitializer, align 1
+@G1025 = addrspace(4) global [1025 x i8] zeroinitializer, align 1
+; CHECK: @G1023 = addrspace(4) global { [1023 x i8], [225 x i8] }
+; CHECK: @G1024 = addrspace(4) global { [1024 x i8], [256 x i8] }
+; CHECK: @G1025 = addrspace(4) global { [1025 x i8], [287 x i8] }
+
+@G1000000 = addrspace(4) global [1000000 x i8] zeroinitializer, align 1
+@G10000000 = addrspace(4) global [10000000 x i8] zeroinitializer, align 1
+@G100000000 = addrspace(4) global [100000000 x i8] zeroinitializer, align 1
+; CHECK: @G1000000 = addrspace(4) global { [1000000 x i8], [249984 x i8] }
+; CHECK: @G10000000 = addrspace(4) global { [10000000 x i8], [262144 x i8] }
+; CHECK: @G100000000 = addrspace(4) global { [100000000 x i8], [262144 x i8] }
--- /dev/null
+; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s
+; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s
+target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7"
+target triple = "amdgcn-amd-amdhsa"
+
+; Here we check that the global redzone sizes grow with the object size
+; for objects in global address space.
+
+@G10 = addrspace(1) global [10 x i8] zeroinitializer, align 1
+; CHECK: @G10 = addrspace(1) global { [10 x i8], [54 x i8] }
+
+@G31 = addrspace(1) global [31 x i8] zeroinitializer, align 1
+@G32 = addrspace(1) global [32 x i8] zeroinitializer, align 1
+@G33 = addrspace(1) global [33 x i8] zeroinitializer, align 1
+; CHECK: @G31 = addrspace(1) global { [31 x i8], [33 x i8] }
+; CHECK: @G32 = addrspace(1) global { [32 x i8], [32 x i8] }
+; CHECK: @G33 = addrspace(1) global { [33 x i8], [63 x i8] }
+
+@G63 = addrspace(1) global [63 x i8] zeroinitializer, align 1
+@G64 = addrspace(1) global [64 x i8] zeroinitializer, align 1
+@G65 = addrspace(1) global [65 x i8] zeroinitializer, align 1
+; CHECK: @G63 = addrspace(1) global { [63 x i8], [33 x i8] }
+; CHECK: @G64 = addrspace(1) global { [64 x i8], [32 x i8] }
+; CHECK: @G65 = addrspace(1) global { [65 x i8], [63 x i8] }
+
+@G127 = addrspace(1) global [127 x i8] zeroinitializer, align 1
+@G128 = addrspace(1) global [128 x i8] zeroinitializer, align 1
+@G129 = addrspace(1) global [129 x i8] zeroinitializer, align 1
+; CHECK: @G127 = addrspace(1) global { [127 x i8], [33 x i8] }
+; CHECK: @G128 = addrspace(1) global { [128 x i8], [32 x i8] }
+; CHECK: @G129 = addrspace(1) global { [129 x i8], [63 x i8] }
+
+@G255 = addrspace(1) global [255 x i8] zeroinitializer, align 1
+@G256 = addrspace(1) global [256 x i8] zeroinitializer, align 1
+@G257 = addrspace(1) global [257 x i8] zeroinitializer, align 1
+; CHECK: @G255 = addrspace(1) global { [255 x i8], [33 x i8] }
+; CHECK: @G256 = addrspace(1) global { [256 x i8], [64 x i8] }
+; CHECK: @G257 = addrspace(1) global { [257 x i8], [95 x i8] }
+
+@G511 = addrspace(1) global [511 x i8] zeroinitializer, align 1
+@G512 = addrspace(1) global [512 x i8] zeroinitializer, align 1
+@G513 = addrspace(1) global [513 x i8] zeroinitializer, align 1
+; CHECK: @G511 = addrspace(1) global { [511 x i8], [97 x i8] }
+; CHECK: @G512 = addrspace(1) global { [512 x i8], [128 x i8] }
+; CHECK: @G513 = addrspace(1) global { [513 x i8], [159 x i8] }
+
+@G1023 = addrspace(1) global [1023 x i8] zeroinitializer, align 1
+@G1024 = addrspace(1) global [1024 x i8] zeroinitializer, align 1
+@G1025 = addrspace(1) global [1025 x i8] zeroinitializer, align 1
+; CHECK: @G1023 = addrspace(1) global { [1023 x i8], [225 x i8] }
+; CHECK: @G1024 = addrspace(1) global { [1024 x i8], [256 x i8] }
+; CHECK: @G1025 = addrspace(1) global { [1025 x i8], [287 x i8] }
+
+@G1000000 = addrspace(1) global [1000000 x i8] zeroinitializer, align 1
+@G10000000 = addrspace(1) global [10000000 x i8] zeroinitializer, align 1
+@G100000000 = addrspace(1) global [100000000 x i8] zeroinitializer, align 1
+; CHECK: @G1000000 = addrspace(1) global { [1000000 x i8], [249984 x i8] }
+; CHECK: @G10000000 = addrspace(1) global { [10000000 x i8], [262144 x i8] }
+; CHECK: @G100000000 = addrspace(1) global { [100000000 x i8], [262144 x i8] }
--- /dev/null
+; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s
+; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s
+target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7"
+target triple = "amdgcn-amd-amdhsa"
+
+; Memory access to lds are not instrumented
+
+@count = addrspace(3) global [100 x i32] undef, align 16
+
+define protected amdgpu_kernel void @lds_store(i32 %i) sanitize_address {
+entry:
+ ; CHECK-NOT: call * __asan_report
+ %arrayidx1 = getelementptr inbounds [100 x i32], [100 x i32] addrspace(3)* @count, i32 0, i32 %i
+ store i32 0, i32 addrspace(3)* %arrayidx1, align 4
+ ret void
+}
+
+define protected amdgpu_kernel void @lds_load(i32 %i) sanitize_address {
+entry:
+ ; CHECK-NOT: call * __asan_report
+ %arrayidx1 = getelementptr inbounds [100 x i32], [100 x i32] addrspace(3)* @count, i32 0, i32 %i
+ %0 = load i32, i32 addrspace(3)* %arrayidx1, align 4
+ ret void
+}
--- /dev/null
+; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s
+; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s
+target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7"
+target triple = "amdgcn-amd-amdhsa"
+
+; Memory access to scratch are not instrumented
+
+define protected amdgpu_kernel void @scratch_store(i32 %i) sanitize_address {
+entry:
+ ; CHECK-NOT: call * __asan_report
+ %c = alloca i32, align 4, addrspace(5)
+ store i32 0, i32 addrspace(5)* %c, align 4
+ ret void
+}
+
+define protected amdgpu_kernel void @scratch_load(i32 %i) sanitize_address {
+entry:
+ ; CHECK-NOT: call * __asan_report
+ %c = alloca i32, align 4, addrspace(5)
+ %0 = load i32, i32 addrspace(5)* %c, align 4
+ ret void
+}
--- /dev/null
+; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s
+; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s
+target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7"
+target triple = "amdgcn-amd-amdhsa"
+
+@x = addrspace(4) global [2 x i32] zeroinitializer, align 4
+
+define protected amdgpu_kernel void @constant_load(i64 %i) sanitize_address {
+entry:
+; CHECK-LABEL: @constant_load
+; CHECK-NOT: load
+;
+; CHECK: %[[LOAD_ADDR:[^ ]*]] = ptrtoint i32 addrspace(4)* %a to i64
+; CHECK: lshr i64 %[[LOAD_ADDR]], 3
+; CHECK: {{or|add}}
+; CHECK: %[[LOAD_SHADOW_PTR:[^ ]*]] = inttoptr
+; CHECK: %[[LOAD_SHADOW:[^ ]*]] = load i8, i8* %[[LOAD_SHADOW_PTR]]
+; CHECK: icmp ne i8
+; CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
+;
+; CHECK: add i64 %{{.*}}, 3
+; CHECK: trunc i64 %{{.*}} 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(i64 %[[LOAD_ADDR]])
+; CHECK: unreachable
+;
+; The actual load.
+; CHECK: load i32, i32 addrspace(4)* %a
+; CHECK: ret void
+
+ %a = getelementptr inbounds [2 x i32], [2 x i32] addrspace(4)* @x, i64 0, i64 %i
+ %q = load i32, i32 addrspace(4)* %a, align 4
+ ret void
+}
--- /dev/null
+; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s
+; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s
+target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7"
+target triple = "amdgcn-amd-amdhsa"
+
+define protected amdgpu_kernel void @generic_store(i32 addrspace(1)* %p, i32 %i) sanitize_address {
+entry:
+; CHECK-LABEL: @generic_store
+; CHECK-NOT: store
+; CHECK: %[[GENERIC_ADDR:[^ ]*]] = bitcast i32* %q to i8*
+; CHECK: call i1 @llvm.amdgcn.is.shared(i8* %[[GENERIC_ADDR]])
+; CHECK: call i1 @llvm.amdgcn.is.private(i8* %[[GENERIC_ADDR]])
+; CHECK: or
+; CHECK: icmp ne i1
+; CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
+;
+; CHECK: %[[STORE_ADDR:[^ ]*]] = ptrtoint i32* %q to i64
+; CHECK: lshr i64 %[[STORE_ADDR]], 3
+; CHECK: {{or|add}}
+; CHECK: %[[STORE_SHADOW_PTR:[^ ]*]] = inttoptr
+; CHECK: %[[STORE_SHADOW:[^ ]*]] = load i8, i8* %[[STORE_SHADOW_PTR]]
+; CHECK: icmp ne i8
+; CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
+;
+; CHECK: add i64 %{{.*}}, 3
+; CHECK: trunc i64 %{{.*}} 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(i64 %[[STORE_ADDR]])
+; CHECK: unreachable
+;
+; The actual store.
+; CHECK: store i32 0, i32* %q
+; CHECK: ret void
+
+ %q = addrspacecast i32 addrspace(1)* %p to i32*
+ store i32 0, i32* %q, align 4
+ ret void
+}
+
+define protected amdgpu_kernel void @generic_load(i32 addrspace(1)* %p, i32 %i) sanitize_address {
+entry:
+; CHECK-LABEL: @generic_load
+; CHECK-NOT: load
+; CHECK: %[[GENERIC_ADDR:[^ ]*]] = bitcast i32* %q to i8*
+; CHECK: call i1 @llvm.amdgcn.is.shared(i8* %[[GENERIC_ADDR]])
+; CHECK: call i1 @llvm.amdgcn.is.private(i8* %[[GENERIC_ADDR]])
+; CHECK: or
+; CHECK: icmp ne i1
+; CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
+;
+; CHECK: %[[STORE_ADDR:[^ ]*]] = ptrtoint i32* %q to i64
+; CHECK: lshr i64 %[[STORE_ADDR]], 3
+; CHECK: {{or|add}}
+; CHECK: %[[STORE_SHADOW_PTR:[^ ]*]] = inttoptr
+; CHECK: %[[STORE_SHADOW:[^ ]*]] = load i8, i8* %[[STORE_SHADOW_PTR]]
+; CHECK: icmp ne i8
+; CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
+;
+; CHECK: add i64 %{{.*}}, 3
+; CHECK: trunc i64 %{{.*}} to i8
+; CHECK: icmp sge i8 %{{.*}}, %[[STORE_SHADOW]]
+; CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
+;
+; The crash block reports the error.
+; CHECK: call void @__asan_report_load4(i64 %[[STORE_ADDR]])
+; CHECK: unreachable
+;
+; The actual store.
+; CHECK: load i32, i32* %q
+; CHECK: ret void
+
+ %q = addrspacecast i32 addrspace(1)* %p to i32*
+ %r = load i32, i32* %q, align 4
+ ret void
+}
--- /dev/null
+; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s
+; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s
+target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7"
+target triple = "amdgcn-amd-amdhsa"
+
+define protected amdgpu_kernel void @global_store(i32 addrspace(1)* %p, i32 %i) sanitize_address {
+entry:
+; CHECK-LABEL: @global_store
+; CHECK-NOT: store
+;
+; CHECK: %[[STORE_ADDR:[^ ]*]] = ptrtoint i32 addrspace(1)* %p to i64
+; CHECK: lshr i64 %[[STORE_ADDR]], 3
+; CHECK: or
+; CHECK: %[[STORE_SHADOW_PTR:[^ ]*]] = inttoptr
+; CHECK: %[[STORE_SHADOW:[^ ]*]] = load i8, i8* %[[STORE_SHADOW_PTR]]
+; CHECK: icmp ne i8
+; CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
+;
+; CHECK: add i64 %{{.*}}, 3
+; CHECK: trunc i64 %{{.*}} 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(i64 %[[STORE_ADDR]])
+; CHECK: unreachable
+;
+; The actual store.
+; CHECK: store i32 0, i32 addrspace(1)* %p
+; CHECK: ret void
+
+ store i32 0, i32 addrspace(1)* %p, align 4
+ ret void
+}
+
+define protected amdgpu_kernel void @global_load(i32 addrspace(1)* %p, i32 %i) sanitize_address {
+entry:
+; CHECK-LABEL: @global_load
+; CHECK-NOT: load
+;
+; CHECK: %[[LOAD_ADDR:[^ ]*]] = ptrtoint i32 addrspace(1)* %p to i64
+; CHECK: lshr i64 %[[LOAD_ADDR]], 3
+; CHECK: {{add|or}}
+; CHECK: %[[LOAD_SHADOW_PTR:[^ ]*]] = inttoptr
+; CHECK: %[[LOAD_SHADOW:[^ ]*]] = load i8, i8* %[[LOAD_SHADOW_PTR]]
+; CHECK: icmp ne i8
+; CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
+;
+; CHECK: add i64 %{{.*}}, 3
+; CHECK: trunc i64 %{{.*}} 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(i64 %[[LOAD_ADDR]])
+; CHECK: unreachable
+;
+; The actual load.
+; CHECK: load i32, i32 addrspace(1)* %p
+; CHECK: ret void
+
+ %q = load i32, i32 addrspace(1)* %p, align 4
+ ret void
+}
--- /dev/null
+; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s
+; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s
+target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7"
+target triple = "amdgcn-amd-amdhsa"
+
+@g = addrspace(1) global [1 x i32] zeroinitializer, align 4
+
+;CHECK: llvm.asan.globals
+
+!llvm.asan.globals = !{!0, !1}
+!0 = !{[1 x i32] addrspace(1)* @g, null, !"name", i1 false, i1 false}
+!1 = !{i8* addrspacecast (i8 addrspace(1)* bitcast ( [1 x i32] addrspace(1)* @g to i8 addrspace(1)*) to i8*), null, !"name", i1 false, i1 false}
--- /dev/null
+; This test checks that we are not instrumenting direct inbound stack accesses.
+; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-opt-stack -S | FileCheck %s
+; RUN: opt < %s -passes='asan-pipeline' -asan-opt-stack -S | FileCheck %s
+; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-opt-stack -asan-mapping-scale=5 -S | FileCheck %s
+; RUN: opt < %s -passes='asan-pipeline' -asan-opt-stack -asan-mapping-scale=5 -S | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+;@sink = global i32* null, align 4
+
+; Ignore direct inbounds stack access.
+define void @foo() uwtable sanitize_address {
+entry:
+ %a = alloca i32, align 4
+ store i32 42, i32* %a, align 4
+ ret void
+; CHECK-LABEL: define void @foo
+; CHECK-NOT: __asan_report
+; CHECK: ret void
+}
+
+; Don't ignore dynamic indexing.
+define void @baz(i64 %i) sanitize_address {
+entry:
+ %a = alloca [10 x i32], align 4
+ %e = getelementptr inbounds [10 x i32], [10 x i32]* %a, i32 0, i64 %i
+ store i32 42, i32* %e, align 4
+ ret void
+; CHECK-LABEL: define void @baz
+; CHECK: __asan_report
+; CHECK: ret void
+}
+
+define void @bar() sanitize_address {
+entry:
+ %a = alloca [10 x i32], align 4
+ %e = getelementptr inbounds [10 x i32], [10 x i32]* %a, i32 0, i64 12
+ store i32 42, i32* %e, align 4
+ ret void
+; CHECK-LABEL: define void @bar
+; CHECK: __asan_report
+; CHECK: ret void
+}
+
+define void @endoftests() sanitize_address {
+entry:
+ ret void
+; CHECK-LABEL: define void @endoftests
+}
+
--- /dev/null
+; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s
+; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s
+target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7"
+target triple = "amdgcn-amd-amdhsa"
+
+@G10 = addrspace(3) global [10 x i8] zeroinitializer, align 1
+; CHECK-NOT: @G10 = addrspace(3) global { [10 x i8], [* x i8] }
--- /dev/null
+; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s
+; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s
+target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7"
+target triple = "amdgcn-amd-amdhsa"
+
+@G10 = addrspace(5) global [10 x i8] zeroinitializer, align 1
+; CHECK-NOT: @G10 = addrspace(5) global { [10 x i8], [* x i8] }