LLVM 24.0.0git
RISCVAsmPrinter.cpp
Go to the documentation of this file.
1//===-- RISCVAsmPrinter.cpp - RISC-V 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 RISC-V assembly language.
11//
12//===----------------------------------------------------------------------===//
13
14#include "RISCVAsmPrinter.h"
21#include "RISCV.h"
24#include "RISCVRegisterInfo.h"
26#include "llvm/ADT/APInt.h"
27#include "llvm/ADT/Statistic.h"
35#include "llvm/IR/Module.h"
36#include "llvm/MC/MCAsmInfo.h"
37#include "llvm/MC/MCContext.h"
38#include "llvm/MC/MCInst.h"
42#include "llvm/MC/MCStreamer.h"
43#include "llvm/MC/MCSymbol.h"
50
51using namespace llvm;
52
53#define DEBUG_TYPE "asm-printer"
54
55STATISTIC(RISCVNumInstrsCompressed,
56 "Number of RISC-V Compressed instructions emitted");
57
58namespace {
59class RISCVAsmPrinter : public AsmPrinter {
60public:
61 static char ID;
62
63private:
64 const RISCVMCOptions &CLOpts;
65 const RISCVSubtarget *STI;
66
67public:
68 explicit RISCVAsmPrinter(TargetMachine &TM,
69 std::unique_ptr<MCStreamer> Streamer)
70 : AsmPrinter(TM, std::move(Streamer), ID),
71 CLOpts(RISCV_MC::getCLOpts(TM.Options.MCOptions)) {}
72
73 StringRef getPassName() const override { return "RISC-V Assembly Printer"; }
74
75 RISCVTargetStreamer &getTargetStreamer() const {
76 return static_cast<RISCVTargetStreamer &>(
77 *OutStreamer->getTargetStreamer());
78 }
79
80 void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
81 const MachineInstr &MI);
82
83 void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
84 const MachineInstr &MI);
85
86 void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
87 const MachineInstr &MI);
88
89 bool runOnMachineFunction(MachineFunction &MF) override;
90
91 void emitInstruction(const MachineInstr *MI) override;
92
93 void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override;
94
95 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
96 const char *ExtraCode, raw_ostream &OS) override;
97 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
98 const char *ExtraCode, raw_ostream &OS) override;
99
100 // Returns whether Inst is compressed.
101 bool EmitToStreamer(MCStreamer &S, const MCInst &Inst,
102 const MCSubtargetInfo &SubtargetInfo);
103 bool EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
104 return EmitToStreamer(S, Inst, *STI);
105 }
106
107 bool lowerPseudoInstExpansion(const MachineInstr *MI, MCInst &Inst);
108
109 typedef std::tuple<unsigned, uint32_t> HwasanMemaccessTuple;
110 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
111 void LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI);
112 void LowerKCFI_CHECK(const MachineInstr &MI);
113 void EmitHwasanMemaccessSymbols(Module &M);
114
115 // Wrapper needed for tblgenned pseudo lowering.
116 bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const;
117
118 void emitStartOfAsmFile(Module &M) override;
119 void emitEndOfAsmFile(Module &M) override;
120
121 void emitFunctionEntryLabel() override;
122 bool emitTargetFeaturePush(const MCSubtargetInfo &STI) override;
123 void emitTargetFeaturePop(const MCSubtargetInfo &STI, bool DidPush) override;
124
125 void emitNoteGnuProperty(const Module &M);
126
127private:
128 void emitNTLHint(const MachineInstr *MI);
129
130 void emitLpadAlignedCall(const MachineInstr &MI);
131
132 // XRay Support
133 void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr *MI);
134 void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr *MI);
135 void LowerPATCHABLE_TAIL_CALL(const MachineInstr *MI);
136 void emitSled(const MachineInstr *MI, SledKind Kind);
137
138 void lowerToMCInst(const MachineInstr *MI, MCInst &OutMI);
139
140 MaybeAlign
141 getRequiredGlobalAlignmentGranule(const GlobalVariable &GV) override;
142};
143} // namespace
144
145void RISCVAsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
146 const MachineInstr &MI) {
147 unsigned NOPBytes = STI->hasStdExtZca() ? 2 : 4;
148 unsigned NumNOPBytes = StackMapOpers(&MI).getNumPatchBytes();
149
150 auto &Ctx = OutStreamer.getContext();
151 MCSymbol *MILabel = Ctx.createTempSymbol();
152 OutStreamer.emitLabel(MILabel);
153
154 SM.recordStackMap(*MILabel, MI);
155 assert(NumNOPBytes % NOPBytes == 0 &&
156 "Invalid number of NOP bytes requested!");
157
158 // Scan ahead to trim the shadow.
159 const MachineBasicBlock &MBB = *MI.getParent();
161 ++MII;
162 while (NumNOPBytes > 0) {
163 if (MII != MBB.end() && MII->isDebugInstr()) {
164 ++MII;
165 continue;
166 }
167 if (MII == MBB.end() || MII->isCall() ||
168 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
169 MII->getOpcode() == TargetOpcode::STACKMAP)
170 break;
171 ++MII;
172 NumNOPBytes -= NOPBytes;
173 }
174
175 // Emit nops.
176 emitNops(NumNOPBytes / NOPBytes);
177}
178
179// Lower a patchpoint of the form:
180// [<def>], <id>, <numBytes>, <target>, <numArgs>
181void RISCVAsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
182 const MachineInstr &MI) {
183 unsigned NOPBytes = STI->hasStdExtZca() ? 2 : 4;
184
185 auto &Ctx = OutStreamer.getContext();
186 MCSymbol *MILabel = Ctx.createTempSymbol();
187 OutStreamer.emitLabel(MILabel);
188 SM.recordPatchPoint(*MILabel, MI);
189
190 PatchPointOpers Opers(&MI);
191
192 const MachineOperand &CalleeMO = Opers.getCallTarget();
193 unsigned EncodedBytes = 0;
194
195 if (CalleeMO.isImm()) {
196 uint64_t CallTarget = CalleeMO.getImm();
197 if (CallTarget) {
198 assert((CallTarget & 0xFFFF'FFFF'FFFF) == CallTarget &&
199 "High 16 bits of call target should be zero.");
200 // Materialize the jump address:
202 RISCVMatInt::generateMCInstSeq(CallTarget, *STI, RISCV::X1, Seq);
203 for (MCInst &Inst : Seq) {
204 bool Compressed = EmitToStreamer(OutStreamer, Inst);
205 EncodedBytes += Compressed ? 2 : 4;
206 }
207 bool Compressed = EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JALR)
208 .addReg(RISCV::X1)
209 .addReg(RISCV::X1)
210 .addImm(0));
211 EncodedBytes += Compressed ? 2 : 4;
212 }
213 } else if (CalleeMO.isGlobal()) {
214 MCOperand CallTargetMCOp;
215 lowerOperand(CalleeMO, CallTargetMCOp);
216 EmitToStreamer(OutStreamer,
217 MCInstBuilder(RISCV::PseudoCALL).addOperand(CallTargetMCOp));
218 EncodedBytes += 8;
219 }
220
221 // Emit padding.
222 unsigned NumBytes = Opers.getNumPatchBytes();
223 assert(NumBytes >= EncodedBytes &&
224 "Patchpoint can't request size less than the length of a call.");
225 assert((NumBytes - EncodedBytes) % NOPBytes == 0 &&
226 "Invalid number of NOP bytes requested!");
227 emitNops((NumBytes - EncodedBytes) / NOPBytes);
228}
229
230void RISCVAsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
231 const MachineInstr &MI) {
232 unsigned NOPBytes = STI->hasStdExtZca() ? 2 : 4;
233
234 StatepointOpers SOpers(&MI);
235 if (unsigned PatchBytes = SOpers.getNumPatchBytes()) {
236 assert(PatchBytes % NOPBytes == 0 &&
237 "Invalid number of NOP bytes requested!");
238 emitNops(PatchBytes / NOPBytes);
239 } else {
240 // Lower call target and choose correct opcode
241 const MachineOperand &CallTarget = SOpers.getCallTarget();
242 MCOperand CallTargetMCOp;
243 switch (CallTarget.getType()) {
246 lowerOperand(CallTarget, CallTargetMCOp);
247 EmitToStreamer(
248 OutStreamer,
249 MCInstBuilder(RISCV::PseudoCALL).addOperand(CallTargetMCOp));
250 break;
252 CallTargetMCOp = MCOperand::createImm(CallTarget.getImm());
253 EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JAL)
254 .addReg(RISCV::X1)
255 .addOperand(CallTargetMCOp));
256 break;
258 CallTargetMCOp = MCOperand::createReg(CallTarget.getReg());
259 EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JALR)
260 .addReg(RISCV::X1)
261 .addOperand(CallTargetMCOp)
262 .addImm(0));
263 break;
264 default:
265 llvm_unreachable("Unsupported operand type in statepoint call target");
266 break;
267 }
268 }
269
270 auto &Ctx = OutStreamer.getContext();
271 MCSymbol *MILabel = Ctx.createTempSymbol();
272 OutStreamer.emitLabel(MILabel);
273 SM.recordStatepoint(*MILabel, MI);
274}
275
276bool RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst,
277 const MCSubtargetInfo &SubtargetInfo) {
278 MCInst CInst;
279 bool Res = RISCVRVC::compress(CInst, Inst, SubtargetInfo);
280 if (Res)
281 ++RISCVNumInstrsCompressed;
282 S.emitInstruction(Res ? CInst : Inst, SubtargetInfo);
283 return Res;
284}
285
286// Simple pseudo-instructions have their lowering (with expansion to real
287// instructions) auto-generated.
288#include "RISCVGenMCPseudoLowering.inc"
289
290// Emit a call to a returns_twice function with LPAD.
291// When Zca is enabled, emit .p2align 2 before the call to ensure the
292// following LPAD is 4-byte aligned. For assembly output, wrap with
293// .option push/exact/pop to prevent relaxation. For object output,
294// emit the pseudo directly so MCCodeEmitter handles it without R_RISCV_RELAX.
295void RISCVAsmPrinter::emitLpadAlignedCall(const MachineInstr &MI) {
296 const MCSubtargetInfo &MCSTI = getSubtargetInfo();
297 const bool IsIndirect = MI.getOpcode() == RISCV::PseudoCALLIndirectLpadAlign,
298 HasZca = MCSTI.hasFeature(RISCV::FeatureStdExtZca),
299 HasRelax = MCSTI.hasFeature(RISCV::FeatureRelax);
300
301 if (HasZca)
302 OutStreamer->emitCodeAlignment(Align(4), MCSTI);
303
304 if (OutStreamer->hasRawTextSupport()) {
305 // Assembly path: wrap call with .option push/exact/pop and emit LPAD
306 // separately so the output is human-readable.
307 RISCVTargetStreamer &RTS = getTargetStreamer();
308 if (HasZca && HasRelax) {
311 }
312
313 MCInst CallInst;
314 if (!IsIndirect) {
315 MCOperand MCOp;
316 lowerOperand(MI.getOperand(0), MCOp);
317 CallInst = MCInstBuilder(RISCV::PseudoCALL).addOperand(MCOp);
318 } else {
319 CallInst = MCInstBuilder(RISCV::JALR)
320 .addReg(RISCV::X1)
321 .addReg(MI.getOperand(0).getReg())
322 .addImm(0);
323 }
324
325 if (HasZca && HasRelax) {
326 MCSubtargetInfo NoRelaxSTI(MCSTI);
327 NoRelaxSTI.ToggleFeature(RISCV::FeatureRelax);
328 EmitToStreamer(*OutStreamer, CallInst, NoRelaxSTI);
330 } else {
331 EmitToStreamer(*OutStreamer, CallInst, MCSTI);
332 }
333
334 // LPAD is encoded as AUIPC X0, label.
335 MCInst LpadInst = MCInstBuilder(RISCV::AUIPC)
336 .addReg(RISCV::X0)
337 .addImm(MI.getOperand(1).getImm());
338 EmitToStreamer(*OutStreamer, LpadInst, MCSTI);
339 } else {
340 // Object path: emit PseudoCALL(Indirect)LpadAlign directly.
341 // MCCodeEmitter::expandFunctionCallLpad expands to AUIPC+JALR+LPAD
342 // without emitting R_RISCV_RELAX on the call fixup.
343 MCInst TmpInst;
344 TmpInst.setOpcode(MI.getOpcode());
345 if (!IsIndirect) {
346 MCOperand MCOp;
347 lowerOperand(MI.getOperand(0), MCOp);
348 TmpInst.addOperand(MCOp);
349 } else {
350 TmpInst.addOperand(MCOperand::createReg(MI.getOperand(0).getReg()));
351 }
352 TmpInst.addOperand(MCOperand::createImm(MI.getOperand(1).getImm()));
353 EmitToStreamer(*OutStreamer, TmpInst, MCSTI);
354 }
355}
356
357// If the instruction has a nontemporal MachineMemOperand, emit an NTL hint
358// instruction before it. NTL hints are always safe to emit since they use
359// HINT encodings that are guaranteed not to trap
360// (riscv-non-isa/riscv-elf-psabi-doc#474).
361void RISCVAsmPrinter::emitNTLHint(const MachineInstr *MI) {
362 if (!STI->getInstrInfo()->requiresNTLHint(*MI))
363 return;
364
365 assert(!MI->memoperands_empty());
366
367 MachineMemOperand *MMO = *(MI->memoperands_begin());
368
369 assert(MMO->isNonTemporal());
370
371 unsigned NontemporalMode = 0;
372 if (MMO->getFlags() & MONontemporalBit0)
373 NontemporalMode += 0b1;
374 if (MMO->getFlags() & MONontemporalBit1)
375 NontemporalMode += 0b10;
376
377 MCInst Hint;
378 if (STI->hasStdExtZca())
379 Hint.setOpcode(RISCV::C_ADD);
380 else
381 Hint.setOpcode(RISCV::ADD);
382
383 Hint.addOperand(MCOperand::createReg(RISCV::X0));
384 Hint.addOperand(MCOperand::createReg(RISCV::X0));
385 Hint.addOperand(MCOperand::createReg(RISCV::X2 + NontemporalMode));
386
387 EmitToStreamer(*OutStreamer, Hint);
388}
389
390void RISCVAsmPrinter::emitInstruction(const MachineInstr *MI) {
391 RISCV_MC::verifyInstructionPredicates(MI->getOpcode(), STI->getFeatureBits());
392
393 emitNTLHint(MI);
394
395 // Do any auto-generated pseudo lowerings.
396 if (MCInst OutInst; lowerPseudoInstExpansion(MI, OutInst)) {
397 EmitToStreamer(*OutStreamer, OutInst);
398 return;
399 }
400
401 switch (MI->getOpcode()) {
402 case RISCV::PseudoTAILX7: {
403 // Lower to PseudoTAILReg with X7 as the register operand.
404 MCOperand SymOp;
405 lowerOperand(MI->getOperand(0), SymOp);
406 MCInst TmpInst;
407 TmpInst.setOpcode(RISCV::PseudoTAILReg);
408 TmpInst.addOperand(MCOperand::createReg(RISCV::X7));
409 TmpInst.addOperand(SymOp);
410 EmitToStreamer(*OutStreamer, TmpInst);
411 return;
412 }
413 case RISCV::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
414 LowerHWASAN_CHECK_MEMACCESS(*MI);
415 return;
416 case RISCV::KCFI_CHECK:
417 LowerKCFI_CHECK(*MI);
418 return;
419 case TargetOpcode::STACKMAP:
420 return LowerSTACKMAP(*OutStreamer, SM, *MI);
421 case TargetOpcode::PATCHPOINT:
422 return LowerPATCHPOINT(*OutStreamer, SM, *MI);
423 case TargetOpcode::STATEPOINT:
424 return LowerSTATEPOINT(*OutStreamer, SM, *MI);
425 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
426 const Function &F = MI->getParent()->getParent()->getFunction();
427 if (F.hasFnAttribute("patchable-function-entry")) {
428 unsigned Num =
429 F.getFnAttributeAsParsedInteger("patchable-function-entry");
430 emitNops(Num);
431 return;
432 }
433 LowerPATCHABLE_FUNCTION_ENTER(MI);
434 return;
435 }
436 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
437 LowerPATCHABLE_FUNCTION_EXIT(MI);
438 return;
439 case TargetOpcode::PATCHABLE_TAIL_CALL:
440 LowerPATCHABLE_TAIL_CALL(MI);
441 return;
442 case RISCV::PseudoCALLLpadAlign:
443 case RISCV::PseudoCALLIndirectLpadAlign:
444 emitLpadAlignedCall(*MI);
445 return;
446 }
447
448 MCInst OutInst;
449 lowerToMCInst(MI, OutInst);
450 EmitToStreamer(*OutStreamer, OutInst);
451}
452
453bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
454 const char *ExtraCode, raw_ostream &OS) {
455 // First try the generic code, which knows about modifiers like 'c' and 'n'.
456 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
457 return false;
458
459 const MachineOperand &MO = MI->getOperand(OpNo);
460 if (ExtraCode && ExtraCode[0]) {
461 if (ExtraCode[1] != 0)
462 return true; // Unknown modifier.
463
464 switch (ExtraCode[0]) {
465 default:
466 return true; // Unknown modifier.
467 case 'z': // Print zero register if zero, regular printing otherwise.
468 if (MO.isImm() && MO.getImm() == 0) {
469 OS << RISCVInstPrinter::getRegisterName(CLOpts, RISCV::X0);
470 return false;
471 }
472 break;
473 case 'i': // Literal 'i' if operand is not a register.
474 if (!MO.isReg())
475 OS << 'i';
476 return false;
477 case 'N': { // Print the register encoding as an integer (0-31)
478 if (!MO.isReg())
479 return true;
480
481 const RISCVRegisterInfo *TRI = STI->getRegisterInfo();
482 OS << TRI->getEncodingValue(MO.getReg());
483 return false;
484 }
485 }
486 }
487
488 switch (MO.getType()) {
490 OS << MO.getImm();
491 return false;
493 OS << RISCVInstPrinter::getRegisterName(CLOpts, MO.getReg());
494 return false;
496 PrintSymbolOperand(MO, OS);
497 return false;
499 MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());
500 Sym->print(OS, MAI);
501 return false;
502 }
503 default:
504 break;
505 }
506
507 return true;
508}
509
510bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
511 unsigned OpNo,
512 const char *ExtraCode,
513 raw_ostream &OS) {
514 if (ExtraCode)
515 return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
516
517 const MachineOperand &AddrReg = MI->getOperand(OpNo);
518 assert(MI->getNumOperands() > OpNo + 1 && "Expected additional operand");
519 const MachineOperand &Offset = MI->getOperand(OpNo + 1);
520 // All memory operands should have a register and an immediate operand (see
521 // RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand).
522 if (!AddrReg.isReg())
523 return true;
524 if (!Offset.isImm() && !Offset.isGlobal() && !Offset.isBlockAddress() &&
525 !Offset.isMCSymbol())
526 return true;
527
528 MCOperand MCO;
529 if (!lowerOperand(Offset, MCO))
530 return true;
531
532 if (Offset.isImm())
533 OS << MCO.getImm();
534 else if (Offset.isGlobal() || Offset.isBlockAddress() || Offset.isMCSymbol())
535 MAI.printExpr(OS, *MCO.getExpr());
536
537 if (Offset.isMCSymbol())
538 MMI->getContext().registerInlineAsmLabel(Offset.getMCSymbol());
539 if (Offset.isBlockAddress()) {
540 const BlockAddress *BA = Offset.getBlockAddress();
541 MCSymbol *Sym = GetBlockAddressSymbol(BA);
542 MMI->getContext().registerInlineAsmLabel(Sym);
543 }
544
545 OS << "(" << RISCVInstPrinter::getRegisterName(CLOpts, AddrReg.getReg())
546 << ")";
547 return false;
548}
549
550bool RISCVAsmPrinter::emitTargetFeaturePush(const MCSubtargetInfo &STI) {
551 RISCVTargetStreamer &RTS = getTargetStreamer();
552 SmallVector<RISCVOptionArchArg> NeedEmitStdOptionArgs;
553 const MCSubtargetInfo &MCSTI = TM.getMCSubtargetInfo();
554 for (const auto &Feature : MCSTI.getAllProcessorFeatures()) {
555 if (STI.hasFeature(Feature.Value) == MCSTI.hasFeature(Feature.Value))
556 continue;
557
559 continue;
560
561 auto Delta = STI.hasFeature(Feature.Value) ? RISCVOptionArchArgType::Plus
562 : RISCVOptionArchArgType::Minus;
563 StringRef ExtName = Feature.key();
564 ExtName.consume_front("experimental-");
565 NeedEmitStdOptionArgs.emplace_back(Delta, ExtName.str());
566 }
567 if (!NeedEmitStdOptionArgs.empty()) {
569 RTS.emitDirectiveOptionArch(NeedEmitStdOptionArgs);
570 RTS.setArchString(
572 return true;
573 }
574
575 return false;
576}
577
578void RISCVAsmPrinter::emitTargetFeaturePop(const MCSubtargetInfo &STI,
579 bool DidPush) {
580 if (DidPush)
581 getTargetStreamer().emitDirectiveOptionPop();
582}
583
584bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
585 STI = &MF.getSubtarget<RISCVSubtarget>();
586
587 bool EmittedOptionArch = emitTargetFeaturePush(*STI);
588
589 SetupMachineFunction(MF);
590 emitFunctionBody();
591
592 // Emit the XRay table
593 emitXRayTable();
594
595 emitTargetFeaturePop(*STI, EmittedOptionArch);
596 return false;
597}
598
599void RISCVAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr *MI) {
600 emitSled(MI, SledKind::FUNCTION_ENTER);
601}
602
603void RISCVAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr *MI) {
604 emitSled(MI, SledKind::FUNCTION_EXIT);
605}
606
607void RISCVAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr *MI) {
608 emitSled(MI, SledKind::TAIL_CALL);
609}
610
611void RISCVAsmPrinter::emitSled(const MachineInstr *MI, SledKind Kind) {
612 // We want to emit the jump instruction and the nops constituting the sled.
613 // The format is as follows:
614 // .Lxray_sled_N
615 // ALIGN
616 // J .tmpN
617 // 21 or 33 C.NOP instructions
618 // .tmpN
619
620 // The following variable holds the count of the number of NOPs to be patched
621 // in for XRay instrumentation during compilation.
622 // Note that RV64 and RV32 each has a sled of 68 and 44 bytes, respectively.
623 // Assuming we're using JAL to jump to .tmpN, then we only need
624 // (68 - 4)/2 = 32 NOPs for RV64 and (44 - 4)/2 = 20 for RV32. However, there
625 // is a chance that we'll use C.JAL instead, so an additional NOP is needed.
626 const uint8_t NoopsInSledCount = STI->is64Bit() ? 33 : 21;
627
628 OutStreamer->emitCodeAlignment(Align(4), *STI);
629 auto CurSled = OutContext.createTempSymbol("xray_sled_", true);
630 OutStreamer->emitLabel(CurSled);
631 auto Target = OutContext.createTempSymbol();
632
633 const MCExpr *TargetExpr = MCSymbolRefExpr::create(Target, OutContext);
634
635 // Emit "J bytes" instruction, which jumps over the nop sled to the actual
636 // start of function.
637 EmitToStreamer(
638 *OutStreamer,
639 MCInstBuilder(RISCV::JAL).addReg(RISCV::X0).addExpr(TargetExpr));
640
641 // Emit NOP instructions
642 for (int8_t I = 0; I < NoopsInSledCount; ++I)
643 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI)
644 .addReg(RISCV::X0)
645 .addReg(RISCV::X0)
646 .addImm(0));
647
648 OutStreamer->emitLabel(Target);
649 recordSled(CurSled, *MI, Kind, 2);
650}
651
652void RISCVAsmPrinter::emitStartOfAsmFile(Module &M) {
653 assert(OutStreamer->getTargetStreamer() &&
654 "target streamer is uninitialized");
655 RISCVTargetStreamer &RTS = getTargetStreamer();
656 StringRef ABIName = M.getTargetABIFromMD();
657 if (!ABIName.empty()) {
659 if (ABI == RISCVABI::ABI::Unknown) {
660 M.getContext().emitError(Twine('\'') + ABIName +
661 "' is not a recognized ABI for this target");
662 } else {
663 RTS.setTargetABI(ABI);
664 }
665 } else if (!RTS.hasTargetABI()) {
666 RTS.setTargetABI(
667 cantFail(RISCVABI::computeTargetABI(TM.getMCSubtargetInfo(), "")));
668 }
669
670 MCSubtargetInfo SubtargetInfo = TM.getMCSubtargetInfo();
671
672 // Use module flag to update feature bits.
673 if (auto *MD = dyn_cast_or_null<MDNode>(M.getModuleFlag("riscv-isa"))) {
674 for (auto &ISA : MD->operands()) {
675 if (auto *ISAString = dyn_cast_or_null<MDString>(ISA)) {
676 auto ParseResult = llvm::RISCVISAInfo::parseArchString(
677 ISAString->getString(), /*EnableExperimentalExtension=*/true,
678 /*ExperimentalExtensionVersionCheck=*/true);
679 if (!errorToBool(ParseResult.takeError())) {
680 auto &ISAInfo = *ParseResult;
681 for (const auto &Feature : SubtargetInfo.getAllProcessorFeatures()) {
682 if (ISAInfo->hasExtension(Feature.key()) &&
683 !SubtargetInfo.hasFeature(Feature.Value))
684 SubtargetInfo.ToggleFeature(Feature.key());
685 }
686 }
687 }
688 }
689
690 RTS.setFlagsFromFeatures(SubtargetInfo);
691 }
692
693 if (M.getTargetTriple().isOSBinFormatELF())
694 RTS.emitTargetAttributes(SubtargetInfo, /*EmitStackAlign=*/true);
695}
696
697void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) {
698 RISCVTargetStreamer &RTS = getTargetStreamer();
699
700 if (M.getTargetTriple().isOSBinFormatELF()) {
702 emitNoteGnuProperty(M);
703 }
704 EmitHwasanMemaccessSymbols(M);
705}
706
707void RISCVAsmPrinter::emitFunctionEntryLabel() {
708 const auto *RMFI = MF->getInfo<RISCVMachineFunctionInfo>();
709 if (RMFI->isVectorCall()) {
710 RISCVTargetStreamer &RTS = getTargetStreamer();
711 RTS.emitDirectiveVariantCC(*CurrentFnSym);
712 }
714}
715
716// Force static initialization.
724
725void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {
726 Register Reg = MI.getOperand(0).getReg();
727 uint32_t AccessInfo = MI.getOperand(1).getImm();
728 MCSymbol *&Sym =
729 HwasanMemaccessSymbols[HwasanMemaccessTuple(Reg, AccessInfo)];
730 if (!Sym) {
731 // FIXME: Make this work on non-ELF.
732 if (!TM.getTargetTriple().isOSBinFormatELF())
733 report_fatal_error("llvm.hwasan.check.memaccess only supported on ELF");
734
735 std::string SymName = "__hwasan_check_x" + utostr(Reg - RISCV::X0) + "_" +
736 utostr(AccessInfo) + "_short";
737 Sym = OutContext.getOrCreateSymbol(SymName);
738 }
739 auto Res = MCSymbolRefExpr::create(Sym, OutContext);
740 auto Expr = MCSpecifierExpr::create(Res, RISCV::S_CALL_PLT, OutContext);
741
742 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr));
743}
744
745void RISCVAsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {
746 Register AddrReg = MI.getOperand(0).getReg();
747 assert(std::next(MI.getIterator())->isCall() &&
748 "KCFI_CHECK not followed by a call instruction");
749 assert(std::next(MI.getIterator())->getOperand(0).getReg() == AddrReg &&
750 "KCFI_CHECK call target doesn't match call operand");
751
752 // Temporary registers for comparing the hashes. If a register is used
753 // for the call target, or reserved by the user, we can clobber another
754 // temporary register as the check is immediately followed by the
755 // call. The check defaults to X6/X7, but can fall back to X28-X31 if
756 // needed.
757 unsigned ScratchRegs[] = {RISCV::X6, RISCV::X7};
758 unsigned NextReg = RISCV::X28;
759 auto isRegAvailable = [&](unsigned Reg) {
760 return Reg != AddrReg && !STI->isRegisterReservedByUser(Reg);
761 };
762 for (auto &Reg : ScratchRegs) {
763 if (isRegAvailable(Reg))
764 continue;
765 while (!isRegAvailable(NextReg))
766 ++NextReg;
767 Reg = NextReg++;
768 if (Reg > RISCV::X31)
769 report_fatal_error("Unable to find scratch registers for KCFI_CHECK");
770 }
771
772 if (AddrReg == RISCV::X0) {
773 // Checking X0 makes no sense. Instead of emitting a load, zero
774 // ScratchRegs[0].
775 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI)
776 .addReg(ScratchRegs[0])
777 .addReg(RISCV::X0)
778 .addImm(0));
779 } else {
780 // Adjust the offset for patchable-function-prefix. This assumes that
781 // patchable-function-prefix is the same for all functions.
782 int NopSize = STI->hasStdExtZca() ? 2 : 4;
783 int64_t PrefixNops =
784 MI.getMF()->getFunction().getFnAttributeAsParsedInteger(
785 "patchable-function-prefix");
786
787 // Load the target function type hash.
788 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::LW)
789 .addReg(ScratchRegs[0])
790 .addReg(AddrReg)
791 .addImm(-(PrefixNops * NopSize + 4)));
792 }
793
794 // Load the expected 32-bit type hash.
795 const int64_t Type = MI.getOperand(1).getImm();
796 const int64_t Hi20 = ((Type + 0x800) >> 12) & 0xFFFFF;
797 const int64_t Lo12 = SignExtend64<12>(Type);
798 if (Hi20) {
799 EmitToStreamer(
800 *OutStreamer,
801 MCInstBuilder(RISCV::LUI).addReg(ScratchRegs[1]).addImm(Hi20));
802 }
803 if (Lo12 || Hi20 == 0) {
804 EmitToStreamer(*OutStreamer,
805 MCInstBuilder((STI->hasFeature(RISCV::Feature64Bit) && Hi20)
806 ? RISCV::ADDIW
807 : RISCV::ADDI)
808 .addReg(ScratchRegs[1])
809 .addReg(ScratchRegs[1])
810 .addImm(Lo12));
811 }
812
813 // Compare the hashes and trap if there's a mismatch.
814 MCSymbol *Pass = OutContext.createTempSymbol();
815 EmitToStreamer(*OutStreamer,
816 MCInstBuilder(RISCV::BEQ)
817 .addReg(ScratchRegs[0])
818 .addReg(ScratchRegs[1])
819 .addExpr(MCSymbolRefExpr::create(Pass, OutContext)));
820
821 MCSymbol *Trap = OutContext.createTempSymbol();
822 OutStreamer->emitLabel(Trap);
823 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::EBREAK));
824 emitKCFITrapEntry(*MI.getMF(), Trap);
825 OutStreamer->emitLabel(Pass);
826}
827
828void RISCVAsmPrinter::EmitHwasanMemaccessSymbols(Module &M) {
829 if (HwasanMemaccessSymbols.empty())
830 return;
831
832 assert(M.getTargetTriple().isOSBinFormatELF());
833 // Use MCSubtargetInfo from TargetMachine. Individual functions may have
834 // attributes that differ from other functions in the module and we have no
835 // way to know which function is correct.
836 const MCSubtargetInfo &MCSTI = TM.getMCSubtargetInfo();
837
838 MCSymbol *HwasanTagMismatchV2Sym =
839 OutContext.getOrCreateSymbol("__hwasan_tag_mismatch_v2");
840 // Annotate symbol as one having incompatible calling convention, so
841 // run-time linkers can instead eagerly bind this function.
842 RISCVTargetStreamer &RTS = getTargetStreamer();
843 RTS.emitDirectiveVariantCC(*HwasanTagMismatchV2Sym);
844
845 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
846 MCSymbolRefExpr::create(HwasanTagMismatchV2Sym, OutContext);
847 auto Expr = MCSpecifierExpr::create(HwasanTagMismatchV2Ref, RISCV::S_CALL_PLT,
848 OutContext);
849
850 for (auto &P : HwasanMemaccessSymbols) {
851 unsigned Reg = std::get<0>(P.first);
852 uint32_t AccessInfo = std::get<1>(P.first);
853 MCSymbol *Sym = P.second;
854
855 unsigned Size =
856 1 << ((AccessInfo >> HWASanAccessInfo::AccessSizeShift) & 0xf);
857 OutStreamer->switchSection(OutContext.getELFSection(
858 ".text.hot", ELF::SHT_PROGBITS,
860 /*IsComdat=*/true));
861
863 OutStreamer->emitSymbolAttribute(Sym, MCSA_Weak);
864 OutStreamer->emitSymbolAttribute(Sym, MCSA_Hidden);
865 OutStreamer->emitLabel(Sym);
866
867 // Extract shadow offset from ptr
868 EmitToStreamer(
869 *OutStreamer,
870 MCInstBuilder(RISCV::SLLI).addReg(RISCV::X6).addReg(Reg).addImm(8),
871 MCSTI);
872 EmitToStreamer(*OutStreamer,
873 MCInstBuilder(RISCV::SRLI)
874 .addReg(RISCV::X6)
875 .addReg(RISCV::X6)
876 .addImm(12),
877 MCSTI);
878 // load shadow tag in X6, X5 contains shadow base
879 EmitToStreamer(*OutStreamer,
880 MCInstBuilder(RISCV::ADD)
881 .addReg(RISCV::X6)
882 .addReg(RISCV::X5)
883 .addReg(RISCV::X6),
884 MCSTI);
885 EmitToStreamer(
886 *OutStreamer,
887 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
888 MCSTI);
889 // Extract tag from pointer and compare it with loaded tag from shadow
890 EmitToStreamer(
891 *OutStreamer,
892 MCInstBuilder(RISCV::SRLI).addReg(RISCV::X7).addReg(Reg).addImm(56),
893 MCSTI);
894 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
895 // X7 contains tag from the pointer, while X6 contains tag from memory
896 EmitToStreamer(*OutStreamer,
897 MCInstBuilder(RISCV::BNE)
898 .addReg(RISCV::X7)
899 .addReg(RISCV::X6)
901 HandleMismatchOrPartialSym, OutContext)),
902 MCSTI);
903 MCSymbol *ReturnSym = OutContext.createTempSymbol();
904 OutStreamer->emitLabel(ReturnSym);
905 EmitToStreamer(*OutStreamer,
906 MCInstBuilder(RISCV::JALR)
907 .addReg(RISCV::X0)
908 .addReg(RISCV::X1)
909 .addImm(0),
910 MCSTI);
911 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
912
913 EmitToStreamer(*OutStreamer,
914 MCInstBuilder(RISCV::ADDI)
915 .addReg(RISCV::X28)
916 .addReg(RISCV::X0)
917 .addImm(16),
918 MCSTI);
919 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
920 EmitToStreamer(
921 *OutStreamer,
922 MCInstBuilder(RISCV::BGEU)
923 .addReg(RISCV::X6)
924 .addReg(RISCV::X28)
925 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
926 MCSTI);
927
928 EmitToStreamer(
929 *OutStreamer,
930 MCInstBuilder(RISCV::ANDI).addReg(RISCV::X28).addReg(Reg).addImm(0xF),
931 MCSTI);
932
933 if (Size != 1)
934 EmitToStreamer(*OutStreamer,
935 MCInstBuilder(RISCV::ADDI)
936 .addReg(RISCV::X28)
937 .addReg(RISCV::X28)
938 .addImm(Size - 1),
939 MCSTI);
940 EmitToStreamer(
941 *OutStreamer,
942 MCInstBuilder(RISCV::BGE)
943 .addReg(RISCV::X28)
944 .addReg(RISCV::X6)
945 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
946 MCSTI);
947
948 EmitToStreamer(
949 *OutStreamer,
950 MCInstBuilder(RISCV::ORI).addReg(RISCV::X6).addReg(Reg).addImm(0xF),
951 MCSTI);
952 EmitToStreamer(
953 *OutStreamer,
954 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
955 MCSTI);
956 EmitToStreamer(*OutStreamer,
957 MCInstBuilder(RISCV::BEQ)
958 .addReg(RISCV::X6)
959 .addReg(RISCV::X7)
960 .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)),
961 MCSTI);
962
963 OutStreamer->emitLabel(HandleMismatchSym);
964
965 // | Previous stack frames... |
966 // +=================================+ <-- [SP + 256]
967 // | ... |
968 // | |
969 // | Stack frame space for x12 - x31.|
970 // | |
971 // | ... |
972 // +---------------------------------+ <-- [SP + 96]
973 // | Saved x11(arg1), as |
974 // | __hwasan_check_* clobbers it. |
975 // +---------------------------------+ <-- [SP + 88]
976 // | Saved x10(arg0), as |
977 // | __hwasan_check_* clobbers it. |
978 // +---------------------------------+ <-- [SP + 80]
979 // | |
980 // | Stack frame space for x9. |
981 // +---------------------------------+ <-- [SP + 72]
982 // | |
983 // | Saved x8(fp), as |
984 // | __hwasan_check_* clobbers it. |
985 // +---------------------------------+ <-- [SP + 64]
986 // | ... |
987 // | |
988 // | Stack frame space for x2 - x7. |
989 // | |
990 // | ... |
991 // +---------------------------------+ <-- [SP + 16]
992 // | Return address (x1) for caller |
993 // | of __hwasan_check_*. |
994 // +---------------------------------+ <-- [SP + 8]
995 // | Reserved place for x0, possibly |
996 // | junk, since we don't save it. |
997 // +---------------------------------+ <-- [x2 / SP]
998
999 // Adjust sp
1000 EmitToStreamer(*OutStreamer,
1001 MCInstBuilder(RISCV::ADDI)
1002 .addReg(RISCV::X2)
1003 .addReg(RISCV::X2)
1004 .addImm(-256),
1005 MCSTI);
1006
1007 // store x10(arg0) by new sp
1008 EmitToStreamer(*OutStreamer,
1009 MCInstBuilder(RISCV::SD)
1010 .addReg(RISCV::X10)
1011 .addReg(RISCV::X2)
1012 .addImm(8 * 10),
1013 MCSTI);
1014 // store x11(arg1) by new sp
1015 EmitToStreamer(*OutStreamer,
1016 MCInstBuilder(RISCV::SD)
1017 .addReg(RISCV::X11)
1018 .addReg(RISCV::X2)
1019 .addImm(8 * 11),
1020 MCSTI);
1021
1022 // store x8(fp) by new sp
1023 EmitToStreamer(
1024 *OutStreamer,
1025 MCInstBuilder(RISCV::SD).addReg(RISCV::X8).addReg(RISCV::X2).addImm(8 *
1026 8),
1027 MCSTI);
1028 // store x1(ra) by new sp
1029 EmitToStreamer(
1030 *OutStreamer,
1031 MCInstBuilder(RISCV::SD).addReg(RISCV::X1).addReg(RISCV::X2).addImm(1 *
1032 8),
1033 MCSTI);
1034 if (Reg != RISCV::X10)
1035 EmitToStreamer(
1036 *OutStreamer,
1037 MCInstBuilder(RISCV::ADDI).addReg(RISCV::X10).addReg(Reg).addImm(0),
1038 MCSTI);
1039 EmitToStreamer(*OutStreamer,
1040 MCInstBuilder(RISCV::ADDI)
1041 .addReg(RISCV::X11)
1042 .addReg(RISCV::X0)
1043 .addImm(AccessInfo & HWASanAccessInfo::RuntimeMask),
1044 MCSTI);
1045
1046 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr),
1047 MCSTI);
1048 }
1049}
1050
1051void RISCVAsmPrinter::emitNoteGnuProperty(const Module &M) {
1052 assert(M.getTargetTriple().isOSBinFormatELF() && "invalid binary format");
1053 uint32_t GnuProps = 0;
1054 if (const Metadata *const Flag = M.getModuleFlag("cf-protection-return");
1055 Flag && !mdconst::extract<ConstantInt>(Flag)->isZero())
1057
1058 if (const Metadata *const Flag = M.getModuleFlag("cf-protection-branch");
1059 Flag && !mdconst::extract<ConstantInt>(Flag)->isZero()) {
1060 using namespace llvm::RISCVISAUtils;
1061 const Metadata *const CFBranchLabelSchemeFlag =
1062 M.getModuleFlag("cf-branch-label-scheme");
1063 assert(CFBranchLabelSchemeFlag &&
1064 "cf-protection=branch should come with cf-branch-label-scheme=... "
1065 "on RISC-V targets");
1066 const StringRef CFBranchLabelScheme =
1067 cast<MDString>(CFBranchLabelSchemeFlag)->getString();
1068 switch (llvm::RISCVCFI::getZicfilpLabelScheme(CFBranchLabelScheme)) {
1070 reportFatalInternalError("invalid RISC-V Zicfilp label scheme");
1073 break;
1075 // TODO: Emit the func-sig bit after the feature is implemented
1076 reportFatalUsageError("the complete func-sig label scheme feature is not "
1077 "implemented yet");
1078 break;
1079 }
1080 }
1081
1082 if (!GnuProps)
1083 return;
1084
1085 auto &RTS = static_cast<RISCVTargetELFStreamer &>(getTargetStreamer());
1086 RTS.emitNoteGnuPropertySection(GnuProps);
1087}
1088
1090 const AsmPrinter &AP) {
1091 MCContext &Ctx = AP.OutContext;
1092 RISCV::Specifier Kind;
1093
1094 switch (MO.getTargetFlags()) {
1095 default:
1096 llvm_unreachable("Unknown target flag on GV operand");
1097 case RISCVII::MO_None:
1098 Kind = RISCV::S_None;
1099 break;
1100 case RISCVII::MO_CALL:
1101 Kind = RISCV::S_CALL_PLT;
1102 break;
1103 case RISCVII::MO_LO:
1104 Kind = RISCV::S_LO;
1105 break;
1106 case RISCVII::MO_HI:
1107 Kind = ELF::R_RISCV_HI20;
1108 break;
1110 Kind = RISCV::S_PCREL_LO;
1111 break;
1113 Kind = RISCV::S_PCREL_HI;
1114 break;
1115 case RISCVII::MO_GOT_HI:
1116 Kind = RISCV::S_GOT_HI;
1117 break;
1119 Kind = RISCV::S_TPREL_LO;
1120 break;
1122 Kind = ELF::R_RISCV_TPREL_HI20;
1123 break;
1125 Kind = ELF::R_RISCV_TPREL_ADD;
1126 break;
1128 Kind = ELF::R_RISCV_TLS_GOT_HI20;
1129 break;
1131 Kind = ELF::R_RISCV_TLS_GD_HI20;
1132 break;
1134 Kind = ELF::R_RISCV_TLSDESC_HI20;
1135 break;
1137 Kind = ELF::R_RISCV_TLSDESC_LOAD_LO12;
1138 break;
1140 Kind = ELF::R_RISCV_TLSDESC_ADD_LO12;
1141 break;
1143 Kind = ELF::R_RISCV_TLSDESC_CALL;
1144 break;
1146 Kind = RISCV::S_QC_ACCESS;
1147 break;
1148 }
1149
1150 const MCExpr *ME = MCSymbolRefExpr::create(Sym, Ctx);
1151
1152 if (!MO.isJTI() && !MO.isMBB() && MO.getOffset())
1154 ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
1155
1156 if (Kind != RISCV::S_None)
1157 ME = MCSpecifierExpr::create(ME, Kind, Ctx);
1158 return MCOperand::createExpr(ME);
1159}
1160
1161bool RISCVAsmPrinter::lowerOperand(const MachineOperand &MO,
1162 MCOperand &MCOp) const {
1163 switch (MO.getType()) {
1164 default:
1165 report_fatal_error("lowerOperand: unknown operand type");
1167 // Ignore all implicit register operands.
1168 if (MO.isImplicit())
1169 return false;
1170 MCOp = MCOperand::createReg(MO.getReg());
1171 break;
1173 // Regmasks are like implicit defs.
1174 return false;
1176 MCOp = MCOperand::createImm(MO.getImm());
1177 break;
1179 MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), *this);
1180 break;
1182 MCOp = lowerSymbolOperand(MO, getSymbolPreferLocal(*MO.getGlobal()), *this);
1183 break;
1185 MCOp = lowerSymbolOperand(MO, GetBlockAddressSymbol(MO.getBlockAddress()),
1186 *this);
1187 break;
1189 MCOp = lowerSymbolOperand(MO, GetExternalSymbolSymbol(MO.getSymbolName()),
1190 *this);
1191 break;
1193 MCOp = lowerSymbolOperand(MO, GetCPISymbol(MO.getIndex()), *this);
1194 break;
1196 MCOp = lowerSymbolOperand(MO, GetJTISymbol(MO.getIndex()), *this);
1197 break;
1199 MCOp = lowerSymbolOperand(MO, MO.getMCSymbol(), *this);
1200 break;
1201 }
1202 return true;
1203}
1204
1206 MCInst &OutMI,
1207 const RISCVSubtarget *STI) {
1209 RISCVVPseudosTable::getPseudoInfo(MI->getOpcode());
1210 if (!RVV)
1211 return false;
1212
1213 OutMI.setOpcode(RVV->BaseInstr);
1214
1215 const TargetInstrInfo *TII = STI->getInstrInfo();
1216 const TargetRegisterInfo *TRI = STI->getRegisterInfo();
1217 assert(TRI && "TargetRegisterInfo expected");
1218
1219 const MCInstrDesc &MCID = MI->getDesc();
1220 uint64_t TSFlags = MCID.TSFlags;
1221 unsigned NumOps = MI->getNumExplicitOperands();
1222
1223 // Skip policy, SEW, VL, VXRM/FRM operands which are the last operands if
1224 // present.
1225 if (RISCVII::hasVecPolicyOp(TSFlags))
1226 --NumOps;
1227 if (RISCVII::hasSEWOp(TSFlags))
1228 --NumOps;
1229 if (RISCVII::hasVLOp(TSFlags))
1230 --NumOps;
1231 if (RISCVII::hasRoundModeOp(TSFlags))
1232 --NumOps;
1233 if (RISCVII::hasTWidenOp(TSFlags))
1234 --NumOps;
1235 if (RISCVII::hasTMOp(TSFlags))
1236 --NumOps;
1237 if (RISCVII::hasTKOp(TSFlags))
1238 --NumOps;
1239
1240 bool hasVLOutput = RISCVInstrInfo::isFaultOnlyFirstLoad(*MI);
1241 for (unsigned OpNo = 0; OpNo != NumOps; ++OpNo) {
1242 const MachineOperand &MO = MI->getOperand(OpNo);
1243 // Skip vl output. It should be the second output.
1244 if (hasVLOutput && OpNo == 1)
1245 continue;
1246
1247 // Skip passthru op. It should be the first operand after the defs.
1248 if (OpNo == MI->getNumExplicitDefs() && MO.isReg() && MO.isTied()) {
1249 assert(MCID.getOperandConstraint(OpNo, MCOI::TIED_TO) == 0 &&
1250 "Expected tied to first def.");
1251 const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode());
1252 // Skip if the next operand in OutMI is not supposed to be tied. Unless it
1253 // is a _TIED instruction.
1254 if (OutMCID.getOperandConstraint(OutMI.getNumOperands(), MCOI::TIED_TO) <
1255 0 &&
1256 !RISCVII::isTiedPseudo(TSFlags))
1257 continue;
1258 }
1259
1260 MCOperand MCOp;
1261 switch (MO.getType()) {
1262 default:
1263 llvm_unreachable("Unknown operand type");
1265 Register Reg = MO.getReg();
1266
1267 if (RISCV::VRM2RegClass.contains(Reg) ||
1268 RISCV::VRM4RegClass.contains(Reg) ||
1269 RISCV::VRM8RegClass.contains(Reg)) {
1270 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0);
1271 assert(Reg && "Subregister does not exist");
1272 } else if (RISCV::FPR16RegClass.contains(Reg)) {
1273 Reg =
1274 TRI->getMatchingSuperReg(Reg, RISCV::sub_16, &RISCV::FPR32RegClass);
1275 assert(Reg && "Subregister does not exist");
1276 } else if (RISCV::FPR64RegClass.contains(Reg)) {
1277 Reg = TRI->getSubReg(Reg, RISCV::sub_32);
1278 assert(Reg && "Superregister does not exist");
1279 } else if (RISCV::VRN2M1RegClass.contains(Reg) ||
1280 RISCV::VRN2M2RegClass.contains(Reg) ||
1281 RISCV::VRN2M4RegClass.contains(Reg) ||
1282 RISCV::VRN3M1RegClass.contains(Reg) ||
1283 RISCV::VRN3M2RegClass.contains(Reg) ||
1284 RISCV::VRN4M1RegClass.contains(Reg) ||
1285 RISCV::VRN4M2RegClass.contains(Reg) ||
1286 RISCV::VRN5M1RegClass.contains(Reg) ||
1287 RISCV::VRN6M1RegClass.contains(Reg) ||
1288 RISCV::VRN7M1RegClass.contains(Reg) ||
1289 RISCV::VRN8M1RegClass.contains(Reg)) {
1290 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0);
1291 assert(Reg && "Subregister does not exist");
1292 }
1293
1294 MCOp = MCOperand::createReg(Reg);
1295 break;
1296 }
1298 MCOp = MCOperand::createImm(MO.getImm());
1299 break;
1300 }
1301 OutMI.addOperand(MCOp);
1302 }
1303
1304 // Unmasked pseudo instructions need to append dummy mask operand to
1305 // V instructions. All V instructions are modeled as the masked version.
1306 const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode());
1307 if (OutMI.getNumOperands() < OutMCID.getNumOperands()) {
1308 assert(OutMCID.operands()[OutMI.getNumOperands()].OperandType ==
1310 "Expected only mask operand to be missing");
1311 OutMI.addOperand(MCOperand::createReg(RISCV::NoRegister));
1312 }
1313
1314 assert(OutMI.getNumOperands() == OutMCID.getNumOperands());
1315 return true;
1316}
1317
1318void RISCVAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {
1319 if (lowerRISCVVMachineInstrToMCInst(MI, OutMI, STI))
1320 return;
1321
1322 OutMI.setOpcode(MI->getOpcode());
1323
1324 for (const MachineOperand &MO : MI->operands()) {
1325 MCOperand MCOp;
1326 if (lowerOperand(MO, MCOp))
1327 OutMI.addOperand(MCOp);
1328 }
1329}
1330
1331void RISCVAsmPrinter::emitMachineConstantPoolValue(
1332 MachineConstantPoolValue *MCPV) {
1333 auto *RCPV = static_cast<RISCVConstantPoolValue *>(MCPV);
1334 MCSymbol *MCSym;
1335
1336 if (RCPV->isGlobalValue()) {
1337 auto *GV = RCPV->getGlobalValue();
1338 MCSym = getSymbol(GV);
1339 } else {
1340 assert(RCPV->isExtSymbol() && "unrecognized constant pool type");
1341 auto Sym = RCPV->getSymbol();
1342 MCSym = GetExternalSymbolSymbol(Sym);
1343 }
1344
1345 const MCExpr *Expr = MCSymbolRefExpr::create(MCSym, OutContext);
1346 uint64_t Size = getDataLayout().getTypeAllocSize(RCPV->getType());
1347 OutStreamer->emitValue(Expr, Size);
1348}
1349
1350MaybeAlign
1351RISCVAsmPrinter::getRequiredGlobalAlignmentGranule(const GlobalVariable &GV) {
1352 const MCSubtargetInfo &MCSTI = TM.getMCSubtargetInfo();
1353 if (!GV.getValueType()->isSized())
1354 return std::nullopt;
1355
1356 // When the alignment granule is determined by a CHERI requirement,
1357 // don't increase alignment if a custom section has been specified,
1358 // as doing so can break existing code that relies on the lack of
1359 // padding (e.g. linker sets).
1360 if (GV.hasSection())
1361 return std::nullopt;
1362
1363 uint64_t Size = GV.getGlobalSize(getDataLayout());
1364 if (MCSTI.hasFeature(RISCV::FeatureVendorXCheriot))
1365 return CHERIoTCapabilityFormat::getRequiredAlignment(Size);
1366
1367 if (MCSTI.hasFeature(RISCV::FeatureStdExtY)) {
1368 if (MCSTI.hasFeature(RISCV::Feature64Bit))
1370 else
1372 }
1373
1374 return std::nullopt;
1375}
1376
1377char RISCVAsmPrinter::ID = 0;
1378
1379INITIALIZE_PASS(RISCVAsmPrinter, "riscv-asm-printer", "RISC-V Assembly Printer",
1380 false, false)
1381
1384 RISCVAsmPrinter &AsmPrinter = static_cast<RISCVAsmPrinter &>(
1385 MAM.getResult<AsmPrinterAnalysis>(M).getPrinter());
1388 return PreservedAnalyses::all();
1389}
1390
1391PreservedAnalyses
1394 RISCVAsmPrinter &AsmPrinter = static_cast<RISCVAsmPrinter &>(
1396 .getCachedResult<AsmPrinterAnalysis>(*MF.getFunction().getParent())
1397 ->getPrinter());
1400 return PreservedAnalyses::all();
1401}
1402
1405 RISCVAsmPrinter &AsmPrinter = static_cast<RISCVAsmPrinter &>(
1406 MAM.getResult<AsmPrinterAnalysis>(M).getPrinter());
1409 return PreservedAnalyses::all();
1410}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock & MBB
static const Function * getParent(const Value *V)
#define X(NUM, ENUM, NAME)
Definition ELF.h:665
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_ABI
Definition Compiler.h:211
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
dxil translate DXIL Translate Metadata
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
static LVOptions Options
Definition LVOptions.cpp:25
static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym, const AsmPrinter &AP)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
print mir2vec MIR2Vec Vocabulary Printer Pass
Definition MIR2Vec.cpp:629
Machine Check Debug Module
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define P(N)
ModuleAnalysisManager MAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static bool lowerRISCVVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, const RISCVSubtarget *STI)
LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmPrinter()
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:479
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:171
std::unique_ptr< MCStreamer > && Streamer
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class is intended to be used as a driving class for all asm writers.
Definition AsmPrinter.h:95
bool doInitialization(Module &M) override
Set up the AsmPrinter when we are working on a new module.
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition AsmPrinter.h:105
bool doFinalization(Module &M) override
Shut down the asmprinter.
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
Definition AsmPrinter.h:478
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.
bool hasSection() const
Check if this global has a custom object file section.
Type * getValueType() const
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
Definition Globals.cpp:640
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:342
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Context object for machine code objects.
Definition MCContext.h:83
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
unsigned getNumOperands() const
Definition MCInst.h:212
unsigned getOpcode() const
Definition MCInst.h:202
void addOperand(const MCOperand Op)
Definition MCInst.h:215
void setOpcode(unsigned Op)
Definition MCInst.h:201
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specified operand constraint if it is present.
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
static MCOperand createExpr(const MCExpr *Val)
Definition MCInst.h:166
int64_t getImm() const
Definition MCInst.h:84
static MCOperand createReg(MCRegister Reg)
Definition MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
const MCExpr * getExpr() const
Definition MCInst.h:118
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.cpp:743
Streaming machine code generation interface.
Definition MCStreamer.h:222
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
virtual bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute)=0
Add the given Attribute to Symbol.
virtual void emitCodeAlignment(Align Alignment, const MCSubtargetInfo &STI, unsigned MaxBytesToEmit=0)
Emit nops until the byte alignment ByteAlignment is reached.
virtual bool hasRawTextSupport() const
Return true if this asm streamer supports emitting unformatted text to the .s file with EmitRawText.
Definition MCStreamer.h:385
MCContext & getContext() const
Definition MCStreamer.h:326
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
MCTargetStreamer * getTargetStreamer()
Definition MCStreamer.h:336
virtual void switchSection(MCSection *Section, uint32_t Subsec=0)
Set the current section where code is being emitted to Section.
bool hasFeature(unsigned Feature) const
const FeatureBitset & ToggleFeature(uint64_t FB)
Toggle a feature and return the re-computed feature bits.
ArrayRef< SubtargetFeatureKV > getAllProcessorFeatures() const
Return processor features.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition MCSymbol.cpp:60
StringRef getName() const
getName - Get the symbol name.
Definition MCSymbol.h:188
MachineInstrBundleIterator< const MachineInstr > const_iterator
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isJTI() const
isJTI - Tests if this is a MO_JumpTableIndex operand.
const BlockAddress * getBlockAddress() const
unsigned getTargetFlags() const
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
MCSymbol * getMCSymbol() const
@ MO_Immediate
Immediate operand.
@ MO_ConstantPoolIndex
Address of indexed Constant in Constant Pool.
@ MO_MCSymbol
MCSymbol reference (for debug/eh info)
@ MO_GlobalAddress
Address of a global value.
@ MO_RegisterMask
Mask of preserved registers.
@ MO_BlockAddress
Address of a basic block.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
@ MO_JumpTableIndex
Address of indexed Jump Table for switch.
int64_t getOffset() const
Return the offset from the symbol in this operand.
bool isMBB() const
isMBB - Tests if this is a MO_MachineBasicBlock operand.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
static LLVM_ABI bool isSupportedExtensionFeature(StringRef Ext)
static LLVM_ABI llvm::Expected< std::unique_ptr< RISCVISAInfo > > parseArchString(StringRef Arch, bool EnableExperimentalExtension, bool ExperimentalExtensionVersionCheck=true)
Parse RISC-V ISA info from arch string.
static const char * getRegisterName(const RISCVMCOptions &CLOpts, MCRegister Reg)
bool requiresNTLHint(const MachineInstr &MI) const
Return true if the instruction requires an NTL hint to be emitted.
const RISCVRegisterInfo * getRegisterInfo() const override
const RISCVInstrInfo * getInstrInfo() const override
virtual void setArchString(StringRef Arch)
virtual void emitDirectiveVariantCC(MCSymbol &Symbol)
void emitTargetAttributes(const MCSubtargetInfo &STI, bool EmitStackAlign)
virtual void setFlagsFromFeatures(const MCSubtargetInfo &STI)
void setTargetABI(RISCVABI::ABI ABI)
virtual void emitDirectiveOptionArch(ArrayRef< RISCVOptionArchArg > Args)
Wrapper class representing virtual and physical registers.
Definition Register.h:20
reference emplace_back(ArgTypes &&... Args)
LLVM_ABI void recordStatepoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a statepoint instruction.
LLVM_ABI void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
LLVM_ABI void recordStackMap(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a stackmap instruction.
std::string str() const
Get the contents as an std::string.
Definition StringRef.h:222
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
bool consume_front(char Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
Definition StringRef.h:661
TargetInstrInfo - Interface to description of machine instruction set.
Primary interface to the complete machine description for the target machine.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
bool isSized() const
Return true if it makes sense to take the size of this type.
Definition Type.h:321
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ SHF_ALLOC
Definition ELF.h:1067
@ SHF_GROUP
Definition ELF.h:1089
@ SHF_EXECINSTR
Definition ELF.h:1070
@ SHT_PROGBITS
Definition ELF.h:965
@ GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED
Definition ELF.h:1739
@ GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS
Definition ELF.h:1740
ABI getTargetABI(StringRef ABIName)
Expected< ABI > computeTargetABI(const MCSubtargetInfo &STI, StringRef ABIName)
ZicfilpLabelSchemeKind getZicfilpLabelScheme(const StringRef CFBranchLabelScheme)
llvm::Expected< std::unique_ptr< RISCVISAInfo > > parseFeatureBits(const MCSubtargetInfo &STI)
static bool hasRoundModeOp(uint64_t TSFlags)
static bool hasTWidenOp(uint64_t TSFlags)
static bool isTiedPseudo(uint64_t TSFlags)
static bool hasTKOp(uint64_t TSFlags)
static bool hasVLOp(uint64_t TSFlags)
static bool hasTMOp(uint64_t TSFlags)
static bool hasVecPolicyOp(uint64_t TSFlags)
static bool hasSEWOp(uint64_t TSFlags)
void generateMCInstSeq(int64_t Val, const MCSubtargetInfo &STI, MCRegister DestReg, SmallVectorImpl< MCInst > &Insts)
bool compress(MCInst &OutInst, const MCInst &MI, const MCSubtargetInfo &STI)
uint16_t Specifier
void emitInstruction(MCObjectStreamer &, const MCInst &Inst, const MCSubtargetInfo &STI)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
Definition Metadata.h:679
This is an optimization pass for GlobalISel generic memory operations.
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
Definition Error.h:1129
@ Offset
Definition DWP.cpp:577
static const MachineMemOperand::Flags MONontemporalBit1
OuterAnalysisManagerProxy< ModuleAnalysisManager, MachineFunction > ModuleAnalysisManagerMachineFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
Target & getTheRISCV32Target()
static const MachineMemOperand::Flags MONontemporalBit0
std::string utostr(uint64_t X, bool isNeg=false)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
Target & getTheRISCV64beTarget()
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
Definition Error.cpp:173
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
LLVM_ABI void setupModuleAsmPrinter(Module &M, ModuleAnalysisManager &MAM, AsmPrinter &AsmPrinter)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition Error.h:769
Target & getTheRISCV64Target()
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
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:1933
LLVM_ABI void setupMachineFunctionAsmPrinter(MachineFunctionAnalysisManager &MFAM, MachineFunction &MF, AsmPrinter &AsmPrinter)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:572
@ MCSA_Weak
.weak
@ MCSA_ELF_TypeFunction
.type _foo, STT_FUNC # aka @function
@ MCSA_Hidden
.hidden (ELF)
Target & getTheRISCV32beTarget()
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:177
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
static Align getRequiredAlignment(AddressType Length)
Returns the required alignment for an allocation of size Length.
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...