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