Distinguish variadic register defines/uses in MCInstrDesc?

Hello,

I'm currently working on a rich disassembler for some ARM/Thumb environment.
I wanted to keep most classes independent of the architecture, so I use
MCInstrInfo and MCInstrAnalysis to find branch instructions (and other
instructions writing to the program counter) and to differentiate between
register definitions and uses to track all instructions the branch depends on.

This works well for most cases, except if there are Thumb pop instructions
involved.

Pop has a variable number of output registers, so MCInstrDesc::getNumDefs
returns zero and, as far as I can see, in the tablegen files 'variable_ops' is
always in the 'ins' list and MCInstrDesc only provides isVariadic();

My current workaround is to assume that all variadic arguments of instructions
that have zero register definitions but are marked as mayLoad are register
definitions. I'm not very happy with this solution.

Is it possible to extend LLVM to check if 'variable_ops' is in 'ins' and/or
'outs' in tablegen, so that MCInstrDesc could provide something like
hasVariadicDefs() and hasVariadicUses()?

That way handling variadic instructions when disassembling would be much
easier and only instructions with variadic uses and defines would need
explicit special casing - if they even exist.

Thanks,
Christoph

Hi Christoph,

As you noticed, MCInstrDesc doesn't distinguish between variadic uses and defs. Since variadic instructions will always require some kind of special handling, it doesn't seem worthwhile to make the model more detailed.

I think your current workaround sounds fine.

/jakob

Hi Christoph,

As you noticed, MCInstrDesc doesn't distinguish between variadic uses and
defs. Since variadic instructions will always require some kind of special
handling, it doesn't seem worthwhile to make the model more detailed.

I don't see what makes them so different from other instructions.
MCInstrDesc provides the information which operands are defines and which uses
for all other instruction types and for variadic there are only three possible
cases:
* All variadic registers are uses (push/stm on ARM)
* All variadic registers are defines (pop/ldm)
* uses and defines are mixed.

I think variable_ops on x86 RET can also be modeled as the first case.

The first two cases don't need any special handling. The start and count of
variadic operands is known through MCInstrDesc and
MCInstruction::getNumOperands(). So I can handle them like any other
instruction if I know which case applies. Only the third case really needs
special handling and I couldn't find an instruction that falls into this case.

I think your current workaround sounds fine.

/jakob

Christoph

Hallo,

I worked on how to handle the distinction between variadic defines and uses
and my current solution is this:

I introduce a new dag item in Instruction called VariadicOperandList, which by
default is undefined. It keeps a marker variable_* and all operands which are
placeholders for variable lists (like 'reglist' on ARM).

I think it's the cleanest solution to keep them in a seperate dag, because
else either register defines would be in the 'ins' list or the parser would
become much more complex to change the order of operands to get the variable
items in 'outs' to the end of the list.

I appended my current patches.

At the moment two tests fail.
2011-06-16-TailCallByVal.ll because an instruction alias for a variadic
instruction isn't recognized and thumb2-ldm.ll fails with "Trying to add an
operand to a machine instr that is already done!"

Any comments?

Thanks,
Christoph Grenz

variable_ops.diff (10.3 KB)

variable_ops_arm.diff (13.1 KB)

Hi Christoph,

What's the motivation here? Why are Jakob's previous recommendations insufficient?

Specifically:
Jakob Stoklund Olesen wrote: