+ std::vector<Record*> AllInstAliases =
+ Records.getAllDerivedDefinitions("InstAlias");
+
+ // Create a map from the qualified name to a list of potential matches.
+ typedef std::set<std::pair<CodeGenInstAlias, int>, AliasPriorityComparator>
+ AliasWithPriority;
+ std::map<std::string, AliasWithPriority> AliasMap;
+ for (std::vector<Record*>::iterator
+ I = AllInstAliases.begin(), E = AllInstAliases.end(); I != E; ++I) {
+ const Record *R = *I;
+ int Priority = R->getValueAsInt("EmitPriority");
+ if (Priority < 1)
+ continue; // Aliases with priority 0 are never emitted.
+
+ const DagInit *DI = R->getValueAsDag("ResultInst");
+ const DefInit *Op = cast<DefInit>(DI->getOperator());
+ AliasMap[getQualifiedName(Op->getDef())].insert(
+ std::make_pair(CodeGenInstAlias(*I, Variant, Target), Priority));
+ }
+
+ // 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;
+
+ // A list of MCOperandPredicates for all operands in use, and the reverse map
+ std::vector<const Record*> MCOpPredicates;
+ DenseMap<const Record*, unsigned> MCOpPredicateMap;
+
+ for (auto &Aliases : AliasMap) {
+ for (auto &Alias : Aliases.second) {
+ const CodeGenInstAlias &CGA = Alias.first;
+ unsigned LastOpNo = CGA.ResultInstOperandIndex.size();
+ unsigned NumResultOps =
+ CountNumOperands(CGA.ResultInst->AsmString, Variant);
+
+ // Don't emit the alias if it has more operands than what it's aliasing.
+ if (NumResultOps < CountNumOperands(CGA.AsmString, Variant))
+ continue;
+
+ IAPrinter IAP(CGA.Result->getAsString(), CGA.AsmString);
+
+ unsigned NumMIOps = 0;
+ for (auto &Operand : CGA.ResultOperands)
+ NumMIOps += Operand.getMINumOperands();
+
+ std::string Cond;
+ Cond = std::string("MI->getNumOperands() == ") + llvm::utostr(NumMIOps);
+ IAP.addCond(Cond);
+
+ bool CantHandle = false;
+
+ unsigned MIOpNum = 0;
+ for (unsigned i = 0, e = LastOpNo; i != e; ++i) {
+ std::string Op = "MI->getOperand(" + llvm::utostr(MIOpNum) + ")";
+
+ const CodeGenInstAlias::ResultOperand &RO = CGA.ResultOperands[i];
+
+ switch (RO.Kind) {
+ case CodeGenInstAlias::ResultOperand::K_Record: {
+ const Record *Rec = RO.getRecord();
+ StringRef ROName = RO.getName();
+ int PrintMethodIdx = -1;
+
+ // These two may have a PrintMethod, which we want to record (if it's
+ // the first time we've seen it) and provide an index for the aliasing
+ // code to use.
+ if (Rec->isSubClassOf("RegisterOperand") ||
+ Rec->isSubClassOf("Operand")) {
+ std::string PrintMethod = Rec->getValueAsString("PrintMethod");
+ if (PrintMethod != "" && PrintMethod != "printOperand") {
+ PrintMethodIdx = std::find(PrintMethods.begin(),
+ PrintMethods.end(), PrintMethod) -
+ PrintMethods.begin();
+ if (static_cast<unsigned>(PrintMethodIdx) == PrintMethods.size())
+ PrintMethods.push_back(PrintMethod);
+ }
+ }
+
+ if (Rec->isSubClassOf("RegisterOperand"))
+ Rec = Rec->getValueAsDef("RegClass");
+ if (Rec->isSubClassOf("RegisterClass")) {
+ IAP.addCond(Op + ".isReg()");
+
+ if (!IAP.isOpMapped(ROName)) {
+ IAP.addOperand(ROName, MIOpNum, PrintMethodIdx);
+ Record *R = CGA.ResultOperands[i].getRecord();
+ if (R->isSubClassOf("RegisterOperand"))
+ R = R->getValueAsDef("RegClass");
+ Cond = std::string("MRI.getRegClass(") + Target.getName() + "::" +
+ R->getName() + "RegClassID)"
+ ".contains(" + Op + ".getReg())";
+ } else {
+ Cond = Op + ".getReg() == MI->getOperand(" +
+ llvm::utostr(IAP.getOpIndex(ROName)) + ").getReg()";
+ }
+ } else {
+ // Assume all printable operands are desired for now. This can be
+ // overridden in the InstAlias instantiation if necessary.
+ IAP.addOperand(ROName, MIOpNum, PrintMethodIdx);
+
+ // There might be an additional predicate on the MCOperand
+ unsigned Entry = MCOpPredicateMap[Rec];
+ if (!Entry) {
+ if (!Rec->isValueUnset("MCOperandPredicate")) {
+ MCOpPredicates.push_back(Rec);
+ Entry = MCOpPredicates.size();
+ MCOpPredicateMap[Rec] = Entry;
+ } else
+ break; // No conditions on this operand at all
+ }
+ Cond = Target.getName() + ClassName + "ValidateMCOperand(" +
+ Op + ", " + llvm::utostr(Entry) + ")";
+ }
+ // for all subcases of ResultOperand::K_Record:
+ IAP.addCond(Cond);
+ break;
+ }
+ case CodeGenInstAlias::ResultOperand::K_Imm: {
+ // Just because the alias has an immediate result, doesn't mean the
+ // MCInst will. An MCExpr could be present, for example.
+ IAP.addCond(Op + ".isImm()");
+
+ Cond = Op + ".getImm() == " +
+ llvm::utostr(CGA.ResultOperands[i].getImm());
+ IAP.addCond(Cond);
+ break;
+ }
+ case CodeGenInstAlias::ResultOperand::K_Reg:
+ // If this is zero_reg, something's playing tricks we're not
+ // equipped to handle.
+ if (!CGA.ResultOperands[i].getRegister()) {
+ CantHandle = true;
+ break;
+ }
+
+ Cond = Op + ".getReg() == " + Target.getName() + "::" +
+ CGA.ResultOperands[i].getRegister()->getName();
+ IAP.addCond(Cond);
+ break;
+ }
+
+ MIOpNum += RO.getMINumOperands();
+ }
+
+ if (CantHandle) continue;
+ IAPrinterMap[Aliases.first].push_back(std::move(IAP));
+ }
+ }
+
+ //////////////////////////////
+ // Write out the printAliasInstr function
+ //////////////////////////////
+
+ std::string Header;
+ raw_string_ostream HeaderO(Header);
+
+ HeaderO << "bool " << Target.getName() << ClassName
+ << "::printAliasInstr(const MCInst"
+ << " *MI, " << (PassSubtarget ? "const MCSubtargetInfo &STI, " : "")
+ << "raw_ostream &OS) {\n";
+
+ std::string Cases;
+ raw_string_ostream CasesO(Cases);
+
+ for (auto &Entry : IAPrinterMap) {
+ std::vector<IAPrinter> &IAPs = Entry.second;
+ std::vector<IAPrinter*> UniqueIAPs;
+
+ for (auto &LHS : IAPs) {
+ bool IsDup = false;
+ for (const auto &RHS : IAPs) {
+ if (&LHS != &RHS && LHS == RHS) {
+ IsDup = true;
+ break;
+ }
+ }
+
+ if (!IsDup)
+ UniqueIAPs.push_back(&LHS);
+ }
+
+ if (UniqueIAPs.empty()) continue;
+
+ CasesO.indent(2) << "case " << Entry.first << ":\n";
+
+ for (std::vector<IAPrinter*>::iterator
+ II = UniqueIAPs.begin(), IE = UniqueIAPs.end(); II != IE; ++II) {
+ IAPrinter *IAP = *II;
+ CasesO.indent(4);
+ IAP->print(CasesO);
+ CasesO << '\n';
+ }
+
+ CasesO.indent(4) << "return false;\n";