distinguishing between real arguments and variable arguments

I'm doing the delay slot optimization for MIPS and I've noticed that two other ports that are doing this have to work around a problem in the instruction abstraction.

Would be nice to fix this and not propagate the hack.

The basic problem is that on a call, you want to get the set of explicit and implicit operands but NOT the variable operands.

There is no way do this without hardcoding this information away from the TD file which is error prone.
Architectures evolve and you can get new call instructions and then have a subtle delay slot bug.

Any suggestions on how to fix LLVM so that we can get the non variable operands?

In Mblaze:

static unsigned getLastRealOperand(MachineBasicBlock::iterator &instr) {
   switch (instr->getOpcode()) {
   default: return instr->getNumOperands();

   // These instructions have a variable number of operands but the first two
   // are the "real" operands that we care about during hazard detection.
   case MBlaze::BRLID:
   case MBlaze::BRALID:
   case MBlaze::BRLD:
   case MBlaze::BRALD:
     return 2;

In Sparc:

void Filler::insertCallUses(MachineBasicBlock::iterator MI,
                             SmallSet<unsigned, 32>& RegUses)

   switch(MI->getOpcode()) {
   default: llvm_unreachable("Unknown opcode.");
   case SP::CALL: break;
   case SP::JMPLrr:
   case SP::JMPLri:
     assert(MI->getNumOperands() >= 2);
     const MachineOperand &Reg = MI->getOperand(0);
     assert(Reg.isReg() && "JMPL first operand is not a register.");
     assert(Reg.isUse() && "JMPL first operand is not a use.");

     const MachineOperand &RegOrImm = MI->getOperand(1);
     if (RegOrImm.isImm())
     assert(RegOrImm.isReg() && "JMPLrr second operand is not a register.");
     assert(RegOrImm.isUse() && "JMPLrr second operand is not a use.");

You can get the number of non-variable operands for a
MachineInstruction with getDesc()->getNumOperands().

That said, if I'm following this right, that isn't quite correct; you
really want to check whether a given operand's value is read before or
after the delay slot executes. The difference might not matter in
practice, but you should probably at least leave a comment mentioning
that, though.