diff --git a/llvm/utils/TableGen/CodeEmitterGen.cpp b/llvm/utils/TableGen/CodeEmitterGen.cpp index a039e0b1e35a..1a967e9742c9 100644 --- a/llvm/utils/TableGen/CodeEmitterGen.cpp +++ b/llvm/utils/TableGen/CodeEmitterGen.cpp @@ -128,7 +128,7 @@ void CodeEmitterGen::run(raw_ostream &o) { // Loop over all of the fields in the instruction, determining which are the // operands to the instruction. - unsigned op = 0; + unsigned NumberedOp = 0; for (unsigned i = 0, e = Vals.size(); i != e; ++i) { if (!Vals[i].getPrefix() && !Vals[i].getValue()->isComplete()) { // Is the operand continuous? If so, we can just mask and OR it in @@ -154,14 +154,25 @@ void CodeEmitterGen::run(raw_ostream &o) { } if (!gotOp) { - /// If this operand is not supposed to be emitted by the generated - /// emitter, skip it. - while (CGI.isFlatOperandNotEmitted(op)) - ++op; + + // If the operand matches by name, reference according to that + // operand number. Non-matching operands are assumed to be in + // order. + unsigned OpIdx; + if (CGI.hasOperandNamed(VarName, OpIdx)) { + assert (!CGI.isFlatOperandNotEmitted(OpIdx) && + "Explicitly used operand also marked as not emitted!"); + } else { + /// If this operand is not supposed to be emitted by the + /// generated emitter, skip it. + while (CGI.isFlatOperandNotEmitted(NumberedOp)) + ++NumberedOp; + OpIdx = NumberedOp++; + } Case += " // op: " + VarName + "\n" + " op = getMachineOpValue(MI, MI.getOperand(" - + utostr(op++) + "));\n"; + + utostr(OpIdx) + "));\n"; gotOp = true; } diff --git a/llvm/utils/TableGen/CodeGenInstruction.cpp b/llvm/utils/TableGen/CodeGenInstruction.cpp index 01a1fe11f531..722ae53ed507 100644 --- a/llvm/utils/TableGen/CodeGenInstruction.cpp +++ b/llvm/utils/TableGen/CodeGenInstruction.cpp @@ -234,13 +234,26 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr) /// specified name, throw an exception. /// unsigned CodeGenInstruction::getOperandNamed(const std::string &Name) const { - assert(!Name.empty() && "Cannot search for operand with no name!"); - for (unsigned i = 0, e = OperandList.size(); i != e; ++i) - if (OperandList[i].Name == Name) return i; + unsigned OpIdx; + if (hasOperandNamed(Name, OpIdx)) return OpIdx; throw "Instruction '" + TheDef->getName() + "' does not have an operand named '$" + Name + "'!"; } +/// hasOperandNamed - Query whether the instruction has an operand of the +/// given name. If so, return true and set OpIdx to the index of the +/// operand. Otherwise, return false. +bool CodeGenInstruction::hasOperandNamed(const std::string &Name, + unsigned &OpIdx) const { + assert(!Name.empty() && "Cannot search for operand with no name!"); + for (unsigned i = 0, e = OperandList.size(); i != e; ++i) + if (OperandList[i].Name == Name) { + OpIdx = i; + return true; + } + return false; +} + std::pair CodeGenInstruction::ParseOperandName(const std::string &Op, bool AllowWholeOp) { diff --git a/llvm/utils/TableGen/CodeGenInstruction.h b/llvm/utils/TableGen/CodeGenInstruction.h index 254cfed073f8..049e694006a7 100644 --- a/llvm/utils/TableGen/CodeGenInstruction.h +++ b/llvm/utils/TableGen/CodeGenInstruction.h @@ -186,6 +186,11 @@ namespace llvm { /// specified name, throw an exception. unsigned getOperandNamed(const std::string &Name) const; + /// hasOperandNamed - Query whether the instruction has an operand of the + /// given name. If so, return true and set OpIdx to the index of the + /// operand. Otherwise, return false. + bool hasOperandNamed(const std::string &Name, unsigned &OpIdx) const; + /// HasOneImplicitDefWithKnownVT - If the instruction has at least one /// implicit def and it has a known VT, return the VT, otherwise return /// MVT::Other.