Index: lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp |
diff --git a/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp b/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp |
index 24d43f9ad6506be9d9e850bf2e4d98613a8870dd..a4cf9f66cd234ca8f803935ddd592f310d2c16ad 100644 |
--- a/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp |
+++ b/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp |
@@ -56,11 +56,15 @@ class PNaClABIVerifyFunctions : public FunctionPass { |
AtomicIntrinsics.reset(new NaCl::AtomicIntrinsics(M.getContext())); |
return false; |
} |
+ virtual void getAnalysisUsage(AnalysisUsage &Info) const { |
+ Info.setPreservesAll(); |
+ Info.addRequired<DataLayout>(); |
+ } |
bool runOnFunction(Function &F); |
virtual void print(raw_ostream &O, const Module *M) const; |
private: |
bool IsWhitelistedMetadata(unsigned MDKind); |
- const char *checkInstruction(const Instruction *Inst); |
+ const char *checkInstruction(const DataLayout *DL, const Instruction *Inst); |
PNaClABIErrorReporter *Reporter; |
bool ReporterIsOwned; |
OwningPtr<NaCl::AtomicIntrinsics> AtomicIntrinsics; |
@@ -88,14 +92,12 @@ bool PNaClABIVerifyFunctions::IsWhitelistedMetadata(unsigned MDKind) { |
// A valid pointer type is either: |
// * a pointer to a valid PNaCl scalar type (except i1), or |
+// * a pointer to a valid PNaCl vector type (except i1), or |
// * a function pointer (with valid argument and return types). |
// |
// i1 is disallowed so that all loads and stores are a whole number of |
// bytes, and so that we do not need to define whether a store of i1 |
// zero-extends. |
-// |
-// Vector pointer types aren't currently allowed because vector memory |
-// accesses go through their scalar elements. |
static bool isValidPointerType(Type *Ty) { |
if (PointerType *PtrTy = dyn_cast<PointerType>(Ty)) { |
if (PtrTy->getAddressSpace() != 0) |
@@ -103,6 +105,9 @@ static bool isValidPointerType(Type *Ty) { |
Type *EltTy = PtrTy->getElementType(); |
if (PNaClABITypeChecker::isValidScalarType(EltTy) && !EltTy->isIntegerTy(1)) |
return true; |
+ if (PNaClABITypeChecker::isValidVectorType(EltTy) && |
+ !cast<VectorType>(EltTy)->getElementType()->isIntegerTy(1)) |
+ return true; |
if (FunctionType *FTy = dyn_cast<FunctionType>(EltTy)) |
return PNaClABITypeChecker::isValidFunctionType(FTy); |
} |
@@ -166,23 +171,32 @@ static bool isValidVectorOperand(const Value *Val) { |
isa<UndefValue>(Val); |
} |
-static bool isAllowedAlignment(unsigned Alignment, Type *Ty) { |
- // Non-atomic integer operations must always use "align 1", since we |
- // do not want the backend to generate code with non-portable |
- // undefined behaviour (such as misaligned access faults) if user |
- // code specifies "align 4" but uses a misaligned pointer. As a |
- // concession to performance, we allow larger alignment values for |
- // floating point types. |
+static bool isAllowedAlignment(const DataLayout *DL, uint64_t Alignment, |
+ Type *Ty) { |
+ // Non-atomic integer operations must always use "align 1", since we do not |
+ // want the backend to generate code with non-portable undefined behaviour |
+ // (such as misaligned access faults) if user code specifies "align 4" but |
+ // uses a misaligned pointer. As a concession to performance, we allow larger |
+ // alignment values for floating point types, and we only allow vectors to be |
+ // aligned by their element's size. |
// |
- // To reduce the set of alignment values that need to be encoded in |
- // pexes, we disallow other alignment values. We require alignments |
- // to be explicit by disallowing Alignment == 0. |
+ // TODO(jfb) Allow vectors to be marked as align == 1. This requires proper |
+ // testing on each supported ISA, and is probably not as common as |
+ // align == elemsize. |
// |
- // Vector memory accesses go through their scalar elements, there is |
- // therefore no such thing as vector alignment. |
- return Alignment == 1 || |
- (Ty->isDoubleTy() && Alignment == 8) || |
- (Ty->isFloatTy() && Alignment == 4); |
+ // To reduce the set of alignment values that need to be encoded in pexes, we |
+ // disallow other alignment values. We require alignments to be explicit by |
+ // disallowing Alignment == 0. |
+ if (Alignment > std::numeric_limits<uint64_t>::max() / CHAR_BIT) |
+ return false; // No overflow assumed below. |
+ else if (VectorType *VTy = dyn_cast<VectorType>(Ty)) |
+ return !VTy->getElementType()->isIntegerTy(1) && |
+ (Alignment * CHAR_BIT == |
+ DL->getTypeSizeInBits(VTy->getElementType())); |
+ else |
+ return Alignment == 1 || |
+ (Ty->isDoubleTy() && Alignment == 8) || |
+ (Ty->isFloatTy() && Alignment == 4); |
} |
static bool hasAllowedAtomicRMWOperation( |
@@ -253,7 +267,8 @@ static bool hasAllowedLockFreeByteSize(const CallInst *Call) { |
// |
// This returns an error string if the instruction is rejected, or |
// NULL if the instruction is allowed. |
-const char *PNaClABIVerifyFunctions::checkInstruction(const Instruction *Inst) { |
+const char *PNaClABIVerifyFunctions::checkInstruction(const DataLayout *DL, |
+ const Instruction *Inst) { |
// If the instruction has a single pointer operand, PtrOperandIndex is |
// set to its operand index. |
unsigned PtrOperandIndex = -1; |
@@ -364,8 +379,7 @@ const char *PNaClABIVerifyFunctions::checkInstruction(const Instruction *Inst) { |
return "volatile load"; |
if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex))) |
return "bad pointer"; |
- if (!isAllowedAlignment(Load->getAlignment(), |
- Load->getType())) |
+ if (!isAllowedAlignment(DL, Load->getAlignment(), Load->getType())) |
return "bad alignment"; |
break; |
} |
@@ -378,7 +392,7 @@ const char *PNaClABIVerifyFunctions::checkInstruction(const Instruction *Inst) { |
return "volatile store"; |
if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex))) |
return "bad pointer"; |
- if (!isAllowedAlignment(Store->getAlignment(), |
+ if (!isAllowedAlignment(DL, Store->getAlignment(), |
Store->getValueOperand()->getType())) |
return "bad alignment"; |
break; |
@@ -541,6 +555,7 @@ const char *PNaClABIVerifyFunctions::checkInstruction(const Instruction *Inst) { |
} |
bool PNaClABIVerifyFunctions::runOnFunction(Function &F) { |
+ const DataLayout *DL = &getAnalysis<DataLayout>(); |
SmallVector<StringRef, 8> MDNames; |
F.getContext().getMDKindNames(MDNames); |
@@ -553,7 +568,7 @@ bool PNaClABIVerifyFunctions::runOnFunction(Function &F) { |
// because some instruction opcodes must be rejected out of hand |
// (regardless of the instruction's result type) and the tests |
// check the reason for rejection. |
- const char *Error = checkInstruction(BBI); |
+ const char *Error = checkInstruction(DL, BBI); |
// Check the instruction's result type. |
bool BadResult = false; |
if (!Error && !(PNaClABITypeChecker::isValidScalarType(Inst->getType()) || |