]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
Fix a memory leak in if_delgroups() introduced in r334118.
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / RISCV / RISCVAsmPrinter.cpp
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.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "RISCV.h"
15 #include "MCTargetDesc/RISCVInstPrinter.h"
16 #include "MCTargetDesc/RISCVMCExpr.h"
17 #include "RISCVTargetMachine.h"
18 #include "TargetInfo/RISCVTargetInfo.h"
19 #include "llvm/CodeGen/AsmPrinter.h"
20 #include "llvm/CodeGen/MachineConstantPool.h"
21 #include "llvm/CodeGen/MachineFunctionPass.h"
22 #include "llvm/CodeGen/MachineInstr.h"
23 #include "llvm/CodeGen/MachineModuleInfo.h"
24 #include "llvm/MC/MCAsmInfo.h"
25 #include "llvm/MC/MCInst.h"
26 #include "llvm/MC/MCStreamer.h"
27 #include "llvm/MC/MCSymbol.h"
28 #include "llvm/Support/TargetRegistry.h"
29 #include "llvm/Support/raw_ostream.h"
30 using namespace llvm;
31
32 #define DEBUG_TYPE "asm-printer"
33
34 namespace {
35 class RISCVAsmPrinter : public AsmPrinter {
36 public:
37   explicit RISCVAsmPrinter(TargetMachine &TM,
38                            std::unique_ptr<MCStreamer> Streamer)
39       : AsmPrinter(TM, std::move(Streamer)) {}
40
41   StringRef getPassName() const override { return "RISCV Assembly Printer"; }
42
43   void EmitInstruction(const MachineInstr *MI) override;
44
45   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
46                        const char *ExtraCode, raw_ostream &OS) override;
47   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
48                              const char *ExtraCode, raw_ostream &OS) override;
49
50   void EmitToStreamer(MCStreamer &S, const MCInst &Inst);
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 #define GEN_COMPRESS_INSTR
62 #include "RISCVGenCompressInstEmitter.inc"
63 void RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
64   MCInst CInst;
65   bool Res = compressInst(CInst, Inst, *TM.getMCSubtargetInfo(),
66                           OutStreamer->getContext());
67   AsmPrinter::EmitToStreamer(*OutStreamer, Res ? CInst : Inst);
68 }
69
70 // Simple pseudo-instructions have their lowering (with expansion to real
71 // instructions) auto-generated.
72 #include "RISCVGenMCPseudoLowering.inc"
73
74 void RISCVAsmPrinter::EmitInstruction(const MachineInstr *MI) {
75   // Do any auto-generated pseudo lowerings.
76   if (emitPseudoExpansionLowering(*OutStreamer, MI))
77     return;
78
79   MCInst TmpInst;
80   LowerRISCVMachineInstrToMCInst(MI, TmpInst, *this);
81   EmitToStreamer(*OutStreamer, TmpInst);
82 }
83
84 bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
85                                       const char *ExtraCode, raw_ostream &OS) {
86   // First try the generic code, which knows about modifiers like 'c' and 'n'.
87   if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
88     return false;
89
90   const MachineOperand &MO = MI->getOperand(OpNo);
91   if (ExtraCode && ExtraCode[0]) {
92     if (ExtraCode[1] != 0)
93       return true; // Unknown modifier.
94
95     switch (ExtraCode[0]) {
96     default:
97       return true; // Unknown modifier.
98     case 'z':      // Print zero register if zero, regular printing otherwise.
99       if (MO.isImm() && MO.getImm() == 0) {
100         OS << RISCVInstPrinter::getRegisterName(RISCV::X0);
101         return false;
102       }
103       break;
104     case 'i': // Literal 'i' if operand is not a register.
105       if (!MO.isReg())
106         OS << 'i';
107       return false;
108     }
109   }
110
111   switch (MO.getType()) {
112   case MachineOperand::MO_Immediate:
113     OS << MO.getImm();
114     return false;
115   case MachineOperand::MO_Register:
116     OS << RISCVInstPrinter::getRegisterName(MO.getReg());
117     return false;
118   default:
119     break;
120   }
121
122   return true;
123 }
124
125 bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
126                                             unsigned OpNo,
127                                             const char *ExtraCode,
128                                             raw_ostream &OS) {
129   if (!ExtraCode) {
130     const MachineOperand &MO = MI->getOperand(OpNo);
131     // For now, we only support register memory operands in registers and
132     // assume there is no addend
133     if (!MO.isReg())
134       return true;
135
136     OS << "0(" << RISCVInstPrinter::getRegisterName(MO.getReg()) << ")";
137     return false;
138   }
139
140   return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
141 }
142
143 // Force static initialization.
144 extern "C" void LLVMInitializeRISCVAsmPrinter() {
145   RegisterAsmPrinter<RISCVAsmPrinter> X(getTheRISCV32Target());
146   RegisterAsmPrinter<RISCVAsmPrinter> Y(getTheRISCV64Target());
147 }