Allow targets to optionally specify custom binary encoder functions for
authorJim Grosbach <grosbach@apple.com>
Tue, 12 Oct 2010 22:21:57 +0000 (22:21 +0000)
committerJim Grosbach <grosbach@apple.com>
Tue, 12 Oct 2010 22:21:57 +0000 (22:21 +0000)
operand values. This is useful for operands which require additional trickery
to encode into the instruction. For example, the ARM shifted immediate and
shifted register operands.

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

utils/TableGen/CodeEmitterGen.cpp
utils/TableGen/CodeGenInstruction.cpp
utils/TableGen/CodeGenInstruction.h

index 64ea16e362d9b387593708bc4383e2bb52fd166b..b7b62d502b08138f838a8a9f1ac5fcb66316122d 100644 (file)
@@ -154,7 +154,6 @@ void CodeEmitterGen::run(raw_ostream &o) {
             }
 
             if (!gotOp) {
-
               // If the operand matches by name, reference according to that
               // operand number. Non-matching operands are assumed to be in
               // order.
@@ -171,10 +170,26 @@ void CodeEmitterGen::run(raw_ostream &o) {
                   ++NumberedOp;
                 OpIdx = NumberedOp++;
               }
-
-              Case += "      // op: " + VarName + "\n"
-                   +  "      op = getMachineOpValue(MI, MI.getOperand("
-                   +  utostr(OpIdx) + "));\n";
+              std::pair<unsigned, unsigned> SO = CGI.getSubOperandNumber(OpIdx);
+              std::string &EncoderMethodName =
+                CGI.OperandList[SO.first].EncoderMethodName;
+
+              // If the source operand has a custom encoder, use it. This will
+              // get the encoding for all of the suboperands.
+              if (!EncoderMethodName.empty()) {
+                // A custom encoder has all of the information for the
+                // sub-operands, if there are more than one, so only
+                // query the encoder once per source operand.
+                if (SO.second == 0) {
+                  Case += "      // op: " + VarName + "\n"
+                       + "      op = " + EncoderMethodName + "(MI, "
+                       + utostr(OpIdx) + ");\n";
+                }
+              } else {
+                Case += "      // op: " + VarName + "\n"
+                     +  "      op = getMachineOpValue(MI, MI.getOperand("
+                     +  utostr(OpIdx) + "));\n";
+              }
               gotOp = true;
             }
 
index 722ae53ed507485797d70238d3dd4870382a86cd..6e71502cbc21ac6748fb201064ab5f9c572ffd89 100644 (file)
@@ -166,10 +166,14 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
 
     Record *Rec = Arg->getDef();
     std::string PrintMethod = "printOperand";
+    std::string EncoderMethod;
     unsigned NumOps = 1;
     DagInit *MIOpInfo = 0;
     if (Rec->isSubClassOf("Operand")) {
       PrintMethod = Rec->getValueAsString("PrintMethod");
+      // If there is an explicit encoder method, use it.
+      if (Rec->getValue("EncoderMethod"))
+        EncoderMethod = Rec->getValueAsString("EncoderMethod");
       MIOpInfo = Rec->getValueAsDag("MIOperandInfo");
 
       // Verify that MIOpInfo has an 'ops' root value.
@@ -204,7 +208,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
       throw "In instruction '" + R->getName() + "', operand #" + utostr(i) +
         " has the same name as a previous operand!";
 
-    OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod,
+    OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod, EncoderMethod,
                                       MIOperandNo, NumOps, MIOpInfo));
     MIOperandNo += NumOps;
   }
index 049e694006a7f783d542bbdfb653c8ad7695fcbc..e895361d69c3c522e9da51d13bab282d63a57a1d 100644 (file)
@@ -78,6 +78,10 @@ namespace llvm {
       /// the asmprinter.
       std::string PrinterMethodName;
 
+      /// EncoderMethodName - The method used to get the machine operand value
+      /// for binary encoding. "getMachineOpValue" by default.
+      std::string EncoderMethodName;
+
       /// MIOperandNo - Currently (this is meant to be phased out), some logical
       /// operands correspond to multiple MachineInstr operands.  In the X86
       /// target for example, one address operand is represented as 4
@@ -101,9 +105,10 @@ namespace llvm {
       std::vector<ConstraintInfo> Constraints;
 
       OperandInfo(Record *R, const std::string &N, const std::string &PMN,
-                  unsigned MION, unsigned MINO, DagInit *MIOI)
-        : Rec(R), Name(N), PrinterMethodName(PMN), MIOperandNo(MION),
-          MINumOperands(MINO), MIOperandInfo(MIOI) {}
+                  const std::string &EMN, unsigned MION, unsigned MINO,
+                  DagInit *MIOI)
+        : Rec(R), Name(N), PrinterMethodName(PMN), EncoderMethodName(EMN),
+          MIOperandNo(MION), MINumOperands(MINO), MIOperandInfo(MIOI) {}
     };
 
     /// NumDefs - Number of def operands declared, this is the number of