From 04cadb3684b14e4aad19f9f29e6c14539866bd56 Mon Sep 17 00:00:00 2001
From: Chris Lattner <sabre@nondot.org>
Date: Mon, 6 Feb 2006 23:40:48 +0000
Subject: [PATCH] Add support for modifier strings in machine instr
 descriptions.  This allows us to avoid creating lots of "Operand" types with
 different printers, instead we can fold several together and use modifiers. 
 For example, we can now use:

${target:call} to say that the operand should be printed like a 'call' operand.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26024 91177308-0d34-0410-b5e6-96231b3b80d8
---
 utils/TableGen/AsmWriterEmitter.cpp | 44 +++++++++++++++++++++++++----
 1 file changed, 38 insertions(+), 6 deletions(-)

diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp
index 0c973995978..ad3ffa5810b 100644
--- a/utils/TableGen/AsmWriterEmitter.cpp
+++ b/utils/TableGen/AsmWriterEmitter.cpp
@@ -37,17 +37,23 @@ namespace {
     /// MiOpNo - For isMachineInstrOperand, this is the operand number of the
     /// machine instruction.
     unsigned MIOpNo;
+    
+    /// MiModifier - For isMachineInstrOperand, this is the modifier string for
+    /// an operand, specified with syntax like ${opname:modifier}.
+    std::string MiModifier;
 
     AsmWriterOperand(const std::string &LitStr)
       : OperandType(isLiteralTextOperand), Str(LitStr) {}
 
-    AsmWriterOperand(const std::string &Printer, unsigned OpNo) 
-      : OperandType(isMachineInstrOperand), Str(Printer), MIOpNo(OpNo) {}
+    AsmWriterOperand(const std::string &Printer, unsigned OpNo, 
+                     const std::string &Modifier) 
+      : OperandType(isMachineInstrOperand), Str(Printer), MIOpNo(OpNo),
+      MiModifier(Modifier) {}
 
     bool operator!=(const AsmWriterOperand &Other) const {
       if (OperandType != Other.OperandType || Str != Other.Str) return true;
       if (OperandType == isMachineInstrOperand)
-        return MIOpNo != Other.MIOpNo;
+        return MIOpNo != Other.MIOpNo || MiModifier != Other.MiModifier;
       return false;
     }
     bool operator==(const AsmWriterOperand &Other) const {
@@ -84,8 +90,12 @@ namespace {
 void AsmWriterOperand::EmitCode(std::ostream &OS) const {
   if (OperandType == isLiteralTextOperand)
     OS << "O << \"" << Str << "\"; ";
-  else
-    OS << Str << "(MI, " << MIOpNo << "); ";
+  else {
+    OS << Str << "(MI, " << MIOpNo;
+    if (!MiModifier.empty())
+      OS << ", \"" << MiModifier << '"';
+    OS << "); ";
+  }
 }
 
 
@@ -155,6 +165,10 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) {
       std::string VarName(AsmString.begin()+DollarPos+1,
                           AsmString.begin()+VarEnd);
 
+      // Modifier - Support ${foo:modifier} syntax, where "modifier" is passed
+      // into printOperand.
+      std::string Modifier;
+      
       // In order to avoid starting the next string at the terminating curly
       // brace, advance the end position past it if we found an opening curly
       // brace.
@@ -162,6 +176,23 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) {
         if (VarEnd >= AsmString.size())
           throw "Reached end of string before terminating curly brace in '"
                 + CGI.TheDef->getName() + "'";
+        
+        // Look for a modifier string.
+        if (AsmString[VarEnd] == ':') {
+          ++VarEnd;
+          if (VarEnd >= AsmString.size())
+            throw "Reached end of string before terminating curly brace in '"
+              + CGI.TheDef->getName() + "'";
+          
+          unsigned ModifierStart = VarEnd;
+          while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
+            ++VarEnd;
+          Modifier = std::string(AsmString.begin()+ModifierStart,
+                                 AsmString.begin()+VarEnd);
+          if (Modifier.empty())
+            throw "Bad operand modifier name in '"+ CGI.TheDef->getName() + "'";
+        }
+        
         if (AsmString[VarEnd] != '}')
           throw "Variable name beginning with '{' did not end with '}' in '"
                 + CGI.TheDef->getName() + "'";
@@ -185,7 +216,8 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) {
       }
 
       if (CurVariant == Variant || CurVariant == ~0U) 
-        Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName, MIOp));
+        Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName, MIOp,
+                                            Modifier));
       LastEmitted = VarEnd;
     }
   }