LLVM  12.0.0git
RISCVAsmPrinter.cpp
Go to the documentation of this file.
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 
17 #include "RISCV.h"
18 #include "RISCVTargetMachine.h"
20 #include "llvm/ADT/Statistic.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"
32 using namespace llvm;
33 
34 #define DEBUG_TYPE "asm-printer"
35 
36 STATISTIC(RISCVNumInstrsCompressed,
37  "Number of RISC-V Compressed instructions emitted");
38 
39 namespace {
40 class RISCVAsmPrinter : public AsmPrinter {
41  const MCSubtargetInfo *STI;
42 
43 public:
44  explicit RISCVAsmPrinter(TargetMachine &TM,
45  std::unique_ptr<MCStreamer> Streamer)
46  : AsmPrinter(TM, std::move(Streamer)), STI(TM.getMCSubtargetInfo()) {}
47 
48  StringRef getPassName() const override { return "RISCV Assembly Printer"; }
49 
50  bool runOnMachineFunction(MachineFunction &MF) override;
51 
52  void emitInstruction(const MachineInstr *MI) override;
53 
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;
58 
59  void EmitToStreamer(MCStreamer &S, const MCInst &Inst);
60  bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
61  const MachineInstr *MI);
62 
63  // Wrapper needed for tblgenned pseudo lowering.
64  bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const {
65  return LowerRISCVMachineOperandToMCOperand(MO, MCOp, *this);
66  }
67 
68  void emitStartOfAsmFile(Module &M) override;
69  void emitEndOfAsmFile(Module &M) override;
70 
71 private:
72  void emitAttributes();
73 };
74 }
75 
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);
84 }
85 
86 // Simple pseudo-instructions have their lowering (with expansion to real
87 // instructions) auto-generated.
88 #include "RISCVGenMCPseudoLowering.inc"
89 
90 void RISCVAsmPrinter::emitInstruction(const MachineInstr *MI) {
91  // Do any auto-generated pseudo lowerings.
92  if (emitPseudoExpansionLowering(*OutStreamer, MI))
93  return;
94 
95  MCInst TmpInst;
96  LowerRISCVMachineInstrToMCInst(MI, TmpInst, *this);
97  EmitToStreamer(*OutStreamer, TmpInst);
98 }
99 
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;
105 
106  const MachineOperand &MO = MI->getOperand(OpNo);
107  if (ExtraCode && ExtraCode[0]) {
108  if (ExtraCode[1] != 0)
109  return true; // Unknown modifier.
110 
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;
118  }
119  break;
120  case 'i': // Literal 'i' if operand is not a register.
121  if (!MO.isReg())
122  OS << 'i';
123  return false;
124  }
125  }
126 
127  switch (MO.getType()) {
129  OS << MO.getImm();
130  return false;
133  return false;
135  PrintSymbolOperand(MO, OS);
136  return false;
138  MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());
139  Sym->print(OS, MAI);
140  return false;
141  }
142  default:
143  break;
144  }
145 
146  return true;
147 }
148 
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;
159 
160  OS << "0(" << RISCVInstPrinter::getRegisterName(MO.getReg()) << ")";
161  return false;
162  }
163 
164  return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
165 }
166 
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());
173  STI = &NewSTI;
174 
175  SetupMachineFunction(MF);
176  emitFunctionBody();
177  return false;
178 }
179 
180 void RISCVAsmPrinter::emitStartOfAsmFile(Module &M) {
181  if (TM.getTargetTriple().isOSBinFormatELF())
182  emitAttributes();
183 }
184 
185 void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) {
186  RISCVTargetStreamer &RTS =
187  static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
188 
189  if (TM.getTargetTriple().isOSBinFormatELF())
191 }
192 
193 void RISCVAsmPrinter::emitAttributes() {
194  RISCVTargetStreamer &RTS =
195  static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
196 
197  const Triple &TT = TM.getTargetTriple();
198  StringRef CPU = TM.getTargetCPU();
199  StringRef FS = TM.getTargetFeatureString();
200  const RISCVTargetMachine &RTM = static_cast<const RISCVTargetMachine &>(TM);
201  /* TuneCPU doesn't impact emission of ELF attributes, ELF attributes only
202  care about arch related features, so we can set TuneCPU as CPU. */
203  const RISCVSubtarget STI(TT, CPU, /*TuneCPU=*/CPU, FS, /*ABIName=*/"", RTM);
204 
205  RTS.emitTargetAttributes(STI);
206 }
207 
208 // Force static initialization.
212 }
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
This class represents lattice values for constants.
Definition: AllocatorList.h:23
void setFeatureBits(const FeatureBitset &FeatureBits_)
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:67
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmPrinter()
STATISTIC(NumFunctions, "Total number of functions")
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
static const char * getRegisterName(unsigned RegNo)
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
Definition: BitVector.h:941
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
const FeatureBitset & getFeatureBits() const
Target & getTheRISCV32Target()
void LowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, const AsmPrinter &AP)
RegisterAsmPrinter - Helper template for registering a target specific assembly printer, for use in the target machine initialization function.
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:158
Address of a global value.
Streaming machine code generation interface.
Definition: MCStreamer.h:197
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Target & getTheRISCV64Target()
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:81
Address of a basic block.
void emitTargetAttributes(const MCSubtargetInfo &STI)
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:45
MachineOperand class - Representation of each machine instruction operand.
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
Definition: AsmPrinter.cpp:235
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant...
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:131
int64_t getImm() const
virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant as...
Representation of each machine instruction.
Definition: MachineInstr.h:62
const BlockAddress * getBlockAddress() const
bool LowerRISCVMachineOperandToMCOperand(const MachineOperand &MO, MCOperand &MCOp, const AsmPrinter &AP)
Generic base class for all target subtargets.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:50
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:66
IRTranslator LLVM IR MI
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1556
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
Register getReg() const
getReg - Returns the register number.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:485
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:34
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition: MCSymbol.cpp:59