[CodeEmitter] Support instruction widths > 64 bits


[CodeEmitter] Support instruction widths > 64 bits

Some VLIW instruction sets are Very Long Indeed. Using uint64_t constricts the Inst encoding to 64 bits (naturally).

This change switches CodeEmitter to a mode that uses APInts when Inst's bitwidth is > 64 bits (NFC for existing targets).

When Inst.BitWidth > 64 the prototype changes to:

void TargetMCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,
                                                SmallVectorImpl<MCFixup> &Fixups,
                                                APInt &Inst,
                                                APInt &Scratch,
                                                const MCSubtargetInfo &STI);

The Inst parameter returns the encoded instruction, the Scratch parameter is used internally for manipulating operands and is exposed so that the underlying storage can be reused between calls to getBinaryCodeForInstr. The goal is to elide any APInt constructions that we can.

Similarly the operand encoding prototype changes to:

getMachineOpValue(const MCInst &MI, const MCOperand &MO, APInt &op, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI);

That is, the operand is passed by reference as APInt rather than returned as uint64_t.

To reiterate, this APInt mode is enabled only when Inst.BitWidth > 64, so this change is NFC for existing targets.


jamesmSep 15 2019, 1:35 AM
rL371927: lld-link: Make Options.td formatting more self-consistent.

Event Timeline

Thanks for working on this. We've had some hacks for >64 bit instructions that we've wanted to get rid of for ages. I gave it a try and I had to fix a couple issues when it merged with our sources (see the inline comments).

Also, I haven't looked into why yet but the compile-time cost of this was quite large for us (16s -> ~5m50s). I assume it's a similar issue to when we did this for the disassembler and found that the sheer number of allocas for APInt were the problem. We ended up switching to a cheaper fixed-length equivalent of APInt for that.


This didn't work for me. I had to change it to .lshrInPlace()


Similarly, I have to change this to use .shl()


Similarly, but .lshr()


The cast to uint8_t drops a const


This needs a UseAPInt version