mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
[ASan] Make ASan instrument variable-masked loads and stores
Summary: Previously we only supported constant-masked loads and stores. Reviewers: kcc, RKSimon, pgousseau, gbedwell, vitalybuka Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D28370 llvm-svn: 291238
This commit is contained in:
parent
a949cf108b
commit
368bad5905
@ -514,7 +514,8 @@ struct AddressSanitizer : public FunctionPass {
|
||||
void instrumentAddress(Instruction *OrigIns, Instruction *InsertBefore,
|
||||
Value *Addr, uint32_t TypeSize, bool IsWrite,
|
||||
Value *SizeArgument, bool UseCalls, uint32_t Exp);
|
||||
void instrumentUnusualSizeOrAlignment(Instruction *I, Value *Addr,
|
||||
void instrumentUnusualSizeOrAlignment(Instruction *I,
|
||||
Instruction *InsertBefore, Value *Addr,
|
||||
uint32_t TypeSize, bool IsWrite,
|
||||
Value *SizeArgument, bool UseCalls,
|
||||
uint32_t Exp);
|
||||
@ -1056,20 +1057,18 @@ Value *AddressSanitizer::isInterestingMemoryAccess(Instruction *I,
|
||||
return nullptr;
|
||||
*IsWrite = false;
|
||||
}
|
||||
// Only instrument if the mask is constant for now.
|
||||
if (isa<ConstantVector>(CI->getOperand(2 + OpOffset))) {
|
||||
auto BasePtr = CI->getOperand(0 + OpOffset);
|
||||
auto Ty = cast<PointerType>(BasePtr->getType())->getElementType();
|
||||
*TypeSize = DL.getTypeStoreSizeInBits(Ty);
|
||||
if (auto AlignmentConstant =
|
||||
dyn_cast<ConstantInt>(CI->getOperand(1 + OpOffset)))
|
||||
*Alignment = (unsigned)AlignmentConstant->getZExtValue();
|
||||
else
|
||||
*Alignment = 1; // No alignment guarantees. We probably got Undef
|
||||
if (MaybeMask)
|
||||
*MaybeMask = CI->getOperand(2 + OpOffset);
|
||||
PtrOperand = BasePtr;
|
||||
}
|
||||
|
||||
auto BasePtr = CI->getOperand(0 + OpOffset);
|
||||
auto Ty = cast<PointerType>(BasePtr->getType())->getElementType();
|
||||
*TypeSize = DL.getTypeStoreSizeInBits(Ty);
|
||||
if (auto AlignmentConstant =
|
||||
dyn_cast<ConstantInt>(CI->getOperand(1 + OpOffset)))
|
||||
*Alignment = (unsigned)AlignmentConstant->getZExtValue();
|
||||
else
|
||||
*Alignment = 1; // No alignment guarantees. We probably got Undef
|
||||
if (MaybeMask)
|
||||
*MaybeMask = CI->getOperand(2 + OpOffset);
|
||||
PtrOperand = BasePtr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1130,24 +1129,25 @@ void AddressSanitizer::instrumentPointerComparisonOrSubtraction(
|
||||
}
|
||||
|
||||
static void doInstrumentAddress(AddressSanitizer *Pass, Instruction *I,
|
||||
Value *Addr, unsigned Alignment,
|
||||
unsigned Granularity, uint32_t TypeSize,
|
||||
bool IsWrite, Value *SizeArgument,
|
||||
bool UseCalls, uint32_t Exp) {
|
||||
Instruction *InsertBefore, Value *Addr,
|
||||
unsigned Alignment, unsigned Granularity,
|
||||
uint32_t TypeSize, bool IsWrite,
|
||||
Value *SizeArgument, bool UseCalls,
|
||||
uint32_t Exp) {
|
||||
// Instrument a 1-, 2-, 4-, 8-, or 16- byte access with one check
|
||||
// if the data is properly aligned.
|
||||
if ((TypeSize == 8 || TypeSize == 16 || TypeSize == 32 || TypeSize == 64 ||
|
||||
TypeSize == 128) &&
|
||||
(Alignment >= Granularity || Alignment == 0 || Alignment >= TypeSize / 8))
|
||||
return Pass->instrumentAddress(I, I, Addr, TypeSize, IsWrite, nullptr,
|
||||
UseCalls, Exp);
|
||||
Pass->instrumentUnusualSizeOrAlignment(I, Addr, TypeSize, IsWrite, nullptr,
|
||||
UseCalls, Exp);
|
||||
return Pass->instrumentAddress(I, InsertBefore, Addr, TypeSize, IsWrite,
|
||||
nullptr, UseCalls, Exp);
|
||||
Pass->instrumentUnusualSizeOrAlignment(I, InsertBefore, Addr, TypeSize,
|
||||
IsWrite, nullptr, UseCalls, Exp);
|
||||
}
|
||||
|
||||
static void instrumentMaskedLoadOrStore(AddressSanitizer *Pass,
|
||||
const DataLayout &DL, Type *IntptrTy,
|
||||
ConstantVector *Mask, Instruction *I,
|
||||
Value *Mask, Instruction *I,
|
||||
Value *Addr, unsigned Alignment,
|
||||
unsigned Granularity, uint32_t TypeSize,
|
||||
bool IsWrite, Value *SizeArgument,
|
||||
@ -1157,15 +1157,30 @@ static void instrumentMaskedLoadOrStore(AddressSanitizer *Pass,
|
||||
unsigned Num = VTy->getVectorNumElements();
|
||||
auto Zero = ConstantInt::get(IntptrTy, 0);
|
||||
for (unsigned Idx = 0; Idx < Num; ++Idx) {
|
||||
// dyn_cast as we might get UndefValue
|
||||
auto Masked = dyn_cast<ConstantInt>(Mask->getOperand(Idx));
|
||||
if (Masked && Masked->isAllOnesValue()) {
|
||||
Value *InstrumentedAddress = nullptr;
|
||||
Instruction *InsertBefore = I;
|
||||
if (auto *Vector = dyn_cast<ConstantVector>(Mask)) {
|
||||
// dyn_cast as we might get UndefValue
|
||||
if (auto *Masked = dyn_cast<ConstantInt>(Vector->getOperand(Idx))) {
|
||||
if (Masked->isNullValue())
|
||||
// Mask is constant false, so no instrumentation needed.
|
||||
continue;
|
||||
// If we have a true or undef value, fall through to doInstrumentAddress
|
||||
// with InsertBefore == I
|
||||
}
|
||||
} else {
|
||||
IRBuilder<> IRB(I);
|
||||
auto InstrumentedAddress =
|
||||
IRB.CreateGEP(Addr, {Zero, ConstantInt::get(IntptrTy, Idx)});
|
||||
doInstrumentAddress(Pass, I, InstrumentedAddress, Alignment, Granularity,
|
||||
ElemTypeSize, IsWrite, SizeArgument, UseCalls, Exp);
|
||||
Value *MaskElem = IRB.CreateExtractElement(Mask, Idx);
|
||||
TerminatorInst *ThenTerm = SplitBlockAndInsertIfThen(MaskElem, I, false);
|
||||
InsertBefore = ThenTerm;
|
||||
}
|
||||
|
||||
IRBuilder<> IRB(InsertBefore);
|
||||
InstrumentedAddress =
|
||||
IRB.CreateGEP(Addr, {Zero, ConstantInt::get(IntptrTy, Idx)});
|
||||
doInstrumentAddress(Pass, I, InsertBefore, InstrumentedAddress, Alignment,
|
||||
Granularity, ElemTypeSize, IsWrite, SizeArgument,
|
||||
UseCalls, Exp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1220,12 +1235,11 @@ void AddressSanitizer::instrumentMop(ObjectSizeOffsetVisitor &ObjSizeVis,
|
||||
|
||||
unsigned Granularity = 1 << Mapping.Scale;
|
||||
if (MaybeMask) {
|
||||
auto Mask = cast<ConstantVector>(MaybeMask);
|
||||
instrumentMaskedLoadOrStore(this, DL, IntptrTy, Mask, I, Addr, Alignment,
|
||||
Granularity, TypeSize, IsWrite, nullptr,
|
||||
UseCalls, Exp);
|
||||
instrumentMaskedLoadOrStore(this, DL, IntptrTy, MaybeMask, I, Addr,
|
||||
Alignment, Granularity, TypeSize, IsWrite,
|
||||
nullptr, UseCalls, Exp);
|
||||
} else {
|
||||
doInstrumentAddress(this, I, Addr, Alignment, Granularity, TypeSize,
|
||||
doInstrumentAddress(this, I, I, Addr, Alignment, Granularity, TypeSize,
|
||||
IsWrite, nullptr, UseCalls, Exp);
|
||||
}
|
||||
}
|
||||
@ -1342,9 +1356,9 @@ void AddressSanitizer::instrumentAddress(Instruction *OrigIns,
|
||||
// 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);
|
||||
Instruction *I, Instruction *InsertBefore, Value *Addr, uint32_t TypeSize,
|
||||
bool IsWrite, Value *SizeArgument, bool UseCalls, uint32_t Exp) {
|
||||
IRBuilder<> IRB(InsertBefore);
|
||||
Value *Size = ConstantInt::get(IntptrTy, TypeSize / 8);
|
||||
Value *AddrLong = IRB.CreatePointerCast(Addr, IntptrTy);
|
||||
if (UseCalls) {
|
||||
@ -1358,8 +1372,8 @@ void AddressSanitizer::instrumentUnusualSizeOrAlignment(
|
||||
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);
|
||||
instrumentAddress(I, InsertBefore, Addr, 8, IsWrite, Size, false, Exp);
|
||||
instrumentAddress(I, InsertBefore, LastByte, 8, IsWrite, Size, false, Exp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,43 @@ define void @store.v4i64.0001(<4 x i32*> %arg) sanitize_address {
|
||||
define void @store.v4f32.variable(<4 x float> %arg, <4 x i1> %mask) sanitize_address {
|
||||
; ALL-LABEL: @store.v4f32.variable
|
||||
%p = load <4 x float>*, <4 x float>** @v4f32, align 8
|
||||
; ALL-NOT: call void @__asan_store
|
||||
; STORE: [[MASK0:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 0
|
||||
; STORE: br i1 [[MASK0]], label %[[THEN0:[0-9A-Za-z]+]], label %[[AFTER0:[0-9A-Za-z]+]]
|
||||
; STORE: <label>:[[THEN0]]:
|
||||
; STORE: [[GEP0:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 0
|
||||
; STORE: [[PGEP0:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP0]] to i64
|
||||
; STORE: call void @__asan_store4(i64 [[PGEP0]])
|
||||
; STORE: br label %[[AFTER0]]
|
||||
; STORE: <label>:[[AFTER0]]
|
||||
|
||||
; STORE: [[MASK1:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 1
|
||||
; STORE: br i1 [[MASK1]], label %[[THEN1:[0-9A-Za-z]+]], label %[[AFTER1:[0-9A-Za-z]+]]
|
||||
; STORE: <label>:[[THEN1]]:
|
||||
; STORE: [[GEP1:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 1
|
||||
; STORE: [[PGEP1:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP1]] to i64
|
||||
; STORE: call void @__asan_store4(i64 [[PGEP1]])
|
||||
; STORE: br label %[[AFTER1]]
|
||||
; STORE: <label>:[[AFTER1]]
|
||||
|
||||
; STORE: [[MASK2:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 2
|
||||
; STORE: br i1 [[MASK2]], label %[[THEN2:[0-9A-Za-z]+]], label %[[AFTER2:[0-9A-Za-z]+]]
|
||||
; STORE: <label>:[[THEN2]]:
|
||||
; STORE: [[GEP2:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 2
|
||||
; STORE: [[PGEP2:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP2]] to i64
|
||||
; STORE: call void @__asan_store4(i64 [[PGEP2]])
|
||||
; STORE: br label %[[AFTER2]]
|
||||
; STORE: <label>:[[AFTER2]]
|
||||
|
||||
; STORE: [[MASK3:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 3
|
||||
; STORE: br i1 [[MASK3]], label %[[THEN3:[0-9A-Za-z]+]], label %[[AFTER3:[0-9A-Za-z]+]]
|
||||
; STORE: <label>:[[THEN3]]:
|
||||
; STORE: [[GEP3:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 3
|
||||
; STORE: [[PGEP3:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP3]] to i64
|
||||
; STORE: call void @__asan_store4(i64 [[PGEP3]])
|
||||
; STORE: br label %[[AFTER3]]
|
||||
; STORE: <label>:[[AFTER3]]
|
||||
|
||||
; STORE: tail call void @llvm.masked.store.v4f32.p0v4f32(<4 x float> %arg, <4 x float>* %p, i32 4, <4 x i1> %mask)
|
||||
tail call void @llvm.masked.store.v4f32.p0v4f32(<4 x float> %arg, <4 x float>* %p, i32 4, <4 x i1> %mask)
|
||||
ret void
|
||||
}
|
||||
@ -165,7 +201,43 @@ define <4 x i32*> @load.v4i64.0001(<4 x i32*> %arg) sanitize_address {
|
||||
define <4 x float> @load.v4f32.variable(<4 x float> %arg, <4 x i1> %mask) sanitize_address {
|
||||
; ALL-LABEL: @load.v4f32.variable
|
||||
%p = load <4 x float>*, <4 x float>** @v4f32, align 8
|
||||
; ALL-NOT: call void @__asan_load
|
||||
; LOAD: [[MASK0:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 0
|
||||
; LOAD: br i1 [[MASK0]], label %[[THEN0:[0-9A-Za-z]+]], label %[[AFTER0:[0-9A-Za-z]+]]
|
||||
; LOAD: <label>:[[THEN0]]:
|
||||
; LOAD: [[GEP0:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 0
|
||||
; LOAD: [[PGEP0:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP0]] to i64
|
||||
; LOAD: call void @__asan_load4(i64 [[PGEP0]])
|
||||
; LOAD: br label %[[AFTER0]]
|
||||
; LOAD: <label>:[[AFTER0]]
|
||||
|
||||
; LOAD: [[MASK1:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 1
|
||||
; LOAD: br i1 [[MASK1]], label %[[THEN1:[0-9A-Za-z]+]], label %[[AFTER1:[0-9A-Za-z]+]]
|
||||
; LOAD: <label>:[[THEN1]]:
|
||||
; LOAD: [[GEP1:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 1
|
||||
; LOAD: [[PGEP1:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP1]] to i64
|
||||
; LOAD: call void @__asan_load4(i64 [[PGEP1]])
|
||||
; LOAD: br label %[[AFTER1]]
|
||||
; LOAD: <label>:[[AFTER1]]
|
||||
|
||||
; LOAD: [[MASK2:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 2
|
||||
; LOAD: br i1 [[MASK2]], label %[[THEN2:[0-9A-Za-z]+]], label %[[AFTER2:[0-9A-Za-z]+]]
|
||||
; LOAD: <label>:[[THEN2]]:
|
||||
; LOAD: [[GEP2:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 2
|
||||
; LOAD: [[PGEP2:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP2]] to i64
|
||||
; LOAD: call void @__asan_load4(i64 [[PGEP2]])
|
||||
; LOAD: br label %[[AFTER2]]
|
||||
; LOAD: <label>:[[AFTER2]]
|
||||
|
||||
; LOAD: [[MASK3:%[0-9A-Za-z]+]] = extractelement <4 x i1> %mask, i64 3
|
||||
; LOAD: br i1 [[MASK3]], label %[[THEN3:[0-9A-Za-z]+]], label %[[AFTER3:[0-9A-Za-z]+]]
|
||||
; LOAD: <label>:[[THEN3]]:
|
||||
; LOAD: [[GEP3:%[0-9A-Za-z]+]] = getelementptr <4 x float>, <4 x float>* %p, i64 0, i64 3
|
||||
; LOAD: [[PGEP3:%[0-9A-Za-z]+]] = ptrtoint float* [[GEP3]] to i64
|
||||
; LOAD: call void @__asan_load4(i64 [[PGEP3]])
|
||||
; LOAD: br label %[[AFTER3]]
|
||||
; LOAD: <label>:[[AFTER3]]
|
||||
|
||||
; LOAD: tail call <4 x float> @llvm.masked.load.v4f32.p0v4f32(<4 x float>* %p, i32 4, <4 x i1> %mask, <4 x float> %arg)
|
||||
%res = tail call <4 x float> @llvm.masked.load.v4f32.p0v4f32(<4 x float>* %p, i32 4, <4 x i1> %mask, <4 x float> %arg)
|
||||
ret <4 x float> %res
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user