命令のプリント、つまりアセンブリ命令をファイルに出力する処理は、基本的にMYRISCVXInstrInfo.tdに記述した命令の定義に基づいて生成される。
LLVMではPrintInstruction()
というメソッドがその役割を担います。
このメソッドはMYRISCVXInstPrinter
クラスに記述されています。
したがって、PrintInstruction()
に関連するメソッドはすべてMYRISCVXInstPrinter
に記述することになります。
build-myriscvx/lib/Target/MYRISCVX/MYRISCVXGenAsmWriter.inc
/// printInstruction - This method is automatically generated by tablegen /// from the instruction set description. void MYRISCVXInstPrinter::printInstruction(const MCInst *MI, raw_ostream &O) { static const char AsmStrs[] = { ... }
ここでサポートメソッドとして追加しなければならないことは、以下の2つ。
printOperand()
: オペランドを出力する。printMemOperand()
: メモリオペランドを出力する。メモリオペランドはimm(reg)
の形式で出力するので、printOperand()
を2回呼び出している。llvm-myriscvx/lib/Target/MYRISCVX/InstPrinter/MYRISCVXInstPrinter.cpp
void MYRISCVXInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) { const MCOperand &Op = MI->getOperand(OpNo); if (Op.isReg()) { printRegName(O, Op.getReg()); return; } if (Op.isImm()) { O << Op.getImm(); return; } assert(Op.isExpr() && "unknown operand kind in printOperand"); Op.getExpr()->print(O, &MAI, true); } void MYRISCVXInstPrinter:: printMemOperand(const MCInst *MI, int opNum, raw_ostream &O) { // Load/Store memory operands -- imm($reg) // If PIC target the target is loaded as the // pattern ld $t9,%call16($gp) printOperand(MI, opNum+1, O); O << "("; printOperand(MI, opNum, O); O << ")"; }
このprintInstruction()
などの命令プリントメソッドとMYRISCVXTargetMachine
との関連付けは、MCTargetDesc/MYRISCVXMCTargetDesc.cpp
で行われている。
llvm-myriscvx/lib/Target/MYRISCVX/MCTargetDesc/MYRISCVXMCTargetDesc.cpp
// MYRISCVXInstPrinterメソッドを返す。 static MCInstPrinter *createMYRISCVXMCInstPrinter(const Triple &T, unsigned SyntaxVariant, const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI) { return new MYRISCVXInstPrinter(MAI, MII, MRI); } extern "C" void LLVMInitializeMYRISCVXTargetMC() { for (Target *T : {&getTheMYRISCVX32Target(), &getTheMYRISCVX64Target()}) { // Register the MC asm info. RegisterMCAsmInfoFn X(*T, createMYRISCVXMCAsmInfo); // Register the MC instruction info. TargetRegistry::RegisterMCInstrInfo(*T, createMYRISCVXMCInstrInfo); // Register the MC register info. TargetRegistry::RegisterMCRegInfo(*T, createMYRISCVXMCRegisterInfo); // Register the MC subtarget info. TargetRegistry::RegisterMCSubtargetInfo(*T, createMYRISCVXMCSubtargetInfo); // Register the MC instruction analyzer. TargetRegistry::RegisterMCInstrAnalysis(*T, createMYRISCVXMCInstrAnalysis); // createMYRISCVXMCInstPrinterクラスを通じて、MYRISCVXInstPrintクラスを登録する。 TargetRegistry::RegisterMCInstPrinter(*T, createMYRISCVXMCInstPrinter); } }