LLVM 20.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
19#include "RISCV.h"
21#include "RISCVTargetMachine.h"
23#include "llvm/ADT/APInt.h"
24#include "llvm/ADT/Statistic.h"
31#include "llvm/IR/Module.h"
32#include "llvm/MC/MCAsmInfo.h"
33#include "llvm/MC/MCContext.h"
34#include "llvm/MC/MCInst.h"
38#include "llvm/MC/MCStreamer.h"
39#include "llvm/MC/MCSymbol.h"
44
45using namespace llvm;
46
47#define DEBUG_TYPE "asm-printer"
48
49STATISTIC(RISCVNumInstrsCompressed,
50 "Number of RISC-V Compressed instructions emitted");
51
52namespace llvm {
53extern const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures];
54} // namespace llvm
55
56namespace {
57class RISCVAsmPrinter : public AsmPrinter {
58 const RISCVSubtarget *STI;
59
60public:
61 explicit RISCVAsmPrinter(TargetMachine &TM,
62 std::unique_ptr<MCStreamer> Streamer)
63 : AsmPrinter(TM, std::move(Streamer)) {}
64
65 StringRef getPassName() const override { return "RISC-V Assembly Printer"; }
66
67 void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
68 const MachineInstr &MI);
69
70 void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
71 const MachineInstr &MI);
72
73 void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
74 const MachineInstr &MI);
75
76 bool runOnMachineFunction(MachineFunction &MF) override;
77
78 void emitInstruction(const MachineInstr *MI) override;
79
80 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
81 const char *ExtraCode, raw_ostream &OS) override;
82 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
83 const char *ExtraCode, raw_ostream &OS) override;
84
85 // Returns whether Inst is compressed.
86 bool EmitToStreamer(MCStreamer &S, const MCInst &Inst);
87
88 bool lowerPseudoInstExpansion(const MachineInstr *MI, MCInst &Inst);
89
90 typedef std::tuple<unsigned, uint32_t> HwasanMemaccessTuple;
91 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
92 void LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI);
93 void LowerKCFI_CHECK(const MachineInstr &MI);
94 void EmitHwasanMemaccessSymbols(Module &M);
95
96 // Wrapper needed for tblgenned pseudo lowering.
97 bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const;
98
99 void emitStartOfAsmFile(Module &M) override;
100 void emitEndOfAsmFile(Module &M) override;
101
102 void emitFunctionEntryLabel() override;
103 bool emitDirectiveOptionArch();
104
105private:
106 void emitAttributes(const MCSubtargetInfo &SubtargetInfo);
107
108 void emitNTLHint(const MachineInstr *MI);
109
110 bool lowerToMCInst(const MachineInstr *MI, MCInst &OutMI);
111};
112}
113
114void RISCVAsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
115 const MachineInstr &MI) {
116 unsigned NOPBytes = STI->hasStdExtCOrZca() ? 2 : 4;
117 unsigned NumNOPBytes = StackMapOpers(&MI).getNumPatchBytes();
118
119 auto &Ctx = OutStreamer.getContext();
120 MCSymbol *MILabel = Ctx.createTempSymbol();
121 OutStreamer.emitLabel(MILabel);
122
123 SM.recordStackMap(*MILabel, MI);
124 assert(NumNOPBytes % NOPBytes == 0 &&
125 "Invalid number of NOP bytes requested!");
126
127 // Scan ahead to trim the shadow.
128 const MachineBasicBlock &MBB = *MI.getParent();
130 ++MII;
131 while (NumNOPBytes > 0) {
132 if (MII == MBB.end() || MII->isCall() ||
133 MII->getOpcode() == RISCV::DBG_VALUE ||
134 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
135 MII->getOpcode() == TargetOpcode::STACKMAP)
136 break;
137 ++MII;
138 NumNOPBytes -= 4;
139 }
140
141 // Emit nops.
142 emitNops(NumNOPBytes / NOPBytes);
143}
144
145// Lower a patchpoint of the form:
146// [<def>], <id>, <numBytes>, <target>, <numArgs>
147void RISCVAsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
148 const MachineInstr &MI) {
149 unsigned NOPBytes = STI->hasStdExtCOrZca() ? 2 : 4;
150
151 auto &Ctx = OutStreamer.getContext();
152 MCSymbol *MILabel = Ctx.createTempSymbol();
153 OutStreamer.emitLabel(MILabel);
154 SM.recordPatchPoint(*MILabel, MI);
155
156 PatchPointOpers Opers(&MI);
157
158 const MachineOperand &CalleeMO = Opers.getCallTarget();
159 unsigned EncodedBytes = 0;
160
161 if (CalleeMO.isImm()) {
162 uint64_t CallTarget = CalleeMO.getImm();
163 if (CallTarget) {
164 assert((CallTarget & 0xFFFF'FFFF'FFFF) == CallTarget &&
165 "High 16 bits of call target should be zero.");
166 // Materialize the jump address:
168 RISCVMatInt::generateMCInstSeq(CallTarget, *STI, RISCV::X1, Seq);
169 for (MCInst &Inst : Seq) {
170 bool Compressed = EmitToStreamer(OutStreamer, Inst);
171 EncodedBytes += Compressed ? 2 : 4;
172 }
173 bool Compressed = EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JALR)
174 .addReg(RISCV::X1)
175 .addReg(RISCV::X1)
176 .addImm(0));
177 EncodedBytes += Compressed ? 2 : 4;
178 }
179 } else if (CalleeMO.isGlobal()) {
180 MCOperand CallTargetMCOp;
181 lowerOperand(CalleeMO, CallTargetMCOp);
182 EmitToStreamer(OutStreamer,
183 MCInstBuilder(RISCV::PseudoCALL).addOperand(CallTargetMCOp));
184 EncodedBytes += 8;
185 }
186
187 // Emit padding.
188 unsigned NumBytes = Opers.getNumPatchBytes();
189 assert(NumBytes >= EncodedBytes &&
190 "Patchpoint can't request size less than the length of a call.");
191 assert((NumBytes - EncodedBytes) % NOPBytes == 0 &&
192 "Invalid number of NOP bytes requested!");
193 emitNops((NumBytes - EncodedBytes) / NOPBytes);
194}
195
196void RISCVAsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
197 const MachineInstr &MI) {
198 unsigned NOPBytes = STI->hasStdExtCOrZca() ? 2 : 4;
199
200 StatepointOpers SOpers(&MI);
201 if (unsigned PatchBytes = SOpers.getNumPatchBytes()) {
202 assert(PatchBytes % NOPBytes == 0 &&
203 "Invalid number of NOP bytes requested!");
204 emitNops(PatchBytes / NOPBytes);
205 } else {
206 // Lower call target and choose correct opcode
207 const MachineOperand &CallTarget = SOpers.getCallTarget();
208 MCOperand CallTargetMCOp;
209 switch (CallTarget.getType()) {
212 lowerOperand(CallTarget, CallTargetMCOp);
213 EmitToStreamer(
214 OutStreamer,
215 MCInstBuilder(RISCV::PseudoCALL).addOperand(CallTargetMCOp));
216 break;
218 CallTargetMCOp = MCOperand::createImm(CallTarget.getImm());
219 EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JAL)
220 .addReg(RISCV::X1)
221 .addOperand(CallTargetMCOp));
222 break;
224 CallTargetMCOp = MCOperand::createReg(CallTarget.getReg());
225 EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JALR)
226 .addReg(RISCV::X1)
227 .addOperand(CallTargetMCOp)
228 .addImm(0));
229 break;
230 default:
231 llvm_unreachable("Unsupported operand type in statepoint call target");
232 break;
233 }
234 }
235
236 auto &Ctx = OutStreamer.getContext();
237 MCSymbol *MILabel = Ctx.createTempSymbol();
238 OutStreamer.emitLabel(MILabel);
239 SM.recordStatepoint(*MILabel, MI);
240}
241
242bool RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
243 MCInst CInst;
244 bool Res = RISCVRVC::compress(CInst, Inst, *STI);
245 if (Res)
246 ++RISCVNumInstrsCompressed;
247 AsmPrinter::EmitToStreamer(*OutStreamer, Res ? CInst : Inst);
248 return Res;
249}
250
251// Simple pseudo-instructions have their lowering (with expansion to real
252// instructions) auto-generated.
253#include "RISCVGenMCPseudoLowering.inc"
254
255// If the target supports Zihintntl and the instruction has a nontemporal
256// MachineMemOperand, emit an NTLH hint instruction before it.
257void RISCVAsmPrinter::emitNTLHint(const MachineInstr *MI) {
258 if (!STI->hasStdExtZihintntl())
259 return;
260
261 if (MI->memoperands_empty())
262 return;
263
264 MachineMemOperand *MMO = *(MI->memoperands_begin());
265 if (!MMO->isNonTemporal())
266 return;
267
268 unsigned NontemporalMode = 0;
269 if (MMO->getFlags() & MONontemporalBit0)
270 NontemporalMode += 0b1;
271 if (MMO->getFlags() & MONontemporalBit1)
272 NontemporalMode += 0b10;
273
274 MCInst Hint;
275 if (STI->hasStdExtCOrZca() && STI->enableRVCHintInstrs())
276 Hint.setOpcode(RISCV::C_ADD_HINT);
277 else
278 Hint.setOpcode(RISCV::ADD);
279
280 Hint.addOperand(MCOperand::createReg(RISCV::X0));
281 Hint.addOperand(MCOperand::createReg(RISCV::X0));
282 Hint.addOperand(MCOperand::createReg(RISCV::X2 + NontemporalMode));
283
284 EmitToStreamer(*OutStreamer, Hint);
285}
286
287void RISCVAsmPrinter::emitInstruction(const MachineInstr *MI) {
288 RISCV_MC::verifyInstructionPredicates(MI->getOpcode(),
289 getSubtargetInfo().getFeatureBits());
290
291 emitNTLHint(MI);
292
293 // Do any auto-generated pseudo lowerings.
294 if (MCInst OutInst; lowerPseudoInstExpansion(MI, OutInst)) {
295 EmitToStreamer(*OutStreamer, OutInst);
296 return;
297 }
298
299 switch (MI->getOpcode()) {
300 case RISCV::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
301 LowerHWASAN_CHECK_MEMACCESS(*MI);
302 return;
303 case RISCV::KCFI_CHECK:
304 LowerKCFI_CHECK(*MI);
305 return;
306 case RISCV::PseudoRVVInitUndefM1:
307 case RISCV::PseudoRVVInitUndefM2:
308 case RISCV::PseudoRVVInitUndefM4:
309 case RISCV::PseudoRVVInitUndefM8:
310 return;
311 case TargetOpcode::STACKMAP:
312 return LowerSTACKMAP(*OutStreamer, SM, *MI);
313 case TargetOpcode::PATCHPOINT:
314 return LowerPATCHPOINT(*OutStreamer, SM, *MI);
315 case TargetOpcode::STATEPOINT:
316 return LowerSTATEPOINT(*OutStreamer, SM, *MI);
317 }
318
319 MCInst OutInst;
320 if (!lowerToMCInst(MI, OutInst))
321 EmitToStreamer(*OutStreamer, OutInst);
322}
323
324bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
325 const char *ExtraCode, raw_ostream &OS) {
326 // First try the generic code, which knows about modifiers like 'c' and 'n'.
327 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
328 return false;
329
330 const MachineOperand &MO = MI->getOperand(OpNo);
331 if (ExtraCode && ExtraCode[0]) {
332 if (ExtraCode[1] != 0)
333 return true; // Unknown modifier.
334
335 switch (ExtraCode[0]) {
336 default:
337 return true; // Unknown modifier.
338 case 'z': // Print zero register if zero, regular printing otherwise.
339 if (MO.isImm() && MO.getImm() == 0) {
341 return false;
342 }
343 break;
344 case 'i': // Literal 'i' if operand is not a register.
345 if (!MO.isReg())
346 OS << 'i';
347 return false;
348 }
349 }
350
351 switch (MO.getType()) {
353 OS << MO.getImm();
354 return false;
357 return false;
359 PrintSymbolOperand(MO, OS);
360 return false;
362 MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());
363 Sym->print(OS, MAI);
364 return false;
365 }
366 default:
367 break;
368 }
369
370 return true;
371}
372
373bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
374 unsigned OpNo,
375 const char *ExtraCode,
376 raw_ostream &OS) {
377 if (ExtraCode)
378 return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
379
380 const MachineOperand &AddrReg = MI->getOperand(OpNo);
381 assert(MI->getNumOperands() > OpNo + 1 && "Expected additional operand");
382 const MachineOperand &Offset = MI->getOperand(OpNo + 1);
383 // All memory operands should have a register and an immediate operand (see
384 // RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand).
385 if (!AddrReg.isReg())
386 return true;
387 if (!Offset.isImm() && !Offset.isGlobal() && !Offset.isBlockAddress() &&
388 !Offset.isMCSymbol())
389 return true;
390
391 MCOperand MCO;
392 if (!lowerOperand(Offset, MCO))
393 return true;
394
395 if (Offset.isImm())
396 OS << MCO.getImm();
397 else if (Offset.isGlobal() || Offset.isBlockAddress() || Offset.isMCSymbol())
398 OS << *MCO.getExpr();
399 OS << "(" << RISCVInstPrinter::getRegisterName(AddrReg.getReg()) << ")";
400 return false;
401}
402
403bool RISCVAsmPrinter::emitDirectiveOptionArch() {
405 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
406 SmallVector<RISCVOptionArchArg> NeedEmitStdOptionArgs;
407 const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo();
408 for (const auto &Feature : RISCVFeatureKV) {
409 if (STI->hasFeature(Feature.Value) == MCSTI.hasFeature(Feature.Value))
410 continue;
411
413 continue;
414
415 auto Delta = STI->hasFeature(Feature.Value) ? RISCVOptionArchArgType::Plus
416 : RISCVOptionArchArgType::Minus;
417 NeedEmitStdOptionArgs.emplace_back(Delta, Feature.Key);
418 }
419 if (!NeedEmitStdOptionArgs.empty()) {
421 RTS.emitDirectiveOptionArch(NeedEmitStdOptionArgs);
422 return true;
423 }
424
425 return false;
426}
427
428bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
429 STI = &MF.getSubtarget<RISCVSubtarget>();
431 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
432
433 bool EmittedOptionArch = emitDirectiveOptionArch();
434
435 SetupMachineFunction(MF);
436 emitFunctionBody();
437
438 if (EmittedOptionArch)
439 RTS.emitDirectiveOptionPop();
440 return false;
441}
442
443void RISCVAsmPrinter::emitStartOfAsmFile(Module &M) {
445 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
446 if (const MDString *ModuleTargetABI =
447 dyn_cast_or_null<MDString>(M.getModuleFlag("target-abi")))
448 RTS.setTargetABI(RISCVABI::getTargetABI(ModuleTargetABI->getString()));
449
450 MCSubtargetInfo SubtargetInfo = *TM.getMCSubtargetInfo();
451
452 // Use module flag to update feature bits.
453 if (auto *MD = dyn_cast_or_null<MDNode>(M.getModuleFlag("riscv-isa"))) {
454 for (auto &ISA : MD->operands()) {
455 if (auto *ISAString = dyn_cast_or_null<MDString>(ISA)) {
457 ISAString->getString(), /*EnableExperimentalExtension=*/true,
458 /*ExperimentalExtensionVersionCheck=*/true);
459 if (!errorToBool(ParseResult.takeError())) {
460 auto &ISAInfo = *ParseResult;
461 for (const auto &Feature : RISCVFeatureKV) {
462 if (ISAInfo->hasExtension(Feature.Key) &&
463 !SubtargetInfo.hasFeature(Feature.Value))
464 SubtargetInfo.ToggleFeature(Feature.Key);
465 }
466 }
467 }
468 }
469
470 RTS.setFlagsFromFeatures(SubtargetInfo);
471 }
472
473 if (TM.getTargetTriple().isOSBinFormatELF())
474 emitAttributes(SubtargetInfo);
475}
476
477void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) {
479 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
480
481 if (TM.getTargetTriple().isOSBinFormatELF())
483 EmitHwasanMemaccessSymbols(M);
484}
485
486void RISCVAsmPrinter::emitAttributes(const MCSubtargetInfo &SubtargetInfo) {
488 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
489 // Use MCSubtargetInfo from TargetMachine. Individual functions may have
490 // attributes that differ from other functions in the module and we have no
491 // way to know which function is correct.
492 RTS.emitTargetAttributes(SubtargetInfo, /*EmitStackAlign*/ true);
493}
494
495void RISCVAsmPrinter::emitFunctionEntryLabel() {
496 const auto *RMFI = MF->getInfo<RISCVMachineFunctionInfo>();
497 if (RMFI->isVectorCall()) {
498 auto &RTS =
499 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
500 RTS.emitDirectiveVariantCC(*CurrentFnSym);
501 }
503}
504
505// Force static initialization.
509}
510
511void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {
512 Register Reg = MI.getOperand(0).getReg();
513 uint32_t AccessInfo = MI.getOperand(1).getImm();
514 MCSymbol *&Sym =
515 HwasanMemaccessSymbols[HwasanMemaccessTuple(Reg, AccessInfo)];
516 if (!Sym) {
517 // FIXME: Make this work on non-ELF.
518 if (!TM.getTargetTriple().isOSBinFormatELF())
519 report_fatal_error("llvm.hwasan.check.memaccess only supported on ELF");
520
521 std::string SymName = "__hwasan_check_x" + utostr(Reg - RISCV::X0) + "_" +
522 utostr(AccessInfo) + "_short";
523 Sym = OutContext.getOrCreateSymbol(SymName);
524 }
526 auto Expr = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, OutContext);
527
528 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr));
529}
530
531void RISCVAsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {
532 Register AddrReg = MI.getOperand(0).getReg();
533 assert(std::next(MI.getIterator())->isCall() &&
534 "KCFI_CHECK not followed by a call instruction");
535 assert(std::next(MI.getIterator())->getOperand(0).getReg() == AddrReg &&
536 "KCFI_CHECK call target doesn't match call operand");
537
538 // Temporary registers for comparing the hashes. If a register is used
539 // for the call target, or reserved by the user, we can clobber another
540 // temporary register as the check is immediately followed by the
541 // call. The check defaults to X6/X7, but can fall back to X28-X31 if
542 // needed.
543 unsigned ScratchRegs[] = {RISCV::X6, RISCV::X7};
544 unsigned NextReg = RISCV::X28;
545 auto isRegAvailable = [&](unsigned Reg) {
546 return Reg != AddrReg && !STI->isRegisterReservedByUser(Reg);
547 };
548 for (auto &Reg : ScratchRegs) {
549 if (isRegAvailable(Reg))
550 continue;
551 while (!isRegAvailable(NextReg))
552 ++NextReg;
553 Reg = NextReg++;
554 if (Reg > RISCV::X31)
555 report_fatal_error("Unable to find scratch registers for KCFI_CHECK");
556 }
557
558 if (AddrReg == RISCV::X0) {
559 // Checking X0 makes no sense. Instead of emitting a load, zero
560 // ScratchRegs[0].
561 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI)
562 .addReg(ScratchRegs[0])
563 .addReg(RISCV::X0)
564 .addImm(0));
565 } else {
566 // Adjust the offset for patchable-function-prefix. This assumes that
567 // patchable-function-prefix is the same for all functions.
568 int NopSize = STI->hasStdExtCOrZca() ? 2 : 4;
569 int64_t PrefixNops = 0;
570 (void)MI.getMF()
571 ->getFunction()
572 .getFnAttribute("patchable-function-prefix")
573 .getValueAsString()
574 .getAsInteger(10, PrefixNops);
575
576 // Load the target function type hash.
577 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::LW)
578 .addReg(ScratchRegs[0])
579 .addReg(AddrReg)
580 .addImm(-(PrefixNops * NopSize + 4)));
581 }
582
583 // Load the expected 32-bit type hash.
584 const int64_t Type = MI.getOperand(1).getImm();
585 const int64_t Hi20 = ((Type + 0x800) >> 12) & 0xFFFFF;
586 const int64_t Lo12 = SignExtend64<12>(Type);
587 if (Hi20) {
588 EmitToStreamer(
589 *OutStreamer,
590 MCInstBuilder(RISCV::LUI).addReg(ScratchRegs[1]).addImm(Hi20));
591 }
592 if (Lo12 || Hi20 == 0) {
593 EmitToStreamer(*OutStreamer,
594 MCInstBuilder((STI->hasFeature(RISCV::Feature64Bit) && Hi20)
595 ? RISCV::ADDIW
596 : RISCV::ADDI)
597 .addReg(ScratchRegs[1])
598 .addReg(ScratchRegs[1])
599 .addImm(Lo12));
600 }
601
602 // Compare the hashes and trap if there's a mismatch.
603 MCSymbol *Pass = OutContext.createTempSymbol();
604 EmitToStreamer(*OutStreamer,
605 MCInstBuilder(RISCV::BEQ)
606 .addReg(ScratchRegs[0])
607 .addReg(ScratchRegs[1])
608 .addExpr(MCSymbolRefExpr::create(Pass, OutContext)));
609
610 MCSymbol *Trap = OutContext.createTempSymbol();
611 OutStreamer->emitLabel(Trap);
612 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::EBREAK));
613 emitKCFITrapEntry(*MI.getMF(), Trap);
614 OutStreamer->emitLabel(Pass);
615}
616
617void RISCVAsmPrinter::EmitHwasanMemaccessSymbols(Module &M) {
618 if (HwasanMemaccessSymbols.empty())
619 return;
620
621 assert(TM.getTargetTriple().isOSBinFormatELF());
622 // Use MCSubtargetInfo from TargetMachine. Individual functions may have
623 // attributes that differ from other functions in the module and we have no
624 // way to know which function is correct.
625 const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo();
626
627 MCSymbol *HwasanTagMismatchV2Sym =
628 OutContext.getOrCreateSymbol("__hwasan_tag_mismatch_v2");
629 // Annotate symbol as one having incompatible calling convention, so
630 // run-time linkers can instead eagerly bind this function.
631 auto &RTS =
632 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
633 RTS.emitDirectiveVariantCC(*HwasanTagMismatchV2Sym);
634
635 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
636 MCSymbolRefExpr::create(HwasanTagMismatchV2Sym, OutContext);
637 auto Expr = RISCVMCExpr::create(HwasanTagMismatchV2Ref,
638 RISCVMCExpr::VK_RISCV_CALL, OutContext);
639
640 for (auto &P : HwasanMemaccessSymbols) {
641 unsigned Reg = std::get<0>(P.first);
642 uint32_t AccessInfo = std::get<1>(P.first);
643 MCSymbol *Sym = P.second;
644
645 unsigned Size =
646 1 << ((AccessInfo >> HWASanAccessInfo::AccessSizeShift) & 0xf);
647 OutStreamer->switchSection(OutContext.getELFSection(
648 ".text.hot", ELF::SHT_PROGBITS,
650 /*IsComdat=*/true));
651
653 OutStreamer->emitSymbolAttribute(Sym, MCSA_Weak);
654 OutStreamer->emitSymbolAttribute(Sym, MCSA_Hidden);
655 OutStreamer->emitLabel(Sym);
656
657 // Extract shadow offset from ptr
658 OutStreamer->emitInstruction(
659 MCInstBuilder(RISCV::SLLI).addReg(RISCV::X6).addReg(Reg).addImm(8),
660 MCSTI);
661 OutStreamer->emitInstruction(MCInstBuilder(RISCV::SRLI)
662 .addReg(RISCV::X6)
663 .addReg(RISCV::X6)
664 .addImm(12),
665 MCSTI);
666 // load shadow tag in X6, X5 contains shadow base
667 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADD)
668 .addReg(RISCV::X6)
669 .addReg(RISCV::X5)
670 .addReg(RISCV::X6),
671 MCSTI);
672 OutStreamer->emitInstruction(
673 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
674 MCSTI);
675 // Extract tag from X5 and compare it with loaded tag from shadow
676 OutStreamer->emitInstruction(
677 MCInstBuilder(RISCV::SRLI).addReg(RISCV::X7).addReg(Reg).addImm(56),
678 MCSTI);
679 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
680 // X7 contains tag from memory, while X6 contains tag from the pointer
681 OutStreamer->emitInstruction(
682 MCInstBuilder(RISCV::BNE)
683 .addReg(RISCV::X7)
684 .addReg(RISCV::X6)
685 .addExpr(MCSymbolRefExpr::create(HandleMismatchOrPartialSym,
686 OutContext)),
687 MCSTI);
688 MCSymbol *ReturnSym = OutContext.createTempSymbol();
689 OutStreamer->emitLabel(ReturnSym);
690 OutStreamer->emitInstruction(MCInstBuilder(RISCV::JALR)
691 .addReg(RISCV::X0)
692 .addReg(RISCV::X1)
693 .addImm(0),
694 MCSTI);
695 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
696
697 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI)
698 .addReg(RISCV::X28)
699 .addReg(RISCV::X0)
700 .addImm(16),
701 MCSTI);
702 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
703 OutStreamer->emitInstruction(
704 MCInstBuilder(RISCV::BGEU)
705 .addReg(RISCV::X6)
706 .addReg(RISCV::X28)
707 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
708 MCSTI);
709
710 OutStreamer->emitInstruction(
711 MCInstBuilder(RISCV::ANDI).addReg(RISCV::X28).addReg(Reg).addImm(0xF),
712 MCSTI);
713
714 if (Size != 1)
715 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI)
716 .addReg(RISCV::X28)
717 .addReg(RISCV::X28)
718 .addImm(Size - 1),
719 MCSTI);
720 OutStreamer->emitInstruction(
721 MCInstBuilder(RISCV::BGE)
722 .addReg(RISCV::X28)
723 .addReg(RISCV::X6)
724 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
725 MCSTI);
726
727 OutStreamer->emitInstruction(
728 MCInstBuilder(RISCV::ORI).addReg(RISCV::X6).addReg(Reg).addImm(0xF),
729 MCSTI);
730 OutStreamer->emitInstruction(
731 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
732 MCSTI);
733 OutStreamer->emitInstruction(
734 MCInstBuilder(RISCV::BEQ)
735 .addReg(RISCV::X6)
736 .addReg(RISCV::X7)
737 .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)),
738 MCSTI);
739
740 OutStreamer->emitLabel(HandleMismatchSym);
741
742 // | Previous stack frames... |
743 // +=================================+ <-- [SP + 256]
744 // | ... |
745 // | |
746 // | Stack frame space for x12 - x31.|
747 // | |
748 // | ... |
749 // +---------------------------------+ <-- [SP + 96]
750 // | Saved x11(arg1), as |
751 // | __hwasan_check_* clobbers it. |
752 // +---------------------------------+ <-- [SP + 88]
753 // | Saved x10(arg0), as |
754 // | __hwasan_check_* clobbers it. |
755 // +---------------------------------+ <-- [SP + 80]
756 // | |
757 // | Stack frame space for x9. |
758 // +---------------------------------+ <-- [SP + 72]
759 // | |
760 // | Saved x8(fp), as |
761 // | __hwasan_check_* clobbers it. |
762 // +---------------------------------+ <-- [SP + 64]
763 // | ... |
764 // | |
765 // | Stack frame space for x2 - x7. |
766 // | |
767 // | ... |
768 // +---------------------------------+ <-- [SP + 16]
769 // | Return address (x1) for caller |
770 // | of __hwasan_check_*. |
771 // +---------------------------------+ <-- [SP + 8]
772 // | Reserved place for x0, possibly |
773 // | junk, since we don't save it. |
774 // +---------------------------------+ <-- [x2 / SP]
775
776 // Adjust sp
777 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI)
778 .addReg(RISCV::X2)
779 .addReg(RISCV::X2)
780 .addImm(-256),
781 MCSTI);
782
783 // store x10(arg0) by new sp
784 OutStreamer->emitInstruction(MCInstBuilder(RISCV::SD)
785 .addReg(RISCV::X10)
786 .addReg(RISCV::X2)
787 .addImm(8 * 10),
788 MCSTI);
789 // store x11(arg1) by new sp
790 OutStreamer->emitInstruction(MCInstBuilder(RISCV::SD)
791 .addReg(RISCV::X11)
792 .addReg(RISCV::X2)
793 .addImm(8 * 11),
794 MCSTI);
795
796 // store x8(fp) by new sp
797 OutStreamer->emitInstruction(
798 MCInstBuilder(RISCV::SD).addReg(RISCV::X8).addReg(RISCV::X2).addImm(8 *
799 8),
800 MCSTI);
801 // store x1(ra) by new sp
802 OutStreamer->emitInstruction(
803 MCInstBuilder(RISCV::SD).addReg(RISCV::X1).addReg(RISCV::X2).addImm(1 *
804 8),
805 MCSTI);
806 if (Reg != RISCV::X10)
807 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI)
808 .addReg(RISCV::X10)
809 .addReg(Reg)
810 .addImm(0),
811 MCSTI);
812 OutStreamer->emitInstruction(
813 MCInstBuilder(RISCV::ADDI)
814 .addReg(RISCV::X11)
815 .addReg(RISCV::X0)
817 MCSTI);
818
819 OutStreamer->emitInstruction(MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr),
820 MCSTI);
821 }
822}
823
825 const AsmPrinter &AP) {
826 MCContext &Ctx = AP.OutContext;
828
829 switch (MO.getTargetFlags()) {
830 default:
831 llvm_unreachable("Unknown target flag on GV operand");
832 case RISCVII::MO_None:
834 break;
835 case RISCVII::MO_CALL:
837 break;
838 case RISCVII::MO_LO:
840 break;
841 case RISCVII::MO_HI:
843 break;
846 break;
849 break;
852 break;
855 break;
858 break;
861 break;
864 break;
867 break;
870 break;
873 break;
876 break;
879 break;
880 }
881
882 const MCExpr *ME =
884
885 if (!MO.isJTI() && !MO.isMBB() && MO.getOffset())
887 ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
888
889 if (Kind != RISCVMCExpr::VK_RISCV_None)
890 ME = RISCVMCExpr::create(ME, Kind, Ctx);
891 return MCOperand::createExpr(ME);
892}
893
894bool RISCVAsmPrinter::lowerOperand(const MachineOperand &MO,
895 MCOperand &MCOp) const {
896 switch (MO.getType()) {
897 default:
898 report_fatal_error("lowerOperand: unknown operand type");
900 // Ignore all implicit register operands.
901 if (MO.isImplicit())
902 return false;
903 MCOp = MCOperand::createReg(MO.getReg());
904 break;
906 // Regmasks are like implicit defs.
907 return false;
909 MCOp = MCOperand::createImm(MO.getImm());
910 break;
912 MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), *this);
913 break;
915 MCOp = lowerSymbolOperand(MO, getSymbolPreferLocal(*MO.getGlobal()), *this);
916 break;
918 MCOp = lowerSymbolOperand(MO, GetBlockAddressSymbol(MO.getBlockAddress()),
919 *this);
920 break;
922 MCOp = lowerSymbolOperand(MO, GetExternalSymbolSymbol(MO.getSymbolName()),
923 *this);
924 break;
926 MCOp = lowerSymbolOperand(MO, GetCPISymbol(MO.getIndex()), *this);
927 break;
929 MCOp = lowerSymbolOperand(MO, GetJTISymbol(MO.getIndex()), *this);
930 break;
932 MCOp = lowerSymbolOperand(MO, MO.getMCSymbol(), *this);
933 break;
934 }
935 return true;
936}
937
939 MCInst &OutMI) {
941 RISCVVPseudosTable::getPseudoInfo(MI->getOpcode());
942 if (!RVV)
943 return false;
944
945 OutMI.setOpcode(RVV->BaseInstr);
946
947 const MachineBasicBlock *MBB = MI->getParent();
948 assert(MBB && "MI expected to be in a basic block");
949 const MachineFunction *MF = MBB->getParent();
950 assert(MF && "MBB expected to be in a machine function");
951
952 const RISCVSubtarget &Subtarget = MF->getSubtarget<RISCVSubtarget>();
953 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
954 const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
955 assert(TRI && "TargetRegisterInfo expected");
956
957 const MCInstrDesc &MCID = MI->getDesc();
958 uint64_t TSFlags = MCID.TSFlags;
959 unsigned NumOps = MI->getNumExplicitOperands();
960
961 // Skip policy, SEW, VL, VXRM/FRM operands which are the last operands if
962 // present.
963 if (RISCVII::hasVecPolicyOp(TSFlags))
964 --NumOps;
965 if (RISCVII::hasSEWOp(TSFlags))
966 --NumOps;
967 if (RISCVII::hasVLOp(TSFlags))
968 --NumOps;
969 if (RISCVII::hasRoundModeOp(TSFlags))
970 --NumOps;
971
972 bool hasVLOutput = RISCV::isFaultFirstLoad(*MI);
973 for (unsigned OpNo = 0; OpNo != NumOps; ++OpNo) {
974 const MachineOperand &MO = MI->getOperand(OpNo);
975 // Skip vl ouput. It should be the second output.
976 if (hasVLOutput && OpNo == 1)
977 continue;
978
979 // Skip passthru op. It should be the first operand after the defs.
980 if (OpNo == MI->getNumExplicitDefs() && MO.isReg() && MO.isTied()) {
981 assert(MCID.getOperandConstraint(OpNo, MCOI::TIED_TO) == 0 &&
982 "Expected tied to first def.");
983 const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode());
984 // Skip if the next operand in OutMI is not supposed to be tied. Unless it
985 // is a _TIED instruction.
987 0 &&
988 !RISCVII::isTiedPseudo(TSFlags))
989 continue;
990 }
991
992 MCOperand MCOp;
993 switch (MO.getType()) {
994 default:
995 llvm_unreachable("Unknown operand type");
997 Register Reg = MO.getReg();
998
999 if (RISCV::VRM2RegClass.contains(Reg) ||
1000 RISCV::VRM4RegClass.contains(Reg) ||
1001 RISCV::VRM8RegClass.contains(Reg)) {
1002 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0);
1003 assert(Reg && "Subregister does not exist");
1004 } else if (RISCV::FPR16RegClass.contains(Reg)) {
1005 Reg =
1006 TRI->getMatchingSuperReg(Reg, RISCV::sub_16, &RISCV::FPR32RegClass);
1007 assert(Reg && "Subregister does not exist");
1008 } else if (RISCV::FPR64RegClass.contains(Reg)) {
1009 Reg = TRI->getSubReg(Reg, RISCV::sub_32);
1010 assert(Reg && "Superregister does not exist");
1011 } else if (RISCV::VRN2M1RegClass.contains(Reg) ||
1012 RISCV::VRN2M2RegClass.contains(Reg) ||
1013 RISCV::VRN2M4RegClass.contains(Reg) ||
1014 RISCV::VRN3M1RegClass.contains(Reg) ||
1015 RISCV::VRN3M2RegClass.contains(Reg) ||
1016 RISCV::VRN4M1RegClass.contains(Reg) ||
1017 RISCV::VRN4M2RegClass.contains(Reg) ||
1018 RISCV::VRN5M1RegClass.contains(Reg) ||
1019 RISCV::VRN6M1RegClass.contains(Reg) ||
1020 RISCV::VRN7M1RegClass.contains(Reg) ||
1021 RISCV::VRN8M1RegClass.contains(Reg)) {
1022 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0);
1023 assert(Reg && "Subregister does not exist");
1024 }
1025
1026 MCOp = MCOperand::createReg(Reg);
1027 break;
1028 }
1030 MCOp = MCOperand::createImm(MO.getImm());
1031 break;
1032 }
1033 OutMI.addOperand(MCOp);
1034 }
1035
1036 // Unmasked pseudo instructions need to append dummy mask operand to
1037 // V instructions. All V instructions are modeled as the masked version.
1038 const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode());
1039 if (OutMI.getNumOperands() < OutMCID.getNumOperands()) {
1040 assert(OutMCID.operands()[OutMI.getNumOperands()].RegClass ==
1041 RISCV::VMV0RegClassID &&
1042 "Expected only mask operand to be missing");
1043 OutMI.addOperand(MCOperand::createReg(RISCV::NoRegister));
1044 }
1045
1046 assert(OutMI.getNumOperands() == OutMCID.getNumOperands());
1047 return true;
1048}
1049
1050bool RISCVAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {
1052 return false;
1053
1054 OutMI.setOpcode(MI->getOpcode());
1055
1056 for (const MachineOperand &MO : MI->operands()) {
1057 MCOperand MCOp;
1058 if (lowerOperand(MO, MCOp))
1059 OutMI.addOperand(MCOp);
1060 }
1061
1062 switch (OutMI.getOpcode()) {
1063 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
1064 const Function &F = MI->getParent()->getParent()->getFunction();
1065 if (F.hasFnAttribute("patchable-function-entry")) {
1066 unsigned Num;
1067 if (F.getFnAttribute("patchable-function-entry")
1068 .getValueAsString()
1069 .getAsInteger(10, Num))
1070 return false;
1071 emitNops(Num);
1072 return true;
1073 }
1074 break;
1075 }
1076 }
1077 return false;
1078}
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
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:131
uint64_t Size
Symbol * Sym
Definition: ELF_riscv.cpp:479
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition: MD5.cpp:55
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
unsigned const TargetRegisterInfo * TRI
Module.h This file contains the declarations for the Module class.
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
#define P(N)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmPrinter()
static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym, const AsmPrinter &AP)
static bool lowerRISCVVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition: Statistic.h:166
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:469
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:86
virtual void emitInstruction(const MachineInstr *)
Targets should implement this to emit instructions.
Definition: AsmPrinter.h:561
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
Definition: AsmPrinter.cpp:403
virtual void emitStartOfAsmFile(Module &)
This virtual method can be overridden by targets that want to emit something at the start of their fi...
Definition: AsmPrinter.h:537
virtual void emitEndOfAsmFile(Module &)
This virtual method can be overridden by targets that want to emit something at the end of their file...
Definition: AsmPrinter.h:541
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition: AsmPrinter.h:96
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
Definition: AsmPrinter.h:387
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.
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:532
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:193
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
MCInstBuilder & addReg(unsigned Reg)
Add a new register operand.
Definition: MCInstBuilder.h:37
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Definition: MCInstBuilder.h:43
MCInstBuilder & addExpr(const MCExpr *Val)
Add a new MCExpr operand.
Definition: MCInstBuilder.h:61
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
unsigned getNumOperands() const
Definition: MCInst.h:208
unsigned getOpcode() const
Definition: MCInst.h:198
void addOperand(const MCOperand Op)
Definition: MCInst.h:210
void setOpcode(unsigned Op)
Definition: MCInst.h:197
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:198
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
Definition: MCInstrDesc.h:237
ArrayRef< MCOperandInfo > operands() const
Definition: MCInstrDesc.h:239
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specified operand constraint if it is present.
Definition: MCInstrDesc.h:219
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:134
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:162
int64_t getImm() const
Definition: MCInst.h:80
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:141
const MCExpr * getExpr() const
Definition: MCInst.h:114
Streaming machine code generation interface.
Definition: MCStreamer.h:213
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.
MCContext & getContext() const
Definition: MCStreamer.h:300
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
Definition: MCStreamer.cpp:414
MCTargetStreamer * getTargetStreamer()
Definition: MCStreamer.h:309
virtual void switchSection(MCSection *Section, uint32_t Subsec=0)
Set the current section where code is being emitted to Section.
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
FeatureBitset ToggleFeature(uint64_t FB)
Toggle a feature and return the re-computed feature bits.
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:188
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:393
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
A single uniqued string.
Definition: Metadata.h:720
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.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Representation of each machine instruction.
Definition: MachineInstr.h:69
A description of a memory reference used in the backend.
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 isImplicit() 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:65
This class represents success/failure for parsing-like operations that find it important to chain tog...
Pass interface - Implemented by all 'passes'.
Definition: Pass.h:94
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
MI-level patchpoint operands.
Definition: StackMaps.h:76
static bool isSupportedExtensionFeature(StringRef Ext)
static 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)
static const RISCVMCExpr * create(const MCExpr *Expr, VariantKind Kind, MCContext &Ctx)
Definition: RISCVMCExpr.cpp:30
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
const RISCVRegisterInfo * getRegisterInfo() const override
const RISCVInstrInfo * getInstrInfo() const override
virtual void emitDirectiveVariantCC(MCSymbol &Symbol)
void emitTargetAttributes(const MCSubtargetInfo &STI, bool EmitStackAlign)
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:19
bool empty() const
Definition: SmallVector.h:94
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:950
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
MI-level stackmap operands.
Definition: StackMaps.h:35
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given stackmap should emit.
Definition: StackMaps.h:50
void recordStatepoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a statepoint instruction.
Definition: StackMaps.cpp:569
void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
Definition: StackMaps.cpp:548
void recordStackMap(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a stackmap instruction.
Definition: StackMaps.cpp:538
MI-level Statepoint operands.
Definition: StackMaps.h:158
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
TargetInstrInfo - Interface to description of machine instruction set.
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:77
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ SHT_PROGBITS
Definition: ELF.h:1089
@ SHF_ALLOC
Definition: ELF.h:1186
@ SHF_GROUP
Definition: ELF.h:1208
@ SHF_EXECINSTR
Definition: ELF.h:1189
ABI getTargetABI(StringRef ABIName)
static bool hasRoundModeOp(uint64_t TSFlags)
static bool isTiedPseudo(uint64_t TSFlags)
static bool hasVLOp(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)
bool isFaultFirstLoad(const MachineInstr &MI)
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
Definition: Error.h:1099
@ Offset
Definition: DWP.cpp:480
static const MachineMemOperand::Flags MONontemporalBit1
Target & getTheRISCV32Target()
static const MachineMemOperand::Flags MONontemporalBit0
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
Target & getTheRISCV64Target()
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1856
const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures]
@ MCSA_Weak
.weak
Definition: MCDirectives.h:45
@ MCSA_ELF_TypeFunction
.type _foo, STT_FUNC # aka @function
Definition: MCDirectives.h:23
@ MCSA_Hidden
.hidden (ELF)
Definition: MCDirectives.h:33
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...
Used to provide key value pairs for feature and CPU bit flags.