Improve the AsmMatcher's ability to handle suboperands.
authorBob Wilson <bob.wilson@apple.com>
Wed, 26 Jan 2011 19:44:55 +0000 (19:44 +0000)
committerBob Wilson <bob.wilson@apple.com>
Wed, 26 Jan 2011 19:44:55 +0000 (19:44 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@124314 91177308-0d34-0410-b5e6-96231b3b80d8

utils/TableGen/AsmMatcherEmitter.cpp
utils/TableGen/CodeGenInstruction.cpp
utils/TableGen/CodeGenInstruction.h

index a2c5de3e1e6dc8c27178159cf6d770ab09ee462f..aa8cc4e4c7d5bb3744a49933b095ca77dd4963f1 100644 (file)
@@ -253,8 +253,11 @@ struct MatchableInfo {
 
     /// 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 @@ struct MatchableInfo {
       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 @@ struct MatchableInfo {
   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 @@ private:
   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 @@ private:
   /// 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::getTokenClass(StringRef Token) {
 }
 
 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 @@ void AsmMatcherInfo::BuildInfo() {
     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 @@ void AsmMatcherInfo::BuildInfo() {
         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::BuildInfo() {
 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 @@ BuildInstructionOperandReference(MatchableInfo *II,
     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 @@ BuildInstructionOperandReference(MatchableInfo *II,
   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 @@ void AsmMatcherInfo::BuildAliasOperandReference(MatchableInfo *II,
         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 @@ void MatchableInfo::BuildInstructionResultOperands() {
     // 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 @@ void MatchableInfo::BuildAliasResultOperands() {
   // 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 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
           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";
index d69a44bc29302ff5f8578172c8cc454dabd6121e..f37d3eabcd414ab6ae249cdf789b5faf625031f6 100644 (file)
@@ -390,6 +390,71 @@ FlattenAsmStringVariants(StringRef Cur, unsigned Variant) {
 /// 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 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) {
   // 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;
-      }
-    }
-
-    // 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);
+      throw TGError(R->getLoc(), "not enough arguments for instruction!");
+
+    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!");
 }
index fb0e50c08b76955042563902d242d18f987d1945..58913b9da26b1ea2d5ea196245e11a76c2431886 100644 (file)
@@ -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 @@ namespace llvm {
     /// 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);
   };    
 }