| 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()) ||
|
|
|