[llvm-commits] [llvm] r124314 - in /llvm/trunk/utils/TableGen: AsmMatcherEmitter.cpp CodeGenInstruction.cpp CodeGenInstruction.h

Bob Wilson bob.wilson at apple.com
Wed Jan 26 11:44:55 PST 2011


Author: bwilson
Date: Wed Jan 26 13:44:55 2011
New Revision: 124314

URL: http://llvm.org/viewvc/llvm-project?rev=124314&view=rev
Log:
Improve the AsmMatcher's ability to handle suboperands.

When an operand class is defined with MIOperandInfo set to a list of
suboperands, the AsmMatcher has so far required that operand to also define
a custom ParserMatchClass, and InstAlias patterns have not been able to
set the individual suboperands separately.  This patch removes both of those
restrictions.  If a "compound" operand does not override the default
ParserMatchClass, then the AsmMatcher will now parse its suboperands
separately.  If an InstAlias operand has the same class as the corresponding
compound operand, then it will be handled as before; but if that check fails,
TableGen will now try to match up a sequence of InstAlias operands with the
corresponding suboperands.

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

Modified: llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp?rev=124314&r1=124313&r2=124314&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp Wed Jan 26 13:44:55 2011
@@ -253,8 +253,11 @@
 
     /// The operand name this is, if anything.
     StringRef SrcOpName;
+
+    /// The suboperand index within SrcOpName, or -1 for the entire operand.
+    int SubOpIdx;
     
-    explicit AsmOperand(StringRef T) : Token(T), Class(0) {}
+    explicit AsmOperand(StringRef T) : Token(T), Class(0), SubOpIdx(-1) {}
   };
   
   /// ResOperand - This represents a single operand in the result instruction
@@ -296,46 +299,41 @@
       Record *Register;
     };
     
-    /// OpInfo - This is the information about the instruction operand that is
-    /// being populated.
-    const CGIOperandList::OperandInfo *OpInfo;
+    /// MINumOperands - The number of MCInst operands populated by this
+    /// operand.
+    unsigned MINumOperands;
     
-    static ResOperand getRenderedOp(unsigned AsmOpNum,
-                                    const CGIOperandList::OperandInfo *Op) {
+    static ResOperand getRenderedOp(unsigned AsmOpNum, unsigned NumOperands) {
       ResOperand X;
       X.Kind = RenderAsmOperand;
       X.AsmOperandNum = AsmOpNum;
-      X.OpInfo = Op;
+      X.MINumOperands = NumOperands;
       return X;
     }
     
-    static ResOperand getTiedOp(unsigned TiedOperandNum,
-                                const CGIOperandList::OperandInfo *Op) {
+    static ResOperand getTiedOp(unsigned TiedOperandNum) {
       ResOperand X;
       X.Kind = TiedOperand;
       X.TiedOperandNum = TiedOperandNum;
-      X.OpInfo = Op;
+      X.MINumOperands = 1;
       return X;
     }
     
-    static ResOperand getImmOp(int64_t Val,
-                               const CGIOperandList::OperandInfo *Op) {
+    static ResOperand getImmOp(int64_t Val) {
       ResOperand X;
       X.Kind = ImmOperand;
       X.ImmVal = Val;
-      X.OpInfo = Op;
+      X.MINumOperands = 1;
       return X;
     }
     
-    static ResOperand getRegOp(Record *Reg,
-                               const CGIOperandList::OperandInfo *Op) {
+    static ResOperand getRegOp(Record *Reg) {
       ResOperand X;
       X.Kind = RegOperand;
       X.Register = Reg;
-      X.OpInfo = Op;
+      X.MINumOperands = 1;
       return X;
     }
-    
   };
 
   /// TheDef - This is the definition of the instruction or InstAlias that this
@@ -397,6 +395,18 @@
   Record *getSingletonRegisterForAsmOperand(unsigned i,
                                             const AsmMatcherInfo &Info) const;  
 
+  /// FindAsmOperand - Find the AsmOperand with the specified name and
+  /// suboperand index.
+  int FindAsmOperand(StringRef N, int SubOpIdx) const {
+    for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i)
+      if (N == AsmOperands[i].SrcOpName &&
+          SubOpIdx == AsmOperands[i].SubOpIdx)
+        return i;
+    return -1;
+  }
+  
+  /// FindAsmOperandNamed - Find the first AsmOperand with the specified name.
+  /// This does not check the suboperand index.
   int FindAsmOperandNamed(StringRef N) const {
     for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i)
       if (N == AsmOperands[i].SrcOpName)
@@ -531,7 +541,8 @@
   ClassInfo *getTokenClass(StringRef Token);
 
   /// getOperandClass - Lookup or create the class for the given operand.
-  ClassInfo *getOperandClass(const CGIOperandList::OperandInfo &OI);
+  ClassInfo *getOperandClass(const CGIOperandList::OperandInfo &OI,
+                             int SubOpIdx = -1);
 
   /// BuildRegisterClasses - Build the ClassInfo* instances for register
   /// classes.
@@ -541,11 +552,9 @@
   /// operand classes.
   void BuildOperandClasses();
 
-  void BuildInstructionOperandReference(MatchableInfo *II,
-                                        StringRef OpName,
-                                        MatchableInfo::AsmOperand &Op);
-  void BuildAliasOperandReference(MatchableInfo *II,
-                                  StringRef OpName,
+  void BuildInstructionOperandReference(MatchableInfo *II, StringRef OpName,
+                                        unsigned AsmOpIdx);
+  void BuildAliasOperandReference(MatchableInfo *II, StringRef OpName,
                                   MatchableInfo::AsmOperand &Op);
                                   
 public:
@@ -806,19 +815,24 @@
 }
 
 ClassInfo *
-AsmMatcherInfo::getOperandClass(const CGIOperandList::OperandInfo &OI) {
-  if (OI.Rec->isSubClassOf("RegisterClass")) {
-    if (ClassInfo *CI = RegisterClassClasses[OI.Rec])
+AsmMatcherInfo::getOperandClass(const CGIOperandList::OperandInfo &OI,
+                                int SubOpIdx) {
+  Record *Rec = OI.Rec;
+  if (SubOpIdx != -1)
+    Rec = dynamic_cast<DefInit*>(OI.MIOperandInfo->getArg(SubOpIdx))->getDef();
+
+  if (Rec->isSubClassOf("RegisterClass")) {
+    if (ClassInfo *CI = RegisterClassClasses[Rec])
       return CI;
-    throw TGError(OI.Rec->getLoc(), "register class has no class info!");
+    throw TGError(Rec->getLoc(), "register class has no class info!");
   }
 
-  assert(OI.Rec->isSubClassOf("Operand") && "Unexpected operand!");
-  Record *MatchClass = OI.Rec->getValueAsDef("ParserMatchClass");
+  assert(Rec->isSubClassOf("Operand") && "Unexpected operand!");
+  Record *MatchClass = Rec->getValueAsDef("ParserMatchClass");
   if (ClassInfo *CI = AsmOperandClasses[MatchClass])
     return CI;
 
-  throw TGError(OI.Rec->getLoc(), "operand has no match class!");
+  throw TGError(Rec->getLoc(), "operand has no match class!");
 }
 
 void AsmMatcherInfo::
@@ -1120,7 +1134,9 @@
     MatchableInfo *II = *it;
 
     // Parse the tokens after the mnemonic.
-    for (unsigned i = 0, e = II->AsmOperands.size(); i != e; ++i) {
+    // Note: BuildInstructionOperandReference may insert new AsmOperands, so
+    // don't precompute the loop bound.
+    for (unsigned i = 0; i != II->AsmOperands.size(); ++i) {
       MatchableInfo::AsmOperand &Op = II->AsmOperands[i];
       StringRef Token = Op.Token;
 
@@ -1151,7 +1167,7 @@
         OperandName = Token.substr(1);
       
       if (II->DefRec.is<const CodeGenInstruction*>())
-        BuildInstructionOperandReference(II, OperandName, Op);
+        BuildInstructionOperandReference(II, OperandName, i);
       else
         BuildAliasOperandReference(II, OperandName, Op);
     }
@@ -1171,9 +1187,10 @@
 void AsmMatcherInfo::
 BuildInstructionOperandReference(MatchableInfo *II,
                                  StringRef OperandName,
-                                 MatchableInfo::AsmOperand &Op) {
+                                 unsigned AsmOpIdx) {
   const CodeGenInstruction &CGI = *II->DefRec.get<const CodeGenInstruction*>();
   const CGIOperandList &Operands = CGI.Operands;
+  MatchableInfo::AsmOperand *Op = &II->AsmOperands[AsmOpIdx];
   
   // Map this token to an operand.
   unsigned Idx;
@@ -1181,8 +1198,29 @@
     throw TGError(II->TheDef->getLoc(), "error: unable to find operand: '" +
                   OperandName.str() + "'");
 
+  // If the instruction operand has multiple suboperands, but the parser
+  // match class for the asm operand is still the default "ImmAsmOperand",
+  // then handle each suboperand separately.
+  if (Op->SubOpIdx == -1 && Operands[Idx].MINumOperands > 1) {
+    Record *Rec = Operands[Idx].Rec;
+    assert(Rec->isSubClassOf("Operand") && "Unexpected operand!");
+    Record *MatchClass = Rec->getValueAsDef("ParserMatchClass");
+    if (MatchClass && MatchClass->getValueAsString("Name") == "Imm") {
+      // Insert remaining suboperands after AsmOpIdx in II->AsmOperands.
+      StringRef Token = Op->Token; // save this in case Op gets moved
+      for (unsigned SI = 1, SE = Operands[Idx].MINumOperands; SI != SE; ++SI) {
+        MatchableInfo::AsmOperand NewAsmOp(Token);
+        NewAsmOp.SubOpIdx = SI;
+        II->AsmOperands.insert(II->AsmOperands.begin()+AsmOpIdx+SI, NewAsmOp);
+      }
+      // Replace Op with first suboperand.
+      Op = &II->AsmOperands[AsmOpIdx]; // update the pointer in case it moved
+      Op->SubOpIdx = 0;
+    }
+  }
+
   // Set up the operand class.
-  Op.Class = getOperandClass(Operands[Idx]);
+  Op->Class = getOperandClass(Operands[Idx], Op->SubOpIdx);
 
   // If the named operand is tied, canonicalize it to the untied operand.
   // For example, something like:
@@ -1196,15 +1234,12 @@
   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)) {
-        OperandName = Operands[i].Name;
-        break;
-      }
-    }
+    std::pair<unsigned, unsigned> Idx = Operands.getSubOperandNumber(OITied);
+    OperandName = Operands[Idx.first].Name;
+    Op->SubOpIdx = Idx.second;
   }
   
-  Op.SrcOpName = OperandName;
+  Op->SrcOpName = OperandName;
 }
 
 /// BuildAliasOperandReference - When parsing an operand reference out of the
@@ -1221,8 +1256,10 @@
         CGA.ResultOperands[i].getName() == OperandName) {
       // It's safe to go with the first one we find, because CodeGenInstAlias
       // validates that all operands with the same name have the same record.
-      unsigned ResultIdx = CGA.ResultInstOperandIndex[i];
-      Op.Class = getOperandClass(CGA.ResultInst->Operands[ResultIdx]);
+      unsigned ResultIdx = CGA.ResultInstOperandIndex[i].first;
+      Op.SubOpIdx = CGA.ResultInstOperandIndex[i].second;
+      Op.Class = getOperandClass(CGA.ResultInst->Operands[ResultIdx],
+                                 Op.SubOpIdx);
       Op.SrcOpName = OperandName;
       return;
     }
@@ -1242,22 +1279,31 @@
     // If this is a tied operand, just copy from the previously handled operand.
     int TiedOp = OpInfo.getTiedRegister();
     if (TiedOp != -1) {
-      ResOperands.push_back(ResOperand::getTiedOp(TiedOp, &OpInfo));
+      ResOperands.push_back(ResOperand::getTiedOp(TiedOp));
       continue;
     }
     
-    // Find out what operand from the asmparser that this MCInst operand comes
-    // from.
+    // Find out what operand from the asmparser this MCInst operand comes from.
     int SrcOperand = FindAsmOperandNamed(OpInfo.Name);
+    if (OpInfo.Name.empty() || SrcOperand == -1)
+      throw TGError(TheDef->getLoc(), "Instruction '" +
+                    TheDef->getName() + "' has operand '" + OpInfo.Name +
+                    "' that doesn't appear in asm string!");
 
-    if (!OpInfo.Name.empty() && SrcOperand != -1) {
-      ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, &OpInfo));
+    // Check if the one AsmOperand populates the entire operand.
+    unsigned NumOperands = OpInfo.MINumOperands;
+    if (AsmOperands[SrcOperand].SubOpIdx == -1) {
+      ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, NumOperands));
       continue;
     }
-    
-    throw TGError(TheDef->getLoc(), "Instruction '" +
-                  TheDef->getName() + "' has operand '" + OpInfo.Name +
-                  "' that doesn't appear in asm string!");
+
+    // Add a separate ResOperand for each suboperand.
+    for (unsigned AI = 0; AI < NumOperands; ++AI) {
+      assert(AsmOperands[SrcOperand+AI].SubOpIdx == (int)AI &&
+             AsmOperands[SrcOperand+AI].SrcOpName == OpInfo.Name &&
+             "unexpected AsmOperands for suboperands");
+      ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand + AI, 1));
+    }
   }
 }
 
@@ -1268,42 +1314,50 @@
   // Loop over all operands of the result instruction, determining how to
   // populate them.
   unsigned AliasOpNo = 0;
+  unsigned LastOpNo = CGA.ResultInstOperandIndex.size();
   for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) {
-    const CGIOperandList::OperandInfo &OpInfo = ResultInst->Operands[i];
+    const CGIOperandList::OperandInfo *OpInfo = &ResultInst->Operands[i];
     
     // If this is a tied operand, just copy from the previously handled operand.
-    int TiedOp = OpInfo.getTiedRegister();
+    int TiedOp = OpInfo->getTiedRegister();
     if (TiedOp != -1) {
-      ResOperands.push_back(ResOperand::getTiedOp(TiedOp, &OpInfo));
-      continue;
-    }
-    
-    // Find out what operand from the asmparser that this MCInst operand comes
-    // from.
-    switch (CGA.ResultOperands[AliasOpNo].Kind) {
-    case CodeGenInstAlias::ResultOperand::K_Record: {
-      StringRef Name = CGA.ResultOperands[AliasOpNo++].getName();
-      int SrcOperand = FindAsmOperandNamed(Name);
-      if (SrcOperand != -1) {
-        ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, &OpInfo));
-        continue;
-      }
-      
-      throw TGError(TheDef->getLoc(), "Instruction '" +
-                    TheDef->getName() + "' has operand '" + OpInfo.Name +
-                    "' that doesn't appear in asm string!");
-    }
-    case CodeGenInstAlias::ResultOperand::K_Imm: {
-      int64_t ImmVal = CGA.ResultOperands[AliasOpNo++].getImm();
-      ResOperands.push_back(ResOperand::getImmOp(ImmVal, &OpInfo));
+      ResOperands.push_back(ResOperand::getTiedOp(TiedOp));
       continue;
     }
 
-    case CodeGenInstAlias::ResultOperand::K_Reg: {
-      Record *Reg = CGA.ResultOperands[AliasOpNo++].getRegister();
-      ResOperands.push_back(ResOperand::getRegOp(Reg, &OpInfo));
-      continue;
-    }
+    // Handle all the suboperands for this operand.
+    const std::string &OpName = OpInfo->Name;
+    for ( ; AliasOpNo <  LastOpNo &&
+            CGA.ResultInstOperandIndex[AliasOpNo].first == i; ++AliasOpNo) {
+      int SubIdx = CGA.ResultInstOperandIndex[AliasOpNo].second;
+
+      // Find out what operand from the asmparser that this MCInst operand
+      // comes from.
+      switch (CGA.ResultOperands[AliasOpNo].Kind) {
+      default: assert(0 && "unexpected InstAlias operand kind");
+      case CodeGenInstAlias::ResultOperand::K_Record: {
+        StringRef Name = CGA.ResultOperands[AliasOpNo].getName();
+        int SrcOperand = FindAsmOperand(Name, SubIdx);
+        if (SrcOperand == -1)
+          throw TGError(TheDef->getLoc(), "Instruction '" +
+                        TheDef->getName() + "' has operand '" + OpName +
+                        "' that doesn't appear in asm string!");
+        unsigned NumOperands = (SubIdx == -1 ? OpInfo->MINumOperands : 1);
+        ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand,
+                                                        NumOperands));
+        break;
+      }
+      case CodeGenInstAlias::ResultOperand::K_Imm: {
+        int64_t ImmVal = CGA.ResultOperands[AliasOpNo].getImm();
+        ResOperands.push_back(ResOperand::getImmOp(ImmVal));
+        break;
+      }
+      case CodeGenInstAlias::ResultOperand::K_Reg: {
+        Record *Reg = CGA.ResultOperands[AliasOpNo].getRegister();
+        ResOperands.push_back(ResOperand::getRegOp(Reg));
+        break;
+      }
+      }
     }
   }
 }
@@ -1362,19 +1416,19 @@
           Signature += "Reg";
         else
           Signature += Op.Class->ClassName;
-        Signature += utostr(OpInfo.OpInfo->MINumOperands);
+        Signature += utostr(OpInfo.MINumOperands);
         Signature += "_" + itostr(OpInfo.AsmOperandNum);
         
         CaseOS << "    ((" << TargetOperandClass << "*)Operands["
                << (OpInfo.AsmOperandNum+1) << "])->" << Op.Class->RenderMethod
-               << "(Inst, " << OpInfo.OpInfo->MINumOperands << ");\n";
+               << "(Inst, " << OpInfo.MINumOperands << ");\n";
         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");
+        //assert(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";

Modified: llvm/trunk/utils/TableGen/CodeGenInstruction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenInstruction.cpp?rev=124314&r1=124313&r2=124314&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/CodeGenInstruction.cpp (original)
+++ llvm/trunk/utils/TableGen/CodeGenInstruction.cpp Wed Jan 26 13:44:55 2011
@@ -390,6 +390,71 @@
 /// CodeGenInstAlias Implementation
 //===----------------------------------------------------------------------===//
 
+/// tryAliasOpMatch - This is a helper function for the CodeGenInstAlias
+/// constructor.  It checks if an argument in an InstAlias pattern matches
+/// the corresponding operand of the instruction.  It returns true on a
+/// successful match, with ResOp set to the result operand to be used.
+bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
+                                       Record *InstOpRec, bool hasSubOps,
+                                       SMLoc Loc, CodeGenTarget &T,
+                                       ResultOperand &ResOp) {
+  Init *Arg = Result->getArg(AliasOpNo);
+  DefInit *ADI = dynamic_cast<DefInit*>(Arg);
+
+  if (ADI && ADI->getDef() == InstOpRec) {
+    // If the operand is a record, it must have a name, and the record type
+    // must match up with the instruction's argument type.
+    if (Result->getArgName(AliasOpNo).empty())
+      throw TGError(Loc, "result argument #" + utostr(AliasOpNo) +
+                    " must have a name!");
+    ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef());
+    return true;
+  }
+
+  // Handle explicit registers.
+  if (ADI && ADI->getDef()->isSubClassOf("Register")) {
+    if (!InstOpRec->isSubClassOf("RegisterClass"))
+      return false;
+
+    if (!T.getRegisterClass(InstOpRec).containsRegister(ADI->getDef()))
+      throw TGError(Loc, "fixed register " +ADI->getDef()->getName()
+                    + " is not a member of the " + InstOpRec->getName() +
+                    " register class!");
+
+    if (!Result->getArgName(AliasOpNo).empty())
+      throw TGError(Loc, "result fixed register argument must "
+                    "not have a name!");
+
+    ResOp = ResultOperand(ADI->getDef());
+    return true;
+  }
+
+  // Handle "zero_reg" for optional def operands.
+  if (ADI && ADI->getDef()->getName() == "zero_reg") {
+
+    // Check if this is an optional def.
+    if (!InstOpRec->isSubClassOf("OptionalDefOperand"))
+      throw TGError(Loc, "reg0 used for result that is not an "
+                    "OptionalDefOperand!");
+
+    ResOp = ResultOperand(static_cast<Record*>(0));
+    return true;
+  }
+
+  if (IntInit *II = dynamic_cast<IntInit*>(Arg)) {
+    if (hasSubOps || !InstOpRec->isSubClassOf("Operand"))
+      return false;
+    // Integer arguments can't have names.
+    if (!Result->getArgName(AliasOpNo).empty())
+      throw TGError(Loc, "result argument #" + utostr(AliasOpNo) +
+                    " must not have a name!");
+    ResOp = ResultOperand(II->getValue());
+    return true;
+  }
+
+  return false;
+}
+
 CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) {
   AsmString = R->getValueAsString("AsmString");
   Result = R->getValueAsDag("ResultInst");
@@ -422,103 +487,51 @@
   // Decode and validate the arguments of the result.
   unsigned AliasOpNo = 0;
   for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) {
+
     // Tied registers don't have an entry in the result dag.
     if (ResultInst->Operands[i].getTiedRegister() != -1)
       continue;
 
     if (AliasOpNo >= Result->getNumArgs())
-      throw TGError(R->getLoc(), "result has " + utostr(Result->getNumArgs()) +
-                    " arguments, but " + ResultInst->TheDef->getName() +
-                    " instruction expects " +
-                    utostr(ResultInst->Operands.size()) + " operands!");
-
-
-    Init *Arg = Result->getArg(AliasOpNo);
-    Record *ResultOpRec = ResultInst->Operands[i].Rec;
-
-    // Handle explicit registers.
-    if (DefInit *ADI = dynamic_cast<DefInit*>(Arg)) {
-      if (ADI->getDef()->isSubClassOf("Register")) {
-        if (!Result->getArgName(AliasOpNo).empty())
-          throw TGError(R->getLoc(), "result fixed register argument must "
-                        "not have a name!");
-
-        if (!ResultOpRec->isSubClassOf("RegisterClass"))
-          throw TGError(R->getLoc(), "result fixed register argument is not "
-                        "passed to a RegisterClass operand!");
-
-        if (!T.getRegisterClass(ResultOpRec).containsRegister(ADI->getDef()))
-          throw TGError(R->getLoc(), "fixed register " +ADI->getDef()->getName()
-                        + " is not a member of the " + ResultOpRec->getName() +
-                        " register class!");
-
-        // Now that it is validated, add it.
-        ResultOperands.push_back(ResultOperand(ADI->getDef()));
-        ResultInstOperandIndex.push_back(i);
-        ++AliasOpNo;
-        continue;
-      }
-      if (ADI->getDef()->getName() == "zero_reg") {
-        if (!Result->getArgName(AliasOpNo).empty())
-          throw TGError(R->getLoc(), "result fixed register argument must "
-                        "not have a name!");
-
-        // Check if this is an optional def.
-        if (!ResultOpRec->isSubClassOf("OptionalDefOperand"))
-          throw TGError(R->getLoc(), "reg0 used for result that is not an "
-                        "OptionalDefOperand!");
-
-        // Now that it is validated, add it.
-        ResultOperands.push_back(ResultOperand(static_cast<Record*>(0)));
-        ResultInstOperandIndex.push_back(i);
-        ++AliasOpNo;
-        continue;
-      }
-    }
+      throw TGError(R->getLoc(), "not enough arguments for instruction!");
 
-    // If the operand is a record, it must have a name, and the record type must
-    // match up with the instruction's argument type.
-    if (DefInit *ADI = dynamic_cast<DefInit*>(Arg)) {
-      if (Result->getArgName(AliasOpNo).empty())
-        throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
-                      " must have a name!");
-
-      if (ADI->getDef() != ResultOpRec)
-        throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
-                      " declared with class " + ADI->getDef()->getName() +
-                      ", instruction operand is class " +
-                      ResultOpRec->getName());
-
-      // Now that it is validated, add it.
-      ResultOperands.push_back(ResultOperand(Result->getArgName(AliasOpNo),
-                                             ADI->getDef()));
-      ResultInstOperandIndex.push_back(i);
+    Record *InstOpRec = ResultInst->Operands[i].Rec;
+    unsigned NumSubOps = ResultInst->Operands[i].MINumOperands;
+    ResultOperand ResOp(static_cast<int64_t>(0));
+    if (tryAliasOpMatch(Result, AliasOpNo, InstOpRec, (NumSubOps > 1),
+                        R->getLoc(), T, ResOp)) {
+      ResultOperands.push_back(ResOp);
+      ResultInstOperandIndex.push_back(std::make_pair(i, -1));
       ++AliasOpNo;
       continue;
     }
 
-    if (IntInit *II = dynamic_cast<IntInit*>(Arg)) {
-      // Integer arguments can't have names.
-      if (!Result->getArgName(AliasOpNo).empty())
-        throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
-                      " must not have a name!");
-      if (ResultInst->Operands[i].MINumOperands != 1 ||
-          !ResultOpRec->isSubClassOf("Operand"))
-        throw TGError(R->getLoc(), "invalid argument class " +
-                      ResultOpRec->getName() +
-                      " for integer result operand!");
-      ResultOperands.push_back(ResultOperand(II->getValue()));
-      ResultInstOperandIndex.push_back(i);
-      ++AliasOpNo;
+    // If the argument did not match the instruction operand, and the operand
+    // is composed of multiple suboperands, try matching the suboperands.
+    if (NumSubOps > 1) {
+      DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo;
+      for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) {
+        if (AliasOpNo >= Result->getNumArgs())
+          throw TGError(R->getLoc(), "not enough arguments for instruction!");
+        Record *SubRec = dynamic_cast<DefInit*>(MIOI->getArg(SubOp))->getDef();
+        if (tryAliasOpMatch(Result, AliasOpNo, SubRec, false,
+                            R->getLoc(), T, ResOp)) {
+          ResultOperands.push_back(ResOp);
+          ResultInstOperandIndex.push_back(std::make_pair(i, SubOp));
+          ++AliasOpNo;
+        } else {
+          throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
+                        " does not match instruction operand class " +
+                        (SubOp == 0 ? InstOpRec->getName() :SubRec->getName()));
+        }
+      }
       continue;
     }
-
-    throw TGError(R->getLoc(), "result of inst alias has unknown operand type");
+    throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
+                  " does not match instruction operand class " +
+                  InstOpRec->getName());
   }
 
   if (AliasOpNo != Result->getNumArgs())
-    throw TGError(R->getLoc(), "result has " + utostr(Result->getNumArgs()) +
-                  " arguments, but " + ResultInst->TheDef->getName() +
-                  " instruction expects " + utostr(ResultInst->Operands.size())+
-                  " operands!");
+    throw TGError(R->getLoc(), "too many operands for instruction!");
 }

Modified: llvm/trunk/utils/TableGen/CodeGenInstruction.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenInstruction.h?rev=124314&r1=124313&r2=124314&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/CodeGenInstruction.h (original)
+++ llvm/trunk/utils/TableGen/CodeGenInstruction.h Wed Jan 26 13:44:55 2011
@@ -16,6 +16,7 @@
 
 #include "llvm/CodeGen/ValueTypes.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/SourceMgr.h"
 #include <string>
 #include <vector>
 #include <utility>
@@ -297,11 +298,18 @@
     /// ResultOperands - The decoded operands for the result instruction.
     std::vector<ResultOperand> ResultOperands;
 
-    /// ResultInstOperandIndex - For each operand, this vector holds the
-    /// corresponding index of an operand in the result instruction.
-    std::vector<unsigned> ResultInstOperandIndex;
+    /// ResultInstOperandIndex - For each operand, this vector holds a pair of
+    /// indices to identify the corresponding operand in the result
+    /// instruction.  The first index specifies the operand and the second
+    /// index specifies the suboperand.  If there are no suboperands or if all
+    /// of them are matched by the operand, the second value should be -1.
+    std::vector<std::pair<unsigned, int> > ResultInstOperandIndex;
     
     CodeGenInstAlias(Record *R, CodeGenTarget &T);
+
+    bool tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
+                         Record *InstOpRec, bool hasSubOps, SMLoc Loc,
+                         CodeGenTarget &T, ResultOperand &ResOp);
   };    
 }
 





More information about the llvm-commits mailing list