diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index 64ea16e362d..b7b62d502b0 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/utils/TableGen/CodeEmitterGen.cpp @@ -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++; } + std::pair SO = CGI.getSubOperandNumber(OpIdx); + std::string &EncoderMethodName = + CGI.OperandList[SO.first].EncoderMethodName; - Case += " // op: " + VarName + "\n" - + " op = getMachineOpValue(MI, MI.getOperand(" - + utostr(OpIdx) + "));\n"; + // 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; } diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 722ae53ed50..6e71502cbc2 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -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; } diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index 049e694006a..e895361d69c 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -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 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