blob: 5b4518dfd04849b89ba41890e0bde85546f144bf [file] [log] [blame]
Alex Bradbury89718422017-10-19 21:37:38 +00001//===-- RISCVAsmPrinter.cpp - RISCV LLVM assembly writer ------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Alex Bradbury89718422017-10-19 21:37:38 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file contains a printer that converts from our internal representation
10// of machine-dependent LLVM code to the RISCV assembly language.
11//
12//===----------------------------------------------------------------------===//
13
14#include "RISCV.h"
15#include "InstPrinter/RISCVInstPrinter.h"
Sameer AbuAsalc1b0e662018-04-06 21:07:05 +000016#include "MCTargetDesc/RISCVMCExpr.h"
Alex Bradbury89718422017-10-19 21:37:38 +000017#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"
29using namespace llvm;
30
31#define DEBUG_TYPE "asm-printer"
32
33namespace {
34class RISCVAsmPrinter : public AsmPrinter {
35public:
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
Alex Bradbury9330e642018-01-10 20:05:09 +000044 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
Nick Desaulniers5277b3f2019-04-10 16:38:43 +000045 const char *ExtraCode, raw_ostream &OS) override;
Alex Bradbury9330e642018-01-10 20:05:09 +000046 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
Nick Desaulniers5277b3f2019-04-10 16:38:43 +000047 const char *ExtraCode, raw_ostream &OS) override;
Alex Bradbury9330e642018-01-10 20:05:09 +000048
Sameer AbuAsalc1b0e662018-04-06 21:07:05 +000049 void EmitToStreamer(MCStreamer &S, const MCInst &Inst);
Alex Bradbury89718422017-10-19 21:37:38 +000050 bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
51 const MachineInstr *MI);
Alex Bradburyec8aa912017-11-08 13:24:21 +000052
53 // Wrapper needed for tblgenned pseudo lowering.
54 bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const {
55 return LowerRISCVMachineOperandToMCOperand(MO, MCOp, *this);
56 }
Alex Bradbury89718422017-10-19 21:37:38 +000057};
58}
59
Sameer AbuAsalc1b0e662018-04-06 21:07:05 +000060#define GEN_COMPRESS_INSTR
61#include "RISCVGenCompressInstEmitter.inc"
62void RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
63 MCInst CInst;
64 bool Res = compressInst(CInst, Inst, *TM.getMCSubtargetInfo(),
65 OutStreamer->getContext());
66 AsmPrinter::EmitToStreamer(*OutStreamer, Res ? CInst : Inst);
67}
68
Alex Bradbury89718422017-10-19 21:37:38 +000069// Simple pseudo-instructions have their lowering (with expansion to real
70// instructions) auto-generated.
71#include "RISCVGenMCPseudoLowering.inc"
72
73void RISCVAsmPrinter::EmitInstruction(const MachineInstr *MI) {
74 // Do any auto-generated pseudo lowerings.
75 if (emitPseudoExpansionLowering(*OutStreamer, MI))
76 return;
77
78 MCInst TmpInst;
Alex Bradburyec8aa912017-11-08 13:24:21 +000079 LowerRISCVMachineInstrToMCInst(MI, TmpInst, *this);
Alex Bradbury89718422017-10-19 21:37:38 +000080 EmitToStreamer(*OutStreamer, TmpInst);
81}
82
Alex Bradbury9330e642018-01-10 20:05:09 +000083bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
Alex Bradbury9330e642018-01-10 20:05:09 +000084 const char *ExtraCode, raw_ostream &OS) {
Alex Bradbury9330e642018-01-10 20:05:09 +000085 // First try the generic code, which knows about modifiers like 'c' and 'n'.
Nick Desaulniers5277b3f2019-04-10 16:38:43 +000086 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
Alex Bradbury9330e642018-01-10 20:05:09 +000087 return false;
88
89 if (!ExtraCode) {
90 const MachineOperand &MO = MI->getOperand(OpNo);
91 switch (MO.getType()) {
92 case MachineOperand::MO_Immediate:
93 OS << MO.getImm();
94 return false;
95 case MachineOperand::MO_Register:
96 OS << RISCVInstPrinter::getRegisterName(MO.getReg());
97 return false;
98 default:
99 break;
100 }
101 }
102
103 return true;
104}
105
106bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
Nick Desaulniers5277b3f2019-04-10 16:38:43 +0000107 unsigned OpNo,
Alex Bradbury9330e642018-01-10 20:05:09 +0000108 const char *ExtraCode,
109 raw_ostream &OS) {
Alex Bradbury9330e642018-01-10 20:05:09 +0000110 if (!ExtraCode) {
111 const MachineOperand &MO = MI->getOperand(OpNo);
112 // For now, we only support register memory operands in registers and
113 // assume there is no addend
114 if (!MO.isReg())
115 return true;
116
117 OS << "0(" << RISCVInstPrinter::getRegisterName(MO.getReg()) << ")";
118 return false;
119 }
120
Nick Desaulniers5277b3f2019-04-10 16:38:43 +0000121 return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
Alex Bradbury9330e642018-01-10 20:05:09 +0000122}
123
Alex Bradbury89718422017-10-19 21:37:38 +0000124// Force static initialization.
125extern "C" void LLVMInitializeRISCVAsmPrinter() {
126 RegisterAsmPrinter<RISCVAsmPrinter> X(getTheRISCV32Target());
127 RegisterAsmPrinter<RISCVAsmPrinter> Y(getTheRISCV64Target());
128}