mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-07-21 02:29:22 +00:00
asan: optimization experiments
The experiments can be used to evaluate potential optimizations that remove instrumentation (assess false negatives). Instead of completely removing some instrumentation, you set Exp to a non-zero value (mask of optimization experiments that want to remove instrumentation of this instruction). If Exp is non-zero, this pass will emit special calls into runtime (e.g. __asan_report_exp_load1 instead of __asan_report_load1). These calls make runtime terminate the program in a special way (with a different exit status). Then you run the new compiler on a buggy corpus, collect the special terminations (ideally, you don't see them at all -- no false negatives) and make the decision on the optimization. The exact reaction to experiments in runtime is not implemented in this patch. It will be defined and implemented in a subsequent patch. http://reviews.llvm.org/D8198 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@232502 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
78158ce3a4
commit
6e4a97dfce
@ -83,8 +83,6 @@ static const char *const kAsanModuleCtorName = "asan.module_ctor";
|
|||||||
static const char *const kAsanModuleDtorName = "asan.module_dtor";
|
static const char *const kAsanModuleDtorName = "asan.module_dtor";
|
||||||
static const uint64_t kAsanCtorAndDtorPriority = 1;
|
static const uint64_t kAsanCtorAndDtorPriority = 1;
|
||||||
static const char *const kAsanReportErrorTemplate = "__asan_report_";
|
static const char *const kAsanReportErrorTemplate = "__asan_report_";
|
||||||
static const char *const kAsanReportLoadN = "__asan_report_load_n";
|
|
||||||
static const char *const kAsanReportStoreN = "__asan_report_store_n";
|
|
||||||
static const char *const kAsanRegisterGlobalsName = "__asan_register_globals";
|
static const char *const kAsanRegisterGlobalsName = "__asan_register_globals";
|
||||||
static const char *const kAsanUnregisterGlobalsName =
|
static const char *const kAsanUnregisterGlobalsName =
|
||||||
"__asan_unregister_globals";
|
"__asan_unregister_globals";
|
||||||
@ -216,6 +214,11 @@ static cl::opt<bool> ClDynamicAllocaStack(
|
|||||||
cl::desc("Use dynamic alloca to represent stack variables"), cl::Hidden,
|
cl::desc("Use dynamic alloca to represent stack variables"), cl::Hidden,
|
||||||
cl::init(true));
|
cl::init(true));
|
||||||
|
|
||||||
|
static cl::opt<uint32_t> ClForceExperiment(
|
||||||
|
"asan-force-experiment",
|
||||||
|
cl::desc("Force optimization experiment (for testing)"), cl::Hidden,
|
||||||
|
cl::init(0));
|
||||||
|
|
||||||
// Debug flags.
|
// Debug flags.
|
||||||
static cl::opt<int> ClDebug("asan-debug", cl::desc("debug"), cl::Hidden,
|
static cl::opt<int> ClDebug("asan-debug", cl::desc("debug"), cl::Hidden,
|
||||||
cl::init(0));
|
cl::init(0));
|
||||||
@ -412,12 +415,16 @@ struct AddressSanitizer : public FunctionPass {
|
|||||||
void instrumentPointerComparisonOrSubtraction(Instruction *I);
|
void instrumentPointerComparisonOrSubtraction(Instruction *I);
|
||||||
void instrumentAddress(Instruction *OrigIns, Instruction *InsertBefore,
|
void instrumentAddress(Instruction *OrigIns, Instruction *InsertBefore,
|
||||||
Value *Addr, uint32_t TypeSize, bool IsWrite,
|
Value *Addr, uint32_t TypeSize, bool IsWrite,
|
||||||
Value *SizeArgument, bool UseCalls);
|
Value *SizeArgument, bool UseCalls, uint32_t Exp);
|
||||||
|
void instrumentUnusualSizeOrAlignment(Instruction *I, Value *Addr,
|
||||||
|
uint32_t TypeSize, bool IsWrite,
|
||||||
|
Value *SizeArgument, bool UseCalls,
|
||||||
|
uint32_t Exp);
|
||||||
Value *createSlowPathCmp(IRBuilder<> &IRB, Value *AddrLong,
|
Value *createSlowPathCmp(IRBuilder<> &IRB, Value *AddrLong,
|
||||||
Value *ShadowValue, uint32_t TypeSize);
|
Value *ShadowValue, uint32_t TypeSize);
|
||||||
Instruction *generateCrashCode(Instruction *InsertBefore, Value *Addr,
|
Instruction *generateCrashCode(Instruction *InsertBefore, Value *Addr,
|
||||||
bool IsWrite, size_t AccessSizeIndex,
|
bool IsWrite, size_t AccessSizeIndex,
|
||||||
Value *SizeArgument);
|
Value *SizeArgument, uint32_t Exp);
|
||||||
void instrumentMemIntrinsic(MemIntrinsic *MI);
|
void instrumentMemIntrinsic(MemIntrinsic *MI);
|
||||||
Value *memToShadow(Value *Shadow, IRBuilder<> &IRB);
|
Value *memToShadow(Value *Shadow, IRBuilder<> &IRB);
|
||||||
bool runOnFunction(Function &F) override;
|
bool runOnFunction(Function &F) override;
|
||||||
@ -445,11 +452,12 @@ struct AddressSanitizer : public FunctionPass {
|
|||||||
Function *AsanInitFunction;
|
Function *AsanInitFunction;
|
||||||
Function *AsanHandleNoReturnFunc;
|
Function *AsanHandleNoReturnFunc;
|
||||||
Function *AsanPtrCmpFunction, *AsanPtrSubFunction;
|
Function *AsanPtrCmpFunction, *AsanPtrSubFunction;
|
||||||
// This array is indexed by AccessIsWrite and log2(AccessSize).
|
// This array is indexed by AccessIsWrite, Experiment and log2(AccessSize).
|
||||||
Function *AsanErrorCallback[2][kNumberOfAccessSizes];
|
Function *AsanErrorCallback[2][2][kNumberOfAccessSizes];
|
||||||
Function *AsanMemoryAccessCallback[2][kNumberOfAccessSizes];
|
Function *AsanMemoryAccessCallback[2][2][kNumberOfAccessSizes];
|
||||||
// This array is indexed by AccessIsWrite.
|
// This array is indexed by AccessIsWrite and Experiment.
|
||||||
Function *AsanErrorCallbackSized[2], *AsanMemoryAccessCallbackSized[2];
|
Function *AsanErrorCallbackSized[2][2];
|
||||||
|
Function *AsanMemoryAccessCallbackSized[2][2];
|
||||||
Function *AsanMemmove, *AsanMemcpy, *AsanMemset;
|
Function *AsanMemmove, *AsanMemcpy, *AsanMemset;
|
||||||
InlineAsm *EmptyAsm;
|
InlineAsm *EmptyAsm;
|
||||||
GlobalsMetadata GlobalsMD;
|
GlobalsMetadata GlobalsMD;
|
||||||
@ -904,6 +912,19 @@ void AddressSanitizer::instrumentMop(ObjectSizeOffsetVisitor &ObjSizeVis,
|
|||||||
Value *Addr = isInterestingMemoryAccess(I, &IsWrite, &TypeSize, &Alignment);
|
Value *Addr = isInterestingMemoryAccess(I, &IsWrite, &TypeSize, &Alignment);
|
||||||
assert(Addr);
|
assert(Addr);
|
||||||
|
|
||||||
|
// Optimization experiments.
|
||||||
|
// The experiments can be used to evaluate potential optimizations that remove
|
||||||
|
// instrumentation (assess false negatives). Instead of completely removing
|
||||||
|
// some instrumentation, you set Exp to a non-zero value (mask of optimization
|
||||||
|
// experiments that want to remove instrumentation of this instruction).
|
||||||
|
// If Exp is non-zero, this pass will emit special calls into runtime
|
||||||
|
// (e.g. __asan_report_exp_load1 instead of __asan_report_load1). These calls
|
||||||
|
// make runtime terminate the program in a special way (with a different
|
||||||
|
// exit status). Then you run the new compiler on a buggy corpus, collect
|
||||||
|
// the special terminations (ideally, you don't see them at all -- no false
|
||||||
|
// negatives) and make the decision on the optimization.
|
||||||
|
uint32_t Exp = ClForceExperiment;
|
||||||
|
|
||||||
if (ClOpt && ClOptGlobals) {
|
if (ClOpt && ClOptGlobals) {
|
||||||
// If initialization order checking is disabled, a simple access to a
|
// If initialization order checking is disabled, a simple access to a
|
||||||
// dynamically initialized global is always valid.
|
// dynamically initialized global is always valid.
|
||||||
@ -935,23 +956,10 @@ void AddressSanitizer::instrumentMop(ObjectSizeOffsetVisitor &ObjSizeVis,
|
|||||||
if ((TypeSize == 8 || TypeSize == 16 || TypeSize == 32 || TypeSize == 64 ||
|
if ((TypeSize == 8 || TypeSize == 16 || TypeSize == 32 || TypeSize == 64 ||
|
||||||
TypeSize == 128) &&
|
TypeSize == 128) &&
|
||||||
(Alignment >= Granularity || Alignment == 0 || Alignment >= TypeSize / 8))
|
(Alignment >= Granularity || Alignment == 0 || Alignment >= TypeSize / 8))
|
||||||
return instrumentAddress(I, I, Addr, TypeSize, IsWrite, nullptr, UseCalls);
|
return instrumentAddress(I, I, Addr, TypeSize, IsWrite, nullptr, UseCalls,
|
||||||
// Instrument unusual size or unusual alignment.
|
Exp);
|
||||||
// We can not do it with a single check, so we do 1-byte check for the first
|
instrumentUnusualSizeOrAlignment(I, Addr, TypeSize, IsWrite, nullptr,
|
||||||
// and the last bytes. We call __asan_report_*_n(addr, real_size) to be able
|
UseCalls, Exp);
|
||||||
// to report the actual access size.
|
|
||||||
IRBuilder<> IRB(I);
|
|
||||||
Value *Size = ConstantInt::get(IntptrTy, TypeSize / 8);
|
|
||||||
Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
|
|
||||||
if (UseCalls) {
|
|
||||||
IRB.CreateCall2(AsanMemoryAccessCallbackSized[IsWrite], AddrLong, Size);
|
|
||||||
} else {
|
|
||||||
Value *LastByte = IRB.CreateIntToPtr(
|
|
||||||
IRB.CreateAdd(AddrLong, ConstantInt::get(IntptrTy, TypeSize / 8 - 1)),
|
|
||||||
Addr->getType());
|
|
||||||
instrumentAddress(I, I, Addr, 8, IsWrite, Size, false);
|
|
||||||
instrumentAddress(I, I, LastByte, 8, IsWrite, Size, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate the result of Module::getOrInsertFunction called for an interface
|
// Validate the result of Module::getOrInsertFunction called for an interface
|
||||||
@ -969,12 +977,26 @@ static Function *checkInterfaceFunction(Constant *FuncOrBitcast) {
|
|||||||
Instruction *AddressSanitizer::generateCrashCode(Instruction *InsertBefore,
|
Instruction *AddressSanitizer::generateCrashCode(Instruction *InsertBefore,
|
||||||
Value *Addr, bool IsWrite,
|
Value *Addr, bool IsWrite,
|
||||||
size_t AccessSizeIndex,
|
size_t AccessSizeIndex,
|
||||||
Value *SizeArgument) {
|
Value *SizeArgument,
|
||||||
|
uint32_t Exp) {
|
||||||
IRBuilder<> IRB(InsertBefore);
|
IRBuilder<> IRB(InsertBefore);
|
||||||
CallInst *Call =
|
Value *ExpVal = Exp == 0 ? nullptr : ConstantInt::get(IRB.getInt32Ty(), Exp);
|
||||||
SizeArgument
|
CallInst *Call = nullptr;
|
||||||
? IRB.CreateCall2(AsanErrorCallbackSized[IsWrite], Addr, SizeArgument)
|
if (SizeArgument) {
|
||||||
: IRB.CreateCall(AsanErrorCallback[IsWrite][AccessSizeIndex], Addr);
|
if (Exp == 0)
|
||||||
|
Call = IRB.CreateCall2(AsanErrorCallbackSized[IsWrite][0], Addr,
|
||||||
|
SizeArgument);
|
||||||
|
else
|
||||||
|
Call = IRB.CreateCall3(AsanErrorCallbackSized[IsWrite][1], Addr,
|
||||||
|
SizeArgument, ExpVal);
|
||||||
|
} else {
|
||||||
|
if (Exp == 0)
|
||||||
|
Call =
|
||||||
|
IRB.CreateCall(AsanErrorCallback[IsWrite][0][AccessSizeIndex], Addr);
|
||||||
|
else
|
||||||
|
Call = IRB.CreateCall2(AsanErrorCallback[IsWrite][1][AccessSizeIndex],
|
||||||
|
Addr, ExpVal);
|
||||||
|
}
|
||||||
|
|
||||||
// We don't do Call->setDoesNotReturn() because the BB already has
|
// We don't do Call->setDoesNotReturn() because the BB already has
|
||||||
// UnreachableInst at the end.
|
// UnreachableInst at the end.
|
||||||
@ -1004,14 +1026,19 @@ Value *AddressSanitizer::createSlowPathCmp(IRBuilder<> &IRB, Value *AddrLong,
|
|||||||
void AddressSanitizer::instrumentAddress(Instruction *OrigIns,
|
void AddressSanitizer::instrumentAddress(Instruction *OrigIns,
|
||||||
Instruction *InsertBefore, Value *Addr,
|
Instruction *InsertBefore, Value *Addr,
|
||||||
uint32_t TypeSize, bool IsWrite,
|
uint32_t TypeSize, bool IsWrite,
|
||||||
Value *SizeArgument, bool UseCalls) {
|
Value *SizeArgument, bool UseCalls,
|
||||||
|
uint32_t Exp) {
|
||||||
IRBuilder<> IRB(InsertBefore);
|
IRBuilder<> IRB(InsertBefore);
|
||||||
Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
|
Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
|
||||||
size_t AccessSizeIndex = TypeSizeToSizeIndex(TypeSize);
|
size_t AccessSizeIndex = TypeSizeToSizeIndex(TypeSize);
|
||||||
|
|
||||||
if (UseCalls) {
|
if (UseCalls) {
|
||||||
IRB.CreateCall(AsanMemoryAccessCallback[IsWrite][AccessSizeIndex],
|
if (Exp == 0)
|
||||||
AddrLong);
|
IRB.CreateCall(AsanMemoryAccessCallback[IsWrite][0][AccessSizeIndex],
|
||||||
|
AddrLong);
|
||||||
|
else
|
||||||
|
IRB.CreateCall2(AsanMemoryAccessCallback[IsWrite][1][AccessSizeIndex],
|
||||||
|
AddrLong, ConstantInt::get(IRB.getInt32Ty(), Exp));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1046,10 +1073,36 @@ void AddressSanitizer::instrumentAddress(Instruction *OrigIns,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Instruction *Crash = generateCrashCode(CrashTerm, AddrLong, IsWrite,
|
Instruction *Crash = generateCrashCode(CrashTerm, AddrLong, IsWrite,
|
||||||
AccessSizeIndex, SizeArgument);
|
AccessSizeIndex, SizeArgument, Exp);
|
||||||
Crash->setDebugLoc(OrigIns->getDebugLoc());
|
Crash->setDebugLoc(OrigIns->getDebugLoc());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Instrument unusual size or unusual alignment.
|
||||||
|
// We can not do it with a single check, so we do 1-byte check for the first
|
||||||
|
// and the last bytes. We call __asan_report_*_n(addr, real_size) to be able
|
||||||
|
// to report the actual access size.
|
||||||
|
void AddressSanitizer::instrumentUnusualSizeOrAlignment(
|
||||||
|
Instruction *I, Value *Addr, uint32_t TypeSize, bool IsWrite,
|
||||||
|
Value *SizeArgument, bool UseCalls, uint32_t Exp) {
|
||||||
|
IRBuilder<> IRB(I);
|
||||||
|
Value *Size = ConstantInt::get(IntptrTy, TypeSize / 8);
|
||||||
|
Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
|
||||||
|
if (UseCalls) {
|
||||||
|
if (Exp == 0)
|
||||||
|
IRB.CreateCall2(AsanMemoryAccessCallbackSized[IsWrite][0], AddrLong,
|
||||||
|
Size);
|
||||||
|
else
|
||||||
|
IRB.CreateCall3(AsanMemoryAccessCallbackSized[IsWrite][1], AddrLong, Size,
|
||||||
|
ConstantInt::get(IRB.getInt32Ty(), Exp));
|
||||||
|
} else {
|
||||||
|
Value *LastByte = IRB.CreateIntToPtr(
|
||||||
|
IRB.CreateAdd(AddrLong, ConstantInt::get(IntptrTy, TypeSize / 8 - 1)),
|
||||||
|
Addr->getType());
|
||||||
|
instrumentAddress(I, I, Addr, 8, IsWrite, Size, false, Exp);
|
||||||
|
instrumentAddress(I, I, LastByte, 8, IsWrite, Size, false, Exp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AddressSanitizerModule::poisonOneInitializer(Function &GlobalInit,
|
void AddressSanitizerModule::poisonOneInitializer(Function &GlobalInit,
|
||||||
GlobalValue *ModuleName) {
|
GlobalValue *ModuleName) {
|
||||||
// Set up the arguments to our poison/unpoison functions.
|
// Set up the arguments to our poison/unpoison functions.
|
||||||
@ -1342,33 +1395,34 @@ bool AddressSanitizerModule::runOnModule(Module &M) {
|
|||||||
void AddressSanitizer::initializeCallbacks(Module &M) {
|
void AddressSanitizer::initializeCallbacks(Module &M) {
|
||||||
IRBuilder<> IRB(*C);
|
IRBuilder<> IRB(*C);
|
||||||
// Create __asan_report* callbacks.
|
// Create __asan_report* callbacks.
|
||||||
for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
|
// IsWrite, TypeSize and Exp are encoded in the function name.
|
||||||
for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes;
|
for (int Exp = 0; Exp < 2; Exp++) {
|
||||||
AccessSizeIndex++) {
|
for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
|
||||||
// IsWrite and TypeSize are encoded in the function name.
|
const std::string TypeStr = AccessIsWrite ? "store" : "load";
|
||||||
std::string Suffix =
|
const std::string ExpStr = Exp ? "exp_" : "";
|
||||||
(AccessIsWrite ? "store" : "load") + itostr(1 << AccessSizeIndex);
|
const Type *ExpType = Exp ? Type::getInt32Ty(*C) : nullptr;
|
||||||
AsanErrorCallback[AccessIsWrite][AccessSizeIndex] =
|
AsanErrorCallbackSized[AccessIsWrite][Exp] =
|
||||||
checkInterfaceFunction(
|
checkInterfaceFunction(M.getOrInsertFunction(
|
||||||
M.getOrInsertFunction(kAsanReportErrorTemplate + Suffix,
|
kAsanReportErrorTemplate + ExpStr + TypeStr + "_n",
|
||||||
IRB.getVoidTy(), IntptrTy, nullptr));
|
IRB.getVoidTy(), IntptrTy, IntptrTy, ExpType, nullptr));
|
||||||
AsanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] =
|
AsanMemoryAccessCallbackSized[AccessIsWrite][Exp] =
|
||||||
checkInterfaceFunction(
|
checkInterfaceFunction(M.getOrInsertFunction(
|
||||||
M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + Suffix,
|
ClMemoryAccessCallbackPrefix + ExpStr + TypeStr + "N",
|
||||||
IRB.getVoidTy(), IntptrTy, nullptr));
|
IRB.getVoidTy(), IntptrTy, IntptrTy, ExpType, nullptr));
|
||||||
|
for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes;
|
||||||
|
AccessSizeIndex++) {
|
||||||
|
const std::string Suffix = TypeStr + itostr(1 << AccessSizeIndex);
|
||||||
|
AsanErrorCallback[AccessIsWrite][Exp][AccessSizeIndex] =
|
||||||
|
checkInterfaceFunction(M.getOrInsertFunction(
|
||||||
|
kAsanReportErrorTemplate + ExpStr + Suffix, IRB.getVoidTy(),
|
||||||
|
IntptrTy, ExpType, nullptr));
|
||||||
|
AsanMemoryAccessCallback[AccessIsWrite][Exp][AccessSizeIndex] =
|
||||||
|
checkInterfaceFunction(M.getOrInsertFunction(
|
||||||
|
ClMemoryAccessCallbackPrefix + ExpStr + Suffix, IRB.getVoidTy(),
|
||||||
|
IntptrTy, ExpType, nullptr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AsanErrorCallbackSized[0] = checkInterfaceFunction(M.getOrInsertFunction(
|
|
||||||
kAsanReportLoadN, IRB.getVoidTy(), IntptrTy, IntptrTy, nullptr));
|
|
||||||
AsanErrorCallbackSized[1] = checkInterfaceFunction(M.getOrInsertFunction(
|
|
||||||
kAsanReportStoreN, IRB.getVoidTy(), IntptrTy, IntptrTy, nullptr));
|
|
||||||
|
|
||||||
AsanMemoryAccessCallbackSized[0] = checkInterfaceFunction(
|
|
||||||
M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + "loadN",
|
|
||||||
IRB.getVoidTy(), IntptrTy, IntptrTy, nullptr));
|
|
||||||
AsanMemoryAccessCallbackSized[1] = checkInterfaceFunction(
|
|
||||||
M.getOrInsertFunction(ClMemoryAccessCallbackPrefix + "storeN",
|
|
||||||
IRB.getVoidTy(), IntptrTy, IntptrTy, nullptr));
|
|
||||||
|
|
||||||
AsanMemmove = checkInterfaceFunction(M.getOrInsertFunction(
|
AsanMemmove = checkInterfaceFunction(M.getOrInsertFunction(
|
||||||
ClMemoryAccessCallbackPrefix + "memmove", IRB.getInt8PtrTy(),
|
ClMemoryAccessCallbackPrefix + "memmove", IRB.getInt8PtrTy(),
|
||||||
|
113
test/Instrumentation/AddressSanitizer/experiment-call.ll
Normal file
113
test/Instrumentation/AddressSanitizer/experiment-call.ll
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
; Test optimization experiments.
|
||||||
|
; -asan-force-experiment flag turns all memory accesses into experiments.
|
||||||
|
; RUN: opt < %s -asan -asan-module -asan-force-experiment=42 -asan-instrumentation-with-call-threshold=0 -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"
|
||||||
|
target triple = "x86_64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
define void @load1(i8* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
%t = load i8, i8* %p, align 1
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @load1
|
||||||
|
; CHECK: __asan_exp_load1{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @load2(i16* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
%t = load i16, i16* %p, align 2
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @load2
|
||||||
|
; CHECK: __asan_exp_load2{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @load4(i32* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
%t = load i32, i32* %p, align 4
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @load4
|
||||||
|
; CHECK: __asan_exp_load4{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @load8(i64* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
%t = load i64, i64* %p, align 8
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @load8
|
||||||
|
; CHECK: __asan_exp_load8{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @load16(i128* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
%t = load i128, i128* %p, align 16
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @load16
|
||||||
|
; CHECK: __asan_exp_load16{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @loadN(i48* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
%t = load i48, i48* %p, align 1
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @loadN
|
||||||
|
; CHECK: __asan_exp_loadN{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @store1(i8* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
store i8 1, i8* %p, align 1
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @store1
|
||||||
|
; CHECK: __asan_exp_store1{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @store2(i16* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
store i16 1, i16* %p, align 2
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @store2
|
||||||
|
; CHECK: __asan_exp_store2{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @store4(i32* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
store i32 1, i32* %p, align 4
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @store4
|
||||||
|
; CHECK: __asan_exp_store4{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @store8(i64* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
store i64 1, i64* %p, align 8
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @store8
|
||||||
|
; CHECK: __asan_exp_store8{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @store16(i128* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
store i128 1, i128* %p, align 16
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @store16
|
||||||
|
; CHECK: __asan_exp_store16{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @storeN(i48* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
store i48 1, i48* %p, align 1
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @storeN
|
||||||
|
; CHECK: __asan_exp_storeN{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
113
test/Instrumentation/AddressSanitizer/experiment.ll
Normal file
113
test/Instrumentation/AddressSanitizer/experiment.ll
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
; Test optimization experiments.
|
||||||
|
; -asan-force-experiment flag turns all memory accesses into experiments.
|
||||||
|
; RUN: opt < %s -asan -asan-module -asan-force-experiment=42 -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"
|
||||||
|
target triple = "x86_64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
define void @load1(i8* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
%t = load i8, i8* %p, align 1
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @load1
|
||||||
|
; CHECK: __asan_report_exp_load1{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @load2(i16* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
%t = load i16, i16* %p, align 2
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @load2
|
||||||
|
; CHECK: __asan_report_exp_load2{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @load4(i32* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
%t = load i32, i32* %p, align 4
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @load4
|
||||||
|
; CHECK: __asan_report_exp_load4{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @load8(i64* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
%t = load i64, i64* %p, align 8
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @load8
|
||||||
|
; CHECK: __asan_report_exp_load8{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @load16(i128* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
%t = load i128, i128* %p, align 16
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @load16
|
||||||
|
; CHECK: __asan_report_exp_load16{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @loadN(i48* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
%t = load i48, i48* %p, align 1
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @loadN
|
||||||
|
; CHECK: __asan_report_exp_load_n{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @store1(i8* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
store i8 1, i8* %p, align 1
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @store1
|
||||||
|
; CHECK: __asan_report_exp_store1{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @store2(i16* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
store i16 1, i16* %p, align 2
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @store2
|
||||||
|
; CHECK: __asan_report_exp_store2{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @store4(i32* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
store i32 1, i32* %p, align 4
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @store4
|
||||||
|
; CHECK: __asan_report_exp_store4{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @store8(i64* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
store i64 1, i64* %p, align 8
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @store8
|
||||||
|
; CHECK: __asan_report_exp_store8{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @store16(i128* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
store i128 1, i128* %p, align 16
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @store16
|
||||||
|
; CHECK: __asan_report_exp_store16{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @storeN(i48* %p) sanitize_address {
|
||||||
|
entry:
|
||||||
|
store i48 1, i48* %p, align 1
|
||||||
|
ret void
|
||||||
|
; CHECK-LABEL: define void @storeN
|
||||||
|
; CHECK: __asan_report_exp_store_n{{.*}} i32 42
|
||||||
|
; CHECK: ret void
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user