Hi,
We are using the AsmParser to analyse inline asm instructions in our backend, i.e. to get the actual size in bytes of an instruction or to find all calls,.. I assume this might be similar to what you want to do.
I let AsmPrinter do all the hard work of parsing inline asm and instantiating everything. This might be a bit of an overkill though if you do not need inline-asm parsing (it replaces placeholders with proper register names, ...). For your case it might be sufficient to have a look at the code in AsmParser::EmitInlineAsm(StringRef Str, ..). You will need to have a proper context and MCStreamer object though..
Here is what I did to make this happen:
1) Extract a header for the MCNullStreamer class to include/llvm/MC to be able to make subclasses. I will attach the modified files for your convenience.
2) Make the EmitInlineAsm functions in AsmPrinter public. Move construction and deletion of the Mangler in AsmPrinter.cpp into the constructor/destructor of AsmPrinter. In AsmPrinter::EmitInlineAsm (AsmPrinterInlineAsm.cpp:93), add an 'if (MMI) { .. }' to skip the DiagnosticHandler stuff if MMI is not set.
3) Create a subclass of MCNullStreamer to visit all parsed instructions in the inline asm code, like so:
class InstrAnalyzer : public MCNullStreamer {
const MCInstrInfo &MII;
unsigned size;
public:
InstrAnalyzer(MCContext &ctx)
: MCNullStreamer(ctx), MII(ctx.getInstrInfo()), size(0)
{ }
virtual void EmitInstruction(const MCInst &Inst) {
const MCInstrDesc &MID = MII.get(Inst.getOpcode());
size += MID.getSize();
}
};
4) Create a new AsmPrinter and use it to parse and emit asm, e.g. like so (our backend is called Patmos, so do not wonder about this..):
unsigned int PatmosInstrInfo::getInstrSize(const MachineInstr *MI) const {
if (MI->isInlineAsm()) {
// PTM is the TargetMachine
// TODO is there a way to get the current context?
MCContext Ctx(*PTM.getMCAsmInfo(),
*PTM.getRegisterInfo(), *PTM.getInstrInfo(), 0);
// PIA is deleted by AsmPrinter
PatmosInstrAnalyzer *PIA = new InstrAnalyzer(Ctx);
// PTM.getTargetLowering()->getObjFileLowering() might not yet be
// initialized, so we create a new section object for this temp context
const MCSection* TS = Ctx.getELFSection(".text",
ELF::SHT_PROGBITS, 0,
SectionKind::getText());
PIA->SwitchSection(TS);
PatmosAsmPrinter PAP(PTM, *PIA);
PAP.EmitInlineAsm(MI);
return PIA->getSize();
}
else if (MI->isBundle()) {
// handle bundles..
unsigned size = ...;
return size;
}
else {
// trust the desc..
return MI->getDesc().getSize();
}
}
I tested this with LLVM 3.2, and it should work with LLVM 3.3 (though I am not finished testing it..).
Cheers,
Stefan Hepp
MCNullStreamer.h (4.47 KB)
MCNullStreamer.cpp (877 Bytes)