| Index: src/PNaClTranslator.cpp
|
| diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp
|
| index 46bbdb8c677148e8839e96d4b9964890d6da9ae6..2bd47b87a2bdbceee961e01f0a27506df77eddd4 100644
|
| --- a/src/PNaClTranslator.cpp
|
| +++ b/src/PNaClTranslator.cpp
|
| @@ -61,7 +61,7 @@ public:
|
| virtual ~ExtendedType() {}
|
|
|
| ExtendedType::TypeKind getKind() const { return Kind; }
|
| - void Dump(Ice::Ostream &Stream) const;
|
| + void dump(Ice::Ostream &Stream) const;
|
|
|
| /// Changes the extended type to a simple type with the given
|
| /// value.
|
| @@ -87,7 +87,7 @@ private:
|
| };
|
|
|
| Ice::Ostream &operator<<(Ice::Ostream &Stream, const ExtendedType &Ty) {
|
| - Ty.Dump(Stream);
|
| + Ty.dump(Stream);
|
| return Stream;
|
| }
|
|
|
| @@ -137,7 +137,7 @@ public:
|
| }
|
| };
|
|
|
| -void ExtendedType::Dump(Ice::Ostream &Stream) const {
|
| +void ExtendedType::dump(Ice::Ostream &Stream) const {
|
| Stream << Kind;
|
| switch (Kind) {
|
| case Simple: {
|
| @@ -1316,6 +1316,57 @@ private:
|
| return false;
|
| }
|
|
|
| + // Types of errors that can occur for insertelement and extractelement
|
| + // instructions.
|
| + enum VectorIndexCheckValue {
|
| + VectorIndexNotVector,
|
| + VectorIndexNotConstant,
|
| + VectorIndexNotInRange,
|
| + VectorIndexNotI32,
|
| + VectorIndexValid
|
| + };
|
| +
|
| + void dumpVectorIndexCheckValue(raw_ostream &Stream,
|
| + VectorIndexCheckValue Value) const {
|
| + switch (Value) {
|
| + default:
|
| + report_fatal_error("Unknown VectorIndexCheckValue");
|
| + break;
|
| + case VectorIndexNotVector:
|
| + Stream << "Vector index on non vector";
|
| + break;
|
| + case VectorIndexNotConstant:
|
| + Stream << "Vector index not integer constant";
|
| + break;
|
| + case VectorIndexNotInRange:
|
| + Stream << "Vector index not in range of vector";
|
| + break;
|
| + case VectorIndexNotI32:
|
| + Stream << "Vector index not of type " << Ice::IceType_i32;
|
| + break;
|
| + case VectorIndexValid:
|
| + Stream << "Valid vector index";
|
| + break;
|
| + }
|
| + }
|
| +
|
| + // Returns whether the given vector index (for insertelement and
|
| + // extractelement instructions) is valid.
|
| + VectorIndexCheckValue validateVectorIndex(const Ice::Operand *Vec,
|
| + const Ice::Operand *Index) const {
|
| + Ice::Type VecType = Vec->getType();
|
| + if (!Ice::isVectorType(VecType))
|
| + return VectorIndexNotVector;
|
| + const auto *C = dyn_cast<Ice::ConstantInteger32>(Index);
|
| + if (C == nullptr)
|
| + return VectorIndexNotConstant;
|
| + if (C->getValue() >= typeNumElements(VecType))
|
| + return VectorIndexNotInRange;
|
| + if (Index->getType() != Ice::IceType_i32)
|
| + return VectorIndexNotI32;
|
| + return VectorIndexValid;
|
| + }
|
| +
|
| // Reports that the given binary Opcode, for the given type Ty,
|
| // is not understood.
|
| void ReportInvalidBinopOpcode(unsigned Opcode, Ice::Type Ty);
|
| @@ -1548,6 +1599,22 @@ private:
|
| return false;
|
| }
|
| }
|
| +
|
| + // Creates an error instruction, generating a value of type Ty, and
|
| + // adds a placeholder so that instruction indices line up.
|
| + // Some instructions, such as a call, will not generate a value
|
| + // if the return type is void. In such cases, a placeholder value
|
| + // for the badly formed instruction is not needed. Hence, if Ty is
|
| + // void, an error instruction is not appended.
|
| + // TODO(kschimpf) Remove error recovery once implementation complete.
|
| + void appendErrorInstruction(Ice::Type Ty) {
|
| + // Note: we don't worry about downstream translation errors because
|
| + // the function will not be translated if any errors occur.
|
| + if (Ty == Ice::IceType_void)
|
| + return;
|
| + Ice::Variable *Var = getNextInstVar(Ty);
|
| + CurrentNode->appendInst(Ice::InstAssign::create(Func, Var, Var));
|
| + }
|
| };
|
|
|
| void FunctionParser::ReportInvalidBinopOpcode(unsigned Opcode, Ice::Type Ty) {
|
| @@ -1622,7 +1689,7 @@ void FunctionParser::ProcessRecord() {
|
| // constructor.
|
| for (size_t i = 1; i < NumBbs; ++i)
|
| InstallNextBasicBlock();
|
| - break;
|
| + return;
|
| }
|
| case naclbitc::FUNC_CODE_INST_BINOP: {
|
| // BINOP: [opval, opval, opcode]
|
| @@ -1637,8 +1704,8 @@ void FunctionParser::ProcessRecord() {
|
| raw_string_ostream StrBuf(Buffer);
|
| StrBuf << "Binop argument types differ: " << Type1 << " and " << Type2;
|
| Error(StrBuf.str());
|
| - // TODO(kschimpf) Remove error recovery once implementation complete.
|
| - Op2 = Op1;
|
| + appendErrorInstruction(Type1);
|
| + return;
|
| }
|
|
|
| Ice::InstArithmetic::OpKind Opcode;
|
| @@ -1646,7 +1713,7 @@ void FunctionParser::ProcessRecord() {
|
| return;
|
| CurrentNode->appendInst(Ice::InstArithmetic::create(
|
| Func, Opcode, getNextInstVar(Type1), Op1, Op2));
|
| - break;
|
| + return;
|
| }
|
| case naclbitc::FUNC_CODE_INST_CAST: {
|
| // CAST: [opval, destty, castopc]
|
| @@ -1662,6 +1729,7 @@ void FunctionParser::ProcessRecord() {
|
| raw_string_ostream StrBuf(Buffer);
|
| StrBuf << "Cast opcode not understood: " << Values[2];
|
| Error(StrBuf.str());
|
| + appendErrorInstruction(CastType);
|
| return;
|
| }
|
| Ice::Type SrcType = Src->getType();
|
| @@ -1672,11 +1740,12 @@ void FunctionParser::ProcessRecord() {
|
| StrBuf << "Illegal cast: " << Instruction::getOpcodeName(LLVMCastOp)
|
| << " " << SrcType << " to " << CastType;
|
| Error(StrBuf.str());
|
| + appendErrorInstruction(CastType);
|
| return;
|
| }
|
| CurrentNode->appendInst(
|
| Ice::InstCast::create(Func, CastKind, getNextInstVar(CastType), Src));
|
| - break;
|
| + return;
|
| }
|
| case naclbitc::FUNC_CODE_INST_VSELECT: {
|
| // VSELECT: [opval, opval, pred]
|
| @@ -1690,6 +1759,7 @@ void FunctionParser::ProcessRecord() {
|
| StrBuf << "Select operands not same type. Found " << ThenType << " and "
|
| << ElseType;
|
| Error(StrBuf.str());
|
| + appendErrorInstruction(ThenType);
|
| return;
|
| }
|
| Ice::Operand *CondVal = getRelativeOperand(Values[2], BaseIndex);
|
| @@ -1703,6 +1773,7 @@ void FunctionParser::ProcessRecord() {
|
| StrBuf << "Select condition type " << CondType
|
| << " not allowed for values of type " << ThenType;
|
| Error(StrBuf.str());
|
| + appendErrorInstruction(ThenType);
|
| return;
|
| }
|
| } else if (CondVal->getType() != Ice::IceType_i1) {
|
| @@ -1711,11 +1782,12 @@ void FunctionParser::ProcessRecord() {
|
| StrBuf << "Select condition " << CondVal << " not type i1. Found: "
|
| << CondVal->getType();
|
| Error(StrBuf.str());
|
| + appendErrorInstruction(ThenType);
|
| return;
|
| }
|
| CurrentNode->appendInst(Ice::InstSelect::create(
|
| Func, getNextInstVar(ThenType), CondVal, ThenVal, ElseVal));
|
| - break;
|
| + return;
|
| }
|
| case naclbitc::FUNC_CODE_INST_EXTRACTELT: {
|
| // EXTRACTELT: [opval, opval]
|
| @@ -1723,25 +1795,21 @@ void FunctionParser::ProcessRecord() {
|
| return;
|
| Ice::Operand *Vec = getRelativeOperand(Values[0], BaseIndex);
|
| Ice::Type VecType = Vec->getType();
|
| - if (!Ice::isVectorType(VecType)) {
|
| - std::string Buffer;
|
| - raw_string_ostream StrBuf(Buffer);
|
| - StrBuf << "Extractelement not on vector. Found: " << *Vec;
|
| - Error(StrBuf.str());
|
| - }
|
| Ice::Operand *Index = getRelativeOperand(Values[1], BaseIndex);
|
| - if (Index->getType() != Ice::IceType_i32) {
|
| + VectorIndexCheckValue IndexCheckValue = validateVectorIndex(Vec, Index);
|
| + if (IndexCheckValue != VectorIndexValid) {
|
| std::string Buffer;
|
| raw_string_ostream StrBuf(Buffer);
|
| - StrBuf << "Extractelement index " << *Index << " not i32. Found: "
|
| - << Index->getType();
|
| + dumpVectorIndexCheckValue(StrBuf, IndexCheckValue);
|
| + StrBuf << ": extractelement " << VecType << " " << *Vec << ", "
|
| + << Index->getType() << " " << *Index;
|
| Error(StrBuf.str());
|
| + appendErrorInstruction(VecType);
|
| + return;
|
| }
|
| - // TODO(kschimpf): Restrict index to a legal constant index (once
|
| - // constants can be defined).
|
| CurrentNode->appendInst(Ice::InstExtractElement::create(
|
| Func, getNextInstVar(typeElementType(VecType)), Vec, Index));
|
| - break;
|
| + return;
|
| }
|
| case naclbitc::FUNC_CODE_INST_INSERTELT: {
|
| // INSERTELT: [opval, opval, opval]
|
| @@ -1749,35 +1817,23 @@ void FunctionParser::ProcessRecord() {
|
| return;
|
| Ice::Operand *Vec = getRelativeOperand(Values[0], BaseIndex);
|
| Ice::Type VecType = Vec->getType();
|
| - if (!Ice::isVectorType(VecType)) {
|
| - std::string Buffer;
|
| - raw_string_ostream StrBuf(Buffer);
|
| - StrBuf << "Insertelement not on vector. Found: " << *Vec;
|
| - Error(StrBuf.str());
|
| - }
|
| Ice::Operand *Elt = getRelativeOperand(Values[1], BaseIndex);
|
| - Ice::Type EltType = Elt->getType();
|
| - if (EltType != typeElementType(VecType)) {
|
| - std::string Buffer;
|
| - raw_string_ostream StrBuf(Buffer);
|
| - StrBuf << "Insertelement element " << *Elt << " not type "
|
| - << typeElementType(VecType)
|
| - << ". Found: " << EltType;
|
| - Error(StrBuf.str());
|
| - }
|
| Ice::Operand *Index = getRelativeOperand(Values[2], BaseIndex);
|
| - if (Index->getType() != Ice::IceType_i32) {
|
| + VectorIndexCheckValue IndexCheckValue = validateVectorIndex(Vec, Index);
|
| + if (IndexCheckValue != VectorIndexValid) {
|
| std::string Buffer;
|
| raw_string_ostream StrBuf(Buffer);
|
| - StrBuf << "Insertelement index " << *Index << " not i32. Found: "
|
| - << Index->getType();
|
| + dumpVectorIndexCheckValue(StrBuf, IndexCheckValue);
|
| + StrBuf << ": insertelement " << VecType << " " << *Vec << ", "
|
| + << Elt->getType() << " " << *Elt << ", " << Index->getType() << " "
|
| + << *Index;
|
| Error(StrBuf.str());
|
| + appendErrorInstruction(Elt->getType());
|
| + return;
|
| }
|
| - // TODO(kschimpf): Restrict index to a legal constant index (once
|
| - // constants can be defined).
|
| CurrentNode->appendInst(Ice::InstInsertElement::create(
|
| Func, getNextInstVar(VecType), Vec, Elt, Index));
|
| - break;
|
| + return;
|
| }
|
| case naclbitc::FUNC_CODE_INST_CMP2: {
|
| // CMP2: [opval, opval, pred]
|
| @@ -1787,16 +1843,16 @@ void FunctionParser::ProcessRecord() {
|
| Ice::Operand *Op2 = getRelativeOperand(Values[1], BaseIndex);
|
| Ice::Type Op1Type = Op1->getType();
|
| Ice::Type Op2Type = Op2->getType();
|
| + Ice::Type DestType = getCompareResultType(Op1Type);
|
| if (Op1Type != Op2Type) {
|
| std::string Buffer;
|
| raw_string_ostream StrBuf(Buffer);
|
| StrBuf << "Compare argument types differ: " << Op1Type
|
| << " and " << Op2Type;
|
| Error(StrBuf.str());
|
| - // TODO(kschimpf) Remove error recovery once implementation complete.
|
| + appendErrorInstruction(DestType);
|
| Op2 = Op1;
|
| }
|
| - Ice::Type DestType = getCompareResultType(Op1Type);
|
| if (DestType == Ice::IceType_void) {
|
| std::string Buffer;
|
| raw_string_ostream StrBuf(Buffer);
|
| @@ -1813,8 +1869,7 @@ void FunctionParser::ProcessRecord() {
|
| StrBuf << "Compare record contains unknown integer predicate index: "
|
| << Values[2];
|
| Error(StrBuf.str());
|
| - // TODO(kschimpf) Remove error recovery once implementation complete.
|
| - Cond = Ice::InstIcmp::Eq;
|
| + appendErrorInstruction(DestType);
|
| }
|
| CurrentNode->appendInst(
|
| Ice::InstIcmp::create(Func, Cond, Dest, Op1, Op2));
|
| @@ -1826,8 +1881,7 @@ void FunctionParser::ProcessRecord() {
|
| StrBuf << "Compare record contains unknown float predicate index: "
|
| << Values[2];
|
| Error(StrBuf.str());
|
| - // TODO(kschimpf) Remove error recovery once implementation complete.
|
| - Cond = Ice::InstFcmp::False;
|
| + appendErrorInstruction(DestType);
|
| }
|
| CurrentNode->appendInst(
|
| Ice::InstFcmp::create(Func, Cond, Dest, Op1, Op2));
|
| @@ -1837,9 +1891,10 @@ void FunctionParser::ProcessRecord() {
|
| raw_string_ostream StrBuf(Buffer);
|
| StrBuf << "Compare on type not understood: " << Op1Type;
|
| Error(StrBuf.str());
|
| + appendErrorInstruction(DestType);
|
| return;
|
| }
|
| - break;
|
| + return;
|
| }
|
| case naclbitc::FUNC_CODE_INST_RET: {
|
| // RET: [opval?]
|
| @@ -1852,7 +1907,7 @@ void FunctionParser::ProcessRecord() {
|
| Ice::InstRet::create(Func, getRelativeOperand(Values[0], BaseIndex)));
|
| }
|
| InstIsTerminating = true;
|
| - break;
|
| + return;
|
| }
|
| case naclbitc::FUNC_CODE_INST_BR: {
|
| if (Values.size() == 1) {
|
| @@ -1882,7 +1937,7 @@ void FunctionParser::ProcessRecord() {
|
| Ice::InstBr::create(Func, Cond, ThenBlock, ElseBlock));
|
| }
|
| InstIsTerminating = true;
|
| - break;
|
| + return;
|
| }
|
| case naclbitc::FUNC_CODE_INST_SWITCH: {
|
| // SWITCH: [Condty, Cond, BbIndex, NumCases Case ...]
|
| @@ -1940,7 +1995,7 @@ void FunctionParser::ProcessRecord() {
|
| }
|
| CurrentNode->appendInst(Switch);
|
| InstIsTerminating = true;
|
| - break;
|
| + return;
|
| }
|
| case naclbitc::FUNC_CODE_INST_UNREACHABLE: {
|
| // UNREACHABLE: []
|
| @@ -1949,21 +2004,22 @@ void FunctionParser::ProcessRecord() {
|
| CurrentNode->appendInst(
|
| Ice::InstUnreachable::create(Func));
|
| InstIsTerminating = true;
|
| - break;
|
| + return;
|
| }
|
| case naclbitc::FUNC_CODE_INST_PHI: {
|
| // PHI: [ty, val1, bb1, ..., valN, bbN] for n >= 2.
|
| if (!isValidRecordSizeAtLeast(3, "function block phi"))
|
| return;
|
| + Ice::Type Ty = Context->getSimpleTypeByID(Values[0]);
|
| if ((Values.size() & 0x1) == 0) {
|
| // Not an odd number of values.
|
| std::string Buffer;
|
| raw_string_ostream StrBuf(Buffer);
|
| StrBuf << "function block phi record size not valid: " << Values.size();
|
| Error(StrBuf.str());
|
| + appendErrorInstruction(Ty);
|
| return;
|
| }
|
| - Ice::Type Ty = Context->getSimpleTypeByID(Values[0]);
|
| if (Ty == Ice::IceType_void) {
|
| Error("Phi record using type void not allowed");
|
| return;
|
| @@ -1979,47 +2035,53 @@ void FunctionParser::ProcessRecord() {
|
| StrBuf << "Value " << *Op << " not type " << Ty
|
| << " in phi instruction. Found: " << Op->getType();
|
| Error(StrBuf.str());
|
| + appendErrorInstruction(Ty);
|
| return;
|
| }
|
| Phi->addArgument(Op, getBasicBlock(Values[i + 1]));
|
| }
|
| CurrentNode->appendInst(Phi);
|
| - break;
|
| + return;
|
| }
|
| case naclbitc::FUNC_CODE_INST_ALLOCA: {
|
| // ALLOCA: [Size, align]
|
| if (!isValidRecordSize(2, "function block alloca"))
|
| return;
|
| Ice::Operand *ByteCount = getRelativeOperand(Values[0], BaseIndex);
|
| + Ice::Type PtrTy = Context->getIcePointerType();
|
| if (ByteCount->getType() != Ice::IceType_i32) {
|
| std::string Buffer;
|
| raw_string_ostream StrBuf(Buffer);
|
| StrBuf << "Alloca on non-i32 value. Found: " << *ByteCount;
|
| Error(StrBuf.str());
|
| + appendErrorInstruction(PtrTy);
|
| return;
|
| }
|
| unsigned Alignment;
|
| extractAlignment("Alloca", Values[1], Alignment);
|
| - CurrentNode->appendInst(
|
| - Ice::InstAlloca::create(Func, ByteCount, Alignment,
|
| - getNextInstVar(Context->getIcePointerType())));
|
| - break;
|
| + CurrentNode->appendInst(Ice::InstAlloca::create(Func, ByteCount, Alignment,
|
| + getNextInstVar(PtrTy)));
|
| + return;
|
| }
|
| case naclbitc::FUNC_CODE_INST_LOAD: {
|
| // LOAD: [address, align, ty]
|
| if (!isValidRecordSize(3, "function block load"))
|
| return;
|
| Ice::Operand *Address = getRelativeOperand(Values[0], BaseIndex);
|
| - if (!isValidPointerType(Address, "Load"))
|
| + Ice::Type Ty = Context->getSimpleTypeByID(Values[2]);
|
| + if (!isValidPointerType(Address, "Load")) {
|
| + appendErrorInstruction(Ty);
|
| return;
|
| + }
|
| unsigned Alignment;
|
| extractAlignment("Load", Values[1], Alignment);
|
| - Ice::Type Ty = Context->getSimpleTypeByID(Values[2]);
|
| - if (!isValidLoadStoreAlignment(Alignment, Ty, "Load"))
|
| + if (!isValidLoadStoreAlignment(Alignment, Ty, "Load")) {
|
| + appendErrorInstruction(Ty);
|
| return;
|
| + }
|
| CurrentNode->appendInst(
|
| Ice::InstLoad::create(Func, getNextInstVar(Ty), Address, Alignment));
|
| - break;
|
| + return;
|
| }
|
| case naclbitc::FUNC_CODE_INST_STORE: {
|
| // STORE: [address, value, align]
|
| @@ -2035,7 +2097,7 @@ void FunctionParser::ProcessRecord() {
|
| return;
|
| CurrentNode->appendInst(
|
| Ice::InstStore::create(Func, Value, Address, Alignment));
|
| - break;
|
| + return;
|
| }
|
| case naclbitc::FUNC_CODE_INST_CALL:
|
| case naclbitc::FUNC_CODE_INST_CALL_INDIRECT: {
|
| @@ -2059,19 +2121,6 @@ void FunctionParser::ProcessRecord() {
|
| ParamsStartIndex = 3;
|
| }
|
|
|
| - // Extract call information.
|
| - uint64_t CCInfo = Values[0];
|
| - CallingConv::ID CallingConv;
|
| - if (!naclbitc::DecodeCallingConv(CCInfo >> 1, CallingConv)) {
|
| - std::string Buffer;
|
| - raw_string_ostream StrBuf(Buffer);
|
| - StrBuf << "Function call calling convention value " << (CCInfo >> 1)
|
| - << " not understood.";
|
| - Error(StrBuf.str());
|
| - return;
|
| - }
|
| - bool IsTailCall = static_cast<bool>(CCInfo & 1);
|
| -
|
| // Extract out the called function and its return type.
|
| uint32_t CalleeIndex = convertRelativeToAbsIndex(Values[1], BaseIndex);
|
| Ice::Operand *Callee = getOperand(CalleeIndex);
|
| @@ -2094,6 +2143,7 @@ void FunctionParser::ProcessRecord() {
|
| raw_string_ostream StrBuf(Buffer);
|
| StrBuf << "Invalid PNaCl intrinsic call to " << Name;
|
| Error(StrBuf.str());
|
| + appendErrorInstruction(ReturnType);
|
| return;
|
| }
|
| }
|
| @@ -2101,6 +2151,20 @@ void FunctionParser::ProcessRecord() {
|
| ReturnType = Context->getSimpleTypeByID(Values[2]);
|
| }
|
|
|
| + // Extract call information.
|
| + uint64_t CCInfo = Values[0];
|
| + CallingConv::ID CallingConv;
|
| + if (!naclbitc::DecodeCallingConv(CCInfo >> 1, CallingConv)) {
|
| + std::string Buffer;
|
| + raw_string_ostream StrBuf(Buffer);
|
| + StrBuf << "Function call calling convention value " << (CCInfo >> 1)
|
| + << " not understood.";
|
| + Error(StrBuf.str());
|
| + appendErrorInstruction(ReturnType);
|
| + return;
|
| + }
|
| + bool IsTailCall = static_cast<bool>(CCInfo & 1);
|
| +
|
| // Create the call instruction.
|
| Ice::Variable *Dest = (ReturnType == Ice::IceType_void)
|
| ? nullptr
|
| @@ -2171,12 +2235,12 @@ void FunctionParser::ProcessRecord() {
|
| if (!isValidRecordSize(2, "function block forward type ref"))
|
| return;
|
| setOperand(Values[0], createInstVar(Context->getSimpleTypeByID(Values[1])));
|
| - break;
|
| + return;
|
| }
|
| default:
|
| // Generate error message!
|
| BlockParserBaseClass::ProcessRecord();
|
| - break;
|
| + return;
|
| }
|
| }
|
|
|
|
|