LLVM 17.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"
19#include "RISCVTargetMachine.h"
21#include "llvm/ADT/Statistic.h"
28#include "llvm/MC/MCAsmInfo.h"
29#include "llvm/MC/MCContext.h"
30#include "llvm/MC/MCInst.h"
34#include "llvm/MC/MCStreamer.h"
35#include "llvm/MC/MCSymbol.h"
39
40using namespace llvm;
41
42#define DEBUG_TYPE "asm-printer"
43
44STATISTIC(RISCVNumInstrsCompressed,
45 "Number of RISC-V Compressed instructions emitted");
46
47namespace {
48class RISCVAsmPrinter : public AsmPrinter {
49 const RISCVSubtarget *STI;
50
51public:
52 explicit RISCVAsmPrinter(TargetMachine &TM,
53 std::unique_ptr<MCStreamer> Streamer)
54 : AsmPrinter(TM, std::move(Streamer)) {}
55
56 StringRef getPassName() const override { return "RISCV Assembly Printer"; }
57
58 bool runOnMachineFunction(MachineFunction &MF) override;
59
60 void emitInstruction(const MachineInstr *MI) override;
61
62 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
63 const char *ExtraCode, raw_ostream &OS) override;
64 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
65 const char *ExtraCode, raw_ostream &OS) override;
66
67 void EmitToStreamer(MCStreamer &S, const MCInst &Inst);
68 bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
69 const MachineInstr *MI);
70
71 typedef std::tuple<unsigned, uint32_t> HwasanMemaccessTuple;
72 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
73 void LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI);
74 void EmitHwasanMemaccessSymbols(Module &M);
75
76 // Wrapper needed for tblgenned pseudo lowering.
77 bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const {
78 return lowerRISCVMachineOperandToMCOperand(MO, MCOp, *this);
79 }
80
81 void emitStartOfAsmFile(Module &M) override;
82 void emitEndOfAsmFile(Module &M) override;
83
84 void emitFunctionEntryLabel() override;
85
86private:
87 void emitAttributes();
88};
89}
90
91void RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
92 MCInst CInst;
93 bool Res = RISCVRVC::compress(CInst, Inst, *STI);
94 if (Res)
95 ++RISCVNumInstrsCompressed;
96 AsmPrinter::EmitToStreamer(*OutStreamer, Res ? CInst : Inst);
97}
98
99// Simple pseudo-instructions have their lowering (with expansion to real
100// instructions) auto-generated.
101#include "RISCVGenMCPseudoLowering.inc"
102
103void RISCVAsmPrinter::emitInstruction(const MachineInstr *MI) {
104 RISCV_MC::verifyInstructionPredicates(MI->getOpcode(),
105 getSubtargetInfo().getFeatureBits());
106
107 // Do any auto-generated pseudo lowerings.
108 if (emitPseudoExpansionLowering(*OutStreamer, MI))
109 return;
110
111
112 switch (MI->getOpcode()) {
113 case RISCV::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
114 LowerHWASAN_CHECK_MEMACCESS(*MI);
115 return;
116 case RISCV::PseudoRVVInitUndefM1:
117 case RISCV::PseudoRVVInitUndefM2:
118 case RISCV::PseudoRVVInitUndefM4:
119 case RISCV::PseudoRVVInitUndefM8:
120 return;
121 }
122
123 MCInst TmpInst;
124 if (!lowerRISCVMachineInstrToMCInst(MI, TmpInst, *this))
125 EmitToStreamer(*OutStreamer, TmpInst);
126}
127
128bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
129 const char *ExtraCode, raw_ostream &OS) {
130 // First try the generic code, which knows about modifiers like 'c' and 'n'.
131 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
132 return false;
133
134 const MachineOperand &MO = MI->getOperand(OpNo);
135 if (ExtraCode && ExtraCode[0]) {
136 if (ExtraCode[1] != 0)
137 return true; // Unknown modifier.
138
139 switch (ExtraCode[0]) {
140 default:
141 return true; // Unknown modifier.
142 case 'z': // Print zero register if zero, regular printing otherwise.
143 if (MO.isImm() && MO.getImm() == 0) {
145 return false;
146 }
147 break;
148 case 'i': // Literal 'i' if operand is not a register.
149 if (!MO.isReg())
150 OS << 'i';
151 return false;
152 }
153 }
154
155 switch (MO.getType()) {
157 OS << MO.getImm();
158 return false;
161 return false;
163 PrintSymbolOperand(MO, OS);
164 return false;
166 MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());
167 Sym->print(OS, MAI);
168 return false;
169 }
170 default:
171 break;
172 }
173
174 return true;
175}
176
177bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
178 unsigned OpNo,
179 const char *ExtraCode,
180 raw_ostream &OS) {
181 if (ExtraCode)
182 return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
183
184 const MachineOperand &MO = MI->getOperand(OpNo);
185 // For now, we only support register memory operands in registers and
186 // assume there is no addend
187 if (!MO.isReg())
188 return true;
189
190 OS << "0(" << RISCVInstPrinter::getRegisterName(MO.getReg()) << ")";
191 return false;
192}
193
194bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
195 STI = &MF.getSubtarget<RISCVSubtarget>();
196
197 SetupMachineFunction(MF);
198 emitFunctionBody();
199 return false;
200}
201
202void RISCVAsmPrinter::emitStartOfAsmFile(Module &M) {
204 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
205 if (const MDString *ModuleTargetABI =
206 dyn_cast_or_null<MDString>(M.getModuleFlag("target-abi")))
207 RTS.setTargetABI(RISCVABI::getTargetABI(ModuleTargetABI->getString()));
208 if (TM.getTargetTriple().isOSBinFormatELF())
209 emitAttributes();
210}
211
212void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) {
214 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
215
216 if (TM.getTargetTriple().isOSBinFormatELF())
218 EmitHwasanMemaccessSymbols(M);
219}
220
221void RISCVAsmPrinter::emitAttributes() {
223 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
224 // Use MCSubtargetInfo from TargetMachine. Individual functions may have
225 // attributes that differ from other functions in the module and we have no
226 // way to know which function is correct.
227 RTS.emitTargetAttributes(*TM.getMCSubtargetInfo());
228}
229
230void RISCVAsmPrinter::emitFunctionEntryLabel() {
231 const auto *RMFI = MF->getInfo<RISCVMachineFunctionInfo>();
232 if (RMFI->isVectorCall()) {
233 auto &RTS =
234 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
235 RTS.emitDirectiveVariantCC(*CurrentFnSym);
236 }
238}
239
240// Force static initialization.
244}
245
246void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {
247 Register Reg = MI.getOperand(0).getReg();
248 uint32_t AccessInfo = MI.getOperand(1).getImm();
249 MCSymbol *&Sym =
250 HwasanMemaccessSymbols[HwasanMemaccessTuple(Reg, AccessInfo)];
251 if (!Sym) {
252 // FIXME: Make this work on non-ELF.
253 if (!TM.getTargetTriple().isOSBinFormatELF())
254 report_fatal_error("llvm.hwasan.check.memaccess only supported on ELF");
255
256 std::string SymName = "__hwasan_check_x" + utostr(Reg - RISCV::X0) + "_" +
257 utostr(AccessInfo) + "_short";
258 Sym = OutContext.getOrCreateSymbol(SymName);
259 }
260 auto Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, OutContext);
261 auto Expr = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, OutContext);
262
263 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr));
264}
265
266void RISCVAsmPrinter::EmitHwasanMemaccessSymbols(Module &M) {
267 if (HwasanMemaccessSymbols.empty())
268 return;
269
270 assert(TM.getTargetTriple().isOSBinFormatELF());
271 // Use MCSubtargetInfo from TargetMachine. Individual functions may have
272 // attributes that differ from other functions in the module and we have no
273 // way to know which function is correct.
274 const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo();
275
276 MCSymbol *HwasanTagMismatchV2Sym =
277 OutContext.getOrCreateSymbol("__hwasan_tag_mismatch_v2");
278 // Annotate symbol as one having incompatible calling convention, so
279 // run-time linkers can instead eagerly bind this function.
280 auto &RTS =
281 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
282 RTS.emitDirectiveVariantCC(*HwasanTagMismatchV2Sym);
283
284 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
285 MCSymbolRefExpr::create(HwasanTagMismatchV2Sym, OutContext);
286 auto Expr = RISCVMCExpr::create(HwasanTagMismatchV2Ref,
287 RISCVMCExpr::VK_RISCV_CALL, OutContext);
288
289 for (auto &P : HwasanMemaccessSymbols) {
290 unsigned Reg = std::get<0>(P.first);
291 uint32_t AccessInfo = std::get<1>(P.first);
292 MCSymbol *Sym = P.second;
293
294 unsigned Size =
295 1 << ((AccessInfo >> HWASanAccessInfo::AccessSizeShift) & 0xf);
296 OutStreamer->switchSection(OutContext.getELFSection(
297 ".text.hot", ELF::SHT_PROGBITS,
299 /*IsComdat=*/true));
300
301 OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
302 OutStreamer->emitSymbolAttribute(Sym, MCSA_Weak);
303 OutStreamer->emitSymbolAttribute(Sym, MCSA_Hidden);
304 OutStreamer->emitLabel(Sym);
305
306 // Extract shadow offset from ptr
307 OutStreamer->emitInstruction(
308 MCInstBuilder(RISCV::SLLI).addReg(RISCV::X6).addReg(Reg).addImm(8),
309 MCSTI);
310 OutStreamer->emitInstruction(MCInstBuilder(RISCV::SRLI)
311 .addReg(RISCV::X6)
312 .addReg(RISCV::X6)
313 .addImm(12),
314 MCSTI);
315 // load shadow tag in X6, X5 contains shadow base
316 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADD)
317 .addReg(RISCV::X6)
318 .addReg(RISCV::X5)
319 .addReg(RISCV::X6),
320 MCSTI);
321 OutStreamer->emitInstruction(
322 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
323 MCSTI);
324 // Extract tag from X5 and compare it with loaded tag from shadow
325 OutStreamer->emitInstruction(
326 MCInstBuilder(RISCV::SRLI).addReg(RISCV::X7).addReg(Reg).addImm(56),
327 MCSTI);
328 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
329 // X7 contains tag from memory, while X6 contains tag from the pointer
330 OutStreamer->emitInstruction(
331 MCInstBuilder(RISCV::BNE)
332 .addReg(RISCV::X7)
333 .addReg(RISCV::X6)
334 .addExpr(MCSymbolRefExpr::create(HandleMismatchOrPartialSym,
335 OutContext)),
336 MCSTI);
337 MCSymbol *ReturnSym = OutContext.createTempSymbol();
338 OutStreamer->emitLabel(ReturnSym);
339 OutStreamer->emitInstruction(MCInstBuilder(RISCV::JALR)
340 .addReg(RISCV::X0)
341 .addReg(RISCV::X1)
342 .addImm(0),
343 MCSTI);
344 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
345
346 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI)
347 .addReg(RISCV::X28)
348 .addReg(RISCV::X0)
349 .addImm(16),
350 MCSTI);
351 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
352 OutStreamer->emitInstruction(
353 MCInstBuilder(RISCV::BGEU)
354 .addReg(RISCV::X6)
355 .addReg(RISCV::X28)
356 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
357 MCSTI);
358
359 OutStreamer->emitInstruction(
360 MCInstBuilder(RISCV::ANDI).addReg(RISCV::X28).addReg(Reg).addImm(0xF),
361 MCSTI);
362
363 if (Size != 1)
364 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI)
365 .addReg(RISCV::X28)
366 .addReg(RISCV::X28)
367 .addImm(Size - 1),
368 MCSTI);
369 OutStreamer->emitInstruction(
370 MCInstBuilder(RISCV::BGE)
371 .addReg(RISCV::X28)
372 .addReg(RISCV::X6)
373 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
374 MCSTI);
375
376 OutStreamer->emitInstruction(
377 MCInstBuilder(RISCV::ORI).addReg(RISCV::X6).addReg(Reg).addImm(0xF),
378 MCSTI);
379 OutStreamer->emitInstruction(
380 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
381 MCSTI);
382 OutStreamer->emitInstruction(
383 MCInstBuilder(RISCV::BEQ)
384 .addReg(RISCV::X6)
385 .addReg(RISCV::X7)
386 .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)),
387 MCSTI);
388
389 OutStreamer->emitLabel(HandleMismatchSym);
390
391 // | Previous stack frames... |
392 // +=================================+ <-- [SP + 256]
393 // | ... |
394 // | |
395 // | Stack frame space for x12 - x31.|
396 // | |
397 // | ... |
398 // +---------------------------------+ <-- [SP + 96]
399 // | Saved x11(arg1), as |
400 // | __hwasan_check_* clobbers it. |
401 // +---------------------------------+ <-- [SP + 88]
402 // | Saved x10(arg0), as |
403 // | __hwasan_check_* clobbers it. |
404 // +---------------------------------+ <-- [SP + 80]
405 // | |
406 // | Stack frame space for x9. |
407 // +---------------------------------+ <-- [SP + 72]
408 // | |
409 // | Saved x8(fp), as |
410 // | __hwasan_check_* clobbers it. |
411 // +---------------------------------+ <-- [SP + 64]
412 // | ... |
413 // | |
414 // | Stack frame space for x2 - x7. |
415 // | |
416 // | ... |
417 // +---------------------------------+ <-- [SP + 16]
418 // | Return address (x1) for caller |
419 // | of __hwasan_check_*. |
420 // +---------------------------------+ <-- [SP + 8]
421 // | Reserved place for x0, possibly |
422 // | junk, since we don't save it. |
423 // +---------------------------------+ <-- [x2 / SP]
424
425 // Adjust sp
426 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI)
427 .addReg(RISCV::X2)
428 .addReg(RISCV::X2)
429 .addImm(-256),
430 MCSTI);
431
432 // store x10(arg0) by new sp
433 OutStreamer->emitInstruction(MCInstBuilder(RISCV::SD)
434 .addReg(RISCV::X10)
435 .addReg(RISCV::X2)
436 .addImm(8 * 10),
437 MCSTI);
438 // store x11(arg1) by new sp
439 OutStreamer->emitInstruction(MCInstBuilder(RISCV::SD)
440 .addReg(RISCV::X11)
441 .addReg(RISCV::X2)
442 .addImm(8 * 11),
443 MCSTI);
444
445 // store x8(fp) by new sp
446 OutStreamer->emitInstruction(
447 MCInstBuilder(RISCV::SD).addReg(RISCV::X8).addReg(RISCV::X2).addImm(8 *
448 8),
449 MCSTI);
450 // store x1(ra) by new sp
451 OutStreamer->emitInstruction(
452 MCInstBuilder(RISCV::SD).addReg(RISCV::X1).addReg(RISCV::X2).addImm(1 *
453 8),
454 MCSTI);
455 if (Reg != RISCV::X10)
456 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI)
457 .addReg(RISCV::X10)
458 .addReg(Reg)
459 .addImm(0),
460 MCSTI);
461 OutStreamer->emitInstruction(
462 MCInstBuilder(RISCV::ADDI)
463 .addReg(RISCV::X11)
464 .addReg(RISCV::X0)
466 MCSTI);
467
468 OutStreamer->emitInstruction(MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr),
469 MCSTI);
470 }
471}
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:127
uint64_t Size
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
IRTranslator LLVM IR MI
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
#define P(N)
const char LLVMTargetMachineRef TM
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmPrinter()
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition: Statistic.h:167
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:84
virtual void emitInstruction(const MachineInstr *)
Targets should implement this to emit instructions.
Definition: AsmPrinter.h:571
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
Definition: AsmPrinter.cpp:398
virtual void emitStartOfAsmFile(Module &)
This virtual method can be overridden by targets that want to emit something at the start of their fi...
Definition: AsmPrinter.h:547
virtual void emitEndOfAsmFile(Module &)
This virtual method can be overridden by targets that want to emit something at the end of their file...
Definition: AsmPrinter.h:551
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
Definition: AsmPrinter.h:399
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...
virtual void emitFunctionEntryLabel()
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
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.
MCInstBuilder & addReg(unsigned Reg)
Add a new register operand.
Definition: MCInstBuilder.h:31
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Definition: MCInstBuilder.h:37
MCInstBuilder & addExpr(const MCExpr *Val)
Add a new MCExpr operand.
Definition: MCInstBuilder.h:55
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
Streaming machine code generation interface.
Definition: MCStreamer.h:212
Generic base class for all target subtargets.
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:192
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:386
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition: MCSymbol.cpp:58
StringRef getName() const
getName - Get the symbol name.
Definition: MCSymbol.h:203
A single uniqued string.
Definition: Metadata.h:611
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Representation of each machine instruction.
Definition: MachineInstr.h:68
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
const BlockAddress * getBlockAddress() const
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Register getReg() const
getReg - Returns the register number.
@ MO_Immediate
Immediate operand.
@ MO_GlobalAddress
Address of a global value.
@ MO_BlockAddress
Address of a basic block.
@ MO_Register
Register operand.
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
static const char * getRegisterName(MCRegister Reg)
static const RISCVMCExpr * create(const MCExpr *Expr, VariantKind Kind, MCContext &Ctx)
Definition: RISCVMCExpr.cpp:31
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
void emitTargetAttributes(const MCSubtargetInfo &STI)
virtual void emitDirectiveVariantCC(MCSymbol &Symbol)
void setTargetABI(RISCVABI::ABI ABI)
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:78
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
@ SHF_ALLOC
Definition: ELF.h:1083
@ SHF_GROUP
Definition: ELF.h:1105
@ SHF_EXECINSTR
Definition: ELF.h:1086
@ SHT_PROGBITS
Definition: ELF.h:995
ABI getTargetABI(StringRef ABIName)
bool compress(MCInst &OutInst, const MCInst &MI, const MCSubtargetInfo &STI)
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
Target & getTheRISCV32Target()
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:145
bool lowerRISCVMachineOperandToMCOperand(const MachineOperand &MO, MCOperand &MCOp, const AsmPrinter &AP)
bool lowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, AsmPrinter &AP)
Target & getTheRISCV64Target()
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:1909
@ MCSA_Weak
.weak
Definition: MCDirectives.h:45
@ MCSA_ELF_TypeFunction
.type _foo, STT_FUNC # aka @function
Definition: MCDirectives.h:23
@ MCSA_Hidden
.hidden (ELF)
Definition: MCDirectives.h:33
Definition: BitVector.h:851
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...