operands. e.g.
def CALL32r : I<0xFF, MRM2r, (ops GR32:$dst, variable_ops),
"call {*}$dst", [(X86call GR32:$dst)]>;
TableGen should emit operand informations for the "required" operands.
Added a target instruction info flag M_VARIABLE_OPS to indicate the target
instruction may have more operands in addition to the minimum required
operands.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28791
91177308-0d34-0410-b5e6-
96231b3b80d8
// block.
const unsigned M_USES_CUSTOM_DAG_SCHED_INSERTION = 1 << 11;
+// M_VARIABLE_OPS - Set if this instruction can have a variable number of extra
+// operands in addition to the minimum number operands specified.
+const unsigned M_VARIABLE_OPS = 1 << 12;
+
// Machine operand flags
// M_LOOK_UP_PTR_REG_CLASS - Set if this operand is a pointer value and it
// requires a callback to look up its register class.
class TargetInstrDescriptor {
public:
const char * Name; // Assembly language mnemonic for the opcode.
- int numOperands; // Number of args; -1 if variable #args
+ unsigned numOperands; // Num of args (may be more if variable_ops).
InstrSchedClass schedClass; // enum identifying instr sched class
unsigned Flags; // flags identifying machine instr class
unsigned TSFlags; // Target Specific Flag values
const TargetRegisterClass
*getInstrOperandRegClass(const TargetInstrDescriptor *II, unsigned Op) const {
+ if (Op >= II->numOperands) {
+ if (II->Flags & M_VARIABLE_OPS)
+ return NULL;
+ assert(false && "Invalid operand # of instruction");
+ }
const TargetOperandInfo &toi = II->OpInfo[Op];
return (toi.Flags & M_LOOK_UP_PTR_REG_CLASS)
? getPointerRegClass() : toi.RegClass;
return get(Opcode).Flags & M_USES_CUSTOM_DAG_SCHED_INSERTION;
}
+ bool hasVariableOperands(MachineOpCode Opcode) const {
+ return get(Opcode).Flags & M_VARIABLE_OPS;
+ }
+
/// Return true if the instruction is a register to register move
/// and leave the source and dest operands in the passed parameters.
virtual bool isMoveInstr(const MachineInstr& MI,
///
bool MachineInstr::OperandsComplete() const {
int NumOperands = TargetInstrDescriptors[Opcode].numOperands;
- if (NumOperands >= 0 && getNumOperands() >= (unsigned)NumOperands)
+ if ((TargetInstrDescriptors[Opcode].Flags & M_VARIABLE_OPS) == 0 &&
+ getNumOperands() >= (unsigned)NumOperands)
return true; // Broken: we have all the operands of this instruction!
return false;
}
unsigned NodeOperands = CountOperands(Node);
unsigned NumMIOperands = NodeOperands + NumResults;
#ifndef NDEBUG
- assert((unsigned(II.numOperands) == NumMIOperands || II.numOperands == -1)&&
+ assert((unsigned(II.numOperands) == NumMIOperands ||
+ (II.Flags & M_VARIABLE_OPS)) &&
"#operands for dag node doesn't match .td file!");
#endif
static std::vector<Record*> GetOperandInfo(const CodeGenInstruction &Inst) {
std::vector<Record*> Result;
- if (Inst.hasVariableNumberOfOperands)
- return Result; // No info for variable operand instrs.
-
for (unsigned i = 0, e = Inst.OperandList.size(); i != e; ++i) {
if (Inst.OperandList[i].Rec->isSubClassOf("RegisterClass")) {
Result.push_back(Inst.OperandList[i].Rec);
std::map<std::vector<Record*>, unsigned> &EmittedLists,
std::map<std::vector<Record*>, unsigned> &OpInfo,
std::ostream &OS) {
- int NumOperands;
- if (Inst.hasVariableNumberOfOperands)
- NumOperands = -1;
- else if (!Inst.OperandList.empty())
+ int MinOperands;
+ if (!Inst.OperandList.empty())
// Each logical operand can be multiple MI operands.
- NumOperands = Inst.OperandList.back().MIOperandNo +
+ MinOperands = Inst.OperandList.back().MIOperandNo +
Inst.OperandList.back().MINumOperands;
else
- NumOperands = 0;
+ MinOperands = 0;
OS << " { \"";
if (Inst.Name.empty())
unsigned ItinClass = !IsItineraries ? 0 :
ItinClassNumber(Inst.TheDef->getValueAsDef("Itinerary")->getName());
- OS << "\",\t" << NumOperands << ", " << ItinClass
+ OS << "\",\t" << MinOperands << ", " << ItinClass
<< ", 0";
// Try to determine (from the pattern), if the instruction is a store.
if (Inst.isTerminator) OS << "|M_TERMINATOR_FLAG";
if (Inst.usesCustomDAGSchedInserter)
OS << "|M_USES_CUSTOM_DAG_SCHED_INSERTION";
+ if (Inst.hasVariableNumberOfOperands)
+ OS << "|M_VARIABLE_OPS";
OS << ", 0";
// Emit all of the target-specific flags...