diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp new file mode 100644 index 000000000000..57631dcb5115 --- /dev/null +++ b/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp @@ -0,0 +1,147 @@ +//===-- 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; + + const MachineOperand &MO = MI->getOperand(OpNo); + if (ExtraCode && ExtraCode[0]) { + if (ExtraCode[1] != 0) + return true; // Unknown modifier. + + switch (ExtraCode[0]) { + default: + return true; // Unknown modifier. + case 'z': // Print zero register if zero, regular printing otherwise. + if (MO.isImm() && MO.getImm() == 0) { + OS << RISCVInstPrinter::getRegisterName(RISCV::X0); + return false; + } + break; + case 'i': // Literal 'i' if operand is not a register. + if (!MO.isReg()) + OS << 'i'; + return false; + } + } + + 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()); +} |