[llvm-commits] [llvm] r118217 - /llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp

Chris Lattner sabre at nondot.org
Wed Nov 3 17:43:46 PDT 2010


Author: lattner
Date: Wed Nov  3 19:43:46 2010
New Revision: 118217

URL: http://llvm.org/viewvc/llvm-project?rev=118217&view=rev
Log:
take a big step to making aliases more general and less of a hack:
now matchables contain an explicit list of how to populate each
operand in the result instruction instead of having them somehow
magically be correlated to the input inst.

Modified:
    llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp

Modified: llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp?rev=118217&r1=118216&r2=118217&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp Wed Nov  3 19:43:46 2010
@@ -81,7 +81,6 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
-#include <list>
 #include <map>
 #include <set>
 using namespace llvm;
@@ -258,6 +257,55 @@
     
     explicit AsmOperand(StringRef T) : Token(T), Class(0), OperandInfo(0) {}
   };
+  
+  /// ResOperand - This represents a single operand in the result instruction
+  /// generated by the match.  In cases (like addressing modes) where a single
+  /// assembler operand expands to multiple MCOperands, this represents the
+  /// single assembler operand, not the MCOperand.
+  struct ResOperand {
+    enum {
+      /// RenderAsmOperand - This represents an operand result that is
+      /// generated by calling the render method on the assembly operand.  The
+      /// corresponding AsmOperand is specified by AsmOperandNum.
+      RenderAsmOperand,
+      
+      /// TiedOperand - This represents a result operand that is a duplicate of
+      /// a previous result operand.
+      TiedOperand
+    } Kind;
+    
+    union {
+      /// This is the operand # in the AsmOperands list that this should be
+      /// copied from.
+      unsigned AsmOperandNum;
+      
+      /// TiedOperandNum - This is the (earlier) result operand that should be
+      /// copied from.
+      unsigned TiedOperandNum;
+    };
+    
+    /// OpInfo - This is the information about the instruction operand that is
+    /// being populated.
+    const CGIOperandList::OperandInfo *OpInfo;
+    
+    static ResOperand getRenderedOp(unsigned AsmOpNum,
+                                    const CGIOperandList::OperandInfo *Op) {
+      ResOperand X;
+      X.Kind = RenderAsmOperand;
+      X.AsmOperandNum = AsmOpNum;
+      X.OpInfo = Op;
+      return X;
+    }
+    
+    static ResOperand getTiedOp(unsigned TiedOperandNum,
+                                const CGIOperandList::OperandInfo *Op) {
+      ResOperand X;
+      X.Kind = TiedOperand;
+      X.TiedOperandNum = TiedOperandNum;
+      X.OpInfo = Op;
+      return X;
+    }
+  };
 
   /// InstrName - The target name for this instruction.
   std::string InstrName;
@@ -266,9 +314,13 @@
   /// matchable came from.
   Record *const TheDef;
   
-  /// OperandList - This is the operand list that came from the (ins) and (outs)
-  /// list of the alias or instruction.
-  const CGIOperandList &OperandList;
+  // FIXME: REMOVE.
+  const CGIOperandList &TheOperandList;
+
+  
+  /// ResOperands - This is the operand list that should be built for the result
+  /// MCInst.
+  std::vector<ResOperand> ResOperands;
 
   /// AsmString - The assembly string for this instruction (with variants
   /// removed), e.g. "movsx $src, $dst".
@@ -293,12 +345,12 @@
   std::string ConversionFnKind;
   
   MatchableInfo(const CodeGenInstruction &CGI)
-    : TheDef(CGI.TheDef), OperandList(CGI.Operands), AsmString(CGI.AsmString) {
+    : TheDef(CGI.TheDef), TheOperandList(CGI.Operands), AsmString(CGI.AsmString) {
     InstrName = TheDef->getName();
   }
 
   MatchableInfo(const CodeGenInstAlias *Alias)
-    : TheDef(Alias->TheDef), OperandList(Alias->Operands),
+    : TheDef(Alias->TheDef), TheOperandList(Alias->Operands),
       AsmString(Alias->AsmString) {
         
     // FIXME: Huge hack.
@@ -320,6 +372,8 @@
   Record *getSingletonRegisterForAsmOperand(unsigned i,
                                             const AsmMatcherInfo &Info) const;  
 
+  void BuildResultOperands();
+
   /// operator< - Compare two matchables.
   bool operator<(const MatchableInfo &RHS) const {
     // The primary comparator is the instruction mnemonic.
@@ -452,6 +506,9 @@
   /// operand classes.
   void BuildOperandClasses();
 
+  void BuildInstructionOperandReference(MatchableInfo *II,
+                                        MatchableInfo::AsmOperand &Op);
+
 public:
   AsmMatcherInfo(Record *AsmParser, CodeGenTarget &Target);
 
@@ -652,33 +709,6 @@
     }
   }
   
-  // Validate the operand list to ensure we can handle this instruction.
-  for (unsigned i = 0, e = OperandList.size(); i != e; ++i) {
-    const CGIOperandList::OperandInfo &OI = OperandList[i];
-
-    // Validate tied operands.
-    if (OI.getTiedRegister() != -1) {
-      // If we have a tied operand that consists of multiple MCOperands, reject
-      // it.  We reject aliases and ignore instructions for now.
-      if (OI.MINumOperands != 1) {
-        if (!Hack)
-          throw TGError(TheDef->getLoc(),
-                        "ERROR: tied operand '" + OI.Name +
-                        "' has multiple MCOperands!");
-        
-        // FIXME: Should reject these.  The ARM backend hits this with $lane in a
-        // bunch of instructions.  It is unclear what the right answer is.
-        DEBUG({
-          errs() << "warning: '" << InstrName << "': "
-                 << "ignoring instruction with multi-operand tied operand '"
-                 << OI.Name << "'\n";
-        });
-        return false;
-      }
-    }
-  }
-  
-  
   return true;
 }
 
@@ -944,6 +974,52 @@
     RegisterPrefix(AsmParser->getValueAsString("RegisterPrefix")) {
 }
 
+/// BuildInstructionOperandReference - The specified operand is a reference to a
+/// named operand such as $src.  Resolve the Class and OperandInfo pointers.
+void AsmMatcherInfo::
+BuildInstructionOperandReference(MatchableInfo *II,
+                                 MatchableInfo::AsmOperand &Op) {
+  StringRef Token = Op.Token;
+  assert(Token[0] == '$' && "Not an operand name ref");
+  
+  StringRef OperandName;
+  if (Token[1] == '{')
+    OperandName = Token.substr(2, Token.size() - 3);
+  else
+    OperandName = Token.substr(1);
+  
+  const CGIOperandList &Operands = II->TheOperandList;
+   
+  
+  // Map this token to an operand. FIXME: Move elsewhere.
+  unsigned Idx;
+  if (!Operands.hasOperandNamed(OperandName, Idx))
+    throw TGError(II->TheDef->getLoc(), "error: unable to find operand: '" +
+                  OperandName.str() + "'");
+  
+  // FIXME: This is annoying, the named operand may be tied (e.g.,
+  // XCHG8rm). What we want is the untied operand, which we now have to
+  // grovel for. Only worry about this for single entry operands, we have to
+  // clean this up anyway.
+  const CGIOperandList::OperandInfo *OI = &Operands[Idx];
+  int OITied = OI->getTiedRegister();
+  if (OITied != -1) {
+    // The tied operand index is an MIOperand index, find the operand that
+    // contains it.
+    for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+      if (Operands[i].MIOperandNo == unsigned(OITied)) {
+        OI = &Operands[i];
+        break;
+      }
+    }
+    
+    assert(OI && "Unable to find tied operand target!");
+  }
+  
+  Op.Class = getOperandClass(Token, *OI);
+  Op.OperandInfo = OI;
+}
+
 
 void AsmMatcherInfo::BuildInfo() {
   // Build information about all of the AssemblerPredicates.
@@ -981,6 +1057,27 @@
     if (CGI.TheDef->getValueAsBit("isCodeGenOnly"))
       continue;
     
+    // Validate the operand list to ensure we can handle this instruction.
+    for (unsigned i = 0, e = CGI.Operands.size(); i != e; ++i) {
+      const CGIOperandList::OperandInfo &OI = CGI.Operands[i];
+      
+      // Validate tied operands.
+      if (OI.getTiedRegister() != -1) {
+        // If we have a tied operand that consists of multiple MCOperands, reject
+        // it.  We reject aliases and ignore instructions for now.
+        if (OI.MINumOperands != 1) {
+          // FIXME: Should reject these.  The ARM backend hits this with $lane
+          // in a bunch of instructions. It is unclear what the right answer is.
+          DEBUG({
+            errs() << "warning: '" << CGI.TheDef->getName() << "': "
+            << "ignoring instruction with multi-operand tied operand '"
+            << OI.Name << "'\n";
+          });
+          continue;
+        }
+      }
+    }
+    
     OwningPtr<MatchableInfo> II(new MatchableInfo(CGI));
 
     II->Initialize(*this, SingletonRegisters);
@@ -1048,46 +1145,56 @@
       }
 
       // Otherwise this is an operand reference.
-      StringRef OperandName;
-      if (Token[1] == '{')
-        OperandName = Token.substr(2, Token.size() - 3);
-      else
-        OperandName = Token.substr(1);
-
-      // Map this token to an operand. FIXME: Move elsewhere.
-      unsigned Idx;
-      if (!II->OperandList.hasOperandNamed(OperandName, Idx))
-        throw TGError(II->TheDef->getLoc(), "error: unable to find operand: '" +
-                      OperandName.str() + "'");
-
-      // FIXME: This is annoying, the named operand may be tied (e.g.,
-      // XCHG8rm). What we want is the untied operand, which we now have to
-      // grovel for. Only worry about this for single entry operands, we have to
-      // clean this up anyway.
-      const CGIOperandList::OperandInfo *OI = &II->OperandList[Idx];
-      int OITied = OI->getTiedRegister();
-      if (OITied != -1) {
-        // The tied operand index is an MIOperand index, find the operand that
-        // contains it.
-        for (unsigned i = 0, e = II->OperandList.size(); i != e; ++i) {
-          if (II->OperandList[i].MIOperandNo == unsigned(OITied)) {
-            OI = &II->OperandList[i];
-            break;
-          }
-        }
-
-        assert(OI && "Unable to find tied operand target!");
-      }
-
-      Op.Class = getOperandClass(Token, *OI);
-      Op.OperandInfo = OI;
+      BuildInstructionOperandReference(II, Op);
     }
+    
+    II->BuildResultOperands();
   }
 
   // Reorder classes so that classes preceed super classes.
   std::sort(Classes.begin(), Classes.end(), less_ptr<ClassInfo>());
 }
 
+void MatchableInfo::BuildResultOperands() {
+  /// OperandMap - This is a mapping from the MCInst operands (specified by the
+  /// II.OperandList operands) to the AsmOperands that they are filled in from.
+  SmallVector<int, 16> OperandMap(TheOperandList.size(), -1);
+  
+  // Order the (class) operands by the order to convert them into an MCInst.
+  for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
+    MatchableInfo::AsmOperand &Op = AsmOperands[i];
+    if (!Op.OperandInfo) continue;
+    
+    
+    // FIXME: eliminate the mapping+unmapping.
+    unsigned LogicalOpNum = Op.OperandInfo - &TheOperandList[0];
+    assert(LogicalOpNum < OperandMap.size() && "Invalid operand number");
+    OperandMap[LogicalOpNum] = i;
+  }
+  
+  for (unsigned i = 0, e = TheOperandList.size(); i != e; ++i) {
+    const CGIOperandList::OperandInfo &OpInfo = TheOperandList[i];
+    
+    // Find out what operand from the asmparser that this MCInst operand comes
+    // from.
+    int SrcOperand = OperandMap[i];
+    if (SrcOperand != -1) {
+      ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, &OpInfo));
+      continue;
+    }
+    
+    // Otherwise, this must be a tied operand.
+    int TiedOp = OpInfo.getTiedRegister();
+    if (TiedOp == -1)
+      throw TGError(TheDef->getLoc(), "Instruction '" +
+                    TheDef->getName() + "' has operand '" + OpInfo.Name +
+                    "' that doesn't appear in asm string!");
+
+    ResOperands.push_back(ResOperand::getTiedOp(TiedOp, &OpInfo));
+  }
+}
+
+
 static void EmitConvertToMCInst(CodeGenTarget &Target,
                                 std::vector<MatchableInfo*> &Infos,
                                 raw_ostream &OS) {
@@ -1100,7 +1207,6 @@
   std::set<std::string> GeneratedFns;
 
   // Start the unified conversion function.
-
   CvtOS << "static void ConvertToMCInst(ConversionKind Kind, MCInst &Inst, "
         << "unsigned Opcode,\n"
         << "                      const SmallVectorImpl<MCParsedAsmOperand*"
@@ -1117,42 +1223,25 @@
   // TargetOperandClass - This is the target's operand class, like X86Operand.
   std::string TargetOperandClass = Target.getName() + "Operand";
 
-  /// OperandMap - This is a mapping from the MCInst operands (specified by the
-  /// II.OperandList operands) to the AsmOperands that they filled in from.
-  SmallVector<int, 16> OperandMap;
-  
   for (std::vector<MatchableInfo*>::const_iterator it = Infos.begin(),
          ie = Infos.end(); it != ie; ++it) {
     MatchableInfo &II = **it;
 
-    OperandMap.clear();
-    OperandMap.resize(II.OperandList.size(), -1);
-    
-    // Order the (class) operands by the order to convert them into an MCInst.
-    for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) {
-      MatchableInfo::AsmOperand &Op = II.AsmOperands[i];
-      if (!Op.OperandInfo) continue;
-      
-      unsigned LogicalOpNum = Op.OperandInfo - &II.OperandList[0];
-      assert(LogicalOpNum < OperandMap.size() && "Invalid operand number");
-      OperandMap[LogicalOpNum] = i;
-    }
-
     // Build the conversion function signature.
     std::string Signature = "Convert";
     std::string CaseBody;
     raw_string_ostream CaseOS(CaseBody);
     
     // Compute the convert enum and the case body.
-    for (unsigned i = 0, e = II.OperandList.size(); i != e; ++i) {
-      const CGIOperandList::OperandInfo &OpInfo = II.OperandList[i];
+    for (unsigned i = 0, e = II.ResOperands.size(); i != e; ++i) {
+      const MatchableInfo::ResOperand &OpInfo = II.ResOperands[i];
 
-      // Find out what operand from the asmparser that this MCInst operand comes
-      // from.
-      int SrcOperand = OperandMap[i];
-      if (SrcOperand != -1) {
-        // Otherwise, this comes from something we parsed.
-        MatchableInfo::AsmOperand &Op = II.AsmOperands[SrcOperand];
+      // Generate code to populate each result operand.
+      switch (OpInfo.Kind) {
+      default: assert(0 && "Unknown result operand kind");
+      case MatchableInfo::ResOperand::RenderAsmOperand: {
+        // This comes from something we parsed.
+        MatchableInfo::AsmOperand &Op = II.AsmOperands[OpInfo.AsmOperandNum];
         
         // Registers are always converted the same, don't duplicate the
         // conversion function based on them.
@@ -1162,29 +1251,25 @@
         else
           Signature += Op.Class->ClassName;
         Signature += utostr(Op.OperandInfo->MINumOperands);
-        Signature += "_" + itostr(SrcOperand);
+        Signature += "_" + itostr(OpInfo.AsmOperandNum);
         
         CaseOS << "    ((" << TargetOperandClass << "*)Operands["
-               << SrcOperand << "+1])->" << Op.Class->RenderMethod
+               << (OpInfo.AsmOperandNum+1) << "])->" << Op.Class->RenderMethod
                << "(Inst, " << Op.OperandInfo->MINumOperands << ");\n";
-        continue;
+        break;
+      }
+          
+      case MatchableInfo::ResOperand::TiedOperand: {
+        // If this operand is tied to a previous one, just copy the MCInst
+        // operand from the earlier one.We can only tie single MCOperand values.
+      //assert(OpInfo.OpInfo->MINumOperands == 1 && "Not a singular MCOperand");
+        unsigned TiedOp = OpInfo.TiedOperandNum;
+        assert(i > TiedOp && "Tied operand preceeds its target!");
+        CaseOS << "    Inst.addOperand(Inst.getOperand(" << TiedOp << "));\n";
+        Signature += "__Tie" + utostr(TiedOp);
+        break;
+      }
       }
-      
-      // Otherwise, this must be a tied operand if not, it is something that is
-      // mentioned in the ins/outs list but not in the asm string.
-      int TiedOp = OpInfo.getTiedRegister();
-      if (TiedOp == -1)
-        throw TGError(II.TheDef->getLoc(), "Instruction '" +
-                      II.TheDef->getName() + "' has operand '" + OpInfo.Name +
-                      "' that doesn't appear in asm string!");
-
-      // If this operand is tied to a previous one, just copy the MCInst operand
-      // from the earlier one.
-      // Copy the tied operand.  We can only tie single MCOperand values.
-      assert(OpInfo.MINumOperands == 1 && "Not a singular MCOperand");
-      assert(i > unsigned(TiedOp) && "Tied operand preceeds its target!");
-      CaseOS << "    Inst.addOperand(Inst.getOperand(" << TiedOp << "));\n";
-      Signature += "__Tie" + itostr(TiedOp);
     }
     
     II.ConversionFnKind = Signature;





More information about the llvm-commits mailing list