X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FFixedLenDecoderEmitter.cpp;h=df61511c8dd57d858c058b356e5cab65322a36ee;hb=85b811eedd5ba15cee44bef5ec05d846c36dbed1;hp=27114cba5e5460d562c846b47bff532000782423;hpb=6426140b901104b8f9333e9168c0e96a2a8e2c25;p=oota-llvm.git diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp index 27114cba5e5..df61511c8dd 100644 --- a/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -44,9 +44,10 @@ struct EncodingField { struct OperandInfo { std::vector Fields; std::string Decoder; + bool HasCompleteDecoder; - OperandInfo(std::string D) - : Decoder(D) { } + OperandInfo(std::string D, bool HCD) + : Decoder(D), HasCompleteDecoder(HCD) { } void addField(unsigned Base, unsigned Width, unsigned Offset) { Fields.push_back(EncodingField(Base, Width, Offset)); @@ -85,8 +86,7 @@ public: FixedLenDecoderEmitter(RecordKeeper &R, std::string PredicateNamespace, std::string GPrefix = "if (", - std::string GPostfix = " == MCDisassembler::Fail)" - " return MCDisassembler::Fail;", + std::string GPostfix = " == MCDisassembler::Fail)", std::string ROK = "MCDisassembler::Success", std::string RFail = "MCDisassembler::Fail", std::string L = "") : @@ -208,7 +208,7 @@ typedef std::vector insn_t; /// /// The Debug output shows the path that the decoding tree follows to reach the /// the conclusion that there is a conflict. VST4q8a is a vst4 to double-spaced -/// even registers, while VST4q8b is a vst4 to double-spaced odd regsisters. +/// even registers, while VST4q8b is a vst4 to double-spaced odd registers. /// /// The encoding info in the .td files does not specify this meta information, /// which could have been used by the decoder to resolve the conflict. The @@ -230,7 +230,7 @@ protected: std::vector VariableInstructions; // Map of well-known segment value to its delegate. - std::map FilterChooserMap; + std::map> FilterChooserMap; // Number of instructions which fall under FilteredInstructions category. unsigned NumFiltered; @@ -333,8 +333,8 @@ protected: // Parent emitter const FixedLenDecoderEmitter *Emitter; - FilterChooser(const FilterChooser &) LLVM_DELETED_FUNCTION; - void operator=(const FilterChooser &) LLVM_DELETED_FUNCTION; + FilterChooser(const FilterChooser &) = delete; + void operator=(const FilterChooser &) = delete; public: FilterChooser(const std::vector &Insts, @@ -343,10 +343,8 @@ public: unsigned BW, const FixedLenDecoderEmitter *E) : AllInstructions(Insts), Opcodes(IDs), Operands(Ops), Filters(), - Parent(nullptr), BestIndex(-1), BitWidth(BW), Emitter(E) { - for (unsigned i = 0; i < BitWidth; ++i) - FilterBitValues.push_back(BIT_UNFILTERED); - + FilterBitValues(BW, BIT_UNFILTERED), Parent(nullptr), BestIndex(-1), + BitWidth(BW), Emitter(E) { doFilter(); } @@ -450,10 +448,13 @@ protected: const Filter &Best) const; void emitBinaryParser(raw_ostream &o, unsigned &Indentation, - const OperandInfo &OpInfo) const; + const OperandInfo &OpInfo, + bool &OpHasCompleteDecoder) const; - void emitDecoder(raw_ostream &OS, unsigned Indentation, unsigned Opc) const; - unsigned getDecoderIndex(DecoderSet &Decoders, unsigned Opc) const; + void emitDecoder(raw_ostream &OS, unsigned Indentation, unsigned Opc, + bool &HasCompleteDecoder) const; + unsigned getDecoderIndex(DecoderSet &Decoders, unsigned Opc, + bool &HasCompleteDecoder) const; // Assign a single filter and run with it. void runSingleFilter(unsigned startBit, unsigned numBit, bool mixed); @@ -530,12 +531,6 @@ Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, } Filter::~Filter() { - std::map::iterator filterIterator; - for (filterIterator = FilterChooserMap.begin(); - filterIterator != FilterChooserMap.end(); - filterIterator++) { - delete filterIterator->second; - } } // Divides the decoding task into sub tasks and delegates them to the @@ -545,26 +540,20 @@ Filter::~Filter() { // instructions. In order to unambiguously decode the singleton, we need to // match the remaining undecoded encoding bits against the singleton. void Filter::recurse() { - std::map >::const_iterator mapIterator; - // Starts by inheriting our parent filter chooser's filter bit values. std::vector BitValueArray(Owner->FilterBitValues); - if (VariableInstructions.size()) { + if (!VariableInstructions.empty()) { // Conservatively marks each segment position as BIT_UNSET. for (unsigned bitIndex = 0; bitIndex < NumBits; ++bitIndex) BitValueArray[StartBit + bitIndex] = BIT_UNSET; // Delegates to an inferior filter chooser for further processing on this // group of instructions whose segment values are variable. - FilterChooserMap.insert(std::pair( - (unsigned)-1, - new FilterChooser(Owner->AllInstructions, - VariableInstructions, - Owner->Operands, - BitValueArray, - *Owner) - )); + FilterChooserMap.insert( + std::make_pair(-1U, llvm::make_unique( + Owner->AllInstructions, VariableInstructions, + Owner->Operands, BitValueArray, *Owner))); } // No need to recurse for a singleton filtered instruction. @@ -576,13 +565,11 @@ void Filter::recurse() { } // Otherwise, create sub choosers. - for (mapIterator = FilteredInstructions.begin(); - mapIterator != FilteredInstructions.end(); - mapIterator++) { + for (const auto &Inst : FilteredInstructions) { // Marks all the segment positions with either BIT_TRUE or BIT_FALSE. for (unsigned bitIndex = 0; bitIndex < NumBits; ++bitIndex) { - if (mapIterator->first & (1ULL << bitIndex)) + if (Inst.first & (1ULL << bitIndex)) BitValueArray[StartBit + bitIndex] = BIT_TRUE; else BitValueArray[StartBit + bitIndex] = BIT_FALSE; @@ -590,14 +577,10 @@ void Filter::recurse() { // Delegates to an inferior filter chooser for further processing on this // category of instructions. - FilterChooserMap.insert(std::pair( - mapIterator->first, - new FilterChooser(Owner->AllInstructions, - mapIterator->second, - Owner->Operands, - BitValueArray, - *Owner) - )); + FilterChooserMap.insert(std::make_pair( + Inst.first, llvm::make_unique( + Owner->AllInstructions, Inst.second, + Owner->Operands, BitValueArray, *Owner))); } } @@ -630,20 +613,16 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const { TableInfo.Table.push_back(NumBits); // A new filter entry begins a new scope for fixup resolution. - TableInfo.FixupStack.push_back(FixupList()); - - std::map::const_iterator filterIterator; + TableInfo.FixupStack.emplace_back(); DecoderTable &Table = TableInfo.Table; size_t PrevFilter = 0; bool HasFallthrough = false; - for (filterIterator = FilterChooserMap.begin(); - filterIterator != FilterChooserMap.end(); - filterIterator++) { + for (auto &Filter : FilterChooserMap) { // Field value -1 implies a non-empty set of variable instructions. // See also recurse(). - if (filterIterator->first == (unsigned)-1) { + if (Filter.first == (unsigned)-1) { HasFallthrough = true; // Each scope should always have at least one filter value to check @@ -658,7 +637,7 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const { Table.push_back(MCD::OPC_FilterValue); // Encode and emit the value to filter against. uint8_t Buffer[8]; - unsigned Len = encodeULEB128(filterIterator->first, Buffer); + unsigned Len = encodeULEB128(Filter.first, Buffer); Table.insert(Table.end(), Buffer, Buffer + Len); // Reserve space for the NumToSkip entry. We'll backpatch the value // later. @@ -671,7 +650,7 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const { // Now delegate to the sub filter chooser for further decodings. // The case may fallthrough, which happens if the remaining well-known // encoding bits do not match exactly. - filterIterator->second->emitTableEntries(TableInfo); + Filter.second->emitTableEntries(TableInfo); // Now that we've emitted the body of the handler, update the NumToSkip // of the filter itself to be able to skip forward when false. Subtract @@ -700,7 +679,7 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const { // Returns the number of fanout produced by the filter. More fanout implies // the filter distinguishes more categories of instructions. unsigned Filter::usefulness() const { - if (VariableInstructions.size()) + if (!VariableInstructions.empty()) return FilteredInstructions.size(); else return FilteredInstructions.size() + 1; @@ -803,7 +782,9 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS, OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n"; break; } - case MCD::OPC_Decode: { + case MCD::OPC_Decode: + case MCD::OPC_TryDecode: { + bool IsTry = *I == MCD::OPC_TryDecode; ++I; // Extract the ULEB128 encoded Opcode to a buffer. uint8_t Buffer[8], *p = Buffer; @@ -812,7 +793,8 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS, && "ULEB128 value too large!"); // Decode the Opcode value. unsigned Opc = decodeULEB128(Buffer); - OS.indent(Indentation) << "MCD::OPC_Decode, "; + OS.indent(Indentation) << "MCD::OPC_" << (IsTry ? "Try" : "") + << "Decode, "; for (p = Buffer; *p >= 128; ++p) OS << utostr(*p) << ", "; OS << utostr(*p) << ", "; @@ -822,8 +804,25 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS, OS << utostr(*I) << ", "; OS << utostr(*I++) << ", "; + if (!IsTry) { + OS << "// Opcode: " + << NumberedInstructions->at(Opc)->TheDef->getName() << "\n"; + break; + } + + // Fallthrough for OPC_TryDecode. + + // 16-bit numtoskip value. + uint8_t Byte = *I++; + uint32_t NumToSkip = Byte; + OS << utostr(Byte) << ", "; + Byte = *I++; + OS << utostr(Byte) << ", "; + NumToSkip |= Byte << 8; + OS << "// Opcode: " - << NumberedInstructions->at(Opc)->TheDef->getName() << "\n"; + << NumberedInstructions->at(Opc)->TheDef->getName() + << ", skip to: " << ((I - Table.begin()) + NumToSkip) << "\n"; break; } case MCD::OPC_SoftFail: { @@ -872,16 +871,15 @@ emitPredicateFunction(formatted_raw_ostream &OS, PredicateSet &Predicates, // The predicate function is just a big switch statement based on the // input predicate index. OS.indent(Indentation) << "static bool checkDecoderPredicate(unsigned Idx, " - << "uint64_t Bits) {\n"; + << "const FeatureBitset& Bits) {\n"; Indentation += 2; if (!Predicates.empty()) { OS.indent(Indentation) << "switch (Idx) {\n"; OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n"; unsigned Index = 0; - for (PredicateSet::const_iterator I = Predicates.begin(), E = Predicates.end(); - I != E; ++I, ++Index) { - OS.indent(Indentation) << "case " << Index << ":\n"; - OS.indent(Indentation+2) << "return (" << *I << ");\n"; + for (const auto &Predicate : Predicates) { + OS.indent(Indentation) << "case " << Index++ << ":\n"; + OS.indent(Indentation+2) << "return (" << Predicate << ");\n"; } OS.indent(Indentation) << "}\n"; } else { @@ -901,16 +899,16 @@ emitDecoderFunction(formatted_raw_ostream &OS, DecoderSet &Decoders, OS.indent(Indentation) << "static DecodeStatus decodeToMCInst(DecodeStatus S," << " unsigned Idx, InsnType insn, MCInst &MI,\n"; OS.indent(Indentation) << " uint64_t " - << "Address, const void *Decoder) {\n"; + << "Address, const void *Decoder, bool &DecodeComplete) {\n"; Indentation += 2; + OS.indent(Indentation) << "DecodeComplete = true;\n"; OS.indent(Indentation) << "InsnType tmp;\n"; OS.indent(Indentation) << "switch (Idx) {\n"; OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n"; unsigned Index = 0; - for (DecoderSet::const_iterator I = Decoders.begin(), E = Decoders.end(); - I != E; ++I, ++Index) { - OS.indent(Indentation) << "case " << Index << ":\n"; - OS << *I; + for (const auto &Decoder : Decoders) { + OS.indent(Indentation) << "case " << Index++ << ":\n"; + OS << Decoder; OS.indent(Indentation+2) << "return S;\n"; } OS.indent(Indentation) << "}\n"; @@ -1059,71 +1057,78 @@ unsigned FilterChooser::getIslands(std::vector &StartBits, } void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation, - const OperandInfo &OpInfo) const { + const OperandInfo &OpInfo, + bool &OpHasCompleteDecoder) const { const std::string &Decoder = OpInfo.Decoder; - if (OpInfo.numFields() == 1) { - OperandInfo::const_iterator OI = OpInfo.begin(); - o.indent(Indentation) << "tmp = fieldFromInstruction" - << "(insn, " << OI->Base << ", " << OI->Width - << ");\n"; - } else { + if (OpInfo.numFields() != 1) o.indent(Indentation) << "tmp = 0;\n"; - for (OperandInfo::const_iterator OI = OpInfo.begin(), OE = OpInfo.end(); - OI != OE; ++OI) { - o.indent(Indentation) << "tmp |= (fieldFromInstruction" - << "(insn, " << OI->Base << ", " << OI->Width - << ") << " << OI->Offset << ");\n"; - } + + for (const EncodingField &EF : OpInfo) { + o.indent(Indentation) << "tmp "; + if (OpInfo.numFields() != 1) o << '|'; + o << "= fieldFromInstruction" + << "(insn, " << EF.Base << ", " << EF.Width << ')'; + if (OpInfo.numFields() != 1 || EF.Offset != 0) + o << " << " << EF.Offset; + o << ";\n"; } - if (Decoder != "") + if (Decoder != "") { + OpHasCompleteDecoder = OpInfo.HasCompleteDecoder; o.indent(Indentation) << Emitter->GuardPrefix << Decoder - << "(MI, tmp, Address, Decoder)" - << Emitter->GuardPostfix << "\n"; - else - o.indent(Indentation) << "MI.addOperand(MCOperand::CreateImm(tmp));\n"; - + << "(MI, tmp, Address, Decoder)" + << Emitter->GuardPostfix + << " { " << (OpHasCompleteDecoder ? "" : "DecodeComplete = false; ") + << "return MCDisassembler::Fail; }\n"; + } else { + OpHasCompleteDecoder = true; + o.indent(Indentation) << "MI.addOperand(MCOperand::createImm(tmp));\n"; + } } void FilterChooser::emitDecoder(raw_ostream &OS, unsigned Indentation, - unsigned Opc) const { - std::map >::const_iterator OpIter = - Operands.find(Opc); - const std::vector& InsnOperands = OpIter->second; - for (std::vector::const_iterator - I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) { + unsigned Opc, bool &HasCompleteDecoder) const { + HasCompleteDecoder = true; + + for (const auto &Op : Operands.find(Opc)->second) { // If a custom instruction decoder was specified, use that. - if (I->numFields() == 0 && I->Decoder.size()) { - OS.indent(Indentation) << Emitter->GuardPrefix << I->Decoder + if (Op.numFields() == 0 && Op.Decoder.size()) { + HasCompleteDecoder = Op.HasCompleteDecoder; + OS.indent(Indentation) << Emitter->GuardPrefix << Op.Decoder << "(MI, insn, Address, Decoder)" - << Emitter->GuardPostfix << "\n"; + << Emitter->GuardPostfix + << " { " << (HasCompleteDecoder ? "" : "DecodeComplete = false; ") + << "return MCDisassembler::Fail; }\n"; break; } - emitBinaryParser(OS, Indentation, *I); + bool OpHasCompleteDecoder; + emitBinaryParser(OS, Indentation, Op, OpHasCompleteDecoder); + if (!OpHasCompleteDecoder) + HasCompleteDecoder = false; } } unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders, - unsigned Opc) const { + unsigned Opc, + bool &HasCompleteDecoder) const { // Build up the predicate string. SmallString<256> Decoder; // FIXME: emitDecoder() function can take a buffer directly rather than // a stream. raw_svector_ostream S(Decoder); unsigned I = 4; - emitDecoder(S, I, Opc); - S.flush(); + emitDecoder(S, I, Opc, HasCompleteDecoder); // Using the full decoder string as the key value here is a bit // heavyweight, but is effective. If the string comparisons become a // performance concern, we can implement a mangling of the predicate - // data easilly enough with a map back to the actual string. That's + // data easily enough with a map back to the actual string. That's // overkill for now, though. // Make sure the predicate is in the table. - Decoders.insert(Decoder.str()); + Decoders.insert(StringRef(Decoder)); // Now figure out the index for when we write out the table. DecoderSet::const_iterator P = std::find(Decoders.begin(), Decoders.end(), @@ -1134,17 +1139,18 @@ unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders, static void emitSinglePredicateMatch(raw_ostream &o, StringRef str, const std::string &PredicateNamespace) { if (str[0] == '!') - o << "!(Bits & " << PredicateNamespace << "::" - << str.slice(1,str.size()) << ")"; + o << "!Bits[" << PredicateNamespace << "::" + << str.slice(1,str.size()) << "]"; else - o << "(Bits & " << PredicateNamespace << "::" << str << ")"; + o << "Bits[" << PredicateNamespace << "::" << str << "]"; } bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation, unsigned Opc) const { ListInit *Predicates = AllInstructions[Opc]->TheDef->getValueAsListInit("Predicates"); - for (unsigned i = 0; i < Predicates->getSize(); ++i) { + bool IsFirstEmission = true; + for (unsigned i = 0; i < Predicates->size(); ++i) { Record *Pred = Predicates->getElementAsRecord(i); if (!Pred->getValue("AssemblerMatcherPredicate")) continue; @@ -1154,7 +1160,7 @@ bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation, if (!P.length()) continue; - if (i != 0) + if (!IsFirstEmission) o << " && "; StringRef SR(P); @@ -1165,14 +1171,15 @@ bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation, pairs = pairs.second.split(','); } emitSinglePredicateMatch(o, pairs.first, Emitter->PredicateNamespace); + IsFirstEmission = false; } - return Predicates->getSize() > 0; + return !Predicates->empty(); } bool FilterChooser::doesOpcodeNeedPredicate(unsigned Opc) const { ListInit *Predicates = AllInstructions[Opc]->TheDef->getValueAsListInit("Predicates"); - for (unsigned i = 0; i < Predicates->getSize(); ++i) { + for (unsigned i = 0; i < Predicates->size(); ++i) { Record *Pred = Predicates->getElementAsRecord(i); if (!Pred->getValue("AssemblerMatcherPredicate")) continue; @@ -1192,7 +1199,7 @@ unsigned FilterChooser::getPredicateIndex(DecoderTableInfo &TableInfo, // Using the full predicate string as the key value here is a bit // heavyweight, but is effective. If the string comparisons become a // performance concern, we can implement a mangling of the predicate - // data easilly enough with a map back to the actual string. That's + // data easily enough with a map back to the actual string. That's // overkill for now, though. // Make sure the predicate is in the table. @@ -1223,7 +1230,6 @@ void FilterChooser::emitPredicateTableEntry(DecoderTableInfo &TableInfo, SmallString<16> PBytes; raw_svector_ostream S(PBytes); encodeULEB128(PIdx, S); - S.flush(); TableInfo.Table.push_back(MCD::OPC_CheckPredicate); // Predicate index @@ -1282,16 +1288,13 @@ void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo, raw_svector_ostream S(MaskBytes); if (NeedPositiveMask) { encodeULEB128(PositiveMask.getZExtValue(), S); - S.flush(); for (unsigned i = 0, e = MaskBytes.size(); i != e; ++i) TableInfo.Table.push_back(MaskBytes[i]); } else TableInfo.Table.push_back(0); if (NeedNegativeMask) { MaskBytes.clear(); - S.resync(); encodeULEB128(NegativeMask.getZExtValue(), S); - S.flush(); for (unsigned i = 0, e = MaskBytes.size(); i != e; ++i) TableInfo.Table.push_back(MaskBytes[i]); } else @@ -1338,22 +1341,41 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, // Check for soft failure of the match. emitSoftFailTableEntry(TableInfo, Opc); - TableInfo.Table.push_back(MCD::OPC_Decode); + bool HasCompleteDecoder; + unsigned DIdx = getDecoderIndex(TableInfo.Decoders, Opc, HasCompleteDecoder); + + // Produce OPC_Decode or OPC_TryDecode opcode based on the information + // whether the instruction decoder is complete or not. If it is complete + // then it handles all possible values of remaining variable/unfiltered bits + // and for any value can determine if the bitpattern is a valid instruction + // or not. This means OPC_Decode will be the final step in the decoding + // process. If it is not complete, then the Fail return code from the + // decoder method indicates that additional processing should be done to see + // if there is any other instruction that also matches the bitpattern and + // can decode it. + TableInfo.Table.push_back(HasCompleteDecoder ? MCD::OPC_Decode : + MCD::OPC_TryDecode); uint8_t Buffer[8], *p; encodeULEB128(Opc, Buffer); for (p = Buffer; *p >= 128 ; ++p) TableInfo.Table.push_back(*p); TableInfo.Table.push_back(*p); - unsigned DIdx = getDecoderIndex(TableInfo.Decoders, Opc); SmallString<16> Bytes; raw_svector_ostream S(Bytes); encodeULEB128(DIdx, S); - S.flush(); // Decoder index for (unsigned i = 0, e = Bytes.size(); i != e; ++i) TableInfo.Table.push_back(Bytes[i]); + + if (!HasCompleteDecoder) { + // Push location for NumToSkip backpatching. + TableInfo.FixupStack.back().push_back(TableInfo.Table.size()); + // Allocate the space for the fixup. + TableInfo.Table.push_back(0); + TableInfo.Table.push_back(0); + } } // Emits table entries to decode the singleton, and then to decode the rest. @@ -1363,7 +1385,7 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, // complex singletons need predicate checks from the first singleton // to refer forward to the variable filterchooser that follows. - TableInfo.FixupStack.push_back(FixupList()); + TableInfo.FixupStack.emplace_back(); emitSingletonTableEntry(TableInfo, Opc); @@ -1380,7 +1402,7 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, void FilterChooser::runSingleFilter(unsigned startBit, unsigned numBit, bool mixed) { Filters.clear(); - Filters.push_back(Filter(*this, startBit, numBit, true)); + Filters.emplace_back(*this, startBit, numBit, true); BestIndex = 0; // Sole Filter instance to choose from. bestFilter().recurse(); } @@ -1390,9 +1412,9 @@ void FilterChooser::runSingleFilter(unsigned startBit, unsigned numBit, void FilterChooser::reportRegion(bitAttr_t RA, unsigned StartBit, unsigned BitIndex, bool AllowMixed) { if (RA == ATTR_MIXED && AllowMixed) - Filters.push_back(Filter(*this, StartBit, BitIndex - StartBit, true)); + Filters.emplace_back(*this, StartBit, BitIndex - StartBit, true); else if (RA == ATTR_ALL_SET && !AllowMixed) - Filters.push_back(Filter(*this, StartBit, BitIndex - StartBit, false)); + Filters.emplace_back(*this, StartBit, BitIndex - StartBit, false); } // FilterProcessor scans the well-known encoding bits of the instructions and @@ -1709,7 +1731,8 @@ static bool populateInstruction(CodeGenTarget &Target, // of trying to auto-generate the decoder. std::string InstDecoder = Def.getValueAsString("DecoderMethod"); if (InstDecoder != "") { - InsnOperands.push_back(OperandInfo(InstDecoder)); + bool HasCompleteInstDecoder = Def.getValueAsBit("hasCompleteDecoder"); + InsnOperands.push_back(OperandInfo(InstDecoder, HasCompleteInstDecoder)); Operands[Opc] = InsnOperands; return true; } @@ -1812,7 +1835,7 @@ static bool populateInstruction(CodeGenTarget &Target, unsigned NumberOps = CGI.Operands.size(); while (NumberedOp < NumberOps && (CGI.Operands.isFlatOperandNotEmitted(NumberedOp) || - (NamedOpIndices.size() && NamedOpIndices.count( + (!NamedOpIndices.empty() && NamedOpIndices.count( CGI.Operands.getSubOperandNumber(NumberedOp).first)))) ++NumberedOp; @@ -1865,7 +1888,14 @@ static bool populateInstruction(CodeGenTarget &Target, if (!isReg && String && String->getValue() != "") Decoder = String->getValue(); - OperandInfo OpInfo(Decoder); + RecordVal *HasCompleteDecoderVal = + TypeRecord->getValue("hasCompleteDecoder"); + BitInit *HasCompleteDecoderBit = HasCompleteDecoderVal ? + dyn_cast(HasCompleteDecoderVal->getValue()) : nullptr; + bool HasCompleteDecoder = HasCompleteDecoderBit ? + HasCompleteDecoderBit->getValue() : true; + + OperandInfo OpInfo(Decoder, HasCompleteDecoder); OpInfo.addField(bitStart, bitWidth, 0); NumberedInsnOperands[Name].push_back(OpInfo); @@ -1881,20 +1911,20 @@ static bool populateInstruction(CodeGenTarget &Target, } // For each operand, see if we can figure out where it is encoded. - for (std::vector >::const_iterator - NI = InOutOperands.begin(), NE = InOutOperands.end(); NI != NE; ++NI) { - if (!NumberedInsnOperands[NI->second].empty()) { + for (const auto &Op : InOutOperands) { + if (!NumberedInsnOperands[Op.second].empty()) { InsnOperands.insert(InsnOperands.end(), - NumberedInsnOperands[NI->second].begin(), - NumberedInsnOperands[NI->second].end()); + NumberedInsnOperands[Op.second].begin(), + NumberedInsnOperands[Op.second].end()); continue; - } else if (!NumberedInsnOperands[TiedNames[NI->second]].empty()) { - if (!NumberedInsnOperandsNoTie.count(TiedNames[NI->second])) { + } + if (!NumberedInsnOperands[TiedNames[Op.second]].empty()) { + if (!NumberedInsnOperandsNoTie.count(TiedNames[Op.second])) { // Figure out to which (sub)operand we're tied. - unsigned i = CGI.Operands.getOperandNamed(TiedNames[NI->second]); + unsigned i = CGI.Operands.getOperandNamed(TiedNames[Op.second]); int tiedTo = CGI.Operands[i].getTiedRegister(); if (tiedTo == -1) { - i = CGI.Operands.getOperandNamed(NI->second); + i = CGI.Operands.getOperandNamed(Op.second); tiedTo = CGI.Operands[i].getTiedRegister(); } @@ -1902,7 +1932,7 @@ static bool populateInstruction(CodeGenTarget &Target, std::pair SO = CGI.Operands.getSubOperandNumber(tiedTo); - InsnOperands.push_back(NumberedInsnOperands[TiedNames[NI->second]] + InsnOperands.push_back(NumberedInsnOperands[TiedNames[Op.second]] [SO.second]); } } @@ -1916,7 +1946,7 @@ static bool populateInstruction(CodeGenTarget &Target, // for decoding register classes. // FIXME: This need to be extended to handle instructions with custom // decoder methods, and operands with (simple) MIOperandInfo's. - TypedInit *TI = cast(NI->first); + TypedInit *TI = cast(Op.first); RecordRecTy *Type = cast(TI->getType()); Record *TypeRecord = Type->getRecord(); bool isReg = false; @@ -1937,7 +1967,14 @@ static bool populateInstruction(CodeGenTarget &Target, if (!isReg && String && String->getValue() != "") Decoder = String->getValue(); - OperandInfo OpInfo(Decoder); + RecordVal *HasCompleteDecoderVal = + TypeRecord->getValue("hasCompleteDecoder"); + BitInit *HasCompleteDecoderBit = HasCompleteDecoderVal ? + dyn_cast(HasCompleteDecoderVal->getValue()) : nullptr; + bool HasCompleteDecoder = HasCompleteDecoderBit ? + HasCompleteDecoderBit->getValue() : true; + + OperandInfo OpInfo(Decoder, HasCompleteDecoder); unsigned Base = ~0U; unsigned Width = 0; unsigned Offset = 0; @@ -1960,8 +1997,8 @@ static bool populateInstruction(CodeGenTarget &Target, continue; } - if (Var->getName() != NI->second && - Var->getName() != TiedNames[NI->second]) { + if (Var->getName() != Op.second && + Var->getName() != TiedNames[Op.second]) { if (Base != ~0U) { OpInfo.addField(Base, Width, Offset); Base = ~0U; @@ -2042,7 +2079,7 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) { << " InsnType insn, uint64_t Address,\n" << " const void *DisAsm,\n" << " const MCSubtargetInfo &STI) {\n" - << " uint64_t Bits = STI.getFeatureBits();\n" + << " const FeatureBitset& Bits = STI.getFeatureBits();\n" << "\n" << " const uint8_t *Ptr = DecodeTable;\n" << " uint32_t CurFieldValue = 0;\n" @@ -2126,12 +2163,52 @@ static void emitDecodeInstruction(formatted_raw_ostream &OS) { << " Ptr += Len;\n" << " unsigned DecodeIdx = decodeULEB128(Ptr, &Len);\n" << " Ptr += Len;\n" - << " DEBUG(dbgs() << Loc << \": OPC_Decode: opcode \" << Opc\n" - << " << \", using decoder \" << DecodeIdx << \"\\n\" );\n" - << " DEBUG(dbgs() << \"----- DECODE SUCCESSFUL -----\\n\");\n" << "\n" + << " MI.clear();\n" << " MI.setOpcode(Opc);\n" - << " return decodeToMCInst(S, DecodeIdx, insn, MI, Address, DisAsm);\n" + << " bool DecodeComplete;\n" + << " S = decodeToMCInst(S, DecodeIdx, insn, MI, Address, DisAsm, DecodeComplete);\n" + << " assert(DecodeComplete);\n" + << "\n" + << " DEBUG(dbgs() << Loc << \": OPC_Decode: opcode \" << Opc\n" + << " << \", using decoder \" << DecodeIdx << \": \"\n" + << " << (S != MCDisassembler::Fail ? \"PASS\" : \"FAIL\") << \"\\n\");\n" + << " return S;\n" + << " }\n" + << " case MCD::OPC_TryDecode: {\n" + << " unsigned Len;\n" + << " // Decode the Opcode value.\n" + << " unsigned Opc = decodeULEB128(++Ptr, &Len);\n" + << " Ptr += Len;\n" + << " unsigned DecodeIdx = decodeULEB128(Ptr, &Len);\n" + << " Ptr += Len;\n" + << " // NumToSkip is a plain 16-bit integer.\n" + << " unsigned NumToSkip = *Ptr++;\n" + << " NumToSkip |= (*Ptr++) << 8;\n" + << "\n" + << " // Perform the decode operation.\n" + << " MCInst TmpMI;\n" + << " TmpMI.setOpcode(Opc);\n" + << " bool DecodeComplete;\n" + << " S = decodeToMCInst(S, DecodeIdx, insn, TmpMI, Address, DisAsm, DecodeComplete);\n" + << " DEBUG(dbgs() << Loc << \": OPC_TryDecode: opcode \" << Opc\n" + << " << \", using decoder \" << DecodeIdx << \": \");\n" + << "\n" + << " if (DecodeComplete) {\n" + << " // Decoding complete.\n" + << " DEBUG(dbgs() << (S != MCDisassembler::Fail ? \"PASS\" : \"FAIL\") << \"\\n\");\n" + << " MI = TmpMI;\n" + << " return S;\n" + << " } else {\n" + << " assert(S == MCDisassembler::Fail);\n" + << " // If the decoding was incomplete, skip.\n" + << " Ptr += NumToSkip;\n" + << " DEBUG(dbgs() << \"FAIL: continuing at \" << (Ptr - DecodeTable) << \"\\n\");\n" + << " // Reset decode status. This also drops a SoftFail status that could be\n" + << " // set before the decode attempt.\n" + << " S = MCDisassembler::Success;\n" + << " }\n" + << " break;\n" << " }\n" << " case MCD::OPC_SoftFail: {\n" << " // Decode the mask values.\n" @@ -2198,12 +2275,10 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) { } DecoderTableInfo TableInfo; - for (std::map, - std::vector >::const_iterator - I = OpcMap.begin(), E = OpcMap.end(); I != E; ++I) { + for (const auto &Opc : OpcMap) { // Emit the decoder for this namespace+width combination. - FilterChooser FC(*NumberedInstructions, I->second, Operands, - 8*I->first.second, this); + FilterChooser FC(*NumberedInstructions, Opc.second, Operands, + 8*Opc.first.second, this); // The decode table is cleared for each top level decoder function. The // predicates and decoders themselves, however, are shared across all @@ -2211,7 +2286,7 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) { TableInfo.Table.clear(); TableInfo.FixupStack.clear(); TableInfo.Table.reserve(16384); - TableInfo.FixupStack.push_back(FixupList()); + TableInfo.FixupStack.emplace_back(); FC.emitTableEntries(TableInfo); // Any NumToSkip fixups in the top level scope can resolve to the // OPC_Fail at the end of the table. @@ -2224,7 +2299,7 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) { TableInfo.Table.push_back(MCD::OPC_Fail); // Print the table to the output stream. - emitTable(OS, TableInfo.Table, 0, FC.getBitWidth(), I->first.first); + emitTable(OS, TableInfo.Table, 0, FC.getBitWidth(), Opc.first.first); OS.flush(); }