Implementing the instruction printer support class for the M88k Target – The Target Description
By Peggy Johnston / April 3, 2022 / No Comments / Emitting machine instructions, Exams of IT, Global instruction selection, Implementing the assembler parser, ITCertification Exams
The M88kInstPrinter class has a similar structure to the M88kMCCodeEmitter class. As mentioned previously, the InstPrinter class is responsible for emitting the textual representation of LLVM instructions. Most of the class is generated by TableGen, but we have to add support for printing the operands. The class is declared in the M88kInstPrinter.h header file. The implementation is in the M88kInstPrinter.cpp file:
- Let’s begin with the header file. After including the required header files and declaring the llvm namespace, two forward references are declared to reduce the number of required includes:
namespace llvm {
class MCAsmInfo;
class MCOperand;
- Besides the constructor, we only need to implement the printOperand() and printInst() methods. The other methods are generated by TableGen:
class M88kInstPrinter : public MCInstPrinter {
public:
M88kInstPrinter(const MCAsmInfo &MAI,
const MCInstrInfo &MII,
const MCRegisterInfo &MRI)
: MCInstPrinter(MAI, MII, MRI) {}
std::pair
getMnemonic(const MCInst *MI) override;
void printInstruction(const MCInst *MI,
uint64_t Address,
const MCSubtargetInfo &STI,
raw_ostream &O);
static const char *getRegisterName(MCRegister RegNo);
void printOperand(const MCInst *MI, int OpNum,
const MCSubtargetInfo &STI,
raw_ostream &O);
void printInst(const MCInst *MI, uint64_t Address,
StringRef Annot,
const MCSubtargetInfo &STI,
raw_ostream &O) override;
};
} // end namespace llvm
- The implementation lives in the M88kInstPrint.cpp file. After including the required header file and using the llvm namespace, the file with the generated C++ fragments is included:
using namespace llvm;
define DEBUG_TYPE “asm-printer”
include “M88kGenAsmWriter.inc”
- The printOperand() method checks the type of the operand and emits either a register name or an immediate. The register name is looked up with the getRegisterName() generated method:
void M88kInstPrinter::printOperand(
const MCInst *MI, int OpNum,
const MCSubtargetInfo &STI, raw_ostream &O) {
const MCOperand &MO = MI->getOperand(OpNum);
if (MO.isReg()) {
if (!MO.getReg())
O << ‘0’;
else
O << ‘%’ << getRegisterName(MO.getReg());
} else if (MO.isImm())
O << MO.getImm();
else
llvm_unreachable(“Invalid operand”);
}
- The printInst() method only calls the printInstruction() generated method to print the instruction, and after that, the printAnnotation() method to print possible annotations:
void M88kInstPrinter::printInst(
const MCInst *MI, uint64_t Address, StringRef Annot,
const MCSubtargetInfo &STI, raw_ostream &O) {
printInstruction(MI, Address, STI, O);
printAnnotation(O, Annot);
}