LLVM  15.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"
30 #include "llvm/MC/TargetRegistry.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 *MCSTI;
42  const RISCVSubtarget *STI;
43 
44 public:
45  explicit RISCVAsmPrinter(TargetMachine &TM,
46  std::unique_ptr<MCStreamer> Streamer)
47  : AsmPrinter(TM, std::move(Streamer)), MCSTI(TM.getMCSubtargetInfo()) {}
48 
49  StringRef getPassName() const override { return "RISCV Assembly Printer"; }
50 
51  bool runOnMachineFunction(MachineFunction &MF) override;
52 
53  void emitInstruction(const MachineInstr *MI) override;
54 
55  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
56  const char *ExtraCode, raw_ostream &OS) override;
57  bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
58  const char *ExtraCode, raw_ostream &OS) override;
59 
60  void EmitToStreamer(MCStreamer &S, const MCInst &Inst);
61  bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
62  const MachineInstr *MI);
63 
64  // Wrapper needed for tblgenned pseudo lowering.
65  bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const {
66  return lowerRISCVMachineOperandToMCOperand(MO, MCOp, *this);
67  }
68 
69  void emitStartOfAsmFile(Module &M) override;
70  void emitEndOfAsmFile(Module &M) override;
71 
72  void emitFunctionEntryLabel() override;
73 
74 private:
75  void emitAttributes();
76 };
77 }
78 
79 #define GEN_COMPRESS_INSTR
80 #include "RISCVGenCompressInstEmitter.inc"
81 void RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
82  MCInst CInst;
83  bool Res = compressInst(CInst, Inst, *STI, OutStreamer->getContext());
84  if (Res)
85  ++RISCVNumInstrsCompressed;
86  AsmPrinter::EmitToStreamer(*OutStreamer, Res ? CInst : Inst);
87 }
88 
89 // Simple pseudo-instructions have their lowering (with expansion to real
90 // instructions) auto-generated.
91 #include "RISCVGenMCPseudoLowering.inc"
92 
93 void RISCVAsmPrinter::emitInstruction(const MachineInstr *MI) {
94  // Do any auto-generated pseudo lowerings.
95  if (emitPseudoExpansionLowering(*OutStreamer, MI))
96  return;
97 
98  MCInst TmpInst;
99  if (!lowerRISCVMachineInstrToMCInst(MI, TmpInst, *this))
100  EmitToStreamer(*OutStreamer, TmpInst);
101 }
102 
103 bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
104  const char *ExtraCode, raw_ostream &OS) {
105  // First try the generic code, which knows about modifiers like 'c' and 'n'.
106  if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
107  return false;
108 
109  const MachineOperand &MO = MI->getOperand(OpNo);
110  if (ExtraCode && ExtraCode[0]) {
111  if (ExtraCode[1] != 0)
112  return true; // Unknown modifier.
113 
114  switch (ExtraCode[0]) {
115  default:
116  return true; // Unknown modifier.
117  case 'z': // Print zero register if zero, regular printing otherwise.
118  if (MO.isImm() && MO.getImm() == 0) {
119  OS << RISCVInstPrinter::getRegisterName(RISCV::X0);
120  return false;
121  }
122  break;
123  case 'i': // Literal 'i' if operand is not a register.
124  if (!MO.isReg())
125  OS << 'i';
126  return false;
127  }
128  }
129 
130  switch (MO.getType()) {
132  OS << MO.getImm();
133  return false;
136  return false;
138  PrintSymbolOperand(MO, OS);
139  return false;
141  MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());
142  Sym->print(OS, MAI);
143  return false;
144  }
145  default:
146  break;
147  }
148 
149  return true;
150 }
151 
152 bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
153  unsigned OpNo,
154  const char *ExtraCode,
155  raw_ostream &OS) {
156  if (!ExtraCode) {
157  const MachineOperand &MO = MI->getOperand(OpNo);
158  // For now, we only support register memory operands in registers and
159  // assume there is no addend
160  if (!MO.isReg())
161  return true;
162 
163  OS << "0(" << RISCVInstPrinter::getRegisterName(MO.getReg()) << ")";
164  return false;
165  }
166 
167  return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
168 }
169 
170 bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
171  // Set the current MCSubtargetInfo to a copy which has the correct
172  // feature bits for the current MachineFunction
173  MCSubtargetInfo &NewSTI =
174  OutStreamer->getContext().getSubtargetCopy(*TM.getMCSubtargetInfo());
176  MCSTI = &NewSTI;
177  STI = &MF.getSubtarget<RISCVSubtarget>();
178 
179  SetupMachineFunction(MF);
180  emitFunctionBody();
181  return false;
182 }
183 
184 void RISCVAsmPrinter::emitStartOfAsmFile(Module &M) {
185  if (TM.getTargetTriple().isOSBinFormatELF())
186  emitAttributes();
187 }
188 
189 void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) {
190  RISCVTargetStreamer &RTS =
191  static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
192 
193  if (TM.getTargetTriple().isOSBinFormatELF())
195 }
196 
197 void RISCVAsmPrinter::emitAttributes() {
198  RISCVTargetStreamer &RTS =
199  static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
200  RTS.emitTargetAttributes(*MCSTI);
201 }
202 
203 void RISCVAsmPrinter::emitFunctionEntryLabel() {
205  RISCVTargetStreamer &RTS =
206  static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
207  RTS.setTargetABI(STI->getTargetABI());
208 }
209 
210 // Force static initialization.
214 }
AsmPrinter.h
llvm::MachineOperand::MO_BlockAddress
@ MO_BlockAddress
Address of a basic block.
Definition: MachineOperand.h:62
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:104
MachineInstr.h
llvm::MachineOperand::MO_Immediate
@ MO_Immediate
Immediate operand.
Definition: MachineOperand.h:52
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::MCSymbol
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
llvm::RISCVTargetStreamer::emitTargetAttributes
void emitTargetAttributes(const MCSubtargetInfo &STI)
Definition: RISCVTargetStreamer.cpp:47
llvm::getTheRISCV64Target
Target & getTheRISCV64Target()
Definition: RISCVTargetInfo.cpp:18
Statistic.h
llvm::MachineOperand::getBlockAddress
const BlockAddress * getBlockAddress() const
Definition: MachineOperand.h:577
RISCVMCExpr.h
llvm::MCSubtargetInfo::setFeatureBits
void setFeatureBits(const FeatureBitset &FeatureBits_)
Definition: MCSubtargetInfo.h:113
llvm::MCInst
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
llvm::MachineOperand::MO_Register
@ MO_Register
Register operand.
Definition: MachineOperand.h:51
llvm::AsmPrinter::EmitToStreamer
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
Definition: AsmPrinter.cpp:401
RISCVInstPrinter.h
llvm::MCStreamer
Streaming machine code generation interface.
Definition: MCStreamer.h:212
llvm::MachineOperand::MO_GlobalAddress
@ MO_GlobalAddress
Address of a global value.
Definition: MachineOperand.h:61
llvm::MachineOperand::getImm
int64_t getImm() const
Definition: MachineOperand.h:546
llvm::AsmPrinter::PrintAsmMemoryOperand
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...
Definition: AsmPrinterInlineAsm.cpp:509
Y
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
llvm::lowerRISCVMachineInstrToMCInst
bool lowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, AsmPrinter &AP)
Definition: RISCVMCInstLower.cpp:213
llvm::AsmPrinter::emitFunctionEntryLabel
virtual void emitFunctionEntryLabel()
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
Definition: AsmPrinter.cpp:1029
MCSymbol.h
MCInst.h
llvm::MachineOperand
MachineOperand class - Representation of each machine instruction operand.
Definition: MachineOperand.h:48
llvm::MCSubtargetInfo::getFeatureBits
const FeatureBitset & getFeatureBits() const
Definition: MCSubtargetInfo.h:112
llvm::STATISTIC
STATISTIC(NumFunctions, "Total number of functions")
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:54
llvm::MCSymbol::print
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition: MCSymbol.cpp:58
X
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
llvm::MachineFunction::getSubtarget
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Definition: MachineFunction.h:656
RISCVTargetStreamer.h
llvm::MachineOperand::isReg
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Definition: MachineOperand.h:320
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:66
LLVM_EXTERNAL_VISIBILITY
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:126
llvm::lowerRISCVMachineOperandToMCOperand
bool lowerRISCVMachineOperandToMCOperand(const MachineOperand &MO, MCOperand &MCOp, const AsmPrinter &AP)
Definition: RISCVMCInstLower.cpp:90
MachineConstantPool.h
llvm::MachineOperand::getType
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Definition: MachineOperand.h:218
MachineFunctionPass.h
llvm::RISCVSubtarget
Definition: RISCVSubtarget.h:35
llvm::TargetMachine
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:77
llvm::move
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:1675
MachineModuleInfo.h
llvm::MachineOperand::getReg
Register getReg() const
getReg - Returns the register number.
Definition: MachineOperand.h:359
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
RISCV.h
llvm::MachineFunction
Definition: MachineFunction.h:257
llvm::RISCVTargetStreamer::finishAttributeSection
virtual void finishAttributeSection()
Definition: RISCVTargetStreamer.cpp:36
LLVMInitializeRISCVAsmPrinter
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmPrinter()
Definition: RISCVAsmPrinter.cpp:211
MCAsmInfo.h
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::RISCVTargetStreamer::setTargetABI
void setTargetABI(RISCVABI::ABI ABI)
Definition: RISCVTargetStreamer.cpp:42
std
Definition: BitVector.h:851
llvm::AsmPrinter
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:81
llvm::MachineOperand::isImm
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Definition: MachineOperand.h:322
MCStreamer.h
TM
const char LLVMTargetMachineRef TM
Definition: PassBuilderBindings.cpp:47
RISCVTargetInfo.h
llvm::MCOperand
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
llvm::RISCVTargetStreamer
Definition: RISCVTargetStreamer.h:20
llvm::RISCVInstPrinter::getRegisterName
static const char * getRegisterName(unsigned RegNo)
Definition: RISCVInstPrinter.cpp:197
llvm::RegisterAsmPrinter
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...
Definition: TargetRegistry.h:1381
raw_ostream.h
TargetRegistry.h
llvm::MCSubtargetInfo
Generic base class for all target subtargets.
Definition: MCSubtargetInfo.h:76
llvm::getTheRISCV32Target
Target & getTheRISCV32Target()
Definition: RISCVTargetInfo.cpp:13
llvm::AsmPrinter::PrintAsmOperand
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.
Definition: AsmPrinterInlineAsm.cpp:467
RISCVTargetMachine.h