X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FFixedLenDecoderEmitter.cpp;h=f78c6ca6d2179911774bd1954b867d6a0346edbf;hb=4b885ee8e225e0be4d7dead8ad1b827971d53d8a;hp=7c29422ec1b9030675f712543904aee09db20407;hpb=1b40b342ebaa26f54308f34f368f8a38374ccc6b;p=oota-llvm.git diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp index 7c29422ec1b..f78c6ca6d21 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 @@ -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, @@ -448,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); @@ -540,7 +543,7 @@ void Filter::recurse() { // 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; @@ -610,7 +613,7 @@ 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()); + TableInfo.FixupStack.emplace_back(); DecoderTable &Table = TableInfo.Table; @@ -676,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; @@ -779,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; @@ -788,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) << ", "; @@ -798,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: { @@ -848,7 +871,7 @@ 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"; @@ -876,8 +899,9 @@ 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"; @@ -1033,7 +1057,8 @@ 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) @@ -1049,40 +1074,52 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation, 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 { + 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 (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, Op); + 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 @@ -1091,7 +1128,7 @@ unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders, // 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(), @@ -1102,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; @@ -1122,7 +1160,7 @@ bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation, if (!P.length()) continue; - if (i != 0) + if (!IsFirstEmission) o << " && "; StringRef SR(P); @@ -1133,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; @@ -1191,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 @@ -1250,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 @@ -1306,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. @@ -1331,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); @@ -1348,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(); } @@ -1358,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 @@ -1677,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; } @@ -1780,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; @@ -1833,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); @@ -1905,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; @@ -2010,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" @@ -2094,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" @@ -2177,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.