diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index 6466b5fecd9..c8af097250d 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -220,16 +220,11 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) { unsigned OpNo = CGI.getOperandNamed(VarName); CodeGenInstruction::OperandInfo OpInfo = CGI.OperandList[OpNo]; - // If this is a two-address instruction, verify the second operand isn't - // used. - unsigned MIOp = OpInfo.MIOperandNo; - if (CGI.isTwoAddress && MIOp == 1) - throw "Should refer to operand #0 instead of #1 for two-address" - " instruction '" + CGI.TheDef->getName() + "'!"; - - if (CurVariant == Variant || CurVariant == ~0U) + if (CurVariant == Variant || CurVariant == ~0U) { + unsigned MIOp = OpInfo.MIOperandNo; Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName, MIOp, Modifier)); + } } LastEmitted = VarEnd; } diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index bc415fcc1db..c64b5f454d2 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/utils/TableGen/CodeEmitterGen.cpp @@ -125,7 +125,8 @@ void CodeEmitterGen::run(std::ostream &o) { BitsInit *BI = R->getValueAsBitsInit("Inst"); const std::vector &Vals = R->getValues(); - + CodeGenInstruction &CGI = Target.getInstruction(InstName); + // Loop over all of the fields in the instruction, determining which are the // operands to the instruction. unsigned op = 0; @@ -154,16 +155,15 @@ void CodeEmitterGen::run(std::ostream &o) { } if (!gotOp) { + /// If this operand is not supposed to be emitted by the generated + /// emitter, skip it. + while (CGI.isFlatOperandNotEmitted(op)) + ++op; + Case += " // op: " + VarName + "\n" + " op = getMachineOpValue(MI, MI.getOperand(" - + utostr(op++) - + "));\n"; + + utostr(op++) + "));\n"; gotOp = true; - - // If this is a two-address instruction and we just got the dest - // op, skip the src op. - if (op == 1 && Target.getInstruction(InstName).isTwoAddress) - ++op; } unsigned opMask = (1 << N) - 1; @@ -185,7 +185,7 @@ void CodeEmitterGen::run(std::ostream &o) { } } - std::vector &InstList = CaseMap[Case]; + std::vector &InstList = CaseMap[Case]; InstList.push_back(InstName); } diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index d99af1b67a3..e0d6b9837e4 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -57,6 +57,11 @@ namespace llvm { unsigned MIOperandNo; unsigned MINumOperands; // The number of operands. + /// DoNotEncode - Bools are set to true in this vector for each operand in + /// the DisableEncoding list. These should not be emitted by the code + /// emitter. + std::vector DoNotEncode; + /// MIOperandInfo - Default MI operand type. Note an operand may be made /// up of multiple MI operands. DagInit *MIOperandInfo; @@ -82,7 +87,6 @@ namespace llvm { bool isCall; bool isLoad; bool isStore; - bool isTwoAddress; bool isPredicated; bool isConvertibleToThreeAddress; bool isCommutable; @@ -107,6 +111,25 @@ namespace llvm { return OperandList[Op.first].MIOperandNo + Op.second; } + /// getSubOperandNumber - Unflatten a operand number into an + /// operand/suboperand pair. + std::pair getSubOperandNumber(unsigned Op) const { + for (unsigned i = 0; ; ++i) { + assert(i < OperandList.size() && "Invalid flat operand #"); + if (OperandList[i].MIOperandNo+OperandList[i].MINumOperands > Op) + return std::make_pair(i, Op-OperandList[i].MIOperandNo); + } + } + + + /// isFlatOperandNotEmitted - Return true if the specified flat operand # + /// should not be emitted with the code emitter. + bool isFlatOperandNotEmitted(unsigned FlatOpNo) const { + std::pair Op = getSubOperandNumber(FlatOpNo); + if (OperandList[Op.first].DoNotEncode.size() > Op.second) + return OperandList[Op.first].DoNotEncode[Op.second]; + return false; + } CodeGenInstruction(Record *R, const std::string &AsmStr); diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index 2281519ad14..4613c1ba248 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -343,7 +343,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr) isCall = R->getValueAsBit("isCall"); isLoad = R->getValueAsBit("isLoad"); isStore = R->getValueAsBit("isStore"); - isTwoAddress = R->getValueAsBit("isTwoAddress"); + bool isTwoAddress = R->getValueAsBit("isTwoAddress"); isPredicated = false; // set below. isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress"); isCommutable = R->getValueAsBit("isCommutable"); @@ -413,6 +413,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr) MIOperandNo += NumOps; } + // Parse Constraints. ParseConstraints(R->getValueAsString("Constraints"), this); // For backward compatibility: isTwoAddress means operand 1 is tied to @@ -430,6 +431,21 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr) for (unsigned j = 0, e = OperandList[op].MINumOperands; j != e; ++j) if (OperandList[op].Constraints[j].empty()) OperandList[op].Constraints[j] = "0"; + + // Parse the DisableEncoding field. + std::string DisableEncoding = R->getValueAsString("DisableEncoding"); + while (1) { + std::string OpName = getToken(DisableEncoding, " ,\t"); + if (OpName.empty()) break; + + // Figure out which operand this is. + std::pair Op = ParseOperandName(OpName, false); + + // Mark the operand as not-to-be encoded. + if (Op.second >= OperandList[Op.first].DoNotEncode.size()) + OperandList[Op.first].DoNotEncode.resize(Op.second+1); + OperandList[Op.first].DoNotEncode[Op.second] = true; + } }