diff options
Diffstat (limited to 'utils/TableGen')
24 files changed, 524 insertions, 234 deletions
diff --git a/utils/TableGen/ARMDecoderEmitter.cpp b/utils/TableGen/ARMDecoderEmitter.cpp index a7cbbcd..8a5dc8b 100644 --- a/utils/TableGen/ARMDecoderEmitter.cpp +++ b/utils/TableGen/ARMDecoderEmitter.cpp @@ -421,6 +421,9 @@ public: protected: // Populates the insn given the uid. void insnWithID(insn_t &Insn, unsigned Opcode) const { + if (AllInstructions[Opcode]->isPseudo) + return; + BitsInit &Bits = getBitsField(*AllInstructions[Opcode]->TheDef, "Inst"); for (unsigned i = 0; i < BIT_WIDTH; ++i) diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 1fb92ee..a6a4fec 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -1153,7 +1153,7 @@ void AsmMatcherInfo::BuildInfo() { assert(FeatureNo < 32 && "Too many subtarget features!"); } - StringRef CommentDelimiter = AsmParser->getValueAsString("CommentDelimiter"); + std::string CommentDelimiter = AsmParser->getValueAsString("CommentDelimiter"); // Parse the instructions; we need to do this first so that we can gather the // singleton register classes. @@ -1656,6 +1656,10 @@ static void EmitValidateOperandClass(AsmMatcherInfo &Info, OS << " " << Info.Target.getName() << "Operand &Operand = *(" << Info.Target.getName() << "Operand*)GOp;\n"; + // The InvalidMatchClass is not to match any operand. + OS << " if (Kind == InvalidMatchClass)\n"; + OS << " return false;\n\n"; + // Check for Token operands first. OS << " if (Operand.isToken())\n"; OS << " return MatchTokenString(Operand.getToken()) == Kind;\n\n"; @@ -1817,15 +1821,44 @@ static void EmitComputeAvailableFeatures(AsmMatcherInfo &Info, Info.AsmParser->getValueAsString("AsmParserClassName"); OS << "unsigned " << Info.Target.getName() << ClassName << "::\n" - << "ComputeAvailableFeatures(const " << Info.Target.getName() - << "Subtarget *Subtarget) const {\n"; + << "ComputeAvailableFeatures(uint64_t FB) const {\n"; OS << " unsigned Features = 0;\n"; for (std::map<Record*, SubtargetFeatureInfo*>::const_iterator it = Info.SubtargetFeatures.begin(), ie = Info.SubtargetFeatures.end(); it != ie; ++it) { SubtargetFeatureInfo &SFI = *it->second; - OS << " if (" << SFI.TheDef->getValueAsString("CondString") - << ")\n"; + + OS << " if ("; + std::string CondStorage = SFI.TheDef->getValueAsString("AssemblerCondString"); + StringRef Conds = CondStorage; + std::pair<StringRef,StringRef> Comma = Conds.split(','); + bool First = true; + do { + if (!First) + OS << " && "; + + bool Neg = false; + StringRef Cond = Comma.first; + if (Cond[0] == '!') { + Neg = true; + Cond = Cond.substr(1); + } + + OS << "((FB & " << Info.Target.getName() << "::" << Cond << ")"; + if (Neg) + OS << " == 0"; + else + OS << " != 0"; + OS << ")"; + + if (Comma.second.empty()) + break; + + First = false; + Comma = Comma.second.split(','); + } while (true); + + OS << ")\n"; OS << " Features |= " << SFI.getEnumName() << ";\n"; } OS << " return Features;\n"; @@ -2140,8 +2173,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "#undef GET_ASSEMBLER_HEADER\n"; OS << " // This should be included into the middle of the declaration of\n"; OS << " // your subclasses implementation of TargetAsmParser.\n"; - OS << " unsigned ComputeAvailableFeatures(const " << - Target.getName() << "Subtarget *Subtarget) const;\n"; + OS << " unsigned ComputeAvailableFeatures(uint64_t FeatureBits) const;\n"; OS << " enum MatchResultTy {\n"; OS << " Match_ConversionFail,\n"; OS << " Match_InvalidOperand,\n"; diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index b77d2e4..f44f050 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -606,92 +606,29 @@ void AsmWriterEmitter::EmitGetInstructionName(raw_ostream &O) { } namespace { - -/// SubtargetFeatureInfo - Helper class for storing information on a subtarget -/// feature which participates in instruction matching. -struct SubtargetFeatureInfo { - /// \brief The predicate record for this feature. - const Record *TheDef; - - /// \brief An unique index assigned to represent this feature. - unsigned Index; - - SubtargetFeatureInfo(const Record *D, unsigned Idx) : TheDef(D), Index(Idx) {} - - /// \brief The name of the enumerated constant identifying this feature. - std::string getEnumName() const { - return "Feature_" + TheDef->getName(); - } -}; - -struct AsmWriterInfo { - /// Map of Predicate records to their subtarget information. - std::map<const Record*, SubtargetFeatureInfo*> SubtargetFeatures; - - /// getSubtargetFeature - Lookup or create the subtarget feature info for the - /// given operand. - SubtargetFeatureInfo *getSubtargetFeature(const Record *Def) const { - assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!"); - std::map<const Record*, SubtargetFeatureInfo*>::const_iterator I = - SubtargetFeatures.find(Def); - return I == SubtargetFeatures.end() ? 0 : I->second; - } - - void addReqFeatures(const std::vector<Record*> &Features) { - for (std::vector<Record*>::const_iterator - I = Features.begin(), E = Features.end(); I != E; ++I) { - const Record *Pred = *I; - - // Ignore predicates that are not intended for the assembler. - if (!Pred->getValueAsBit("AssemblerMatcherPredicate")) - continue; - - if (Pred->getName().empty()) - throw TGError(Pred->getLoc(), "Predicate has no name!"); - - // Don't add the predicate again. - if (getSubtargetFeature(Pred)) - continue; - - unsigned FeatureNo = SubtargetFeatures.size(); - SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo); - assert(FeatureNo < 32 && "Too many subtarget features!"); - } - } - - const SubtargetFeatureInfo *getFeatureInfo(const Record *R) { - return SubtargetFeatures[R]; - } -}; - // IAPrinter - Holds information about an InstAlias. Two InstAliases match if // they both have the same conditionals. In which case, we cannot print out the // alias for that pattern. class IAPrinter { - AsmWriterInfo &AWI; std::vector<std::string> Conds; std::map<StringRef, unsigned> OpMap; std::string Result; std::string AsmString; std::vector<Record*> ReqFeatures; public: - IAPrinter(AsmWriterInfo &Info, std::string R, std::string AS) - : AWI(Info), Result(R), AsmString(AS) {} + IAPrinter(std::string R, std::string AS) + : Result(R), AsmString(AS) {} void addCond(const std::string &C) { Conds.push_back(C); } - void addReqFeatures(const std::vector<Record*> &Features) { - AWI.addReqFeatures(Features); - ReqFeatures = Features; - } void addOperand(StringRef Op, unsigned Idx) { OpMap[Op] = Idx; } unsigned getOpIndex(StringRef Op) { return OpMap[Op]; } bool isOpMapped(StringRef Op) { return OpMap.find(Op) != OpMap.end(); } - bool print(raw_ostream &O) { + void print(raw_ostream &O) { if (Conds.empty() && ReqFeatures.empty()) { O.indent(6) << "return true;\n"; - return false; + return; } O << "if ("; @@ -706,27 +643,6 @@ public: O << *I; } - if (!ReqFeatures.empty()) { - if (Conds.begin() != Conds.end()) { - O << " &&\n"; - O.indent(8); - } else { - O << "if ("; - } - - std::string Req; - raw_string_ostream ReqO(Req); - - for (std::vector<Record*>::iterator - I = ReqFeatures.begin(), E = ReqFeatures.end(); I != E; ++I) { - if (I != ReqFeatures.begin()) ReqO << " | "; - ReqO << AWI.getFeatureInfo(*I)->getEnumName(); - } - - O << "(AvailableFeatures & (" << ReqO.str() << ")) == (" - << ReqO.str() << ')'; - } - O << ") {\n"; O.indent(6) << "// " << Result << "\n"; O.indent(6) << "AsmString = \"" << AsmString << "\";\n"; @@ -738,7 +654,6 @@ public: O.indent(6) << "break;\n"; O.indent(4) << '}'; - return !ReqFeatures.empty(); } bool operator==(const IAPrinter &RHS) { @@ -770,53 +685,6 @@ public: } // end anonymous namespace -/// EmitSubtargetFeatureFlagEnumeration - Emit the subtarget feature flag -/// definitions. -static void EmitSubtargetFeatureFlagEnumeration(AsmWriterInfo &Info, - raw_ostream &O) { - O << "namespace {\n\n"; - O << "// Flags for subtarget features that participate in " - << "alias instruction matching.\n"; - O << "enum SubtargetFeatureFlag {\n"; - - for (std::map<const Record*, SubtargetFeatureInfo*>::const_iterator - I = Info.SubtargetFeatures.begin(), - E = Info.SubtargetFeatures.end(); I != E; ++I) { - SubtargetFeatureInfo &SFI = *I->second; - O << " " << SFI.getEnumName() << " = (1 << " << SFI.Index << "),\n"; - } - - O << " Feature_None = 0\n"; - O << "};\n\n"; - O << "} // end anonymous namespace\n\n"; -} - -/// EmitComputeAvailableFeatures - Emit the function to compute the list of -/// available features given a subtarget. -static void EmitComputeAvailableFeatures(AsmWriterInfo &Info, - Record *AsmWriter, - CodeGenTarget &Target, - raw_ostream &O) { - std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); - - O << "unsigned " << Target.getName() << ClassName << "::\n" - << "ComputeAvailableFeatures(const " << Target.getName() - << "Subtarget *Subtarget) const {\n"; - O << " unsigned Features = 0;\n"; - - for (std::map<const Record*, SubtargetFeatureInfo*>::const_iterator - I = Info.SubtargetFeatures.begin(), - E = Info.SubtargetFeatures.end(); I != E; ++I) { - SubtargetFeatureInfo &SFI = *I->second; - O << " if (" << SFI.TheDef->getValueAsString("CondString") - << ")\n"; - O << " Features |= " << SFI.getEnumName() << ";\n"; - } - - O << " return Features;\n"; - O << "}\n\n"; -} - static void EmitGetMapOperandNumber(raw_ostream &O) { O << "static unsigned getMapOperandNumber(" << "const SmallVectorImpl<std::pair<StringRef, unsigned> > &OpMap,\n"; @@ -960,7 +828,6 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { // A map of which conditions need to be met for each instruction operand // before it can be matched to the mnemonic. std::map<std::string, std::vector<IAPrinter*> > IAPrinterMap; - AsmWriterInfo AWI; for (std::map<std::string, std::vector<CodeGenInstAlias*> >::iterator I = AliasMap.begin(), E = AliasMap.end(); I != E; ++I) { @@ -977,9 +844,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { if (NumResultOps < CountNumOperands(CGA->AsmString)) continue; - IAPrinter *IAP = new IAPrinter(AWI, CGA->Result->getAsString(), + IAPrinter *IAP = new IAPrinter(CGA->Result->getAsString(), CGA->AsmString); - IAP->addReqFeatures(CGA->TheDef->getValueAsListOfDefs("Predicates")); std::string Cond; Cond = std::string("MI->getNumOperands() == ") + llvm::utostr(LastOpNo); @@ -1049,9 +915,6 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { } } - EmitSubtargetFeatureFlagEnumeration(AWI, O); - EmitComputeAvailableFeatures(AWI, AsmWriter, Target, O); - std::string Header; raw_string_ostream HeaderO(Header); @@ -1061,7 +924,6 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { std::string Cases; raw_string_ostream CasesO(Cases); - bool NeedAvailableFeatures = false; for (std::map<std::string, std::vector<IAPrinter*> >::iterator I = IAPrinterMap.begin(), E = IAPrinterMap.end(); I != E; ++I) { @@ -1092,7 +954,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { II = UniqueIAPs.begin(), IE = UniqueIAPs.end(); II != IE; ++II) { IAPrinter *IAP = *II; CasesO.indent(4); - NeedAvailableFeatures |= IAP->print(CasesO); + IAP->print(CasesO); CasesO << '\n'; } @@ -1112,8 +974,6 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { O << HeaderO.str(); O.indent(2) << "StringRef AsmString;\n"; O.indent(2) << "SmallVector<std::pair<StringRef, unsigned>, 4> OpMap;\n"; - if (NeedAvailableFeatures) - O.indent(2) << "unsigned AvailableFeatures = getAvailableFeatures();\n\n"; O.indent(2) << "switch (MI->getOpcode()) {\n"; O.indent(2) << "default: return false;\n"; O << CasesO.str(); diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt index 957045e..4d71259 100644 --- a/utils/TableGen/CMakeLists.txt +++ b/utils/TableGen/CMakeLists.txt @@ -34,6 +34,7 @@ add_llvm_utility(tblgen LLVMCConfigurationEmitter.cpp NeonEmitter.cpp OptParserEmitter.cpp + PseudoLoweringEmitter.cpp Record.cpp RegisterInfoEmitter.cpp SetTheory.cpp diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index 9d4dc5c4..d828dfc 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/utils/TableGen/CodeEmitterGen.cpp @@ -34,7 +34,8 @@ void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) { for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end(); I != E; ++I) { Record *R = *I; - if (R->getValueAsString("Namespace") == "TargetOpcode") + if (R->getValueAsString("Namespace") == "TargetOpcode" || + R->getValueAsBit("isPseudo")) continue; BitsInit *BI = R->getValueAsBitsInit("Inst"); @@ -231,7 +232,8 @@ void CodeEmitterGen::run(raw_ostream &o) { const CodeGenInstruction *CGI = *IN; Record *R = CGI->TheDef; - if (R->getValueAsString("Namespace") == "TargetOpcode") { + if (R->getValueAsString("Namespace") == "TargetOpcode" || + R->getValueAsBit("isPseudo")) { o << " 0U,\n"; continue; } @@ -255,7 +257,8 @@ void CodeEmitterGen::run(raw_ostream &o) { for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end(); IC != EC; ++IC) { Record *R = *IC; - if (R->getValueAsString("Namespace") == "TargetOpcode") + if (R->getValueAsString("Namespace") == "TargetOpcode" || + R->getValueAsBit("isPseudo")) continue; const std::string &InstName = R->getValueAsString("Namespace") + "::" + R->getName(); diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 0fe5d05..072893f 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -1744,7 +1744,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ Record *R = DI->getDef(); // Direct reference to a leaf DagNode or PatFrag? Turn it into a - // TreePatternNode if its own. For example: + // TreePatternNode of its own. For example: /// (foo GPR, imm) -> (foo GPR, (imm)) if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag")) return ParseTreePattern(new DagInit(DI, "", diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h index e4e8574..936fd01 100644 --- a/utils/TableGen/CodeGenDAGPatterns.h +++ b/utils/TableGen/CodeGenDAGPatterns.h @@ -26,7 +26,7 @@ namespace llvm { class Record; - struct Init; + class Init; class ListInit; class DagInit; class SDNodeInfo; diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 5fa91be..a52ce86c 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -67,12 +67,14 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { Record *Rec = Arg->getDef(); std::string PrintMethod = "printOperand"; std::string EncoderMethod; + std::string OperandType = "OPERAND_UNKNOWN"; unsigned NumOps = 1; DagInit *MIOpInfo = 0; if (Rec->isSubClassOf("RegisterOperand")) { PrintMethod = Rec->getValueAsString("PrintMethod"); } else if (Rec->isSubClassOf("Operand")) { PrintMethod = Rec->getValueAsString("PrintMethod"); + OperandType = Rec->getValueAsString("OperandType"); // If there is an explicit encoder method, use it. EncoderMethod = Rec->getValueAsString("EncoderMethod"); MIOpInfo = Rec->getValueAsDag("MIOperandInfo"); @@ -96,8 +98,9 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { } else if (Rec->getName() == "variable_ops") { isVariadic = true; continue; - } else if (!Rec->isSubClassOf("RegisterClass") && - !Rec->isSubClassOf("PointerLikeRegClass") && + } else if (Rec->isSubClassOf("RegisterClass")) { + OperandType = "OPERAND_REGISTER"; + } else if (!Rec->isSubClassOf("PointerLikeRegClass") && Rec->getName() != "unknown") throw "Unknown operand class '" + Rec->getName() + "' in '" + R->getName() + "' instruction!"; @@ -111,7 +114,8 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { " has the same name as a previous operand!"; OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod, EncoderMethod, - MIOperandNo, NumOps, MIOpInfo)); + OperandType, MIOperandNo, NumOps, + MIOpInfo)); MIOperandNo += NumOps; } @@ -311,6 +315,8 @@ CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R), Operands(R) { isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove"); hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq"); hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq"); + isCodeGenOnly = R->getValueAsBit("isCodeGenOnly"); + isPseudo = R->getValueAsBit("isPseudo"); ImplicitDefs = R->getValueAsListOfDefs("Defs"); ImplicitUses = R->getValueAsListOfDefs("Uses"); diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index 5f1e0be..8d7669a 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -78,6 +78,10 @@ namespace llvm { /// for binary encoding. "getMachineOpValue" by default. std::string EncoderMethodName; + /// OperandType - A value from MCOI::OperandType representing the type of + /// the operand. + std::string OperandType; + /// MIOperandNo - Currently (this is meant to be phased out), some logical /// operands correspond to multiple MachineInstr operands. In the X86 /// target for example, one address operand is represented as 4 @@ -101,10 +105,11 @@ namespace llvm { std::vector<ConstraintInfo> Constraints; OperandInfo(Record *R, const std::string &N, const std::string &PMN, - const std::string &EMN, unsigned MION, unsigned MINO, - DagInit *MIOI) + const std::string &EMN, const std::string &OT, unsigned MION, + unsigned MINO, DagInit *MIOI) : Rec(R), Name(N), PrinterMethodName(PMN), EncoderMethodName(EMN), - MIOperandNo(MION), MINumOperands(MINO), MIOperandInfo(MIOI) {} + OperandType(OT), MIOperandNo(MION), MINumOperands(MINO), + MIOperandInfo(MIOI) {} /// getTiedOperand - If this operand is tied to another one, return the @@ -235,6 +240,8 @@ namespace llvm { bool isAsCheapAsAMove; bool hasExtraSrcRegAllocReq; bool hasExtraDefRegAllocReq; + bool isCodeGenOnly; + bool isPseudo; CodeGenInstruction(Record *R); diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index 4c0d385..2f9814a 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -588,8 +588,11 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, IMM("imm0_31"); IMM("imm0_31_m1"); IMM("nModImm"); + IMM("imm0_7"); + IMM("imm0_15"); IMM("imm0_255"); IMM("imm0_4095"); + IMM("imm0_65535"); IMM("jt2block_operand"); IMM("t_imm_s4"); IMM("pclabel"); @@ -653,12 +656,12 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, MISC("t2am_imm8s4_offset", "kOperandTypeThumb2AddrModeImm8s4Offset"); // R, I MISC("tb_addrmode", "kOperandTypeARMTBAddrMode"); // I - MISC("t_addrmode_rrs1", "kOperandTypeThumbAddrModeRegS"); // R, R - MISC("t_addrmode_rrs2", "kOperandTypeThumbAddrModeRegS"); // R, R - MISC("t_addrmode_rrs4", "kOperandTypeThumbAddrModeRegS"); // R, R - MISC("t_addrmode_is1", "kOperandTypeThumbAddrModeImmS"); // R, I - MISC("t_addrmode_is2", "kOperandTypeThumbAddrModeImmS"); // R, I - MISC("t_addrmode_is4", "kOperandTypeThumbAddrModeImmS"); // R, I + MISC("t_addrmode_rrs1", "kOperandTypeThumbAddrModeRegS1"); // R, R + MISC("t_addrmode_rrs2", "kOperandTypeThumbAddrModeRegS2"); // R, R + MISC("t_addrmode_rrs4", "kOperandTypeThumbAddrModeRegS4"); // R, R + MISC("t_addrmode_is1", "kOperandTypeThumbAddrModeImmS1"); // R, I + MISC("t_addrmode_is2", "kOperandTypeThumbAddrModeImmS2"); // R, I + MISC("t_addrmode_is4", "kOperandTypeThumbAddrModeImmS4"); // R, I MISC("t_addrmode_rr", "kOperandTypeThumbAddrModeRR"); // R, R MISC("t_addrmode_sp", "kOperandTypeThumbAddrModeSP"); // R, I MISC("t_addrmode_pc", "kOperandTypeThumbAddrModePC"); // R, I @@ -666,14 +669,9 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, return 1; } -#undef SOREG -#undef SOIMM -#undef PRED #undef REG #undef MEM -#undef LEA -#undef IMM -#undef PCR +#undef MISC #undef SET @@ -774,6 +772,11 @@ static void populateInstInfo(CompoundConstantEmitter &infoArray, for (index = 0; index < numInstructions; ++index) { const CodeGenInstruction& inst = *numberedInstructions[index]; + // We don't need to do anything for pseudo-instructions, as we'll never + // see them here. We'll only see real instructions. + if (inst.isPseudo) + continue; + CompoundConstantEmitter *infoStruct = new CompoundConstantEmitter; infoArray.addEntry(infoStruct); @@ -869,8 +872,12 @@ static void emitCommonEnums(raw_ostream &o, unsigned int &i) { operandTypes.addEntry("kOperandTypeARMSPRRegisterList"); operandTypes.addEntry("kOperandTypeARMTBAddrMode"); operandTypes.addEntry("kOperandTypeThumbITMask"); - operandTypes.addEntry("kOperandTypeThumbAddrModeRegS"); - operandTypes.addEntry("kOperandTypeThumbAddrModeImmS"); + operandTypes.addEntry("kOperandTypeThumbAddrModeImmS1"); + operandTypes.addEntry("kOperandTypeThumbAddrModeImmS2"); + operandTypes.addEntry("kOperandTypeThumbAddrModeImmS4"); + operandTypes.addEntry("kOperandTypeThumbAddrModeRegS1"); + operandTypes.addEntry("kOperandTypeThumbAddrModeRegS2"); + operandTypes.addEntry("kOperandTypeThumbAddrModeRegS4"); operandTypes.addEntry("kOperandTypeThumbAddrModeRR"); operandTypes.addEntry("kOperandTypeThumbAddrModeSP"); operandTypes.addEntry("kOperandTypeThumbAddrModePC"); diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp index ba6cd86..c9dcb01 100644 --- a/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -1225,14 +1225,14 @@ bool FixedLenDecoderEmitter::populateInstruction(const CodeGenInstruction &CGI, // // This also removes pseudo instructions from considerations of disassembly, // which is a better design and less fragile than the name matchings. - BitsInit &Bits = getBitsField(Def, "Inst"); - if (Bits.allInComplete()) return false; - // Ignore "asm parser only" instructions. if (Def.getValueAsBit("isAsmParserOnly") || Def.getValueAsBit("isCodeGenOnly")) return false; + BitsInit &Bits = getBitsField(Def, "Inst"); + if (Bits.allInComplete()) return false; + std::vector<OperandInfo> InsnOperands; // If the instruction has specified a custom decoding hook, use that instead @@ -1354,7 +1354,8 @@ bool FixedLenDecoderEmitter::populateInstruction(const CodeGenInstruction &CGI, void FixedLenDecoderEmitter::populateInstructions() { for (unsigned i = 0, e = NumberedInstructions.size(); i < e; ++i) { Record *R = NumberedInstructions[i]->TheDef; - if (R->getValueAsString("Namespace") == "TargetOpcode") + if (R->getValueAsString("Namespace") == "TargetOpcode" || + R->getValueAsBit("isPseudo")) continue; if (populateInstruction(*NumberedInstructions[i], i)) diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 18d4db0..5ebaf17 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -121,6 +121,11 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { " << 16) | (1 << MCOI::TIED_TO))"; } + // Fill in operand type. + Res += ", MCOI::"; + assert(!Inst.Operands[i].OperandType.empty() && "Invalid operand type."); + Res += Inst.Operands[i].OperandType; + Result.push_back(Res); } } @@ -198,8 +203,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) { // Emit all of the MCInstrDesc records in their ENUM ordering. // - OS << "\nstatic const MCInstrDesc " << TargetName - << "Insts[] = {\n"; + OS << "\nMCInstrDesc " << TargetName << "Insts[] = {\n"; const std::vector<const CodeGenInstruction*> &NumberedInstructions = Target.getInstructionsByEnumValue(); @@ -235,6 +239,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) { OS << "#undef GET_INSTRINFO_CTOR\n"; OS << "namespace llvm {\n"; + OS << "extern MCInstrDesc " << TargetName << "Insts[];\n"; OS << ClassName << "::" << ClassName << "(int SO, int DO)\n" << " : TargetInstrInfoImpl(SO, DO) {\n" << " InitMCInstrInfo(" << TargetName << "Insts, " @@ -257,8 +262,10 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, OS << " { "; OS << Num << ",\t" << MinOperands << ",\t" - << Inst.Operands.NumDefs << ",\t" << getItinClassNumber(Inst.TheDef) - << ",\t\"" << Inst.TheDef->getName() << "\", 0"; + << Inst.Operands.NumDefs << ",\t" + << getItinClassNumber(Inst.TheDef) << ",\t" + << Inst.TheDef->getValueAsInt("Size") << ",\t\"" + << Inst.TheDef->getName() << "\", 0"; // Emit all of the target indepedent flags... if (Inst.isReturn) OS << "|(1<<MCID::Return)"; diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index 7a53138..e5e7cea 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -259,7 +259,7 @@ static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType, } else if (VT == MVT::iPTRAny) { // Make sure the user has passed us an argument type to overload. If not, // treat it as an ordinary (not overloaded) intrinsic. - OS << "(" << ArgNo << " < numTys) ? Tys[" << ArgNo + OS << "(" << ArgNo << " < Tys.size()) ? Tys[" << ArgNo << "] : PointerType::getUnqual("; EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo); OS << ")"; diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp index 090faf5..cd0cbeb 100644 --- a/utils/TableGen/LLVMCConfigurationEmitter.cpp +++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp @@ -2969,8 +2969,8 @@ void EmitHookDeclarations(const ToolDescriptions& ToolDescs, for (HookInfoMap::const_iterator B = HookNames.begin(), E = HookNames.end(); B != E; ++B) { - const char* HookName = B->first(); - const HookInfo& Info = B->second; + StringRef HookName = B->first(); + const HookInfo &Info = B->second; O.indent(Indent1) << "std::string " << HookName << "("; diff --git a/utils/TableGen/PseudoLoweringEmitter.cpp b/utils/TableGen/PseudoLoweringEmitter.cpp new file mode 100644 index 0000000..db33c1f --- /dev/null +++ b/utils/TableGen/PseudoLoweringEmitter.cpp @@ -0,0 +1,243 @@ +//===- PseudoLoweringEmitter.cpp - PseudoLowering Generator -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pseudo-lowering" +#include "Error.h" +#include "CodeGenInstruction.h" +#include "PseudoLoweringEmitter.h" +#include "Record.h" +#include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Debug.h" +#include <vector> +using namespace llvm; + +// FIXME: This pass currently can only expand a pseudo to a single instruction. +// The pseudo expansion really should take a list of dags, not just +// a single dag, so we can do fancier things. + +unsigned PseudoLoweringEmitter:: +addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Insn, + IndexedMap<OpData> &OperandMap, unsigned BaseIdx) { + unsigned OpsAdded = 0; + for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) { + if (DefInit *DI = dynamic_cast<DefInit*>(Dag->getArg(i))) { + // Physical register reference. Explicit check for the special case + // "zero_reg" definition. + if (DI->getDef()->isSubClassOf("Register") || + DI->getDef()->getName() == "zero_reg") { + OperandMap[BaseIdx + i].Kind = OpData::Reg; + OperandMap[BaseIdx + i].Data.Reg = DI->getDef(); + ++OpsAdded; + continue; + } + + // Normal operands should always have the same type, or we have a + // problem. + // FIXME: We probably shouldn't ever get a non-zero BaseIdx here. + assert(BaseIdx == 0 && "Named subargument in pseudo expansion?!"); + if (DI->getDef() != Insn.Operands[BaseIdx + i].Rec) + throw TGError(Rec->getLoc(), + "Pseudo operand type '" + DI->getDef()->getName() + + "' does not match expansion operand type '" + + Insn.Operands[BaseIdx + i].Rec->getName() + "'"); + // Source operand maps to destination operand. The Data element + // will be filled in later, just set the Kind for now. Do it + // for each corresponding MachineInstr operand, not just the first. + for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I) + OperandMap[BaseIdx + i + I].Kind = OpData::Operand; + OpsAdded += Insn.Operands[i].MINumOperands; + } else if (IntInit *II = dynamic_cast<IntInit*>(Dag->getArg(i))) { + OperandMap[BaseIdx + i].Kind = OpData::Imm; + OperandMap[BaseIdx + i].Data.Imm = II->getValue(); + ++OpsAdded; + } else if (DagInit *SubDag = dynamic_cast<DagInit*>(Dag->getArg(i))) { + // Just add the operands recursively. This is almost certainly + // a constant value for a complex operand (> 1 MI operand). + unsigned NewOps = + addDagOperandMapping(Rec, SubDag, Insn, OperandMap, BaseIdx + i); + OpsAdded += NewOps; + // Since we added more than one, we also need to adjust the base. + BaseIdx += NewOps - 1; + } else + assert(0 && "Unhandled pseudo-expansion argument type!"); + } + return OpsAdded; +} + +void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) { + DEBUG(dbgs() << "Pseudo definition: " << Rec->getName() << "\n"); + + // Validate that the result pattern has the corrent number and types + // of arguments for the instruction it references. + DagInit *Dag = Rec->getValueAsDag("ResultInst"); + assert(Dag && "Missing result instruction in pseudo expansion!"); + DEBUG(dbgs() << " Result: " << *Dag << "\n"); + + DefInit *OpDef = dynamic_cast<DefInit*>(Dag->getOperator()); + if (!OpDef) + throw TGError(Rec->getLoc(), Rec->getName() + + " has unexpected operator type!"); + Record *Operator = OpDef->getDef(); + if (!Operator->isSubClassOf("Instruction")) + throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + + "' is not an instruction!"); + + CodeGenInstruction Insn(Operator); + + if (Insn.isCodeGenOnly || Insn.isPseudo) + throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + + "' cannot be another pseudo instruction!"); + + if (Insn.Operands.size() != Dag->getNumArgs()) + throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + + "' operand count mismatch"); + + IndexedMap<OpData> OperandMap; + OperandMap.grow(Insn.Operands.size()); + + addDagOperandMapping(Rec, Dag, Insn, OperandMap, 0); + + // If there are more operands that weren't in the DAG, they have to + // be operands that have default values, or we have an error. Currently, + // PredicateOperand and OptionalDefOperand both have default values. + + + // Validate that each result pattern argument has a matching (by name) + // argument in the source instruction, in either the (outs) or (ins) list. + // Also check that the type of the arguments match. + // + // Record the mapping of the source to result arguments for use by + // the lowering emitter. + CodeGenInstruction SourceInsn(Rec); + StringMap<unsigned> SourceOperands; + for (unsigned i = 0, e = SourceInsn.Operands.size(); i != e; ++i) + SourceOperands[SourceInsn.Operands[i].Name] = i; + + DEBUG(dbgs() << " Operand mapping:\n"); + for (unsigned i = 0, e = Insn.Operands.size(); i != e; ++i) { + // We've already handled constant values. Just map instruction operands + // here. + if (OperandMap[Insn.Operands[i].MIOperandNo].Kind != OpData::Operand) + continue; + StringMap<unsigned>::iterator SourceOp = + SourceOperands.find(Dag->getArgName(i)); + if (SourceOp == SourceOperands.end()) + throw TGError(Rec->getLoc(), + "Pseudo output operand '" + Dag->getArgName(i) + + "' has no matching source operand."); + // Map the source operand to the destination operand index for each + // MachineInstr operand. + for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I) + OperandMap[Insn.Operands[i].MIOperandNo + I].Data.Operand = + SourceOp->getValue(); + + DEBUG(dbgs() << " " << SourceOp->getValue() << " ==> " << i << "\n"); + } + + Expansions.push_back(PseudoExpansion(SourceInsn, Insn, OperandMap)); +} + +void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) { + // Emit file header. + EmitSourceFileHeader("Pseudo-instruction MC lowering Source Fragment", o); + + o << "bool " << Target.getName() + "AsmPrinter" << "::\n" + << "emitPseudoExpansionLowering(MCStreamer &OutStreamer,\n" + << " const MachineInstr *MI) {\n" + << " switch (MI->getOpcode()) {\n" + << " default: return false;\n"; + for (unsigned i = 0, e = Expansions.size(); i != e; ++i) { + PseudoExpansion &Expansion = Expansions[i]; + CodeGenInstruction &Source = Expansion.Source; + CodeGenInstruction &Dest = Expansion.Dest; + o << " case " << Source.Namespace << "::" + << Source.TheDef->getName() << ": {\n" + << " MCInst TmpInst;\n" + << " MCOperand MCOp;\n" + << " TmpInst.setOpcode(" << Dest.Namespace << "::" + << Dest.TheDef->getName() << ");\n"; + + // Copy the operands from the source instruction. + // FIXME: Instruction operands with defaults values (predicates and cc_out + // in ARM, for example shouldn't need explicit values in the + // expansion DAG. + unsigned MIOpNo = 0; + for (unsigned OpNo = 0, E = Dest.Operands.size(); OpNo != E; + ++OpNo) { + o << " // Operand: " << Dest.Operands[OpNo].Name << "\n"; + for (unsigned i = 0, e = Dest.Operands[OpNo].MINumOperands; + i != e; ++i) { + switch (Expansion.OperandMap[MIOpNo + i].Kind) { + default: + llvm_unreachable("Unknown operand type?!"); + case OpData::Operand: + o << " lowerOperand(MI->getOperand(" + << Source.Operands[Expansion.OperandMap[MIOpNo].Data + .Operand].MIOperandNo + i + << "), MCOp);\n" + << " TmpInst.addOperand(MCOp);\n"; + break; + case OpData::Imm: + o << " TmpInst.addOperand(MCOperand::CreateImm(" + << Expansion.OperandMap[MIOpNo + i].Data.Imm << "));\n"; + break; + case OpData::Reg: { + Record *Reg = Expansion.OperandMap[MIOpNo + i].Data.Reg; + o << " TmpInst.addOperand(MCOperand::CreateReg("; + // "zero_reg" is special. + if (Reg->getName() == "zero_reg") + o << "0"; + else + o << Reg->getValueAsString("Namespace") << "::" << Reg->getName(); + o << "));\n"; + break; + } + } + } + MIOpNo += Dest.Operands[OpNo].MINumOperands; + } + if (Dest.Operands.isVariadic) { + o << " // variable_ops\n"; + o << " for (unsigned i = " << MIOpNo + << ", e = MI->getNumOperands(); i != e; ++i)\n" + << " if (lowerOperand(MI->getOperand(i), MCOp))\n" + << " TmpInst.addOperand(MCOp);\n"; + } + o << " OutStreamer.EmitInstruction(TmpInst);\n" + << " break;\n" + << " }\n"; + } + o << " }\n return true;\n}\n\n"; +} + +void PseudoLoweringEmitter::run(raw_ostream &o) { + Record *ExpansionClass = Records.getClass("PseudoInstExpansion"); + Record *InstructionClass = Records.getClass("PseudoInstExpansion"); + assert(ExpansionClass && "PseudoInstExpansion class definition missing!"); + assert(InstructionClass && "Instruction class definition missing!"); + + std::vector<Record*> Insts; + for (std::map<std::string, Record*>::const_iterator I = + Records.getDefs().begin(), E = Records.getDefs().end(); I != E; ++I) { + if (I->second->isSubClassOf(ExpansionClass) && + I->second->isSubClassOf(InstructionClass)) + Insts.push_back(I->second); + } + + // Process the pseudo expansion definitions, validating them as we do so. + for (unsigned i = 0, e = Insts.size(); i != e; ++i) + evaluateExpansion(Insts[i]); + + // Generate expansion code to lower the pseudo to an MCInst of the real + // instruction. + emitLoweringEmitter(o); +} + diff --git a/utils/TableGen/PseudoLoweringEmitter.h b/utils/TableGen/PseudoLoweringEmitter.h new file mode 100644 index 0000000..2749280 --- /dev/null +++ b/utils/TableGen/PseudoLoweringEmitter.h @@ -0,0 +1,65 @@ +//===- PseudoLoweringEmitter.h - PseudoLowering Generator -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef PSEUDOLOWERINGEMITTER_H +#define PSEUDOLOWERINGEMITTER_H + +#include "CodeGenInstruction.h" +#include "CodeGenTarget.h" +#include "TableGenBackend.h" +#include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +class PseudoLoweringEmitter : public TableGenBackend { + struct OpData { + enum MapKind { Operand, Imm, Reg }; + MapKind Kind; + union { + unsigned Operand; // Operand number mapped to. + uint64_t Imm; // Integer immedate value. + Record *Reg; // Physical register. + } Data; + }; + struct PseudoExpansion { + CodeGenInstruction Source; // The source pseudo instruction definition. + CodeGenInstruction Dest; // The destination instruction to lower to. + IndexedMap<OpData> OperandMap; + + PseudoExpansion(CodeGenInstruction &s, CodeGenInstruction &d, + IndexedMap<OpData> &m) : + Source(s), Dest(d), OperandMap(m) {} + }; + + RecordKeeper &Records; + + // It's overkill to have an instance of the full CodeGenTarget object, + // but it loads everything on demand, not in the constructor, so it's + // lightweight in performance, so it works out OK. + CodeGenTarget Target; + + SmallVector<PseudoExpansion, 64> Expansions; + + unsigned addDagOperandMapping(Record *Rec, DagInit *Dag, + CodeGenInstruction &Insn, + IndexedMap<OpData> &OperandMap, + unsigned BaseIdx); + void evaluateExpansion(Record *Pseudo); + void emitLoweringEmitter(raw_ostream &o); +public: + PseudoLoweringEmitter(RecordKeeper &R) : Records(R), Target(R) {} + + /// run - Output the pseudo-lowerings. + void run(raw_ostream &o); +}; + +} // end llvm namespace + +#endif diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h index f24f5e6..2f4080b 100644 --- a/utils/TableGen/Record.h +++ b/utils/TableGen/Record.h @@ -34,7 +34,7 @@ class DagRecTy; class RecordRecTy; // Init subclasses. -struct Init; +class Init; class UnsetInit; class BitInit; class BitsInit; @@ -453,7 +453,8 @@ RecTy *resolveTypes(RecTy *T1, RecTy *T2); // Initializer Classes //===----------------------------------------------------------------------===// -struct Init { +class Init { +public: virtual ~Init() {} /// isComplete - This virtual method should be overridden by values that may diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index abb8624..65d4a9b 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -162,16 +162,17 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, OS << getQualifiedName(SR[j]->TheDef) << ", "; OS << "0 };\n"; } + OS << "}\n"; // End of anonymous namespace... - OS << "\n const MCRegisterDesc " << TargetName + OS << "\nMCRegisterDesc " << TargetName << "RegDesc[] = { // Descriptors\n"; - OS << " { \"NOREG\",\t0,\t0,\t0 },\n"; + OS << " { \"NOREG\",\t0,\t0,\t0 },\n"; // Now that register alias and sub-registers sets have been emitted, emit the // register descriptors now. for (unsigned i = 0, e = Regs.size(); i != e; ++i) { const CodeGenRegister &Reg = *Regs[i]; - OS << " { \""; + OS << " { \""; OS << Reg.getName() << "\",\t" << Reg.getName() << "_Overlaps,\t"; if (!Reg.getSubRegs().empty()) OS << Reg.getName() << "_SubRegsSet,\t"; @@ -183,9 +184,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "Empty_SuperRegsSet"; OS << " },\n"; } - OS << " };\n"; // End of register descriptors... - - OS << "}\n\n"; // End of anonymous namespace... + OS << "};\n\n"; // End of register descriptors... // MCRegisterInfo initialization routine. OS << "static inline void Init" << TargetName @@ -545,6 +544,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << " &" << getQualifiedName(RegisterClasses[i].TheDef) << "RegClass,\n"; OS << " };\n"; + OS << "}\n"; // End of anonymous namespace... // Emit extra information about registers. const std::string &TargetName = Target.getName(); @@ -569,7 +569,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Emit SubRegIndex names, skipping 0 const std::vector<Record*> &SubRegIndices = RegBank.getSubRegIndices(); - OS << "\n const char *const SubRegIndexTable[] = { \""; + OS << "\n static const char *const " << TargetName + << "SubRegIndexTable[] = { \""; for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { OS << SubRegIndices[i]->getName(); if (i+1 != e) @@ -587,7 +588,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, } OS << "\n };\n\n"; } - OS << "}\n\n"; // End of anonymous namespace... + OS << "\n"; std::string ClassName = Target.getName() + "GenRegisterInfo"; @@ -658,11 +659,13 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << " }\n}\n\n"; // Emit the constructor of the class... + OS << "extern MCRegisterDesc " << TargetName << "RegDesc[];\n"; + OS << ClassName << "::" << ClassName << "()\n" << " : TargetRegisterInfo(" << TargetName << "RegInfoDesc" << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n" - << " SubRegIndexTable) {\n" + << " " << TargetName << "SubRegIndexTable) {\n" << " InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size()+1 << ");\n" << "}\n\n"; diff --git a/utils/TableGen/SetTheory.h b/utils/TableGen/SetTheory.h index e37a76e..6e8313b 100644 --- a/utils/TableGen/SetTheory.h +++ b/utils/TableGen/SetTheory.h @@ -55,7 +55,7 @@ namespace llvm { class DagInit; -struct Init; +class Init; class Record; class RecordKeeper; diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index df0425e..978e91a 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -81,8 +81,7 @@ unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) { // Begin feature table OS << "// Sorted (by key) array of values for CPU features.\n" - << "static const llvm::SubtargetFeatureKV " - << Target << "FeatureKV[] = {\n"; + << "llvm::SubtargetFeatureKV " << Target << "FeatureKV[] = {\n"; // For each feature unsigned NumFeatures = 0; @@ -141,8 +140,7 @@ unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) { // Begin processor table OS << "// Sorted (by key) array of values for CPU subtype.\n" - << "static const llvm::SubtargetFeatureKV " - << Target << "SubTypeKV[] = {\n"; + << "llvm::SubtargetFeatureKV " << Target << "SubTypeKV[] = {\n"; // For each processor for (unsigned i = 0, N = ProcessorList.size(); i < N;) { @@ -329,9 +327,9 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name << "\"\n" << "namespace " << Name << "Bypass {\n"; - OS << " const unsigned NoBypass = 0;\n"; + OS << " unsigned NoBypass = 0;\n"; for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j) - OS << " const unsigned " << BPs[j]->getName() + OS << " unsigned " << BPs[j]->getName() << " = 1 << " << j << ";\n"; OS << "}\n"; @@ -339,17 +337,16 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, } // Begin stages table - std::string StageTable = "\nstatic const llvm::InstrStage " + Target + - "Stages[] = {\n"; + std::string StageTable = "\nllvm::InstrStage " + Target + "Stages[] = {\n"; StageTable += " { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n"; // Begin operand cycle table - std::string OperandCycleTable = "static const unsigned " + Target + + std::string OperandCycleTable = "unsigned " + Target + "OperandCycles[] = {\n"; OperandCycleTable += " 0, // No itinerary\n"; // Begin pipeline bypass table - std::string BypassTable = "static const unsigned " + Target + + std::string BypassTable = "unsigned " + Target + "ForwardingPathes[] = {\n"; BypassTable += " 0, // No itinerary\n"; @@ -491,7 +488,7 @@ EmitProcessorData(raw_ostream &OS, // Begin processor itinerary table OS << "\n"; - OS << "static const llvm::InstrItinerary " << Name << "[] = {\n"; + OS << "llvm::InstrItinerary " << Name << "[] = {\n"; // For each itinerary class std::vector<InstrItinerary> &ItinList = *ProcListIter++; @@ -533,7 +530,7 @@ void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) { // Begin processor table OS << "\n"; OS << "// Sorted (by key) array of itineraries for CPU subtype.\n" - << "static const llvm::SubtargetInfoKV " + << "llvm::SubtargetInfoKV " << Target << "ProcItinKV[] = {\n"; // For each processor @@ -605,8 +602,7 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS, << "// subtarget options.\n" << "void llvm::"; OS << Target; - OS << "Subtarget::ParseSubtargetFeatures(const std::string &FS,\n" - << " const std::string &CPU) {\n" + OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n" << " DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n" << " DEBUG(dbgs() << \"\\nCPU:\" << CPU);\n"; @@ -615,11 +611,7 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS, return; } - OS << " SubtargetFeatures Features(FS);\n" - << " uint64_t Bits = Features.getFeatureBits(CPU, " - << Target << "SubTypeKV, " << NumProcs << ",\n" - << " " << Target << "FeatureKV, " - << NumFeatures << ");\n"; + OS << " uint64_t Bits = ReInitMCSubtargetInfo(CPU, FS);\n"; for (unsigned i = 0; i < Features.size(); i++) { // Next record @@ -629,10 +621,12 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS, const std::string &Attribute = R->getValueAsString("Attribute"); if (Value=="true" || Value=="false") - OS << " if ((Bits & " << Target << "::" << Instance << ") != 0) " + OS << " if ((Bits & " << Target << "::" + << Instance << ") != 0) " << Attribute << " = " << Value << ";\n"; else - OS << " if ((Bits & " << Target << "::" << Instance << ") != 0 && " + OS << " if ((Bits & " << Target << "::" + << Instance << ") != 0 && " << Attribute << " < " << Value << ") " << Attribute << " = " << Value << ";\n"; } @@ -648,23 +642,36 @@ void SubtargetEmitter::run(raw_ostream &OS) { EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS); + OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n"; + OS << "#undef GET_SUBTARGETINFO_ENUM\n"; + + OS << "namespace llvm {\n"; + Enumeration(OS, "SubtargetFeature", true); + OS << "} // End llvm namespace \n"; + OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n"; + OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n"; OS << "#undef GET_SUBTARGETINFO_MC_DESC\n"; OS << "namespace llvm {\n"; - Enumeration(OS, "SubtargetFeature", true); - OS<<"\n"; +#if 0 + OS << "namespace {\n"; +#endif unsigned NumFeatures = FeatureKeyValues(OS); - OS<<"\n"; + OS << "\n"; unsigned NumProcs = CPUKeyValues(OS); - OS<<"\n"; + OS << "\n"; EmitData(OS); - OS<<"\n"; + OS << "\n"; +#if 0 + OS << "}\n"; +#endif // MCInstrInfo initialization routine. OS << "static inline void Init" << Target - << "MCSubtargetInfo(MCSubtargetInfo *II) {\n"; - OS << " II->InitMCSubtargetInfo("; + << "MCSubtargetInfo(MCSubtargetInfo *II, " + << "StringRef TT, StringRef CPU, StringRef FS) {\n"; + OS << " II->InitMCSubtargetInfo(TT, CPU, FS, "; if (NumFeatures) OS << Target << "FeatureKV, "; else @@ -702,7 +709,8 @@ void SubtargetEmitter::run(raw_ostream &OS) { std::string ClassName = Target + "GenSubtargetInfo"; OS << "namespace llvm {\n"; OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n" - << " explicit " << ClassName << "();\n" + << " explicit " << ClassName << "(StringRef TT, StringRef CPU, " + << "StringRef FS);\n" << "};\n"; OS << "} // End llvm namespace \n"; @@ -712,9 +720,19 @@ void SubtargetEmitter::run(raw_ostream &OS) { OS << "#undef GET_SUBTARGETINFO_CTOR\n"; OS << "namespace llvm {\n"; - OS << ClassName << "::" << ClassName << "()\n" + OS << "extern llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n"; + OS << "extern llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n"; + if (HasItineraries) { + OS << "extern llvm::SubtargetInfoKV " << Target << "ProcItinKV[];\n"; + OS << "extern llvm::InstrStage " << Target << "Stages[];\n"; + OS << "extern unsigned " << Target << "OperandCycles[];\n"; + OS << "extern unsigned " << Target << "ForwardingPathes[];\n"; + } + + OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, " + << "StringRef FS)\n" << " : TargetSubtargetInfo() {\n" - << " InitMCSubtargetInfo("; + << " InitMCSubtargetInfo(TT, CPU, FS, "; if (NumFeatures) OS << Target << "FeatureKV, "; else diff --git a/utils/TableGen/TGParser.h b/utils/TableGen/TGParser.h index 94a1c2b..dce7e1d 100644 --- a/utils/TableGen/TGParser.h +++ b/utils/TableGen/TGParser.h @@ -25,7 +25,7 @@ namespace llvm { class RecordVal; class RecordKeeper; struct RecTy; - struct Init; + class Init; struct MultiClass; struct SubClassReference; struct SubMultiClassReference; diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index ce16c9a..e8eacb8 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -33,6 +33,7 @@ #include "LLVMCConfigurationEmitter.h" #include "NeonEmitter.h" #include "OptParserEmitter.h" +#include "PseudoLoweringEmitter.h" #include "Record.h" #include "RegisterInfoEmitter.h" #include "ARMDecoderEmitter.h" @@ -59,6 +60,7 @@ enum ActionType { GenAsmMatcher, GenARMDecoder, GenDisassembler, + GenPseudoLowering, GenCallingConv, GenClangAttrClasses, GenClangAttrImpl, @@ -106,6 +108,8 @@ namespace { "Generate decoders for ARM/Thumb"), clEnumValN(GenDisassembler, "gen-disassembler", "Generate disassembler"), + clEnumValN(GenPseudoLowering, "gen-pseudo-lowering", + "Generate pseudo instruction lowering"), clEnumValN(GenAsmMatcher, "gen-asm-matcher", "Generate assembly instruction matcher"), clEnumValN(GenDAGISel, "gen-dag-isel", @@ -314,6 +318,9 @@ int main(int argc, char **argv) { case GenDisassembler: DisassemblerEmitter(Records).run(Out.os()); break; + case GenPseudoLowering: + PseudoLoweringEmitter(Records).run(Out.os()); + break; case GenOptParserDefs: OptParserEmitter(Records, true).run(Out.os()); break; diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index f7518a9..ea3bb70 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -229,6 +229,30 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, HasFROperands = hasFROperands(); HasVEX_LPrefix = has256BitOperands() || Rec->getValueAsBit("hasVEX_L"); + // Check for 64-bit inst which does not require REX + Is64Bit = false; + // FIXME: Is there some better way to check for In64BitMode? + std::vector<Record*> Predicates = Rec->getValueAsListOfDefs("Predicates"); + for (unsigned i = 0, e = Predicates.size(); i != e; ++i) { + if (Predicates[i]->getName().find("64Bit") != Name.npos) { + Is64Bit = true; + break; + } + } + // FIXME: These instructions aren't marked as 64-bit in any way + Is64Bit |= Rec->getName() == "JMP64pcrel32" || + Rec->getName() == "MASKMOVDQU64" || + Rec->getName() == "POPFS64" || + Rec->getName() == "POPGS64" || + Rec->getName() == "PUSHFS64" || + Rec->getName() == "PUSHGS64" || + Rec->getName() == "REX64_PREFIX" || + Rec->getName().find("VMREAD64") != Name.npos || + Rec->getName().find("VMWRITE64") != Name.npos || + Rec->getName().find("MOV64") != Name.npos || + Rec->getName().find("PUSH64") != Name.npos || + Rec->getName().find("POP64") != Name.npos; + ShouldBeEmitted = true; } @@ -276,7 +300,7 @@ InstructionContext RecognizableInstr::insnContext() const { insnContext = IC_VEX_XS; else insnContext = IC_VEX; - } else if (Name.find("64") != Name.npos || HasREX_WPrefix) { + } else if (Is64Bit || HasREX_WPrefix) { if (HasREX_WPrefix && HasOpSizePrefix) insnContext = IC_64BIT_REXW_OPSIZE; else if (HasOpSizePrefix) diff --git a/utils/TableGen/X86RecognizableInstr.h b/utils/TableGen/X86RecognizableInstr.h index c7ec18c..677d9f0 100644 --- a/utils/TableGen/X86RecognizableInstr.h +++ b/utils/TableGen/X86RecognizableInstr.h @@ -64,6 +64,8 @@ private: bool HasLockPrefix; /// The isCodeGenOnly filed from the record bool IsCodeGenOnly; + // Whether the instruction has the predicate "Mode64Bit" + bool Is64Bit; /// The instruction name as listed in the tables std::string Name; |