Chromium Code Reviews| Index: lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp |
| diff --git a/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp b/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp |
| index 24d43f9ad6506be9d9e850bf2e4d98613a8870dd..986c6094699e289765b5197b9ca08686fb400d34 100644 |
| --- a/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp |
| +++ b/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp |
| @@ -56,11 +56,14 @@ class PNaClABIVerifyFunctions : public FunctionPass { |
| AtomicIntrinsics.reset(new NaCl::AtomicIntrinsics(M.getContext())); |
| return false; |
| } |
| + virtual void getAnalysisUsage(AnalysisUsage &Info) const { |
| + Info.addRequired<DataLayout>(); |
|
jvoung (off chromium)
2014/06/10 16:28:32
Should probably also setPreservesAll() ?
JF
2014/06/10 18:26:29
Done.
|
| + } |
| 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 +91,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 +104,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 +170,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 +266,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 +378,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 +391,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 +554,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 +567,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()) || |