+namespace {
+// 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 {
+ std::vector<std::string> Conds;
+ std::map<StringRef, unsigned> OpMap;
+ std::string Result;
+ std::string AsmString;
+ SmallVector<Record*, 4> ReqFeatures;
+public:
+ IAPrinter(std::string R, std::string AS)
+ : Result(R), AsmString(AS) {}
+
+ void addCond(const std::string &C) { Conds.push_back(C); }
+
+ void addOperand(StringRef Op, unsigned Idx) {
+ assert(Idx < 0xFF && "Index too large!");
+ OpMap[Op] = Idx;
+ }
+ unsigned getOpIndex(StringRef Op) { return OpMap[Op]; }
+ bool isOpMapped(StringRef Op) { return OpMap.find(Op) != OpMap.end(); }
+
+ void print(raw_ostream &O) {
+ if (Conds.empty() && ReqFeatures.empty()) {
+ O.indent(6) << "return true;\n";
+ return;
+ }
+
+ O << "if (";
+
+ for (std::vector<std::string>::iterator
+ I = Conds.begin(), E = Conds.end(); I != E; ++I) {
+ if (I != Conds.begin()) {
+ O << " &&\n";
+ O.indent(8);
+ }
+
+ O << *I;
+ }
+
+ O << ") {\n";
+ O.indent(6) << "// " << Result << "\n";
+
+ // Directly mangle mapped operands into the string. Each operand is
+ // identified by a '$' sign followed by a byte identifying the number of the
+ // operand. We add one to the index to avoid zero bytes.
+ std::pair<StringRef, StringRef> ASM = StringRef(AsmString).split(' ');
+ SmallString<128> OutString = ASM.first;
+ if (!ASM.second.empty()) {
+ raw_svector_ostream OS(OutString);
+ OS << ' ';
+ for (StringRef::iterator I = ASM.second.begin(), E = ASM.second.end();
+ I != E;) {
+ OS << *I;
+ if (*I == '$') {
+ StringRef::iterator Start = ++I;
+ while (I != E &&
+ ((*I >= 'a' && *I <= 'z') || (*I >= 'A' && *I <= 'Z') ||
+ (*I >= '0' && *I <= '9') || *I == '_'))
+ ++I;
+ StringRef Name(Start, I - Start);
+ assert(isOpMapped(Name) && "Unmapped operand!");
+ OS << format("\\x%02X", (unsigned char)getOpIndex(Name) + 1);
+ } else {
+ ++I;
+ }
+ }
+ }
+
+ // Emit the string.
+ O.indent(6) << "AsmString = \"" << OutString.str() << "\";\n";
+
+ O.indent(6) << "break;\n";
+ O.indent(4) << '}';
+ }
+
+ bool operator==(const IAPrinter &RHS) {
+ if (Conds.size() != RHS.Conds.size())
+ return false;
+
+ unsigned Idx = 0;
+ for (std::vector<std::string>::iterator
+ I = Conds.begin(), E = Conds.end(); I != E; ++I)
+ if (*I != RHS.Conds[Idx++])
+ return false;
+
+ return true;
+ }
+
+ bool operator()(const IAPrinter &RHS) {
+ if (Conds.size() < RHS.Conds.size())
+ return true;
+
+ unsigned Idx = 0;
+ for (std::vector<std::string>::iterator
+ I = Conds.begin(), E = Conds.end(); I != E; ++I)
+ if (*I != RHS.Conds[Idx++])
+ return *I < RHS.Conds[Idx++];
+
+ return false;
+ }
+};
+
+} // end anonymous namespace
+
+static unsigned CountNumOperands(StringRef AsmString) {
+ unsigned NumOps = 0;
+ std::pair<StringRef, StringRef> ASM = AsmString.split(' ');
+
+ while (!ASM.second.empty()) {
+ ++NumOps;
+ ASM = ASM.second.split(' ');
+ }
+
+ return NumOps;
+}
+
+static unsigned CountResultNumOperands(StringRef AsmString) {
+ unsigned NumOps = 0;
+ std::pair<StringRef, StringRef> ASM = AsmString.split('\t');
+
+ if (!ASM.second.empty()) {
+ size_t I = ASM.second.find('{');
+ StringRef Str = ASM.second;
+ if (I != StringRef::npos)
+ Str = ASM.second.substr(I, ASM.second.find('|', I));
+
+ ASM = Str.split(' ');
+
+ do {
+ ++NumOps;
+ ASM = ASM.second.split(' ');
+ } while (!ASM.second.empty());
+ }
+
+ return NumOps;
+}
+
+void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
+ CodeGenTarget Target(Records);
+ Record *AsmWriter = Target.getAsmWriter();
+
+ if (!AsmWriter->getValueAsBit("isMCAsmWriter"))
+ return;
+
+ O << "\n#ifdef PRINT_ALIAS_INSTR\n";
+ O << "#undef PRINT_ALIAS_INSTR\n\n";
+
+ // Emit the method that prints the alias instruction.
+ std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
+
+ std::vector<Record*> AllInstAliases =
+ Records.getAllDerivedDefinitions("InstAlias");
+
+ // Create a map from the qualified name to a list of potential matches.
+ std::map<std::string, std::vector<CodeGenInstAlias*> > AliasMap;
+ for (std::vector<Record*>::iterator
+ I = AllInstAliases.begin(), E = AllInstAliases.end(); I != E; ++I) {
+ CodeGenInstAlias *Alias = new CodeGenInstAlias(*I, Target);
+ const Record *R = *I;
+ if (!R->getValueAsBit("EmitAlias"))
+ continue; // We were told not to emit the alias, but to emit the aliasee.
+ const DagInit *DI = R->getValueAsDag("ResultInst");
+ const DefInit *Op = cast<DefInit>(DI->getOperator());
+ AliasMap[getQualifiedName(Op->getDef())].push_back(Alias);
+ }
+
+ // 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;
+
+ for (std::map<std::string, std::vector<CodeGenInstAlias*> >::iterator
+ I = AliasMap.begin(), E = AliasMap.end(); I != E; ++I) {
+ std::vector<CodeGenInstAlias*> &Aliases = I->second;
+
+ for (std::vector<CodeGenInstAlias*>::iterator
+ II = Aliases.begin(), IE = Aliases.end(); II != IE; ++II) {
+ const CodeGenInstAlias *CGA = *II;
+ unsigned LastOpNo = CGA->ResultInstOperandIndex.size();
+ unsigned NumResultOps =
+ CountResultNumOperands(CGA->ResultInst->AsmString);
+
+ // Don't emit the alias if it has more operands than what it's aliasing.
+ if (NumResultOps < CountNumOperands(CGA->AsmString))
+ continue;
+
+ IAPrinter *IAP = new IAPrinter(CGA->Result->getAsString(),
+ CGA->AsmString);
+
+ std::string Cond;
+ Cond = std::string("MI->getNumOperands() == ") + llvm::utostr(LastOpNo);
+ IAP->addCond(Cond);
+
+ bool CantHandle = false;
+
+ for (unsigned i = 0, e = LastOpNo; i != e; ++i) {
+ const CodeGenInstAlias::ResultOperand &RO = CGA->ResultOperands[i];
+
+ switch (RO.Kind) {
+ case CodeGenInstAlias::ResultOperand::K_Record: {
+ const Record *Rec = RO.getRecord();
+ StringRef ROName = RO.getName();
+
+
+ if (Rec->isSubClassOf("RegisterOperand"))
+ Rec = Rec->getValueAsDef("RegClass");
+ if (Rec->isSubClassOf("RegisterClass")) {
+ Cond = std::string("MI->getOperand(")+llvm::utostr(i)+").isReg()";
+ IAP->addCond(Cond);
+
+ if (!IAP->isOpMapped(ROName)) {
+ IAP->addOperand(ROName, i);
+ 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(MI->getOperand(" + llvm::utostr(i) + ").getReg())";
+ IAP->addCond(Cond);
+ } else {
+ Cond = std::string("MI->getOperand(") +
+ llvm::utostr(i) + ").getReg() == MI->getOperand(" +
+ llvm::utostr(IAP->getOpIndex(ROName)) + ").getReg()";
+ IAP->addCond(Cond);
+ }
+ } else {
+ assert(Rec->isSubClassOf("Operand") && "Unexpected operand!");
+ // FIXME: We may need to handle these situations.
+ delete IAP;
+ IAP = 0;
+ CantHandle = true;
+ break;
+ }
+
+ break;
+ }
+ case CodeGenInstAlias::ResultOperand::K_Imm: {
+ std::string Op = "MI->getOperand(" + llvm::utostr(i) + ")";
+
+ // 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 = std::string("MI->getOperand(") +
+ llvm::utostr(i) + ").getReg() == " + Target.getName() +
+ "::" + CGA->ResultOperands[i].getRegister()->getName();
+ IAP->addCond(Cond);
+ break;
+ }
+
+ if (!IAP) break;
+ }
+
+ if (CantHandle) continue;
+ IAPrinterMap[I->first].push_back(IAP);
+ }
+ }
+
+ std::string Header;
+ raw_string_ostream HeaderO(Header);
+
+ HeaderO << "bool " << Target.getName() << ClassName
+ << "::printAliasInstr(const MCInst"
+ << " *MI, raw_ostream &OS) {\n";
+
+ std::string Cases;
+ raw_string_ostream CasesO(Cases);
+
+ for (std::map<std::string, std::vector<IAPrinter*> >::iterator
+ I = IAPrinterMap.begin(), E = IAPrinterMap.end(); I != E; ++I) {
+ std::vector<IAPrinter*> &IAPs = I->second;
+ std::vector<IAPrinter*> UniqueIAPs;
+
+ for (std::vector<IAPrinter*>::iterator
+ II = IAPs.begin(), IE = IAPs.end(); II != IE; ++II) {
+ IAPrinter *LHS = *II;
+ bool IsDup = false;
+ for (std::vector<IAPrinter*>::iterator
+ III = IAPs.begin(), IIE = IAPs.end(); III != IIE; ++III) {
+ IAPrinter *RHS = *III;
+ if (LHS != RHS && *LHS == *RHS) {
+ IsDup = true;
+ break;
+ }
+ }
+
+ if (!IsDup) UniqueIAPs.push_back(LHS);
+ }
+
+ if (UniqueIAPs.empty()) continue;
+
+ CasesO.indent(2) << "case " << I->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";
+ }
+
+ if (CasesO.str().empty()) {
+ O << HeaderO.str();
+ O << " return false;\n";
+ O << "}\n\n";
+ O << "#endif // PRINT_ALIAS_INSTR\n";
+ return;
+ }
+
+ O << HeaderO.str();
+ O.indent(2) << "const char *AsmString;\n";
+ O.indent(2) << "switch (MI->getOpcode()) {\n";
+ O.indent(2) << "default: return false;\n";
+ O << CasesO.str();
+ O.indent(2) << "}\n\n";
+
+ // Code that prints the alias, replacing the operands with the ones from the
+ // MCInst.
+ O << " unsigned I = 0;\n";
+ O << " while (AsmString[I] != ' ' && AsmString[I] != '\\0')\n";
+ O << " ++I;\n";
+ O << " OS << '\\t' << StringRef(AsmString, I);\n";
+
+ O << " if (AsmString[I] != '\\0') {\n";
+ O << " OS << '\\t';\n";
+ O << " do {\n";
+ O << " if (AsmString[I] == '$') {\n";
+ O << " ++I;\n";
+ O << " printOperand(MI, unsigned(AsmString[I++]) - 1, OS);\n";
+ O << " } else {\n";
+ O << " OS << AsmString[I++];\n";
+ O << " }\n";
+ O << " } while (AsmString[I] != '\\0');\n";
+ O << " }\n\n";
+
+ O << " return true;\n";
+ O << "}\n\n";
+
+ O << "#endif // PRINT_ALIAS_INSTR\n";
+}