llvm.org GIT mirror llvm / 44dcfd3
Replace the old algorithm that emitted the "print the alias for an instruction" with the newer, cleaner model. It uses the IAPrinter class to hold the information that is needed to match an instruction with its alias. This also takes into account the available features of the platform. There is one bit of ugliness. The way the logic determines if a pattern is unique is O(N**2), which is gross. But in reality, the number of items it's checking against isn't large. So while it's N**2, it shouldn't be a massive time sink. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@129110 91177308-0d34-0410-b5e6-96231b3b80d8 Bill Wendling 9 years ago
6 changed file(s) with 99 addition(s) and 163 deletion(s). Raw diff Collapse all Expand all
2424 /// assembly emission is disable.
2525 raw_ostream *CommentStream;
2626 const MCAsmInfo &MAI;
27
28 /// The current set of available features.
29 unsigned AvailableFeatures;
2730 public:
2831 MCInstPrinter(const MCAsmInfo &mai)
29 : CommentStream(0), MAI(mai) {}
32 : CommentStream(0), MAI(mai), AvailableFeatures(0) {}
3033
3134 virtual ~MCInstPrinter();
3235
4346
4447 /// getRegName - Return the assembler register name.
4548 virtual StringRef getRegName(unsigned RegNo) const;
49
50 unsigned getAvailableFeatures() const { return AvailableFeatures; }
51 void setAvailableFeatures(unsigned Value) { AvailableFeatures = Value; }
4652 };
4753
4854 } // namespace llvm
1414 #define DEBUG_TYPE "asm-printer"
1515 #include "X86ATTInstPrinter.h"
1616 #include "X86InstComments.h"
17 #include "X86Subtarget.h"
1718 #include "llvm/MC/MCInst.h"
1819 #include "llvm/MC/MCAsmInfo.h"
1920 #include "llvm/MC/MCExpr.h"
2122 #include "llvm/Support/Format.h"
2223 #include "llvm/Support/FormattedStream.h"
2324 #include "X86GenInstrNames.inc"
25 #include
2426 using namespace llvm;
2527
2628 // Include the auto-generated portion of the assembly writer.
2729 #define GET_INSTRUCTION_NAME
30 #define PRINT_ALIAS_INSTR
31 #include "X86GenRegisterNames.inc"
2832 #include "X86GenAsmWriter.inc"
33 #undef PRINT_ALIAS_INSTR
34 #undef GET_INSTRUCTION_NAME
35
36 X86ATTInstPrinter::X86ATTInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI)
37 : MCInstPrinter(MAI) {
38 // Initialize the set of available features.
39 setAvailableFeatures(ComputeAvailableFeatures(
40 &TM.getSubtarget()));
41 }
2942
3043 void X86ATTInstPrinter::printInst(const MCInst *MI, raw_ostream &OS) {
3144 printInstruction(MI, OS);
3447 if (CommentStream)
3548 EmitAnyX86InstComments(MI, *CommentStream, getRegisterName);
3649 }
50
3751 StringRef X86ATTInstPrinter::getOpcodeName(unsigned Opcode) const {
3852 return getInstructionName(Opcode);
3953 }
40
4154
4255 void X86ATTInstPrinter::printSSECC(const MCInst *MI, unsigned Op,
4356 raw_ostream &O) {
1818 namespace llvm {
1919
2020 class MCOperand;
21 class X86Subtarget;
2122 class TargetMachine;
2223
2324 class X86ATTInstPrinter : public MCInstPrinter {
2425 public:
25 X86ATTInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI)
26 : MCInstPrinter(MAI) {}
26 X86ATTInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI);
2727
2828 virtual void printInst(const MCInst *MI, raw_ostream &OS);
2929 virtual StringRef getOpcodeName(unsigned Opcode) const;
30
31 // Methods used to print the alias of an instruction.
32 unsigned ComputeAvailableFeatures(const X86Subtarget *Subtarget) const;
33 bool printAliasInstr(const MCInst *MI, raw_ostream &OS);
3034
3135 // Autogenerated by tblgen.
3236 void printInstruction(const MCInst *MI, raw_ostream &OS);
1414 #define DEBUG_TYPE "asm-printer"
1515 #include "X86IntelInstPrinter.h"
1616 #include "X86InstComments.h"
17 #include "X86Subtarget.h"
1718 #include "llvm/MC/MCInst.h"
1819 #include "llvm/MC/MCAsmInfo.h"
1920 #include "llvm/MC/MCExpr.h"
2525 public:
2626 X86IntelInstPrinter(TargetMachine &TM, const MCAsmInfo &MAI)
2727 : MCInstPrinter(MAI) {}
28
28
2929 virtual void printInst(const MCInst *MI, raw_ostream &OS);
3030 virtual StringRef getOpcodeName(unsigned Opcode) const;
3131
3333 void printInstruction(const MCInst *MI, raw_ostream &O);
3434 static const char *getRegisterName(unsigned RegNo);
3535 static const char *getInstructionName(unsigned Opcode);
36
3736
3837 void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
3938 void printMemReference(const MCInst *MI, unsigned Op, raw_ostream &O);
625625 bool isOpMapped(StringRef Op) { return OpMap.find(Op) != OpMap.end(); }
626626
627627 void print(raw_ostream &O) {
628 unsigned Indent = 8;
629
630 if (!Conds.empty())
631 O << "if (";
628 if (Conds.empty() && ReqFeatures.empty()) {
629 O.indent(6) << "return true;\n";
630 return;
631 }
632
633 O << "if (";
632634
633635 for (std::vector::iterator
634636 I = Conds.begin(), E = Conds.end(); I != E; ++I) {
635637 if (I != Conds.begin()) {
636638 O << " &&\n";
637 O.indent(Indent);
639 O.indent(8);
638640 }
639641
640642 O << *I;
641643 }
642644
643645 if (!ReqFeatures.empty()) {
644 if (Conds.begin() != Conds.end())
646 if (Conds.begin() != Conds.end()) {
645647 O << " &&\n";
646 else
648 O.indent(8);
649 } else {
647650 O << "if (";
651 }
648652
649653 std::string Req;
650654 raw_string_ostream ReqO(Req);
655659 ReqO << AWI.getFeatureInfo(*I)->getEnumName();
656660 }
657661
658 if (Conds.begin() != Conds.end()) O.indent(Indent);
659662 O << "(AvailableFeatures & (" << ReqO.str() << ")) == ("
660663 << ReqO.str() << ')';
661664 }
662665
663 if (!Conds.empty() || !ReqFeatures.empty()) {
664 O << ") {\n";
665 Indent = 6;
666 } else {
667 Indent = 4;
668 }
669
670 O.indent(Indent) << "// " << Result << "\n";
671 O.indent(Indent) << "AsmString = \"" << AsmString << "\";\n";
666 O << ") {\n";
667 O.indent(6) << "// " << Result << "\n";
668 O.indent(6) << "AsmString = \"" << AsmString << "\";\n";
672669
673670 for (std::map::iterator
674671 I = OpMap.begin(), E = OpMap.end(); I != E; ++I)
675 O.indent(Indent) << "OpMap[\"" << I->first << "\"] = "
676 << I->second << ";\n";
677
678 if (!Conds.empty() || !ReqFeatures.empty())
679 O.indent(4) << '}';
672 O.indent(6) << "OpMap[\"" << I->first << "\"] = "
673 << I->second << ";\n";
674
675 O.indent(6) << "break;\n";
676 O.indent(4) << '}';
680677 }
681678
682679 bool operator==(const IAPrinter &RHS) {
726723
727724 O << " Feature_None = 0\n";
728725 O << "};\n\n";
729 O << "} // end anonymous namespace\n";
726 O << "} // end anonymous namespace\n\n";
730727 }
731728
732729 /// EmitComputeAvailableFeatures - Emit the function to compute the list of
927924
928925 if (CantHandle) continue;
929926 IAPrinterMap[I->first].push_back(IAP);
930
931 #if 0
932 O.indent(4) << "// " << I->first << '\n';
933 O.indent(4);
934 IAP->print(O);
935 #endif
936 }
937 }
938
939 O << "#if 0\n";
927 }
928 }
929
940930 EmitSubtargetFeatureFlagEnumeration(AWI, O);
941931 EmitComputeAvailableFeatures(AWI, AsmWriter, Target, O);
942 O << "#endif\n\n";
943932
944933 O << "bool " << Target.getName() << ClassName
945934 << "::printAliasInstr(const " << MachineInstrClassName
946935 << " *MI, raw_ostream &OS) {\n";
947936
948 if (AliasMap.empty() || !isMC) {
949 // FIXME: Support MachineInstr InstAliases?
937 std::string Cases;
938 raw_string_ostream CasesO(Cases);
939
940 for (std::map >::iterator
941 I = IAPrinterMap.begin(), E = IAPrinterMap.end(); I != E; ++I) {
942 std::vector &IAPs = I->second;
943 std::vector UniqueIAPs;
944
945 for (std::vector::iterator
946 II = IAPs.begin(), IE = IAPs.end(); II != IE; ++II) {
947 IAPrinter *LHS = *II;
948 bool IsDup = false;
949 for (std::vector::iterator
950 III = IAPs.begin(), IIE = IAPs.end(); III != IIE; ++III) {
951 IAPrinter *RHS = *III;
952 if (LHS != RHS && *LHS == *RHS) {
953 IsDup = true;
954 break;
955 }
956 }
957
958 if (!IsDup) UniqueIAPs.push_back(LHS);
959 }
960
961 if (UniqueIAPs.empty()) continue;
962
963 CasesO.indent(2) << "case " << I->first << ":\n";
964
965 for (std::vector::iterator
966 II = UniqueIAPs.begin(), IE = UniqueIAPs.end(); II != IE; ++II) {
967 IAPrinter *IAP = *II;
968 CasesO.indent(4);
969 IAP->print(CasesO);
970 CasesO << '\n';
971 }
972
973 CasesO.indent(4) << "return true;\n";
974 }
975
976 if (CasesO.str().empty() || !isMC) {
950977 O << " return true;\n";
951978 O << "}\n\n";
952979 O << "#endif // PRINT_ALIAS_INSTR\n";
953980 return;
954981 }
955982
956 O << " StringRef AsmString;\n";
957 O << " std::map OpMap;\n";
958 O << " switch (MI->getOpcode()) {\n";
959 O << " default: return true;\n";
960
961 for (std::map >::iterator
962 I = AliasMap.begin(), E = AliasMap.end(); I != E; ++I) {
963 std::vector &Aliases = I->second;
964
965 std::map CondCount;
966 std::map BodyMap;
967
968 std::string AsmString = "";
969
970 for (std::vector::iterator
971 II = Aliases.begin(), IE = Aliases.end(); II != IE; ++II) {
972 const CodeGenInstAlias *CGA = *II;
973 AsmString = CGA->AsmString;
974 unsigned Indent = 8;
975 unsigned LastOpNo = CGA->ResultInstOperandIndex.size();
976
977 std::string Cond;
978 raw_string_ostream CondO(Cond);
979
980 CondO << "if (MI->getNumOperands() == " << LastOpNo;
981
982 std::map OpMap;
983 bool CantHandle = false;
984
985 for (unsigned i = 0, e = LastOpNo; i != e; ++i) {
986 const CodeGenInstAlias::ResultOperand &RO = CGA->ResultOperands[i];
987
988 switch (RO.Kind) {
989 default: assert(0 && "unexpected InstAlias operand kind");
990 case CodeGenInstAlias::ResultOperand::K_Record: {
991 const Record *Rec = RO.getRecord();
992 StringRef ROName = RO.getName();
993
994 if (Rec->isSubClassOf("RegisterClass")) {
995 CondO << " &&\n";
996 CondO.indent(Indent) << "MI->getOperand(" << i << ").isReg() &&\n";
997 if (OpMap.find(ROName) == OpMap.end()) {
998 OpMap[ROName] = i;
999 CondO.indent(Indent)
1000 << "regIsInRegisterClass(RC_"
1001 << CGA->ResultOperands[i].getRecord()->getName()
1002 << ", MI->getOperand(" << i << ").getReg())";
1003 } else {
1004 CondO.indent(Indent)
1005 << "MI->getOperand(" << i
1006 << ").getReg() == MI->getOperand("
1007 << OpMap[ROName] << ").getReg()";
1008 }
1009 } else {
1010 assert(Rec->isSubClassOf("Operand") && "Unexpected operand!");
1011 // FIXME: We need to handle these situations.
1012 CantHandle = true;
1013 break;
1014 }
1015
1016 break;
1017 }
1018 case CodeGenInstAlias::ResultOperand::K_Imm:
1019 CondO << " &&\n";
1020 CondO.indent(Indent) << "MI->getOperand(" << i << ").getImm() == ";
1021 CondO << CGA->ResultOperands[i].getImm();
1022 break;
1023 case CodeGenInstAlias::ResultOperand::K_Reg:
1024 CondO << " &&\n";
1025 CondO.indent(Indent) << "MI->getOperand(" << i << ").getReg() == ";
1026 CondO << Target.getName() << "::"
1027 << CGA->ResultOperands[i].getRegister()->getName();
1028 break;
1029 }
1030
1031 if (CantHandle) break;
1032 }
1033
1034 if (CantHandle) continue;
1035
1036 CondO << ")";
1037
1038 std::string Body;
1039 raw_string_ostream BodyO(Body);
1040
1041 BodyO << " // " << CGA->Result->getAsString() << "\n";
1042 BodyO << " AsmString = \"" << AsmString << "\";\n";
1043
1044 for (std::map::iterator
1045 III = OpMap.begin(), IIE = OpMap.end(); III != IIE; ++III)
1046 BodyO << " OpMap[\"" << III->first << "\"] = "
1047 << III->second << ";\n";
1048
1049 ++CondCount[CondO.str()];
1050 BodyMap[CondO.str()] = BodyO.str();
1051 }
1052
1053 std::string Code;
1054 raw_string_ostream CodeO(Code);
1055
1056 bool EmitElse = false;
1057 for (std::map::iterator
1058 II = CondCount.begin(), IE = CondCount.end(); II != IE; ++II) {
1059 if (II->second != 1) continue;
1060 CodeO << " ";
1061 if (EmitElse) CodeO << "} else ";
1062 CodeO << II->first << " {\n";
1063 CodeO << BodyMap[II->first];
1064 EmitElse = true;
1065 }
1066
1067 if (CodeO.str().empty()) continue;
1068
1069 O << " case " << I->first << ":\n";
1070 O << CodeO.str();
1071 O << " }\n";
1072 O << " break;\n";
1073 }
1074
1075 O << " }\n\n";
983 O.indent(2) << "StringRef AsmString;\n";
984 O.indent(2) << "std::map OpMap;\n";
985 O.indent(2) << "unsigned AvailableFeatures = getAvailableFeatures();\n\n";
986 O.indent(2) << "switch (MI->getOpcode()) {\n";
987 O.indent(2) << "default: return true;\n";
988 O << CasesO.str();
989 O.indent(2) << "}\n\n";
1076990
1077991 // Code that prints the alias, replacing the operands with the ones from the
1078992 // MCInst.
1079 O << " if (AsmString.empty()) return true;\n";
1080993 O << " std::pair ASM = AsmString.split(' ');\n";
1081994 O << " OS << '\\t' << ASM.first;\n";
1082995