130 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- RISCVAsmPrinter.cpp - RISCV LLVM assembly writer ------------------===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // This file contains a printer that converts from our internal representation
 | |
| // of machine-dependent LLVM code to the RISCV assembly language.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "RISCV.h"
 | |
| #include "MCTargetDesc/RISCVInstPrinter.h"
 | |
| #include "MCTargetDesc/RISCVMCExpr.h"
 | |
| #include "RISCVTargetMachine.h"
 | |
| #include "TargetInfo/RISCVTargetInfo.h"
 | |
| #include "llvm/CodeGen/AsmPrinter.h"
 | |
| #include "llvm/CodeGen/MachineConstantPool.h"
 | |
| #include "llvm/CodeGen/MachineFunctionPass.h"
 | |
| #include "llvm/CodeGen/MachineInstr.h"
 | |
| #include "llvm/CodeGen/MachineModuleInfo.h"
 | |
| #include "llvm/MC/MCAsmInfo.h"
 | |
| #include "llvm/MC/MCInst.h"
 | |
| #include "llvm/MC/MCStreamer.h"
 | |
| #include "llvm/MC/MCSymbol.h"
 | |
| #include "llvm/Support/TargetRegistry.h"
 | |
| #include "llvm/Support/raw_ostream.h"
 | |
| using namespace llvm;
 | |
| 
 | |
| #define DEBUG_TYPE "asm-printer"
 | |
| 
 | |
| namespace {
 | |
| class RISCVAsmPrinter : public AsmPrinter {
 | |
| public:
 | |
|   explicit RISCVAsmPrinter(TargetMachine &TM,
 | |
|                            std::unique_ptr<MCStreamer> Streamer)
 | |
|       : AsmPrinter(TM, std::move(Streamer)) {}
 | |
| 
 | |
|   StringRef getPassName() const override { return "RISCV Assembly Printer"; }
 | |
| 
 | |
|   void EmitInstruction(const MachineInstr *MI) override;
 | |
| 
 | |
|   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
 | |
|                        const char *ExtraCode, raw_ostream &OS) override;
 | |
|   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
 | |
|                              const char *ExtraCode, raw_ostream &OS) override;
 | |
| 
 | |
|   void EmitToStreamer(MCStreamer &S, const MCInst &Inst);
 | |
|   bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
 | |
|                                    const MachineInstr *MI);
 | |
| 
 | |
|   // Wrapper needed for tblgenned pseudo lowering.
 | |
|   bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const {
 | |
|     return LowerRISCVMachineOperandToMCOperand(MO, MCOp, *this);
 | |
|   }
 | |
| };
 | |
| }
 | |
| 
 | |
| #define GEN_COMPRESS_INSTR
 | |
| #include "RISCVGenCompressInstEmitter.inc"
 | |
| void RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
 | |
|   MCInst CInst;
 | |
|   bool Res = compressInst(CInst, Inst, *TM.getMCSubtargetInfo(),
 | |
|                           OutStreamer->getContext());
 | |
|   AsmPrinter::EmitToStreamer(*OutStreamer, Res ? CInst : Inst);
 | |
| }
 | |
| 
 | |
| // Simple pseudo-instructions have their lowering (with expansion to real
 | |
| // instructions) auto-generated.
 | |
| #include "RISCVGenMCPseudoLowering.inc"
 | |
| 
 | |
| void RISCVAsmPrinter::EmitInstruction(const MachineInstr *MI) {
 | |
|   // Do any auto-generated pseudo lowerings.
 | |
|   if (emitPseudoExpansionLowering(*OutStreamer, MI))
 | |
|     return;
 | |
| 
 | |
|   MCInst TmpInst;
 | |
|   LowerRISCVMachineInstrToMCInst(MI, TmpInst, *this);
 | |
|   EmitToStreamer(*OutStreamer, TmpInst);
 | |
| }
 | |
| 
 | |
| bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
 | |
|                                       const char *ExtraCode, raw_ostream &OS) {
 | |
|   // First try the generic code, which knows about modifiers like 'c' and 'n'.
 | |
|   if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
 | |
|     return false;
 | |
| 
 | |
|   if (!ExtraCode) {
 | |
|     const MachineOperand &MO = MI->getOperand(OpNo);
 | |
|     switch (MO.getType()) {
 | |
|     case MachineOperand::MO_Immediate:
 | |
|       OS << MO.getImm();
 | |
|       return false;
 | |
|     case MachineOperand::MO_Register:
 | |
|       OS << RISCVInstPrinter::getRegisterName(MO.getReg());
 | |
|       return false;
 | |
|     default:
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
 | |
|                                             unsigned OpNo,
 | |
|                                             const char *ExtraCode,
 | |
|                                             raw_ostream &OS) {
 | |
|   if (!ExtraCode) {
 | |
|     const MachineOperand &MO = MI->getOperand(OpNo);
 | |
|     // For now, we only support register memory operands in registers and
 | |
|     // assume there is no addend
 | |
|     if (!MO.isReg())
 | |
|       return true;
 | |
| 
 | |
|     OS << "0(" << RISCVInstPrinter::getRegisterName(MO.getReg()) << ")";
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
 | |
| }
 | |
| 
 | |
| // Force static initialization.
 | |
| extern "C" void LLVMInitializeRISCVAsmPrinter() {
 | |
|   RegisterAsmPrinter<RISCVAsmPrinter> X(getTheRISCV32Target());
 | |
|   RegisterAsmPrinter<RISCVAsmPrinter> Y(getTheRISCV64Target());
 | |
| }
 |