Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(503)

Unified Diff: lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp

Issue 221693002: PNaCl: Add support for GCC/LLVM vector extensions (Closed) Base URL: http://git.chromium.org/native_client/pnacl-llvm.git@master
Patch Set: Address dschuff's comments. Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp
diff --git a/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp b/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp
index c1c909cc46618e6880b0df260b08ecdf8d173fa6..1ef3ec45f72dcc5d01781f9e9811f7ff025fe567 100644
--- a/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp
+++ b/lib/Analysis/NaCl/PNaClABIVerifyFunctions.cpp
@@ -93,13 +93,15 @@ bool PNaClABIVerifyFunctions::IsWhitelistedMetadata(unsigned MDKind) {
// 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)
return false;
Type *EltTy = PtrTy->getElementType();
- if (PNaClABITypeChecker::isValidScalarType(EltTy) &&
- !EltTy->isIntegerTy(1))
+ if (PNaClABITypeChecker::isValidScalarType(EltTy) && !EltTy->isIntegerTy(1))
return true;
if (FunctionType *FTy = dyn_cast<FunctionType>(EltTy))
return PNaClABITypeChecker::isValidFunctionType(FTy);
@@ -152,6 +154,16 @@ static bool isValidScalarOperand(const Value *Val) {
isa<UndefValue>(Val));
}
+static bool isValidVectorOperand(const Value *Val) {
+ // The types of Instructions and Arguments are checked elsewhere.
+ if (isa<Instruction>(Val) || isa<Argument>(Val))
+ return true;
+ // Contrary to scalars, constant vector values aren't allowed on
+ // instructions, except for aggregate zero and undefined.
+ return PNaClABITypeChecker::isValidVectorType(Val->getType()) &&
+ (isa<ConstantAggregateZero>(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
@@ -163,6 +175,9 @@ static bool isAllowedAlignment(unsigned Alignment, Type *Ty) {
// 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.
+ //
+ // 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);
@@ -253,9 +268,7 @@ const char *PNaClABIVerifyFunctions::checkInstruction(const Instruction *Inst) {
case Instruction::Resume:
// indirectbr may interfere with streaming
case Instruction::IndirectBr:
- // No vector instructions yet
- case Instruction::ExtractElement:
- case Instruction::InsertElement:
+ // TODO(jfb) Figure out ShuffleVector.
case Instruction::ShuffleVector:
// ExtractValue and InsertValue operate on struct values.
case Instruction::ExtractValue:
@@ -312,10 +325,32 @@ const char *PNaClABIVerifyFunctions::checkInstruction(const Instruction *Inst) {
case Instruction::SRem:
case Instruction::Shl:
case Instruction::LShr:
- case Instruction::AShr:
- if (Inst->getOperand(0)->getType()->isIntegerTy(1))
+ case Instruction::AShr: {
+ Type *Op0Ty = Inst->getOperand(0)->getType();
+ if (Op0Ty->isIntegerTy(1))
return "arithmetic on i1";
+ if (VectorType *Op0VTy = dyn_cast<VectorType>(Op0Ty))
+ if (Op0VTy->getElementType()->isIntegerTy(1))
+ return "arithmetic on vector of i1";
break;
+ }
+
+ // Vector.
+ case Instruction::ExtractElement:
+ case Instruction::InsertElement: {
+ // Insert and extract element are restricted to constant indices
+ // that are in range to prevent undefined behavior.
+ Value *Vec = Inst->getOperand(0);
+ Value *Idx = Inst->getOperand(
+ Instruction::InsertElement == Inst->getOpcode() ? 2 : 1);
+ if (!isa<ConstantInt>(Idx))
+ return "non-constant vector insert/extract index";
+ const APInt &I = cast<ConstantInt>(Idx)->getValue();
+ unsigned NumElements = cast<VectorType>(Vec->getType())->getNumElements();
+ if (!I.ult(NumElements))
+ return "out of range vector insert/extract index";
+ break;
+ }
// Memory accesses.
case Instruction::Load: {
@@ -325,11 +360,11 @@ const char *PNaClABIVerifyFunctions::checkInstruction(const Instruction *Inst) {
return "atomic load";
if (Load->isVolatile())
return "volatile load";
+ if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex)))
+ return "bad pointer";
if (!isAllowedAlignment(Load->getAlignment(),
Load->getType()))
return "bad alignment";
- if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex)))
- return "bad pointer";
break;
}
case Instruction::Store: {
@@ -339,11 +374,11 @@ const char *PNaClABIVerifyFunctions::checkInstruction(const Instruction *Inst) {
return "atomic store";
if (Store->isVolatile())
return "volatile store";
+ if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex)))
+ return "bad pointer";
if (!isAllowedAlignment(Store->getAlignment(),
Store->getValueOperand()->getType()))
return "bad alignment";
- if (!isNormalizedPtr(Inst->getOperand(PtrOperandIndex)))
- return "bad pointer";
break;
}
@@ -392,6 +427,7 @@ const char *PNaClABIVerifyFunctions::checkInstruction(const Instruction *Inst) {
ArgNum < E; ++ArgNum) {
const Value *Arg = Call->getArgOperand(ArgNum);
if (!(isValidScalarOperand(Arg) ||
+ isValidVectorOperand(Arg) ||
isNormalizedPtr(Arg) ||
isa<MDNode>(Arg)))
return "bad intrinsic operand";
@@ -476,10 +512,11 @@ const char *PNaClABIVerifyFunctions::checkInstruction(const Instruction *Inst) {
}
// Check the instruction's operands. We have already checked any
- // pointer operands. Any remaining operands must be scalars.
+ // pointer operands. Any remaining operands must be scalars or vectors.
for (unsigned OpNum = 0, E = Inst->getNumOperands(); OpNum < E; ++OpNum) {
if (OpNum != PtrOperandIndex &&
- !isValidScalarOperand(Inst->getOperand(OpNum)))
+ !(isValidScalarOperand(Inst->getOperand(OpNum)) ||
+ isValidVectorOperand(Inst->getOperand(OpNum))))
return "bad operand";
}
@@ -516,14 +553,19 @@ bool PNaClABIVerifyFunctions::runOnFunction(Function &F) {
// check the reason for rejection.
const char *Error = checkInstruction(BBI);
// Check the instruction's result type.
+ bool BadResult = false;
if (!Error && !(PNaClABITypeChecker::isValidScalarType(Inst->getType()) ||
+ PNaClABITypeChecker::isValidVectorType(Inst->getType()) ||
isNormalizedPtr(Inst) ||
isa<AllocaInst>(Inst))) {
Error = "bad result type";
+ BadResult = true;
}
if (Error) {
- Reporter->addError() << "Function " << F.getName() <<
- " disallowed: " << Error << ": " << *BBI << "\n";
+ Reporter->addError()
+ << "Function " << F.getName() << " disallowed: " << Error << ": "
+ << (BadResult ? PNaClABITypeChecker::getTypeName(BBI->getType())
+ : "") << " " << *BBI << "\n";
}
// Check instruction attachment metadata.

Powered by Google App Engine
This is Rietveld 408576698