[llvm-commits] CVS: llvm/utils/TableGen/AsmWriterEmitter.cpp

Chris Lattner lattner at cs.uiuc.edu
Sat Jan 22 09:32:58 PST 2005



Changes in directory llvm/utils/TableGen:

AsmWriterEmitter.cpp updated: 1.10 -> 1.11
---
Log message:

Seperate asmstring parsing from emission.  This allows the code to be simpler
and more understandable.  It also allows us to do simple things like fold 
consequtive literal strings together.  For example, instead of emitting this
for the X86 backend:

  O  << "adc" << "l" << " ";

we now generate this:

  O << "adcl "; 

*whoa* :)

This shrinks the X86 asmwriters from 62729->58267 and 65176->58644 bytes
for the intel/att asm writers respectively.



---
Diffs of the changes:  (+153 -86)

 AsmWriterEmitter.cpp |  239 ++++++++++++++++++++++++++++++++-------------------
 1 files changed, 153 insertions(+), 86 deletions(-)


Index: llvm/utils/TableGen/AsmWriterEmitter.cpp
diff -u llvm/utils/TableGen/AsmWriterEmitter.cpp:1.10 llvm/utils/TableGen/AsmWriterEmitter.cpp:1.11
--- llvm/utils/TableGen/AsmWriterEmitter.cpp:1.10	Fri Jan 21 18:35:22 2005
+++ llvm/utils/TableGen/AsmWriterEmitter.cpp	Sat Jan 22 11:32:42 2005
@@ -25,6 +25,154 @@
          C == '_';
 }
 
+namespace {
+  struct AsmWriterOperand {
+    enum { isLiteralTextOperand, isMachineInstrOperand } OperandType;
+
+    /// Str - For isLiteralTextOperand, this IS the literal text.  For
+    /// isMachineInstrOperand, this is the PrinterMethodName for the operand.
+    std::string Str;
+
+    /// MiOpNo - For isMachineInstrOperand, this is the operand number of the
+    /// machine instruction.
+    unsigned MIOpNo;
+
+    /// OpVT - For isMachineInstrOperand, this is the value type for the
+    /// operand.
+    MVT::ValueType OpVT;
+
+    AsmWriterOperand(const std::string &LitStr)
+      : OperandType(isLiteralTextOperand),  Str(LitStr) {}
+
+    AsmWriterOperand(const std::string &Printer, unsigned OpNo,
+                     MVT::ValueType VT) : OperandType(isMachineInstrOperand),
+                                          Str(Printer), MIOpNo(OpNo), OpVT(VT){}
+
+    void EmitCode(std::ostream &OS) const;
+  };
+
+  struct AsmWriterInst {
+    std::vector<AsmWriterOperand> Operands;
+    
+    void ParseAsmString(const CodeGenInstruction &CGI, unsigned Variant);
+    void EmitCode(std::ostream &OS) const {
+      for (unsigned i = 0, e = Operands.size(); i != e; ++i)
+        Operands[i].EmitCode(OS);
+    }
+  private:
+    void AddLiteralString(const std::string &Str) {
+      // If the last operand was already a literal text string, append this to
+      // it, otherwise add a new operand.
+      if (!Operands.empty() &&
+          Operands.back().OperandType == AsmWriterOperand::isLiteralTextOperand)
+        Operands.back().Str.append(Str);
+      else
+        Operands.push_back(AsmWriterOperand(Str));
+    }
+  };
+}
+
+
+void AsmWriterOperand::EmitCode(std::ostream &OS) const {
+  if (OperandType == isLiteralTextOperand)
+    OS << "O << \"" << Str << "\"; ";
+  else
+    OS << Str << "(MI, " << MIOpNo << ", MVT::" << getName(OpVT) << "); ";
+}
+
+
+/// ParseAsmString - Parse the specified Instruction's AsmString into this
+/// AsmWriterInst.
+///
+void AsmWriterInst::ParseAsmString(const CodeGenInstruction &CGI,
+                                   unsigned Variant) {
+  bool inVariant = false;  // True if we are inside a {.|.|.} region.
+
+  const std::string &AsmString = CGI.AsmString;
+  std::string::size_type LastEmitted = 0;
+  while (LastEmitted != AsmString.size()) {
+    std::string::size_type DollarPos =
+      AsmString.find_first_of("${|}", LastEmitted);
+    if (DollarPos == std::string::npos) DollarPos = AsmString.size();
+
+    // Emit a constant string fragment.
+    if (DollarPos != LastEmitted) {
+      // TODO: this should eventually handle escaping.
+      AddLiteralString(std::string(AsmString.begin()+LastEmitted,
+                                   AsmString.begin()+DollarPos));
+      LastEmitted = DollarPos;
+    } else if (AsmString[DollarPos] == '{') {
+      if (inVariant)
+        throw "Nested variants found for instruction '" + CGI.Name + "'!";
+      LastEmitted = DollarPos+1;
+      inVariant = true;   // We are now inside of the variant!
+      for (unsigned i = 0; i != Variant; ++i) {
+        // Skip over all of the text for an irrelevant variant here.  The
+        // next variant starts at |, or there may not be text for this
+        // variant if we see a }.
+        std::string::size_type NP =
+          AsmString.find_first_of("|}", LastEmitted);
+        if (NP == std::string::npos)
+          throw "Incomplete variant for instruction '" + CGI.Name + "'!";
+        LastEmitted = NP+1;
+        if (AsmString[NP] == '}') {
+          inVariant = false;        // No text for this variant.
+          break;
+        }
+      }
+    } else if (AsmString[DollarPos] == '|') {
+      if (!inVariant)
+        throw "'|' character found outside of a variant in instruction '"
+          + CGI.Name + "'!";
+      // Move to the end of variant list.
+      std::string::size_type NP = AsmString.find('}', LastEmitted);
+      if (NP == std::string::npos)
+        throw "Incomplete variant for instruction '" + CGI.Name + "'!";
+      LastEmitted = NP+1;
+      inVariant = false;
+    } else if (AsmString[DollarPos] == '}') {
+      if (!inVariant)
+        throw "'}' character found outside of a variant in instruction '"
+          + CGI.Name + "'!";
+      LastEmitted = DollarPos+1;
+      inVariant = false;
+    } else if (DollarPos+1 != AsmString.size() &&
+               AsmString[DollarPos+1] == '$') {
+      AddLiteralString("$");  // "$$" -> $
+      LastEmitted = DollarPos+2;
+    } else {
+      // Get the name of the variable.
+      // TODO: should eventually handle ${foo}bar as $foo
+      std::string::size_type VarEnd = DollarPos+1;
+      while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
+        ++VarEnd;
+      std::string VarName(AsmString.begin()+DollarPos+1,
+                          AsmString.begin()+VarEnd);
+      if (VarName.empty())
+        throw "Stray '$' in '" + CGI.Name + "' asm string, maybe you want $$?";
+
+      unsigned OpNo = CGI.getOperandNamed(VarName);
+
+      // If this is a two-address instruction and we are not accessing the
+      // 0th operand, remove an operand.
+      unsigned MIOp = CGI.OperandList[OpNo].MIOperandNo;
+      if (CGI.isTwoAddress && MIOp != 0) {
+        if (MIOp == 1)
+          throw "Should refer to operand #0 instead of #1 for two-address"
+            " instruction '" + CGI.Name + "'!";
+        --MIOp;
+      }
+
+      Operands.push_back(AsmWriterOperand(CGI.OperandList[OpNo].PrinterMethodName,
+                                          MIOp, CGI.OperandList[OpNo].Ty));
+      LastEmitted = VarEnd;
+    }
+  }
+
+  AddLiteralString("\\n");
+}
+
+
 void AsmWriterEmitter::run(std::ostream &O) {
   EmitSourceFileHeader("Assembly Writer Source Fragment", O);
 
@@ -45,96 +193,15 @@
 
   std::string Namespace = Target.inst_begin()->second.Namespace;
 
-  bool inVariant = false;  // True if we are inside a {.|.|.} region.
-
   for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
          E = Target.inst_end(); I != E; ++I)
     if (!I->second.AsmString.empty()) {
-      const std::string &AsmString = I->second.AsmString;
-      O << "  case " << Namespace << "::" << I->first << ": O ";
-
-      std::string::size_type LastEmitted = 0;
-      while (LastEmitted != AsmString.size()) {
-        std::string::size_type DollarPos =
-          AsmString.find_first_of("${|}", LastEmitted);
-        if (DollarPos == std::string::npos) DollarPos = AsmString.size();
-
-        // Emit a constant string fragment.
-        if (DollarPos != LastEmitted) {
-          // TODO: this should eventually handle escaping.
-          O << " << \"" << std::string(AsmString.begin()+LastEmitted,
-                                       AsmString.begin()+DollarPos) << "\"";
-          LastEmitted = DollarPos;
-        } else if (AsmString[DollarPos] == '{') {
-          if (inVariant)
-            throw "Nested variants found for instruction '" + I->first + "'!";
-          LastEmitted = DollarPos+1;
-          inVariant = true;   // We are now inside of the variant!
-          for (unsigned i = 0; i != Variant; ++i) {
-            // Skip over all of the text for an irrelevant variant here.  The
-            // next variant starts at |, or there may not be text for this
-            // variant if we see a }.
-            std::string::size_type NP =
-              AsmString.find_first_of("|}", LastEmitted);
-            if (NP == std::string::npos)
-              throw "Incomplete variant for instruction '" + I->first + "'!";
-            LastEmitted = NP+1;
-            if (AsmString[NP] == '}') {
-              inVariant = false;        // No text for this variant.
-              break;
-            }
-          }
-        } else if (AsmString[DollarPos] == '|') {
-          if (!inVariant)
-            throw "'|' character found outside of a variant in instruction '"
-                  + I->first + "'!";
-          // Move to the end of variant list.
-          std::string::size_type NP = AsmString.find('}', LastEmitted);
-          if (NP == std::string::npos)
-            throw "Incomplete variant for instruction '" + I->first + "'!";
-          LastEmitted = NP+1;
-          inVariant = false;
-        } else if (AsmString[DollarPos] == '}') {
-          if (!inVariant)
-            throw "'}' character found outside of a variant in instruction '"
-                  + I->first + "'!";
-          LastEmitted = DollarPos+1;
-          inVariant = false;
-        } else if (DollarPos+1 != AsmString.size() &&
-                   AsmString[DollarPos+1] == '$') {
-          O << " << '$'";         // "$$" -> $
-	  LastEmitted = DollarPos+2;
-        } else {
-          // Get the name of the variable.
-          // TODO: should eventually handle ${foo}bar as $foo
-          std::string::size_type VarEnd = DollarPos+1;
-          while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
-            ++VarEnd;
-          std::string VarName(AsmString.begin()+DollarPos+1,
-                              AsmString.begin()+VarEnd);
-          if (VarName.empty())
-            throw "Stray '$' in '" + I->first +
-                  "' asm string, maybe you want $$?";
-          unsigned OpNo = I->second.getOperandNamed(VarName);
-
-          // If this is a two-address instruction and we are not accessing the
-          // 0th operand, remove an operand.
-          unsigned MIOp = I->second.OperandList[OpNo].MIOperandNo;
-          if (I->second.isTwoAddress && MIOp != 0) {
-            if (MIOp == 1)
-              throw "Should refer to operand #0 instead of #1 for two-address"
-                    " instruction '" + I->first + "'!";
-            --MIOp;
-          }
-
-          O << ";  " << I->second.OperandList[OpNo].PrinterMethodName 
-            << "(MI, " << MIOp << ", MVT::"
-            << getName(I->second.OperandList[OpNo].Ty) << "); O ";
-          LastEmitted = VarEnd;
-        }
-      }
+      O << "  case " << Namespace << "::" << I->first << ": ";
 
-      O << " << '\\n'; break;\n";
+      AsmWriterInst AWI;
+      AWI.ParseAsmString(I->second, Variant);
+      AWI.EmitCode(O);
+      O << " break;\n";
     }
 
   O << "  }\n"






More information about the llvm-commits mailing list