[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / lib / Target / RISCV / RISCVAsmPrinter.cpp
blobbdf30f8eb1b377888e75d23de6ec82311baa1357
1 //===-- RISCVAsmPrinter.cpp - RISCV LLVM assembly writer ------------------===//
2 //
3 // 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
6 //
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.
12 //===----------------------------------------------------------------------===//
14 #include "MCTargetDesc/RISCVInstPrinter.h"
15 #include "MCTargetDesc/RISCVMCExpr.h"
16 #include "MCTargetDesc/RISCVTargetStreamer.h"
17 #include "RISCV.h"
18 #include "RISCVTargetMachine.h"
19 #include "TargetInfo/RISCVTargetInfo.h"
20 #include "llvm/ADT/Statistic.h"
21 #include "llvm/CodeGen/AsmPrinter.h"
22 #include "llvm/CodeGen/MachineConstantPool.h"
23 #include "llvm/CodeGen/MachineFunctionPass.h"
24 #include "llvm/CodeGen/MachineInstr.h"
25 #include "llvm/CodeGen/MachineModuleInfo.h"
26 #include "llvm/MC/MCAsmInfo.h"
27 #include "llvm/MC/MCInst.h"
28 #include "llvm/MC/MCStreamer.h"
29 #include "llvm/MC/MCSymbol.h"
30 #include "llvm/Support/TargetRegistry.h"
31 #include "llvm/Support/raw_ostream.h"
32 using namespace llvm;
34 #define DEBUG_TYPE "asm-printer"
36 STATISTIC(RISCVNumInstrsCompressed,
37 "Number of RISC-V Compressed instructions emitted");
39 namespace {
40 class RISCVAsmPrinter : public AsmPrinter {
41 const MCSubtargetInfo *STI;
43 public:
44 explicit RISCVAsmPrinter(TargetMachine &TM,
45 std::unique_ptr<MCStreamer> Streamer)
46 : AsmPrinter(TM, std::move(Streamer)), STI(TM.getMCSubtargetInfo()) {}
48 StringRef getPassName() const override { return "RISCV Assembly Printer"; }
50 bool runOnMachineFunction(MachineFunction &MF) override;
52 void emitInstruction(const MachineInstr *MI) override;
54 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
55 const char *ExtraCode, raw_ostream &OS) override;
56 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
57 const char *ExtraCode, raw_ostream &OS) override;
59 void EmitToStreamer(MCStreamer &S, const MCInst &Inst);
60 bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
61 const MachineInstr *MI);
63 // Wrapper needed for tblgenned pseudo lowering.
64 bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const {
65 return LowerRISCVMachineOperandToMCOperand(MO, MCOp, *this);
68 void emitStartOfAsmFile(Module &M) override;
69 void emitEndOfAsmFile(Module &M) override;
71 private:
72 void emitAttributes();
76 #define GEN_COMPRESS_INSTR
77 #include "RISCVGenCompressInstEmitter.inc"
78 void RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
79 MCInst CInst;
80 bool Res = compressInst(CInst, Inst, *STI, OutStreamer->getContext());
81 if (Res)
82 ++RISCVNumInstrsCompressed;
83 AsmPrinter::EmitToStreamer(*OutStreamer, Res ? CInst : Inst);
86 // Simple pseudo-instructions have their lowering (with expansion to real
87 // instructions) auto-generated.
88 #include "RISCVGenMCPseudoLowering.inc"
90 void RISCVAsmPrinter::emitInstruction(const MachineInstr *MI) {
91 // Do any auto-generated pseudo lowerings.
92 if (emitPseudoExpansionLowering(*OutStreamer, MI))
93 return;
95 MCInst TmpInst;
96 if (!lowerRISCVMachineInstrToMCInst(MI, TmpInst, *this))
97 EmitToStreamer(*OutStreamer, TmpInst);
100 bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
101 const char *ExtraCode, raw_ostream &OS) {
102 // First try the generic code, which knows about modifiers like 'c' and 'n'.
103 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
104 return false;
106 const MachineOperand &MO = MI->getOperand(OpNo);
107 if (ExtraCode && ExtraCode[0]) {
108 if (ExtraCode[1] != 0)
109 return true; // Unknown modifier.
111 switch (ExtraCode[0]) {
112 default:
113 return true; // Unknown modifier.
114 case 'z': // Print zero register if zero, regular printing otherwise.
115 if (MO.isImm() && MO.getImm() == 0) {
116 OS << RISCVInstPrinter::getRegisterName(RISCV::X0);
117 return false;
119 break;
120 case 'i': // Literal 'i' if operand is not a register.
121 if (!MO.isReg())
122 OS << 'i';
123 return false;
127 switch (MO.getType()) {
128 case MachineOperand::MO_Immediate:
129 OS << MO.getImm();
130 return false;
131 case MachineOperand::MO_Register:
132 OS << RISCVInstPrinter::getRegisterName(MO.getReg());
133 return false;
134 case MachineOperand::MO_GlobalAddress:
135 PrintSymbolOperand(MO, OS);
136 return false;
137 case MachineOperand::MO_BlockAddress: {
138 MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());
139 Sym->print(OS, MAI);
140 return false;
142 default:
143 break;
146 return true;
149 bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
150 unsigned OpNo,
151 const char *ExtraCode,
152 raw_ostream &OS) {
153 if (!ExtraCode) {
154 const MachineOperand &MO = MI->getOperand(OpNo);
155 // For now, we only support register memory operands in registers and
156 // assume there is no addend
157 if (!MO.isReg())
158 return true;
160 OS << "0(" << RISCVInstPrinter::getRegisterName(MO.getReg()) << ")";
161 return false;
164 return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
167 bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
168 // Set the current MCSubtargetInfo to a copy which has the correct
169 // feature bits for the current MachineFunction
170 MCSubtargetInfo &NewSTI =
171 OutStreamer->getContext().getSubtargetCopy(*TM.getMCSubtargetInfo());
172 NewSTI.setFeatureBits(MF.getSubtarget().getFeatureBits());
173 STI = &NewSTI;
175 SetupMachineFunction(MF);
176 emitFunctionBody();
177 return false;
180 void RISCVAsmPrinter::emitStartOfAsmFile(Module &M) {
181 if (TM.getTargetTriple().isOSBinFormatELF())
182 emitAttributes();
185 void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) {
186 RISCVTargetStreamer &RTS =
187 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
189 if (TM.getTargetTriple().isOSBinFormatELF())
190 RTS.finishAttributeSection();
193 void RISCVAsmPrinter::emitAttributes() {
194 RISCVTargetStreamer &RTS =
195 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
196 RTS.emitTargetAttributes(*STI);
199 // Force static initialization.
200 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmPrinter() {
201 RegisterAsmPrinter<RISCVAsmPrinter> X(getTheRISCV32Target());
202 RegisterAsmPrinter<RISCVAsmPrinter> Y(getTheRISCV64Target());