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