I'm looking at extending AsmPrinter to pretty-print comments after
instructions (I'm adding the necessary fields to MachineInstr to do this).
I'm trying to grok AsmWriterEmitter and having a tough go of it. I look at
X86GenAsmWriter1.inc (the Intel syntax writer) and understand that
there's a case block for printing operands under several switch statements,
one per "fragment."
I need to recode AsmWriterEmitter to call a function right before it emits
the final newline for an instruction to do any instruction post-processing
needed (e.g. printing comments).
AsmWriterInst ::AsmWriterInst seems to be the place to do this but my
reading says that it always appends a newline to whatever string it's
creating. So this can't be used for fragments that don't end in a
newline.
Is this routine only used to generate the switch cases for fragments that
end an instruction? Is it the right place to insert the necessary code?
I also have a few questions on the general design of AsmPrinter. Why is
runOnMachineFunction implemented for each target AsmPrinter? I would
have expected this to live in the base AsmPrinter class with calls out to
specialized helper functions (Template Method pattern). If things were
designed this way, it would be trivial to do what I want:
AsmPrinter::runOnMachineFunction(...) {
[...] // Call helpers to print out constant pools, check calling conventions,
/ /etc.
// Print out code for the function.
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
// Print a label for the basic block.
if (I != MF.begin()) {
printBasicBlockLabel(I, true); // Overridden for each target
O << '\n';
}
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
II != E; ++II) {
// Print the assembly for the instruction.
O << "\t";
printInstruction(II); // Overridden for each target
postInstructionAction(II); // New API for comment printing, etc.
O << "\n";
++EmittedInsts;
}
}
}
Then TableGen wouldn't have to worry about printing newlines either.
The best thing is that parts of postInstructionAction are independent
of the target. Comment printing is a good example. The only thing that
matters on any machine llvm targets is the comment delimeter, which is
already handled by TargetAsmInfo.
Along the same lines, AsmWriterEmitter always dumps this exact
code to each target in the generated printInstruction function:
if (MI->getOpcode() == TargetInstrInfo::INLINEASM) {
printInlineAsm(MI);
return true;
} else if (MI->getOpcode() == TargetInstrInfo::LABEL) {
printLabel(MI);
return true;
}
This could just as well go in the AsmWriter base class and TableGen wouldn't
have to worry about it.
Thoughts?
-Dave