1 //===-- RISCVAsmPrinter.cpp - RISCV LLVM assembly writer ------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains a printer that converts from our internal representation 11 // of machine-dependent LLVM code to the RISCV assembly language. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "RISCV.h" 16 #include "InstPrinter/RISCVInstPrinter.h" 17 #include "RISCVTargetMachine.h" 18 #include "llvm/CodeGen/AsmPrinter.h" 19 #include "llvm/CodeGen/MachineConstantPool.h" 20 #include "llvm/CodeGen/MachineFunctionPass.h" 21 #include "llvm/CodeGen/MachineInstr.h" 22 #include "llvm/CodeGen/MachineModuleInfo.h" 23 #include "llvm/MC/MCAsmInfo.h" 24 #include "llvm/MC/MCInst.h" 25 #include "llvm/MC/MCStreamer.h" 26 #include "llvm/MC/MCSymbol.h" 27 #include "llvm/Support/TargetRegistry.h" 28 #include "llvm/Support/raw_ostream.h" 29 using namespace llvm; 30 31 #define DEBUG_TYPE "asm-printer" 32 33 namespace { 34 class RISCVAsmPrinter : public AsmPrinter { 35 public: 36 explicit RISCVAsmPrinter(TargetMachine &TM, 37 std::unique_ptr<MCStreamer> Streamer) 38 : AsmPrinter(TM, std::move(Streamer)) {} 39 40 StringRef getPassName() const override { return "RISCV Assembly Printer"; } 41 42 void EmitInstruction(const MachineInstr *MI) override; 43 44 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 45 unsigned AsmVariant, const char *ExtraCode, 46 raw_ostream &OS) override; 47 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, 48 unsigned AsmVariant, const char *ExtraCode, 49 raw_ostream &OS) override; 50 51 bool emitPseudoExpansionLowering(MCStreamer &OutStreamer, 52 const MachineInstr *MI); 53 54 // Wrapper needed for tblgenned pseudo lowering. 55 bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const { 56 return LowerRISCVMachineOperandToMCOperand(MO, MCOp, *this); 57 } 58 }; 59 } 60 61 // Simple pseudo-instructions have their lowering (with expansion to real 62 // instructions) auto-generated. 63 #include "RISCVGenMCPseudoLowering.inc" 64 65 void RISCVAsmPrinter::EmitInstruction(const MachineInstr *MI) { 66 // Do any auto-generated pseudo lowerings. 67 if (emitPseudoExpansionLowering(*OutStreamer, MI)) 68 return; 69 70 MCInst TmpInst; 71 LowerRISCVMachineInstrToMCInst(MI, TmpInst, *this); 72 EmitToStreamer(*OutStreamer, TmpInst); 73 } 74 75 bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 76 unsigned AsmVariant, 77 const char *ExtraCode, raw_ostream &OS) { 78 if (AsmVariant != 0) 79 report_fatal_error("There are no defined alternate asm variants"); 80 81 // First try the generic code, which knows about modifiers like 'c' and 'n'. 82 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, OS)) 83 return false; 84 85 if (!ExtraCode) { 86 const MachineOperand &MO = MI->getOperand(OpNo); 87 switch (MO.getType()) { 88 case MachineOperand::MO_Immediate: 89 OS << MO.getImm(); 90 return false; 91 case MachineOperand::MO_Register: 92 OS << RISCVInstPrinter::getRegisterName(MO.getReg()); 93 return false; 94 default: 95 break; 96 } 97 } 98 99 return true; 100 } 101 102 bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 103 unsigned OpNo, unsigned AsmVariant, 104 const char *ExtraCode, 105 raw_ostream &OS) { 106 if (AsmVariant != 0) 107 report_fatal_error("There are no defined alternate asm variants"); 108 109 if (!ExtraCode) { 110 const MachineOperand &MO = MI->getOperand(OpNo); 111 // For now, we only support register memory operands in registers and 112 // assume there is no addend 113 if (!MO.isReg()) 114 return true; 115 116 OS << "0(" << RISCVInstPrinter::getRegisterName(MO.getReg()) << ")"; 117 return false; 118 } 119 120 return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, AsmVariant, ExtraCode, OS); 121 } 122 123 // Force static initialization. 124 extern "C" void LLVMInitializeRISCVAsmPrinter() { 125 RegisterAsmPrinter<RISCVAsmPrinter> X(getTheRISCV32Target()); 126 RegisterAsmPrinter<RISCVAsmPrinter> Y(getTheRISCV64Target()); 127 } 128