diff options
Diffstat (limited to 'llvm/utils')
| -rw-r--r-- | llvm/utils/TableGen/InstrInfoEmitter.cpp | 1093 | ||||
| -rw-r--r-- | llvm/utils/UpdateTestChecks/common.py | 1 | ||||
| -rw-r--r-- | llvm/utils/UpdateTestChecks/mir.py | 11 | ||||
| -rw-r--r-- | llvm/utils/gn/secondary/libcxx/include/BUILD.gn | 1 | ||||
| -rw-r--r-- | llvm/utils/gn/secondary/lldb/source/Target/BUILD.gn | 1 | ||||
| -rwxr-xr-x | llvm/utils/update_llc_test_checks.py | 94 |
6 files changed, 619 insertions, 582 deletions
diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp index 0b90f91..e725de1 100644 --- a/llvm/utils/TableGen/InstrInfoEmitter.cpp +++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp @@ -341,8 +341,6 @@ emitGetOperandIdxName(raw_ostream &OS, void InstrInfoEmitter::emitOperandNameMappings( raw_ostream &OS, const CodeGenTarget &Target, ArrayRef<const CodeGenInstruction *> TargetInstructions) { - StringRef Namespace = Target.getInstNamespace(); - // Map of operand names to their ID. MapVector<StringRef, unsigned> OperandNameToID; @@ -383,38 +381,35 @@ void InstrInfoEmitter::emitOperandNameMappings( const size_t NumOperandNames = OperandNameToID.size(); const unsigned MaxNumOperands = MaxOperandNo + 1; - OS << "#ifdef GET_INSTRINFO_OPERAND_ENUM\n"; - OS << "#undef GET_INSTRINFO_OPERAND_ENUM\n"; - OS << "namespace llvm::" << Namespace << " {\n"; - - assert(NumOperandNames <= UINT16_MAX && - "Too many operands for the operand index -> name table"); - StringRef EnumType = getMinimalTypeForRange(NumOperandNames); - OS << "enum class OpName : " << EnumType << " {\n"; - for (const auto &[Op, I] : OperandNameToID) - OS << " " << Op << " = " << I << ",\n"; - OS << " NUM_OPERAND_NAMES = " << NumOperandNames << ",\n"; - OS << "}; // enum class OpName\n\n"; - - OS << "LLVM_READONLY int16_t getNamedOperandIdx(uint16_t Opcode, OpName " - "Name);\n"; - OS << "LLVM_READONLY OpName getOperandIdxName(uint16_t Opcode, int16_t " - "Idx);\n"; - OS << "} // end namespace llvm::" << Namespace << '\n'; - OS << "#endif //GET_INSTRINFO_OPERAND_ENUM\n\n"; - - OS << "#ifdef GET_INSTRINFO_NAMED_OPS\n"; - OS << "#undef GET_INSTRINFO_NAMED_OPS\n"; - OS << "namespace llvm::" << Namespace << " {\n"; - - emitGetInstructionIndexForOpLookup(OS, OperandMap, InstructionIndex); + const SmallString<32> Namespace({"llvm::", Target.getInstNamespace()}); + { + IfDefEmitter IfDef(OS, "GET_INSTRINFO_OPERAND_ENUM"); + NamespaceEmitter NS(OS, Namespace); + + assert(NumOperandNames <= UINT16_MAX && + "Too many operands for the operand index -> name table"); + StringRef EnumType = getMinimalTypeForRange(NumOperandNames); + OS << "enum class OpName : " << EnumType << " {\n"; + for (const auto &[Op, I] : OperandNameToID) + OS << " " << Op << " = " << I << ",\n"; + OS << " NUM_OPERAND_NAMES = " << NumOperandNames << ",\n"; + OS << "}; // enum class OpName\n\n"; + + OS << "LLVM_READONLY int16_t getNamedOperandIdx(uint16_t Opcode, OpName " + "Name);\n"; + OS << "LLVM_READONLY OpName getOperandIdxName(uint16_t Opcode, int16_t " + "Idx);\n"; + } - emitGetNamedOperandIdx(OS, OperandMap, MaxOperandNo, NumOperandNames); - emitGetOperandIdxName(OS, OperandNameToID, OperandMap, MaxNumOperands, - NumOperandNames); + { + IfDefEmitter IfDef(OS, "GET_INSTRINFO_NAMED_OPS"); + NamespaceEmitter NS(OS, Namespace); + emitGetInstructionIndexForOpLookup(OS, OperandMap, InstructionIndex); - OS << "} // end namespace llvm::" << Namespace << '\n'; - OS << "#endif //GET_INSTRINFO_NAMED_OPS\n\n"; + emitGetNamedOperandIdx(OS, OperandMap, MaxOperandNo, NumOperandNames); + emitGetOperandIdxName(OS, OperandNameToID, OperandMap, MaxNumOperands, + NumOperandNames); + } } /// Generate an enum for all the operand types for this target, under the @@ -439,121 +434,121 @@ void InstrInfoEmitter::emitOperandTypeMappings( ArrayRef<const Record *> RegisterClasses = Records.getAllDerivedDefinitions("RegisterClass"); - OS << "#ifdef GET_INSTRINFO_OPERAND_TYPES_ENUM\n"; - OS << "#undef GET_INSTRINFO_OPERAND_TYPES_ENUM\n"; - OS << "namespace llvm::" << Namespace << "::OpTypes {\n"; - OS << "enum OperandType {\n"; - unsigned EnumVal = 0; - for (ArrayRef<const Record *> RecordsToAdd : - {Operands, RegisterOperands, RegisterClasses}) { - for (const Record *Op : RecordsToAdd) { - if (!Op->isAnonymous()) - OS << " " << Op->getName() << " = " << EnumVal << ",\n"; - ++EnumVal; + + { + IfDefEmitter IfDef(OS, "GET_INSTRINFO_OPERAND_TYPES_ENUM"); + NamespaceEmitter NS(OS, ("llvm::" + Namespace + "::OpTypes").str()); + OS << "enum OperandType {\n"; + + for (ArrayRef<const Record *> RecordsToAdd : + {Operands, RegisterOperands, RegisterClasses}) { + for (const Record *Op : RecordsToAdd) { + if (!Op->isAnonymous()) + OS << " " << Op->getName() << " = " << EnumVal << ",\n"; + ++EnumVal; + } } + + OS << " OPERAND_TYPE_LIST_END" << "\n};\n"; } - OS << " OPERAND_TYPE_LIST_END" - << "\n};\n"; - OS << "} // end namespace llvm::" << Namespace << "::OpTypes\n"; - OS << "#endif // GET_INSTRINFO_OPERAND_TYPES_ENUM\n\n"; - - OS << "#ifdef GET_INSTRINFO_OPERAND_TYPE\n"; - OS << "#undef GET_INSTRINFO_OPERAND_TYPE\n"; - OS << "namespace llvm::" << Namespace << " {\n"; - OS << "LLVM_READONLY\n"; - OS << "static int getOperandType(uint16_t Opcode, uint16_t OpIdx) {\n"; - auto getInstrName = [&](int I) -> StringRef { - return NumberedInstructions[I]->getName(); - }; - // TODO: Factor out duplicate operand lists to compress the tables. - std::vector<size_t> OperandOffsets; - std::vector<const Record *> OperandRecords; - size_t CurrentOffset = 0; - for (const CodeGenInstruction *Inst : NumberedInstructions) { - OperandOffsets.push_back(CurrentOffset); - for (const auto &Op : Inst->Operands) { - const DagInit *MIOI = Op.MIOperandInfo; - if (!ExpandMIOperandInfo || !MIOI || MIOI->getNumArgs() == 0) { - // Single, anonymous, operand. - OperandRecords.push_back(Op.Rec); - ++CurrentOffset; - } else { - for (const Init *Arg : MIOI->getArgs()) { - OperandRecords.push_back(cast<DefInit>(Arg)->getDef()); + { + IfDefEmitter IfDef(OS, "GET_INSTRINFO_OPERAND_TYPE"); + NamespaceEmitter NS(OS, ("llvm::" + Namespace).str()); + OS << "LLVM_READONLY\n"; + OS << "static int getOperandType(uint16_t Opcode, uint16_t OpIdx) {\n"; + auto getInstrName = [&](int I) -> StringRef { + return NumberedInstructions[I]->getName(); + }; + // TODO: Factor out duplicate operand lists to compress the tables. + std::vector<size_t> OperandOffsets; + std::vector<const Record *> OperandRecords; + size_t CurrentOffset = 0; + for (const CodeGenInstruction *Inst : NumberedInstructions) { + OperandOffsets.push_back(CurrentOffset); + for (const auto &Op : Inst->Operands) { + const DagInit *MIOI = Op.MIOperandInfo; + if (!ExpandMIOperandInfo || !MIOI || MIOI->getNumArgs() == 0) { + // Single, anonymous, operand. + OperandRecords.push_back(Op.Rec); ++CurrentOffset; + } else { + for (const Init *Arg : MIOI->getArgs()) { + OperandRecords.push_back(cast<DefInit>(Arg)->getDef()); + ++CurrentOffset; + } } } } - } - // Emit the table of offsets (indexes) into the operand type table. - // Size the unsigned integer offset to save space. - assert(OperandRecords.size() <= UINT32_MAX && - "Too many operands for offset table"); - OS << " static constexpr " << getMinimalTypeForRange(OperandRecords.size()); - OS << " Offsets[] = {\n"; - for (const auto &[Idx, Offset] : enumerate(OperandOffsets)) - OS << " " << Offset << ", // " << getInstrName(Idx) << '\n'; - OS << " };\n"; + // Emit the table of offsets (indexes) into the operand type table. + // Size the unsigned integer offset to save space. + assert(OperandRecords.size() <= UINT32_MAX && + "Too many operands for offset table"); + OS << " static constexpr " + << getMinimalTypeForRange(OperandRecords.size()); + OS << " Offsets[] = {\n"; + for (const auto &[Idx, Offset] : enumerate(OperandOffsets)) + OS << " " << Offset << ", // " << getInstrName(Idx) << '\n'; + OS << " };\n"; - // Add an entry for the end so that we don't need to special case it below. - OperandOffsets.push_back(OperandRecords.size()); - - // Emit the actual operand types in a flat table. - // Size the signed integer operand type to save space. - assert(EnumVal <= INT16_MAX && - "Too many operand types for operand types table"); - OS << "\n using namespace OpTypes;\n"; - OS << " static"; - OS << (EnumVal <= INT8_MAX ? " constexpr int8_t" : " constexpr int16_t"); - OS << " OpcodeOperandTypes[] = {"; - size_t CurOffset = 0; - for (auto [Idx, OpR] : enumerate(OperandRecords)) { - // We print each Opcode's operands in its own row. - if (Idx == OperandOffsets[CurOffset]) { - OS << "\n /* " << getInstrName(CurOffset) << " */\n "; - while (OperandOffsets[++CurOffset] == Idx) - OS << "/* " << getInstrName(CurOffset) << " */\n "; + // Add an entry for the end so that we don't need to special case it below. + OperandOffsets.push_back(OperandRecords.size()); + + // Emit the actual operand types in a flat table. + // Size the signed integer operand type to save space. + assert(EnumVal <= INT16_MAX && + "Too many operand types for operand types table"); + OS << "\n using namespace OpTypes;\n"; + OS << " static"; + OS << (EnumVal <= INT8_MAX ? " constexpr int8_t" : " constexpr int16_t"); + OS << " OpcodeOperandTypes[] = {"; + size_t CurOffset = 0; + for (auto [Idx, OpR] : enumerate(OperandRecords)) { + // We print each Opcode's operands in its own row. + if (Idx == OperandOffsets[CurOffset]) { + OS << "\n /* " << getInstrName(CurOffset) << " */\n "; + while (OperandOffsets[++CurOffset] == Idx) + OS << "/* " << getInstrName(CurOffset) << " */\n "; + } + if ((OpR->isSubClassOf("Operand") || + OpR->isSubClassOf("RegisterOperand") || + OpR->isSubClassOf("RegisterClass")) && + !OpR->isAnonymous()) + OS << OpR->getName(); + else + OS << -1; + OS << ", "; } - if ((OpR->isSubClassOf("Operand") || OpR->isSubClassOf("RegisterOperand") || - OpR->isSubClassOf("RegisterClass")) && - !OpR->isAnonymous()) - OS << OpR->getName(); - else - OS << -1; - OS << ", "; - } - OS << "\n };\n"; + OS << "\n };\n"; - OS << " return OpcodeOperandTypes[Offsets[Opcode] + OpIdx];\n"; - OS << "}\n"; - OS << "} // end namespace llvm::" << Namespace << '\n'; - OS << "#endif // GET_INSTRINFO_OPERAND_TYPE\n\n"; - - OS << "#ifdef GET_INSTRINFO_MEM_OPERAND_SIZE\n"; - OS << "#undef GET_INSTRINFO_MEM_OPERAND_SIZE\n"; - OS << "namespace llvm::" << Namespace << " {\n"; - OS << "LLVM_READONLY\n"; - OS << "static int getMemOperandSize(int OpType) {\n"; - OS << " switch (OpType) {\n"; - std::map<int, SmallVector<StringRef, 0>> SizeToOperandName; - for (const Record *Op : Operands) { - if (!Op->isSubClassOf("X86MemOperand")) - continue; - if (int Size = Op->getValueAsInt("Size")) - SizeToOperandName[Size].push_back(Op->getName()); + OS << " return OpcodeOperandTypes[Offsets[Opcode] + OpIdx];\n"; + OS << "}\n"; } - OS << " default: return 0;\n"; - for (const auto &[Size, OperandNames] : SizeToOperandName) { - for (const StringRef &OperandName : OperandNames) - OS << " case OpTypes::" << OperandName << ":\n"; - OS << " return " << Size << ";\n\n"; + + { + IfDefEmitter IfDef(OS, "GET_INSTRINFO_MEM_OPERAND_SIZE"); + NamespaceEmitter NS(OS, ("llvm::" + Namespace).str()); + + OS << "LLVM_READONLY\n"; + OS << "static int getMemOperandSize(int OpType) {\n"; + OS << " switch (OpType) {\n"; + std::map<int, SmallVector<StringRef, 0>> SizeToOperandName; + for (const Record *Op : Operands) { + if (!Op->isSubClassOf("X86MemOperand")) + continue; + if (int Size = Op->getValueAsInt("Size")) + SizeToOperandName[Size].push_back(Op->getName()); + } + OS << " default: return 0;\n"; + for (const auto &[Size, OperandNames] : SizeToOperandName) { + for (const StringRef &OperandName : OperandNames) + OS << " case OpTypes::" << OperandName << ":\n"; + OS << " return " << Size << ";\n\n"; + } + OS << " }\n}\n"; } - OS << " }\n}\n"; - OS << "} // end namespace llvm::" << Namespace << '\n'; - OS << "#endif // GET_INSTRINFO_MEM_OPERAND_SIZE\n\n"; } // Fixed/Predefined instructions do not have UseLogicalOperandMappings @@ -587,9 +582,8 @@ void InstrInfoEmitter::emitLogicalOperandSizeMappings( InstMap[I->second].push_back((Namespace + "::" + Inst->getName()).str()); } - OS << "#ifdef GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP\n"; - OS << "#undef GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP\n"; - OS << "namespace llvm::" << Namespace << " {\n"; + IfDefEmitter IfDef(OS, "GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP"); + NamespaceEmitter NS(OS, ("llvm::" + Namespace).str()); OS << "LLVM_READONLY static unsigned\n"; OS << "getLogicalOperandSize(uint16_t Opcode, uint16_t LogicalOpIdx) {\n"; if (!InstMap.empty()) { @@ -637,9 +631,6 @@ void InstrInfoEmitter::emitLogicalOperandSizeMappings( OS << " S += getLogicalOperandSize(Opcode, i);\n"; OS << " return S;\n"; OS << "}\n"; - - OS << "} // end namespace llvm::" << Namespace << '\n'; - OS << "#endif // GET_INSTRINFO_LOGICAL_OPERAND_SIZE_MAP\n\n"; } void InstrInfoEmitter::emitMCIIHelperMethods(raw_ostream &OS, @@ -647,48 +638,38 @@ void InstrInfoEmitter::emitMCIIHelperMethods(raw_ostream &OS, ArrayRef<const Record *> TIIPredicates = Records.getAllDerivedDefinitions("TIIPredicate"); - OS << "#ifdef GET_INSTRINFO_MC_HELPER_DECLS\n"; - OS << "#undef GET_INSTRINFO_MC_HELPER_DECLS\n\n"; - - OS << "namespace llvm {\n"; - OS << "class MCInst;\n"; - OS << "class FeatureBitset;\n\n"; + { + IfDefEmitter IfDef(OS, "GET_INSTRINFO_MC_HELPER_DECLS"); + NamespaceEmitter LlvmNS(OS, "llvm"); + OS << "class MCInst;\n"; + OS << "class FeatureBitset;\n\n"; - OS << "namespace " << TargetName << "_MC {\n\n"; + NamespaceEmitter TargetNS(OS, (TargetName + "_MC").str()); + for (const Record *Rec : TIIPredicates) + OS << "bool " << Rec->getValueAsString("FunctionName") + << "(const MCInst &MI);\n"; - for (const Record *Rec : TIIPredicates) { - OS << "bool " << Rec->getValueAsString("FunctionName") - << "(const MCInst &MI);\n"; + OS << "void verifyInstructionPredicates(unsigned Opcode, const " + "FeatureBitset " + "&Features);\n"; } - OS << "void verifyInstructionPredicates(unsigned Opcode, const FeatureBitset " - "&Features);\n"; - - OS << "\n} // end namespace " << TargetName << "_MC\n"; - OS << "} // end namespace llvm\n\n"; - - OS << "#endif // GET_INSTRINFO_MC_HELPER_DECLS\n\n"; - - OS << "#ifdef GET_INSTRINFO_MC_HELPERS\n"; - OS << "#undef GET_INSTRINFO_MC_HELPERS\n\n"; - - OS << "namespace llvm::" << TargetName << "_MC {\n"; + { + IfDefEmitter IfDef(OS, "GET_INSTRINFO_MC_HELPERS"); + NamespaceEmitter NS(OS, ("llvm::" + TargetName + "_MC").str()); - PredicateExpander PE(TargetName); - PE.setExpandForMC(true); + PredicateExpander PE(TargetName); + PE.setExpandForMC(true); - for (const Record *Rec : TIIPredicates) { - OS << "bool " << Rec->getValueAsString("FunctionName"); - OS << "(const MCInst &MI) {\n"; + for (const Record *Rec : TIIPredicates) { + OS << "bool " << Rec->getValueAsString("FunctionName"); + OS << "(const MCInst &MI) {\n"; - OS << PE.getIndent(); - PE.expandStatement(OS, Rec->getValueAsDef("Body")); - OS << "\n}\n\n"; + OS << PE.getIndent(); + PE.expandStatement(OS, Rec->getValueAsDef("Body")); + OS << "\n}\n\n"; + } } - - OS << "} // end namespace llvm::" << TargetName << "_MC\n"; - - OS << "#endif // GET_GENISTRINFO_MC_HELPERS\n\n"; } static std::string @@ -710,148 +691,143 @@ void InstrInfoEmitter::emitFeatureVerifier(raw_ostream &OS, << " defined(GET_AVAILABLE_OPCODE_CHECKER)\n" << "#define GET_COMPUTE_FEATURES\n" << "#endif\n"; - OS << "#ifdef GET_COMPUTE_FEATURES\n" - << "#undef GET_COMPUTE_FEATURES\n" - << "namespace llvm::" << Target.getName() << "_MC {\n"; - - // Emit the subtarget feature enumeration. - SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures, - OS); - // Emit the available features compute function. - OS << "inline "; - SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures( - Target.getName(), "", "computeAvailableFeatures", SubtargetFeatures, OS); - - std::vector<std::vector<const Record *>> FeatureBitsets; - for (const CodeGenInstruction *Inst : Target.getInstructions()) { - FeatureBitsets.emplace_back(); - for (const Record *Predicate : - Inst->TheDef->getValueAsListOfDefs("Predicates")) { - const auto &I = SubtargetFeatures.find(Predicate); - if (I != SubtargetFeatures.end()) - FeatureBitsets.back().push_back(I->second.TheDef); + std::string Namespace = ("llvm::" + Target.getName() + "_MC").str(); + { + IfDefEmitter IfDef(OS, "GET_COMPUTE_FEATURES"); + NamespaceEmitter NS(OS, Namespace); + + // Emit the subtarget feature enumeration. + SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures, + OS); + // Emit the available features compute function. + OS << "inline "; + SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures( + Target.getName(), "", "computeAvailableFeatures", SubtargetFeatures, + OS); + + std::vector<std::vector<const Record *>> FeatureBitsets; + for (const CodeGenInstruction *Inst : Target.getInstructions()) { + FeatureBitsets.emplace_back(); + for (const Record *Predicate : + Inst->TheDef->getValueAsListOfDefs("Predicates")) { + const auto &I = SubtargetFeatures.find(Predicate); + if (I != SubtargetFeatures.end()) + FeatureBitsets.back().push_back(I->second.TheDef); + } } - } - llvm::sort(FeatureBitsets, [&](ArrayRef<const Record *> A, - ArrayRef<const Record *> B) { - if (A.size() < B.size()) - return true; - if (A.size() > B.size()) - return false; - for (auto Pair : zip(A, B)) { - if (std::get<0>(Pair)->getName() < std::get<1>(Pair)->getName()) + llvm::sort(FeatureBitsets, [&](ArrayRef<const Record *> A, + ArrayRef<const Record *> B) { + if (A.size() < B.size()) return true; - if (std::get<0>(Pair)->getName() > std::get<1>(Pair)->getName()) + if (A.size() > B.size()) return false; + for (auto Pair : zip(A, B)) { + if (std::get<0>(Pair)->getName() < std::get<1>(Pair)->getName()) + return true; + if (std::get<0>(Pair)->getName() > std::get<1>(Pair)->getName()) + return false; + } + return false; + }); + FeatureBitsets.erase(llvm::unique(FeatureBitsets), FeatureBitsets.end()); + OS << "inline FeatureBitset computeRequiredFeatures(unsigned Opcode) {\n" + << " enum : " << getMinimalTypeForRange(FeatureBitsets.size()) << " {\n" + << " CEFBS_None,\n"; + for (const auto &FeatureBitset : FeatureBitsets) { + if (FeatureBitset.empty()) + continue; + OS << " " << getNameForFeatureBitset(FeatureBitset) << ",\n"; } - return false; - }); - FeatureBitsets.erase(llvm::unique(FeatureBitsets), FeatureBitsets.end()); - OS << "inline FeatureBitset computeRequiredFeatures(unsigned Opcode) {\n" - << " enum : " << getMinimalTypeForRange(FeatureBitsets.size()) << " {\n" - << " CEFBS_None,\n"; - for (const auto &FeatureBitset : FeatureBitsets) { - if (FeatureBitset.empty()) - continue; - OS << " " << getNameForFeatureBitset(FeatureBitset) << ",\n"; - } - OS << " };\n\n" - << " static constexpr FeatureBitset FeatureBitsets[] = {\n" - << " {}, // CEFBS_None\n"; - for (const auto &FeatureBitset : FeatureBitsets) { - if (FeatureBitset.empty()) - continue; - OS << " {"; - for (const auto &Feature : FeatureBitset) { - const auto &I = SubtargetFeatures.find(Feature); - assert(I != SubtargetFeatures.end() && "Didn't import predicate?"); - OS << I->second.getEnumBitName() << ", "; + OS << " };\n\n" + << " static constexpr FeatureBitset FeatureBitsets[] = {\n" + << " {}, // CEFBS_None\n"; + for (const auto &FeatureBitset : FeatureBitsets) { + if (FeatureBitset.empty()) + continue; + OS << " {"; + for (const auto &Feature : FeatureBitset) { + const auto &I = SubtargetFeatures.find(Feature); + assert(I != SubtargetFeatures.end() && "Didn't import predicate?"); + OS << I->second.getEnumBitName() << ", "; + } + OS << "},\n"; } - OS << "},\n"; - } - OS << " };\n" - << " static constexpr " << getMinimalTypeForRange(FeatureBitsets.size()) - << " RequiredFeaturesRefs[] = {\n"; - ArrayRef<const CodeGenInstruction *> NumberedInstructions = - Target.getInstructions(); - for (const CodeGenInstruction *Inst : NumberedInstructions) { - OS << " CEFBS"; - unsigned NumPredicates = 0; - for (const Record *Predicate : - Inst->TheDef->getValueAsListOfDefs("Predicates")) { - const auto &I = SubtargetFeatures.find(Predicate); - if (I != SubtargetFeatures.end()) { - OS << '_' << I->second.TheDef->getName(); - NumPredicates++; + OS << " };\n" + << " static constexpr " << getMinimalTypeForRange(FeatureBitsets.size()) + << " RequiredFeaturesRefs[] = {\n"; + ArrayRef<const CodeGenInstruction *> NumberedInstructions = + Target.getInstructions(); + for (const CodeGenInstruction *Inst : NumberedInstructions) { + OS << " CEFBS"; + unsigned NumPredicates = 0; + for (const Record *Predicate : + Inst->TheDef->getValueAsListOfDefs("Predicates")) { + const auto &I = SubtargetFeatures.find(Predicate); + if (I != SubtargetFeatures.end()) { + OS << '_' << I->second.TheDef->getName(); + NumPredicates++; + } } + if (!NumPredicates) + OS << "_None"; + OS << ", // " << Inst->getName() << '\n'; } - if (!NumPredicates) - OS << "_None"; - OS << ", // " << Inst->getName() << '\n'; + OS << " };\n\n" + << " assert(Opcode < " << NumberedInstructions.size() << ");\n" + << " return FeatureBitsets[RequiredFeaturesRefs[Opcode]];\n" + << "}\n\n"; + } // end scope for GET_COMPUTE_FEATURES + + { + IfDefEmitter IfDef(OS, "GET_AVAILABLE_OPCODE_CHECKER"); + NamespaceEmitter NS(OS, Namespace); + OS << "bool isOpcodeAvailable(" + << "unsigned Opcode, const FeatureBitset &Features) {\n" + << " FeatureBitset AvailableFeatures = " + << "computeAvailableFeatures(Features);\n" + << " FeatureBitset RequiredFeatures = " + << "computeRequiredFeatures(Opcode);\n" + << " FeatureBitset MissingFeatures =\n" + << " (AvailableFeatures & RequiredFeatures) ^\n" + << " RequiredFeatures;\n" + << " return !MissingFeatures.any();\n" + << "}\n"; + } + + { + IfDefEmitter IfDef(OS, "ENABLE_INSTR_PREDICATE_VERIFIER"); + OS << "#include <sstream>\n\n"; + NamespaceEmitter NS(OS, Namespace); + // Emit the name table for error messages. + OS << "#ifndef NDEBUG\n"; + SubtargetFeatureInfo::emitNameTable(SubtargetFeatures, OS); + OS << "#endif // NDEBUG\n\n"; + // Emit the predicate verifier. + OS << "void verifyInstructionPredicates(\n" + << " unsigned Opcode, const FeatureBitset &Features) {\n" + << "#ifndef NDEBUG\n"; + OS << " FeatureBitset AvailableFeatures = " + "computeAvailableFeatures(Features);\n"; + OS << " FeatureBitset RequiredFeatures = " + << "computeRequiredFeatures(Opcode);\n"; + OS << " FeatureBitset MissingFeatures =\n" + << " (AvailableFeatures & RequiredFeatures) ^\n" + << " RequiredFeatures;\n" + << " if (MissingFeatures.any()) {\n" + << " std::ostringstream Msg;\n" + << " Msg << \"Attempting to emit \" << &" << Target.getName() + << "InstrNameData[" << Target.getName() << "InstrNameIndices[Opcode]]\n" + << " << \" instruction but the \";\n" + << " for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i)\n" + << " if (MissingFeatures.test(i))\n" + << " Msg << SubtargetFeatureNames[i] << \" \";\n" + << " Msg << \"predicate(s) are not met\";\n" + << " report_fatal_error(Msg.str().c_str());\n" + << " }\n" + << "#endif // NDEBUG\n"; + OS << "}\n"; } - OS << " };\n\n" - << " assert(Opcode < " << NumberedInstructions.size() << ");\n" - << " return FeatureBitsets[RequiredFeaturesRefs[Opcode]];\n" - << "}\n\n"; - - OS << "} // end namespace llvm::" << Target.getName() << "_MC\n" - << "#endif // GET_COMPUTE_FEATURES\n\n"; - - OS << "#ifdef GET_AVAILABLE_OPCODE_CHECKER\n" - << "#undef GET_AVAILABLE_OPCODE_CHECKER\n" - << "namespace llvm::" << Target.getName() << "_MC {\n"; - OS << "bool isOpcodeAvailable(" - << "unsigned Opcode, const FeatureBitset &Features) {\n" - << " FeatureBitset AvailableFeatures = " - << "computeAvailableFeatures(Features);\n" - << " FeatureBitset RequiredFeatures = " - << "computeRequiredFeatures(Opcode);\n" - << " FeatureBitset MissingFeatures =\n" - << " (AvailableFeatures & RequiredFeatures) ^\n" - << " RequiredFeatures;\n" - << " return !MissingFeatures.any();\n" - << "}\n"; - OS << "} // end namespace llvm::" << Target.getName() << "_MC\n" - << "#endif // GET_AVAILABLE_OPCODE_CHECKER\n\n"; - - OS << "#ifdef ENABLE_INSTR_PREDICATE_VERIFIER\n" - << "#undef ENABLE_INSTR_PREDICATE_VERIFIER\n" - << "#include <sstream>\n\n"; - - OS << "namespace llvm::" << Target.getName() << "_MC {\n"; - - // Emit the name table for error messages. - OS << "#ifndef NDEBUG\n"; - SubtargetFeatureInfo::emitNameTable(SubtargetFeatures, OS); - OS << "#endif // NDEBUG\n\n"; - - // Emit the predicate verifier. - OS << "void verifyInstructionPredicates(\n" - << " unsigned Opcode, const FeatureBitset &Features) {\n" - << "#ifndef NDEBUG\n"; - OS << " FeatureBitset AvailableFeatures = " - "computeAvailableFeatures(Features);\n"; - OS << " FeatureBitset RequiredFeatures = " - << "computeRequiredFeatures(Opcode);\n"; - OS << " FeatureBitset MissingFeatures =\n" - << " (AvailableFeatures & RequiredFeatures) ^\n" - << " RequiredFeatures;\n" - << " if (MissingFeatures.any()) {\n" - << " std::ostringstream Msg;\n" - << " Msg << \"Attempting to emit \" << &" << Target.getName() - << "InstrNameData[" << Target.getName() << "InstrNameIndices[Opcode]]\n" - << " << \" instruction but the \";\n" - << " for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i)\n" - << " if (MissingFeatures.test(i))\n" - << " Msg << SubtargetFeatureNames[i] << \" \";\n" - << " Msg << \"predicate(s) are not met\";\n" - << " report_fatal_error(Msg.str().c_str());\n" - << " }\n" - << "#endif // NDEBUG\n"; - OS << "}\n"; - OS << "} // end namespace llvm::" << Target.getName() << "_MC\n"; - OS << "#endif // ENABLE_INSTR_PREDICATE_VERIFIER\n\n"; } void InstrInfoEmitter::emitTIIHelperMethods(raw_ostream &OS, @@ -954,270 +930,263 @@ void InstrInfoEmitter::run(raw_ostream &OS) { OS << "#endif // defined(GET_INSTRINFO_MC_DESC) || " "defined(GET_INSTRINFO_CTOR_DTOR)\n\n"; - OS << "#ifdef GET_INSTRINFO_MC_DESC\n"; - OS << "#undef GET_INSTRINFO_MC_DESC\n"; - OS << "namespace llvm {\n\n"; - - // Emit all of the MCInstrDesc records in reverse ENUM ordering. - Timer.startTimer("Emit InstrDesc records"); - OS << "static_assert(sizeof(MCOperandInfo) % sizeof(MCPhysReg) == 0);\n"; - OS << "static constexpr unsigned " << TargetName << "ImpOpBase = sizeof " - << TargetName << "InstrTable::OperandInfo / (sizeof(MCPhysReg));\n\n"; - - OS << "extern const " << TargetName << "InstrTable " << TargetName - << "Descs = {\n {\n"; - SequenceToOffsetTable<StringRef> InstrNames; - unsigned Num = NumberedInstructions.size(); - for (const CodeGenInstruction *Inst : reverse(NumberedInstructions)) { - // Keep a list of the instruction names. - InstrNames.add(Inst->getName()); - // Emit the record into the table. - emitRecord(*Inst, --Num, InstrInfo, EmittedLists, OperandInfoMap, OS); - } - - OS << " }, {\n"; - - // Emit all of the operand info records. - Timer.startTimer("Emit operand info"); - EmitOperandInfo(OS, OperandInfoList); - - OS << " }, {\n"; - - // Emit all of the instruction's implicit uses and defs. - Timer.startTimer("Emit uses/defs"); - for (auto &List : ImplicitLists) { - OS << " /* " << EmittedLists[List] << " */"; - for (auto &Reg : List) - OS << ' ' << getQualifiedName(Reg) << ','; - OS << '\n'; - } - - OS << " }\n};\n\n"; - - // Emit the array of instruction names. - Timer.startTimer("Emit instruction names"); - InstrNames.layout(); - InstrNames.emitStringLiteralDef(OS, Twine("extern const char ") + TargetName + - "InstrNameData[]"); const CodeGenRegBank &RegBank = Target.getRegBank(); const CodeGenHwModes &CGH = Target.getHwModes(); unsigned NumModes = CGH.getNumModeIds(); ArrayRef<const Record *> RegClassByHwMode = Target.getAllRegClassByHwMode(); unsigned NumClassesByHwMode = RegClassByHwMode.size(); - OS << "extern const unsigned " << TargetName << "InstrNameIndices[] = {"; - Num = 0; - for (const CodeGenInstruction *Inst : NumberedInstructions) { - // Newline every eight entries. - if (Num % 8 == 0) - OS << "\n "; - OS << InstrNames.get(Inst->getName()) << "U, "; - ++Num; - } - OS << "\n};\n\n"; - bool HasDeprecationFeatures = llvm::any_of(NumberedInstructions, [](const CodeGenInstruction *Inst) { return !Inst->HasComplexDeprecationPredicate && !Inst->DeprecatedReason.empty(); }); - if (HasDeprecationFeatures) { - OS << "extern const uint8_t " << TargetName - << "InstrDeprecationFeatures[] = {"; - Num = 0; - for (const CodeGenInstruction *Inst : NumberedInstructions) { - if (Num % 8 == 0) - OS << "\n "; - if (!Inst->HasComplexDeprecationPredicate && - !Inst->DeprecatedReason.empty()) - OS << Target.getInstNamespace() << "::" << Inst->DeprecatedReason - << ", "; - else - OS << "uint8_t(-1), "; - ++Num; - } - OS << "\n};\n\n"; - } - bool HasComplexDeprecationInfos = llvm::any_of(NumberedInstructions, [](const CodeGenInstruction *Inst) { return Inst->HasComplexDeprecationPredicate; }); - if (HasComplexDeprecationInfos) { - OS << "extern const MCInstrInfo::ComplexDeprecationPredicate " << TargetName - << "InstrComplexDeprecationInfos[] = {"; + + { + IfDefEmitter IfDef(OS, "GET_INSTRINFO_MC_DESC"); + NamespaceEmitter LlvmNS(OS, "llvm"); + + // Emit all of the MCInstrDesc records in reverse ENUM ordering. + Timer.startTimer("Emit InstrDesc records"); + OS << "static_assert(sizeof(MCOperandInfo) % sizeof(MCPhysReg) == 0);\n"; + OS << "static constexpr unsigned " << TargetName << "ImpOpBase = sizeof " + << TargetName << "InstrTable::OperandInfo / (sizeof(MCPhysReg));\n\n"; + + OS << "extern const " << TargetName << "InstrTable " << TargetName + << "Descs = {\n {\n"; + SequenceToOffsetTable<StringRef> InstrNames; + unsigned Num = NumberedInstructions.size(); + for (const CodeGenInstruction *Inst : reverse(NumberedInstructions)) { + // Keep a list of the instruction names. + InstrNames.add(Inst->getName()); + // Emit the record into the table. + emitRecord(*Inst, --Num, InstrInfo, EmittedLists, OperandInfoMap, OS); + } + + OS << " }, {\n"; + + // Emit all of the operand info records. + Timer.startTimer("Emit operand info"); + EmitOperandInfo(OS, OperandInfoList); + + OS << " }, {\n"; + + // Emit all of the instruction's implicit uses and defs. + Timer.startTimer("Emit uses/defs"); + for (auto &List : ImplicitLists) { + OS << " /* " << EmittedLists[List] << " */"; + for (auto &Reg : List) + OS << ' ' << getQualifiedName(Reg) << ','; + OS << '\n'; + } + + OS << " }\n};\n\n"; + + // Emit the array of instruction names. + Timer.startTimer("Emit instruction names"); + InstrNames.layout(); + InstrNames.emitStringLiteralDef(OS, Twine("extern const char ") + + TargetName + "InstrNameData[]"); + OS << "extern const unsigned " << TargetName << "InstrNameIndices[] = {"; Num = 0; for (const CodeGenInstruction *Inst : NumberedInstructions) { + // Newline every eight entries. if (Num % 8 == 0) OS << "\n "; - if (Inst->HasComplexDeprecationPredicate) - // Emit a function pointer to the complex predicate method. - OS << "&get" << Inst->DeprecatedReason << "DeprecationInfo, "; - else - OS << "nullptr, "; + OS << InstrNames.get(Inst->getName()) << "U, "; ++Num; } OS << "\n};\n\n"; - } - - // MCInstrInfo initialization routine. - Timer.startTimer("Emit initialization routine"); - - if (NumClassesByHwMode != 0) { - OS << "extern const int16_t " << TargetName << "RegClassByHwModeTables[" - << NumModes << "][" << NumClassesByHwMode << "] = {\n"; - for (unsigned M = 0; M < NumModes; ++M) { - OS << " { // " << CGH.getModeName(M, /*IncludeDefault=*/true) << '\n'; - for (unsigned I = 0; I != NumClassesByHwMode; ++I) { - const Record *Class = RegClassByHwMode[I]; - const HwModeSelect &ModeSelect = CGH.getHwModeSelect(Class); - - auto FoundMode = - find_if(ModeSelect.Items, [=](const HwModeSelect::PairType P) { - return P.first == M; - }); - - if (FoundMode == ModeSelect.Items.end()) { - // If a RegClassByHwMode doesn't have an entry corresponding to a - // mode, pad with default register class. - OS << indent(4) << "-1, // Missing mode entry\n"; - } else { - const CodeGenRegisterClass *RegClass = - RegBank.getRegClass(FoundMode->second); - OS << indent(4) << RegClass->getQualifiedIdName() << ",\n"; - } + if (HasDeprecationFeatures) { + OS << "extern const uint8_t " << TargetName + << "InstrDeprecationFeatures[] = {"; + Num = 0; + for (const CodeGenInstruction *Inst : NumberedInstructions) { + if (Num % 8 == 0) + OS << "\n "; + if (!Inst->HasComplexDeprecationPredicate && + !Inst->DeprecatedReason.empty()) + OS << Target.getInstNamespace() << "::" << Inst->DeprecatedReason + << ", "; + else + OS << "uint8_t(-1), "; + ++Num; } - - OS << " },\n"; + OS << "\n};\n\n"; } - OS << "};\n\n"; - } + if (HasComplexDeprecationInfos) { + OS << "extern const MCInstrInfo::ComplexDeprecationPredicate " + << TargetName << "InstrComplexDeprecationInfos[] = {"; + Num = 0; + for (const CodeGenInstruction *Inst : NumberedInstructions) { + if (Num % 8 == 0) + OS << "\n "; + if (Inst->HasComplexDeprecationPredicate) + // Emit a function pointer to the complex predicate method. + OS << "&get" << Inst->DeprecatedReason << "DeprecationInfo, "; + else + OS << "nullptr, "; + ++Num; + } + OS << "\n};\n\n"; + } - OS << "static inline void Init" << TargetName - << "MCInstrInfo(MCInstrInfo *II) {\n"; - OS << " II->InitMCInstrInfo(" << TargetName << "Descs.Insts, " << TargetName - << "InstrNameIndices, " << TargetName << "InstrNameData, "; - if (HasDeprecationFeatures) - OS << TargetName << "InstrDeprecationFeatures, "; - else - OS << "nullptr, "; - if (HasComplexDeprecationInfos) - OS << TargetName << "InstrComplexDeprecationInfos, "; - else - OS << "nullptr, "; - OS << NumberedInstructions.size() << ", "; - - if (NumClassesByHwMode != 0) { - OS << '&' << TargetName << "RegClassByHwModeTables[0][0], " - << NumClassesByHwMode; - } else - OS << "nullptr, 0"; - - OS << ");\n}\n\n"; + // MCInstrInfo initialization routine. + Timer.startTimer("Emit initialization routine"); + + if (NumClassesByHwMode != 0) { + OS << "extern const int16_t " << TargetName << "RegClassByHwModeTables[" + << NumModes << "][" << NumClassesByHwMode << "] = {\n"; + + for (unsigned M = 0; M < NumModes; ++M) { + OS << " { // " << CGH.getModeName(M, /*IncludeDefault=*/true) << '\n'; + for (unsigned I = 0; I != NumClassesByHwMode; ++I) { + const Record *Class = RegClassByHwMode[I]; + const HwModeSelect &ModeSelect = CGH.getHwModeSelect(Class); + + auto FoundMode = + find_if(ModeSelect.Items, [=](const HwModeSelect::PairType P) { + return P.first == M; + }); + + if (FoundMode == ModeSelect.Items.end()) { + // If a RegClassByHwMode doesn't have an entry corresponding to a + // mode, pad with default register class. + OS << indent(4) << "-1, // Missing mode entry\n"; + } else { + const CodeGenRegisterClass *RegClass = + RegBank.getRegClass(FoundMode->second); + OS << indent(4) << RegClass->getQualifiedIdName() << ",\n"; + } + } - OS << "} // end namespace llvm\n"; + OS << " },\n"; + } - OS << "#endif // GET_INSTRINFO_MC_DESC\n\n"; + OS << "};\n\n"; + } - // Create a TargetInstrInfo subclass to hide the MC layer initialization. - OS << "#ifdef GET_INSTRINFO_HEADER\n"; - OS << "#undef GET_INSTRINFO_HEADER\n"; + OS << "static inline void Init" << TargetName + << "MCInstrInfo(MCInstrInfo *II) {\n"; + OS << " II->InitMCInstrInfo(" << TargetName << "Descs.Insts, " + << TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, "; + if (HasDeprecationFeatures) + OS << TargetName << "InstrDeprecationFeatures, "; + else + OS << "nullptr, "; + if (HasComplexDeprecationInfos) + OS << TargetName << "InstrComplexDeprecationInfos, "; + else + OS << "nullptr, "; + OS << NumberedInstructions.size() << ", "; - Twine ClassName = TargetName + "GenInstrInfo"; - OS << "namespace llvm {\n"; - OS << "struct " << ClassName << " : public TargetInstrInfo {\n" - << " explicit " << ClassName - << "(const TargetSubtargetInfo &STI, unsigned CFSetupOpcode = ~0u, " - "unsigned CFDestroyOpcode = ~0u, " - "unsigned CatchRetOpcode = ~0u, unsigned ReturnOpcode = ~0u);\n" - << " ~" << ClassName << "() override = default;\n"; + if (NumClassesByHwMode != 0) { + OS << '&' << TargetName << "RegClassByHwModeTables[0][0], " + << NumClassesByHwMode; + } else + OS << "nullptr, 0"; - OS << "\n};\n} // end namespace llvm\n"; + OS << ");\n}\n\n"; + } // end GET_INSTRINFO_MC_DESC scope. { - NamespaceEmitter LlvmNS(OS, "llvm"); - NamespaceEmitter TargetNS(OS, Target.getInstNamespace()); + // Create a TargetInstrInfo subclass to hide the MC layer initialization. + IfDefEmitter IfDef(OS, "GET_INSTRINFO_HEADER"); + { + NamespaceEmitter LlvmNS(OS, "llvm"); + Twine ClassName = TargetName + "GenInstrInfo"; + OS << "struct " << ClassName << " : public TargetInstrInfo {\n" + << " explicit " << ClassName + << "(const TargetSubtargetInfo &STI, unsigned CFSetupOpcode = ~0u, " + "unsigned CFDestroyOpcode = ~0u, " + "unsigned CatchRetOpcode = ~0u, unsigned ReturnOpcode = ~0u);\n" + << " ~" << ClassName << "() override = default;\n" + << "};\n"; + } // end llvm namespace. + + OS << "\n"; + NamespaceEmitter InstNS(OS, ("llvm::" + Target.getInstNamespace()).str()); for (const Record *R : Records.getAllDerivedDefinitions("Operand")) { if (R->isAnonymous()) continue; - if (const DagInit *D = R->getValueAsDag("MIOperandInfo")) { - for (unsigned i = 0, e = D->getNumArgs(); i < e; ++i) { - if (const StringInit *Name = D->getArgName(i)) - OS << "constexpr unsigned SUBOP_" << R->getName() << "_" - << Name->getValue() << " = " << i << ";\n"; - } + const DagInit *D = R->getValueAsDag("MIOperandInfo"); + if (!D) + continue; + for (const auto &[Idx, Name] : enumerate(D->getArgNames())) { + if (Name) + OS << "constexpr unsigned SUBOP_" << R->getName() << "_" + << Name->getValue() << " = " << Idx << ";\n"; } } - } - - OS << "#endif // GET_INSTRINFO_HEADER\n\n"; - - OS << "#ifdef GET_INSTRINFO_HELPER_DECLS\n"; - OS << "#undef GET_INSTRINFO_HELPER_DECLS\n\n"; - emitTIIHelperMethods(OS, TargetName, /* ExpandDefinition = */ false); - OS << '\n'; - OS << "#endif // GET_INSTRINFO_HELPER_DECLS\n\n"; - - OS << "#ifdef GET_INSTRINFO_HELPERS\n"; - OS << "#undef GET_INSTRINFO_HELPERS\n\n"; - emitTIIHelperMethods(OS, TargetName, /* ExpandDefinition = */ true); - OS << "#endif // GET_INSTRINFO_HELPERS\n\n"; + } // end GET_INSTRINFO_HEADER scope. - OS << "#ifdef GET_INSTRINFO_CTOR_DTOR\n"; - OS << "#undef GET_INSTRINFO_CTOR_DTOR\n"; - - OS << "namespace llvm {\n"; - OS << "extern const " << TargetName << "InstrTable " << TargetName - << "Descs;\n"; - OS << "extern const unsigned " << TargetName << "InstrNameIndices[];\n"; - OS << "extern const char " << TargetName << "InstrNameData[];\n"; - - if (NumClassesByHwMode != 0) { - OS << "extern const int16_t " << TargetName << "RegClassByHwModeTables[" - << NumModes << "][" << NumClassesByHwMode << "];\n"; + { + IfDefEmitter IfDef(OS, "GET_INSTRINFO_HELPER_DECLS"); + emitTIIHelperMethods(OS, TargetName, /* ExpandDefinition = */ false); } - if (HasDeprecationFeatures) - OS << "extern const uint8_t " << TargetName - << "InstrDeprecationFeatures[];\n"; - if (HasComplexDeprecationInfos) - OS << "extern const MCInstrInfo::ComplexDeprecationPredicate " << TargetName - << "InstrComplexDeprecationInfos[];\n"; - OS << ClassName << "::" << ClassName - << "(const TargetSubtargetInfo &STI, unsigned CFSetupOpcode, unsigned " - "CFDestroyOpcode, unsigned CatchRetOpcode, unsigned ReturnOpcode)\n" - << " : TargetInstrInfo(CFSetupOpcode, CFDestroyOpcode, CatchRetOpcode, " - "ReturnOpcode"; - if (NumClassesByHwMode != 0) - OS << ", " << TargetName - << "RegClassByHwModeTables[STI.getHwMode(MCSubtargetInfo::HwMode_" - "RegInfo)]"; - - OS << ") {\n" - << " InitMCInstrInfo(" << TargetName << "Descs.Insts, " << TargetName - << "InstrNameIndices, " << TargetName << "InstrNameData, "; - if (HasDeprecationFeatures) - OS << TargetName << "InstrDeprecationFeatures, "; - else - OS << "nullptr, "; - if (HasComplexDeprecationInfos) - OS << TargetName << "InstrComplexDeprecationInfos, "; - else - OS << "nullptr, "; - OS << NumberedInstructions.size(); - - if (NumClassesByHwMode != 0) { - OS << ", &" << TargetName << "RegClassByHwModeTables[0][0], " - << NumClassesByHwMode; + { + IfDefEmitter IfDef(OS, "GET_INSTRINFO_HELPERS"); + emitTIIHelperMethods(OS, TargetName, /* ExpandDefinition = */ true); } - OS << ");\n" - "}\n" - "} // end namespace llvm\n"; + { + IfDefEmitter IfDef(OS, "GET_INSTRINFO_CTOR_DTOR"); + NamespaceEmitter LlvmNS(OS, "llvm"); + OS << "extern const " << TargetName << "InstrTable " << TargetName + << "Descs;\n"; + OS << "extern const unsigned " << TargetName << "InstrNameIndices[];\n"; + OS << "extern const char " << TargetName << "InstrNameData[];\n"; + + if (NumClassesByHwMode != 0) { + OS << "extern const int16_t " << TargetName << "RegClassByHwModeTables[" + << NumModes << "][" << NumClassesByHwMode << "];\n"; + } + + if (HasDeprecationFeatures) + OS << "extern const uint8_t " << TargetName + << "InstrDeprecationFeatures[];\n"; + if (HasComplexDeprecationInfos) + OS << "extern const MCInstrInfo::ComplexDeprecationPredicate " + << TargetName << "InstrComplexDeprecationInfos[];\n"; + Twine ClassName = TargetName + "GenInstrInfo"; + OS << ClassName << "::" << ClassName + << "(const TargetSubtargetInfo &STI, unsigned CFSetupOpcode, unsigned " + "CFDestroyOpcode, unsigned CatchRetOpcode, unsigned ReturnOpcode)\n" + << " : TargetInstrInfo(CFSetupOpcode, CFDestroyOpcode, CatchRetOpcode, " + "ReturnOpcode"; + if (NumClassesByHwMode != 0) + OS << ", " << TargetName + << "RegClassByHwModeTables[STI.getHwMode(MCSubtargetInfo::HwMode_" + "RegInfo)]"; + + OS << ") {\n" + << " InitMCInstrInfo(" << TargetName << "Descs.Insts, " << TargetName + << "InstrNameIndices, " << TargetName << "InstrNameData, "; + if (HasDeprecationFeatures) + OS << TargetName << "InstrDeprecationFeatures, "; + else + OS << "nullptr, "; + if (HasComplexDeprecationInfos) + OS << TargetName << "InstrComplexDeprecationInfos, "; + else + OS << "nullptr, "; + OS << NumberedInstructions.size(); - OS << "#endif // GET_INSTRINFO_CTOR_DTOR\n\n"; + if (NumClassesByHwMode != 0) { + OS << ", &" << TargetName << "RegClassByHwModeTables[0][0], " + << NumClassesByHwMode; + } + + OS << ");\n" + "}\n"; + } // end GET_INSTRINFO_CTOR_DTOR scope. ArrayRef<const CodeGenInstruction *> TargetInstructions = Target.getTargetInstructions(); @@ -1384,8 +1353,6 @@ void InstrInfoEmitter::emitRecord( void InstrInfoEmitter::emitEnums( raw_ostream &OS, ArrayRef<const CodeGenInstruction *> NumberedInstructions) { - OS << "#ifdef GET_INSTRINFO_ENUM\n"; - OS << "#undef GET_INSTRINFO_ENUM\n"; const CodeGenTarget &Target = CDP.getTargetInfo(); StringRef Namespace = Target.getInstNamespace(); @@ -1393,48 +1360,48 @@ void InstrInfoEmitter::emitEnums( if (Namespace.empty()) PrintFatalError("No instructions defined!"); - OS << "namespace llvm::" << Namespace << " {\n"; + { + IfDefEmitter IfDef(OS, "GET_INSTRINFO_ENUM"); + NamespaceEmitter NS(OS, ("llvm::" + Namespace).str()); - auto II = llvm::max_element( - NumberedInstructions, - [](const CodeGenInstruction *InstA, const CodeGenInstruction *InstB) { - return InstA->getName().size() < InstB->getName().size(); - }); - size_t MaxNameSize = (*II)->getName().size(); + auto II = llvm::max_element( + NumberedInstructions, + [](const CodeGenInstruction *InstA, const CodeGenInstruction *InstB) { + return InstA->getName().size() < InstB->getName().size(); + }); + size_t MaxNameSize = (*II)->getName().size(); - OS << " enum {\n"; - for (const CodeGenInstruction *Inst : NumberedInstructions) { - OS << " " << left_justify(Inst->getName(), MaxNameSize) << " = " - << Target.getInstrIntValue(Inst->TheDef) << ", // " - << SrcMgr.getFormattedLocationNoOffset(Inst->TheDef->getLoc().front()) - << '\n'; + OS << " enum {\n"; + for (const CodeGenInstruction *Inst : NumberedInstructions) { + OS << " " << left_justify(Inst->getName(), MaxNameSize) << " = " + << Target.getInstrIntValue(Inst->TheDef) << ", // " + << SrcMgr.getFormattedLocationNoOffset(Inst->TheDef->getLoc().front()) + << '\n'; + } + OS << " INSTRUCTION_LIST_END = " << NumberedInstructions.size() << '\n'; + OS << " };\n"; + + ArrayRef<const Record *> RegClassesByHwMode = + Target.getAllRegClassByHwMode(); + if (!RegClassesByHwMode.empty()) { + OS << " enum RegClassByHwModeUses : uint16_t {\n"; + for (const Record *ClassByHwMode : RegClassesByHwMode) + OS << indent(4) << ClassByHwMode->getName() << ",\n"; + OS << " };\n"; + } } - OS << " INSTRUCTION_LIST_END = " << NumberedInstructions.size() << '\n'; - OS << " };\n"; - ArrayRef<const Record *> RegClassesByHwMode = Target.getAllRegClassByHwMode(); - if (!RegClassesByHwMode.empty()) { - OS << " enum RegClassByHwModeUses : uint16_t {\n"; - for (const Record *ClassByHwMode : RegClassesByHwMode) - OS << indent(4) << ClassByHwMode->getName() << ",\n"; + { + IfDefEmitter IfDef(OS, "GET_INSTRINFO_SCHED_ENUM"); + NamespaceEmitter NS(OS, ("llvm::" + Namespace + "::Sched").str()); + + OS << " enum {\n"; + auto ExplictClasses = SchedModels.explicitSchedClasses(); + for (const auto &[Idx, Class] : enumerate(ExplictClasses)) + OS << " " << Class.Name << "\t= " << Idx << ",\n"; + OS << " SCHED_LIST_END = " << ExplictClasses.size() << '\n'; OS << " };\n"; } - - OS << "} // end namespace llvm::" << Namespace << '\n'; - OS << "#endif // GET_INSTRINFO_ENUM\n\n"; - - OS << "#ifdef GET_INSTRINFO_SCHED_ENUM\n"; - OS << "#undef GET_INSTRINFO_SCHED_ENUM\n"; - OS << "namespace llvm::" << Namespace << "::Sched {\n"; - OS << " enum {\n"; - auto ExplictClasses = SchedModels.explicitSchedClasses(); - for (const auto &[Idx, Class] : enumerate(ExplictClasses)) - OS << " " << Class.Name << "\t= " << Idx << ",\n"; - OS << " SCHED_LIST_END = " << ExplictClasses.size() << '\n'; - OS << " };\n"; - OS << "} // end namespace llvm::" << Namespace << "::Sched\n"; - - OS << "#endif // GET_INSTRINFO_SCHED_ENUM\n\n"; } static TableGen::Emitter::OptClass<InstrInfoEmitter> diff --git a/llvm/utils/UpdateTestChecks/common.py b/llvm/utils/UpdateTestChecks/common.py index 2dad16a..baa0377 100644 --- a/llvm/utils/UpdateTestChecks/common.py +++ b/llvm/utils/UpdateTestChecks/common.py @@ -605,6 +605,7 @@ TRIPLE_IR_RE = re.compile(r'^\s*target\s+triple\s*=\s*"([^"]+)"$') TRIPLE_ARG_RE = re.compile(r"-m?triple[= ]([^ ]+)") MARCH_ARG_RE = re.compile(r"-march[= ]([^ ]+)") DEBUG_ONLY_ARG_RE = re.compile(r"-debug-only[= ]([^ ]+)") +STOP_PASS_RE = re.compile(r"-stop-(before|after)=(\w+)") IS_DEBUG_RECORD_RE = re.compile(r"^(\s+)#dbg_") IS_SWITCH_CASE_RE = re.compile(r"^\s+i\d+ \d+, label %\S+") diff --git a/llvm/utils/UpdateTestChecks/mir.py b/llvm/utils/UpdateTestChecks/mir.py index 24bb8b3..01ee0e1 100644 --- a/llvm/utils/UpdateTestChecks/mir.py +++ b/llvm/utils/UpdateTestChecks/mir.py @@ -163,13 +163,15 @@ def add_mir_checks_for_function( print_fixed_stack, first_check_is_next, at_the_function_name, + check_indent=None, ): printed_prefixes = set() for run in run_list: for prefix in run[0]: if prefix in printed_prefixes: break - if not func_dict[prefix][func_name]: + # func_info can be empty if there was a prefix conflict. + if not func_dict[prefix].get(func_name): continue if printed_prefixes: # Add some space between different check prefixes. @@ -185,6 +187,7 @@ def add_mir_checks_for_function( func_dict[prefix][func_name], print_fixed_stack, first_check_is_next, + check_indent, ) break else: @@ -204,6 +207,7 @@ def add_mir_check_lines( func_info, print_fixed_stack, first_check_is_next, + check_indent=None, ): func_body = str(func_info).splitlines() if single_bb: @@ -220,7 +224,10 @@ def add_mir_check_lines( first_line = func_body[0] indent = len(first_line) - len(first_line.lstrip(" ")) # A check comment, indented the appropriate amount - check = "{:>{}}; {}".format("", indent, prefix) + if check_indent is not None: + check = "{}; {}".format(check_indent, prefix) + else: + check = "{:>{}}; {}".format("", indent, prefix) output_lines.append("{}-LABEL: name: {}".format(check, func_name)) diff --git a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn index 9e0b951..27bd2ce 100644 --- a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn +++ b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn @@ -336,6 +336,7 @@ if (current_toolchain == default_toolchain) { "__chrono/gps_clock.h", "__chrono/hh_mm_ss.h", "__chrono/high_resolution_clock.h", + "__chrono/is_clock.h", "__chrono/leap_second.h", "__chrono/literals.h", "__chrono/local_info.h", diff --git a/llvm/utils/gn/secondary/lldb/source/Target/BUILD.gn b/llvm/utils/gn/secondary/lldb/source/Target/BUILD.gn index 783eb96..679373d 100644 --- a/llvm/utils/gn/secondary/lldb/source/Target/BUILD.gn +++ b/llvm/utils/gn/secondary/lldb/source/Target/BUILD.gn @@ -72,6 +72,7 @@ static_library("Target") { "Statistics.cpp", "StopInfo.cpp", "StructuredDataPlugin.cpp", + "SyntheticFrameProvider.cpp", "SystemRuntime.cpp", "Target.cpp", "TargetList.cpp", diff --git a/llvm/utils/update_llc_test_checks.py b/llvm/utils/update_llc_test_checks.py index 8c57e75..98864be 100755 --- a/llvm/utils/update_llc_test_checks.py +++ b/llvm/utils/update_llc_test_checks.py @@ -15,7 +15,7 @@ import argparse import os # Used to advertise this file's name ("autogenerated_note"). import sys -from UpdateTestChecks import common +from UpdateTestChecks import common, mir # llc is the only llc-like in the LLVM tree but downstream forks can add # additional ones here if they have them. @@ -33,6 +33,7 @@ def update_test(ti: common.TestInfo): break run_list = [] + mir_run_list = [] for l in ti.run_lines: if "|" not in l: common.warn("Skipping unparsable RUN line: " + l) @@ -57,9 +58,14 @@ def update_test(ti: common.TestInfo): if m: march_in_cmd = m.groups()[0] + target_list = run_list m = common.DEBUG_ONLY_ARG_RE.search(llc_cmd) if m and m.groups()[0] == "isel": from UpdateTestChecks import isel as output_type + elif not m and common.STOP_PASS_RE.search(llc_cmd): + # MIR output mode. If -debug-only is present assume + # the debug output is the main point of interest. + target_list = mir_run_list else: from UpdateTestChecks import asm as output_type @@ -84,7 +90,7 @@ def update_test(ti: common.TestInfo): # FIXME: We should use multiple check prefixes to common check lines. For # now, we just ignore all but the last. - run_list.append( + target_list.append( ( check_prefixes, llc_tool, @@ -119,14 +125,20 @@ def update_test(ti: common.TestInfo): ginfo=ginfo, ) - for ( - prefixes, - llc_tool, - llc_args, - preprocess_cmd, - triple_in_cmd, - march_in_cmd, - ) in run_list: + # Dictionary to store MIR function bodies separately + mir_func_dict = {} + for run_tuple, is_mir in [(run, False) for run in run_list] + [ + (run, True) for run in mir_run_list + ]: + ( + prefixes, + llc_tool, + llc_args, + preprocess_cmd, + triple_in_cmd, + march_in_cmd, + ) = run_tuple + common.debug("Extracted LLC cmd:", llc_tool, llc_args) common.debug("Extracted FileCheck prefixes:", str(prefixes)) @@ -141,22 +153,54 @@ def update_test(ti: common.TestInfo): if not triple: triple = common.get_triple_from_march(march_in_cmd) - scrubber, function_re = output_type.get_run_handler(triple) - if 0 == builder.process_run_line( - function_re, scrubber, raw_tool_output, prefixes - ): - common.warn( - "Couldn't match any function. Possibly the wrong target triple has been provided" + if is_mir: + # MIR output mode + common.debug("Detected MIR output mode for prefixes:", str(prefixes)) + for prefix in prefixes: + if prefix not in mir_func_dict: + mir_func_dict[prefix] = {} + + mir.build_function_info_dictionary( + ti.path, + raw_tool_output, + triple, + prefixes, + mir_func_dict, + ti.args.verbose, ) - builder.processed_prefixes(prefixes) + else: + # ASM output mode + scrubber, function_re = output_type.get_run_handler(triple) + if 0 == builder.process_run_line( + function_re, scrubber, raw_tool_output, prefixes + ): + common.warn( + "Couldn't match any function. Possibly the wrong target triple has been provided" + ) + builder.processed_prefixes(prefixes) func_dict = builder.finish_and_get_func_dict() + + # Check for conflicts: same prefix used for both ASM and MIR + conflicting_prefixes = set(func_dict.keys()) & set(mir_func_dict.keys()) + if conflicting_prefixes: + common.warn( + "The following prefixes are used for both ASM and MIR output, which will cause FileCheck failures: {}".format( + ", ".join(sorted(conflicting_prefixes)) + ), + test_file=ti.path, + ) + for prefix in conflicting_prefixes: + mir_func_dict[prefix] = {} + func_dict[prefix] = {} + global_vars_seen_dict = {} is_in_function = False is_in_function_start = False func_name = None prefix_set = set([prefix for p in run_list for prefix in p[0]]) + prefix_set.update([prefix for p in mir_run_list for prefix in p[0]]) common.debug("Rewriting FileCheck prefixes:", str(prefix_set)) output_lines = [] @@ -221,6 +265,22 @@ def update_test(ti: common.TestInfo): is_filtered=builder.is_filtered(), ) ) + + # Also add MIR checks if we have them for this function + if mir_run_list and func_name: + mir.add_mir_checks_for_function( + ti.path, + output_lines, + mir_run_list, + mir_func_dict, + func_name, + single_bb=False, # Don't skip basic block labels. + print_fixed_stack=False, # Don't print fixed stack (ASM tests don't need it). + first_check_is_next=False, # First check is LABEL, not NEXT. + at_the_function_name=False, # Use "name:" not "@name". + check_indent="", # No indentation for IR files (not MIR files). + ) + is_in_function_start = False if is_in_function: |
