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"
22#include "RISCVRegisterInfo.h"
24#include "llvm/ADT/APInt.h"
25#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
81
82 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
83 const char *ExtraCode, raw_ostream &OS) override;
84 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
85 const char *ExtraCode, raw_ostream &OS) override;
86
87 // Returns whether Inst is compressed.
88 bool EmitToStreamer(MCStreamer &S, const MCInst &Inst,
89 const MCSubtargetInfo &SubtargetInfo);
90 bool EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
91 return EmitToStreamer(S, Inst, *STI);
92 }
93
94 bool lowerPseudoInstExpansion(const MachineInstr *MI, MCInst &Inst);
95
96 typedef std::tuple<unsigned, uint32_t> HwasanMemaccessTuple;
97 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
98 void LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI);
99 void LowerKCFI_CHECK(const MachineInstr &MI);
100 void EmitHwasanMemaccessSymbols(Module &M);
101
102 // Wrapper needed for tblgenned pseudo lowering.
103 bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const;
104
105 void emitStartOfAsmFile(Module &M) override;
106 void emitEndOfAsmFile(Module &M) override;
107
108 void emitFunctionEntryLabel() override;
109 bool emitDirectiveOptionArch();
110
111private:
112 void emitAttributes(const MCSubtargetInfo &SubtargetInfo);
113
114 void emitNTLHint(const MachineInstr *MI);
115
116 // XRay Support
117 void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr *MI);
118 void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr *MI);
119 void LowerPATCHABLE_TAIL_CALL(const MachineInstr *MI);
120 void emitSled(const MachineInstr *MI, SledKind Kind);
121
122 bool lowerToMCInst(const MachineInstr *MI, MCInst &OutMI);
123};
124}
125
126void RISCVAsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
127 const MachineInstr &MI) {
128 unsigned NOPBytes = STI->hasStdExtCOrZca() ? 2 : 4;
129 unsigned NumNOPBytes = StackMapOpers(&MI).getNumPatchBytes();
130
131 auto &Ctx = OutStreamer.getContext();
132 MCSymbol *MILabel = Ctx.createTempSymbol();
133 OutStreamer.emitLabel(MILabel);
134
135 SM.recordStackMap(*MILabel, MI);
136 assert(NumNOPBytes % NOPBytes == 0 &&
137 "Invalid number of NOP bytes requested!");
138
139 // Scan ahead to trim the shadow.
140 const MachineBasicBlock &MBB = *MI.getParent();
142 ++MII;
143 while (NumNOPBytes > 0) {
144 if (MII == MBB.end() || MII->isCall() ||
145 MII->getOpcode() == RISCV::DBG_VALUE ||
146 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
147 MII->getOpcode() == TargetOpcode::STACKMAP)
148 break;
149 ++MII;
150 NumNOPBytes -= 4;
151 }
152
153 // Emit nops.
154 emitNops(NumNOPBytes / NOPBytes);
155}
156
157// Lower a patchpoint of the form:
158// [<def>], <id>, <numBytes>, <target>, <numArgs>
159void RISCVAsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
160 const MachineInstr &MI) {
161 unsigned NOPBytes = STI->hasStdExtCOrZca() ? 2 : 4;
162
163 auto &Ctx = OutStreamer.getContext();
164 MCSymbol *MILabel = Ctx.createTempSymbol();
165 OutStreamer.emitLabel(MILabel);
166 SM.recordPatchPoint(*MILabel, MI);
167
168 PatchPointOpers Opers(&MI);
169
170 const MachineOperand &CalleeMO = Opers.getCallTarget();
171 unsigned EncodedBytes = 0;
172
173 if (CalleeMO.isImm()) {
174 uint64_t CallTarget = CalleeMO.getImm();
175 if (CallTarget) {
176 assert((CallTarget & 0xFFFF'FFFF'FFFF) == CallTarget &&
177 "High 16 bits of call target should be zero.");
178 // Materialize the jump address:
180 RISCVMatInt::generateMCInstSeq(CallTarget, *STI, RISCV::X1, Seq);
181 for (MCInst &Inst : Seq) {
182 bool Compressed = EmitToStreamer(OutStreamer, Inst);
183 EncodedBytes += Compressed ? 2 : 4;
184 }
185 bool Compressed = EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JALR)
186 .addReg(RISCV::X1)
187 .addReg(RISCV::X1)
188 .addImm(0));
189 EncodedBytes += Compressed ? 2 : 4;
190 }
191 } else if (CalleeMO.isGlobal()) {
192 MCOperand CallTargetMCOp;
193 lowerOperand(CalleeMO, CallTargetMCOp);
194 EmitToStreamer(OutStreamer,
195 MCInstBuilder(RISCV::PseudoCALL).addOperand(CallTargetMCOp));
196 EncodedBytes += 8;
197 }
198
199 // Emit padding.
200 unsigned NumBytes = Opers.getNumPatchBytes();
201 assert(NumBytes >= EncodedBytes &&
202 "Patchpoint can't request size less than the length of a call.");
203 assert((NumBytes - EncodedBytes) % NOPBytes == 0 &&
204 "Invalid number of NOP bytes requested!");
205 emitNops((NumBytes - EncodedBytes) / NOPBytes);
206}
207
208void RISCVAsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
209 const MachineInstr &MI) {
210 unsigned NOPBytes = STI->hasStdExtCOrZca() ? 2 : 4;
211
212 StatepointOpers SOpers(&MI);
213 if (unsigned PatchBytes = SOpers.getNumPatchBytes()) {
214 assert(PatchBytes % NOPBytes == 0 &&
215 "Invalid number of NOP bytes requested!");
216 emitNops(PatchBytes / NOPBytes);
217 } else {
218 // Lower call target and choose correct opcode
219 const MachineOperand &CallTarget = SOpers.getCallTarget();
220 MCOperand CallTargetMCOp;
221 switch (CallTarget.getType()) {
224 lowerOperand(CallTarget, CallTargetMCOp);
225 EmitToStreamer(
226 OutStreamer,
227 MCInstBuilder(RISCV::PseudoCALL).addOperand(CallTargetMCOp));
228 break;
230 CallTargetMCOp = MCOperand::createImm(CallTarget.getImm());
231 EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JAL)
232 .addReg(RISCV::X1)
233 .addOperand(CallTargetMCOp));
234 break;
236 CallTargetMCOp = MCOperand::createReg(CallTarget.getReg());
237 EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JALR)
238 .addReg(RISCV::X1)
239 .addOperand(CallTargetMCOp)
240 .addImm(0));
241 break;
242 default:
243 llvm_unreachable("Unsupported operand type in statepoint call target");
244 break;
245 }
246 }
247
248 auto &Ctx = OutStreamer.getContext();
249 MCSymbol *MILabel = Ctx.createTempSymbol();
250 OutStreamer.emitLabel(MILabel);
251 SM.recordStatepoint(*MILabel, MI);
252}
253
254bool RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst,
255 const MCSubtargetInfo &SubtargetInfo) {
256 MCInst CInst;
257 bool Res = RISCVRVC::compress(CInst, Inst, SubtargetInfo);
258 if (Res)
259 ++RISCVNumInstrsCompressed;
260 S.emitInstruction(Res ? CInst : Inst, SubtargetInfo);
261 return Res;
262}
263
264// Simple pseudo-instructions have their lowering (with expansion to real
265// instructions) auto-generated.
266#include "RISCVGenMCPseudoLowering.inc"
267
268// If the target supports Zihintntl and the instruction has a nontemporal
269// MachineMemOperand, emit an NTLH hint instruction before it.
270void RISCVAsmPrinter::emitNTLHint(const MachineInstr *MI) {
271 if (!STI->hasStdExtZihintntl())
272 return;
273
274 if (MI->memoperands_empty())
275 return;
276
277 MachineMemOperand *MMO = *(MI->memoperands_begin());
278 if (!MMO->isNonTemporal())
279 return;
280
281 unsigned NontemporalMode = 0;
282 if (MMO->getFlags() & MONontemporalBit0)
283 NontemporalMode += 0b1;
284 if (MMO->getFlags() & MONontemporalBit1)
285 NontemporalMode += 0b10;
286
287 MCInst Hint;
288 if (STI->hasStdExtCOrZca() && STI->enableRVCHintInstrs())
289 Hint.setOpcode(RISCV::C_ADD_HINT);
290 else
291 Hint.setOpcode(RISCV::ADD);
292
293 Hint.addOperand(MCOperand::createReg(RISCV::X0));
294 Hint.addOperand(MCOperand::createReg(RISCV::X0));
295 Hint.addOperand(MCOperand::createReg(RISCV::X2 + NontemporalMode));
296
297 EmitToStreamer(*OutStreamer, Hint);
298}
299
300void RISCVAsmPrinter::emitInstruction(const MachineInstr *MI) {
301 RISCV_MC::verifyInstructionPredicates(MI->getOpcode(),
302 getSubtargetInfo().getFeatureBits());
303
304 emitNTLHint(MI);
305
306 // Do any auto-generated pseudo lowerings.
307 if (MCInst OutInst; lowerPseudoInstExpansion(MI, OutInst)) {
308 EmitToStreamer(*OutStreamer, OutInst);
309 return;
310 }
311
312 switch (MI->getOpcode()) {
313 case RISCV::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
314 LowerHWASAN_CHECK_MEMACCESS(*MI);
315 return;
316 case RISCV::KCFI_CHECK:
317 LowerKCFI_CHECK(*MI);
318 return;
319 case TargetOpcode::STACKMAP:
320 return LowerSTACKMAP(*OutStreamer, SM, *MI);
321 case TargetOpcode::PATCHPOINT:
322 return LowerPATCHPOINT(*OutStreamer, SM, *MI);
323 case TargetOpcode::STATEPOINT:
324 return LowerSTATEPOINT(*OutStreamer, SM, *MI);
325 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
326 // patchable-function-entry is handled in lowerToMCInst
327 // Therefore, we break out of the switch statement if we encounter it here.
328 const Function &F = MI->getParent()->getParent()->getFunction();
329 if (F.hasFnAttribute("patchable-function-entry"))
330 break;
331
332 LowerPATCHABLE_FUNCTION_ENTER(MI);
333 return;
334 }
335 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
336 LowerPATCHABLE_FUNCTION_EXIT(MI);
337 return;
338 case TargetOpcode::PATCHABLE_TAIL_CALL:
339 LowerPATCHABLE_TAIL_CALL(MI);
340 return;
341 }
342
343 MCInst OutInst;
344 if (!lowerToMCInst(MI, OutInst))
345 EmitToStreamer(*OutStreamer, OutInst);
346}
347
348bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
349 const char *ExtraCode, raw_ostream &OS) {
350 // First try the generic code, which knows about modifiers like 'c' and 'n'.
351 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
352 return false;
353
354 const MachineOperand &MO = MI->getOperand(OpNo);
355 if (ExtraCode && ExtraCode[0]) {
356 if (ExtraCode[1] != 0)
357 return true; // Unknown modifier.
358
359 switch (ExtraCode[0]) {
360 default:
361 return true; // Unknown modifier.
362 case 'z': // Print zero register if zero, regular printing otherwise.
363 if (MO.isImm() && MO.getImm() == 0) {
365 return false;
366 }
367 break;
368 case 'i': // Literal 'i' if operand is not a register.
369 if (!MO.isReg())
370 OS << 'i';
371 return false;
372 case 'N': // Print the register encoding as an integer (0-31)
373 if (!MO.isReg())
374 return true;
375
376 const RISCVRegisterInfo *TRI = STI->getRegisterInfo();
377 OS << TRI->getEncodingValue(MO.getReg());
378 return false;
379 }
380 }
381
382 switch (MO.getType()) {
384 OS << MO.getImm();
385 return false;
388 return false;
390 PrintSymbolOperand(MO, OS);
391 return false;
393 MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());
394 Sym->print(OS, MAI);
395 return false;
396 }
397 default:
398 break;
399 }
400
401 return true;
402}
403
404bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
405 unsigned OpNo,
406 const char *ExtraCode,
407 raw_ostream &OS) {
408 if (ExtraCode)
409 return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
410
411 const MachineOperand &AddrReg = MI->getOperand(OpNo);
412 assert(MI->getNumOperands() > OpNo + 1 && "Expected additional operand");
413 const MachineOperand &Offset = MI->getOperand(OpNo + 1);
414 // All memory operands should have a register and an immediate operand (see
415 // RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand).
416 if (!AddrReg.isReg())
417 return true;
418 if (!Offset.isImm() && !Offset.isGlobal() && !Offset.isBlockAddress() &&
419 !Offset.isMCSymbol())
420 return true;
421
422 MCOperand MCO;
423 if (!lowerOperand(Offset, MCO))
424 return true;
425
426 if (Offset.isImm())
427 OS << MCO.getImm();
428 else if (Offset.isGlobal() || Offset.isBlockAddress() || Offset.isMCSymbol())
429 OS << *MCO.getExpr();
430
431 if (Offset.isMCSymbol())
432 MMI->getContext().registerInlineAsmLabel(Offset.getMCSymbol());
433 if (Offset.isBlockAddress()) {
434 const BlockAddress *BA = Offset.getBlockAddress();
435 MCSymbol *Sym = GetBlockAddressSymbol(BA);
436 MMI->getContext().registerInlineAsmLabel(Sym);
437 }
438
439 OS << "(" << RISCVInstPrinter::getRegisterName(AddrReg.getReg()) << ")";
440 return false;
441}
442
443bool RISCVAsmPrinter::emitDirectiveOptionArch() {
445 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
446 SmallVector<RISCVOptionArchArg> NeedEmitStdOptionArgs;
447 const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo();
448 for (const auto &Feature : RISCVFeatureKV) {
449 if (STI->hasFeature(Feature.Value) == MCSTI.hasFeature(Feature.Value))
450 continue;
451
453 continue;
454
455 auto Delta = STI->hasFeature(Feature.Value) ? RISCVOptionArchArgType::Plus
456 : RISCVOptionArchArgType::Minus;
457 NeedEmitStdOptionArgs.emplace_back(Delta, Feature.Key);
458 }
459 if (!NeedEmitStdOptionArgs.empty()) {
461 RTS.emitDirectiveOptionArch(NeedEmitStdOptionArgs);
462 return true;
463 }
464
465 return false;
466}
467
468bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
469 STI = &MF.getSubtarget<RISCVSubtarget>();
471 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
472
473 bool EmittedOptionArch = emitDirectiveOptionArch();
474
475 SetupMachineFunction(MF);
476 emitFunctionBody();
477
478 // Emit the XRay table
479 emitXRayTable();
480
481 if (EmittedOptionArch)
482 RTS.emitDirectiveOptionPop();
483 return false;
484}
485
486void RISCVAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr *MI) {
487 emitSled(MI, SledKind::FUNCTION_ENTER);
488}
489
490void RISCVAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr *MI) {
491 emitSled(MI, SledKind::FUNCTION_EXIT);
492}
493
494void RISCVAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr *MI) {
495 emitSled(MI, SledKind::TAIL_CALL);
496}
497
498void RISCVAsmPrinter::emitSled(const MachineInstr *MI, SledKind Kind) {
499 // We want to emit the jump instruction and the nops constituting the sled.
500 // The format is as follows:
501 // .Lxray_sled_N
502 // ALIGN
503 // J .tmpN
504 // 21 or 33 C.NOP instructions
505 // .tmpN
506
507 // The following variable holds the count of the number of NOPs to be patched
508 // in for XRay instrumentation during compilation.
509 // Note that RV64 and RV32 each has a sled of 68 and 44 bytes, respectively.
510 // Assuming we're using JAL to jump to .tmpN, then we only need
511 // (68 - 4)/2 = 32 NOPs for RV64 and (44 - 4)/2 = 20 for RV32. However, there
512 // is a chance that we'll use C.JAL instead, so an additional NOP is needed.
513 const uint8_t NoopsInSledCount =
514 MI->getParent()->getParent()->getSubtarget<RISCVSubtarget>().is64Bit()
515 ? 33
516 : 21;
517
518 OutStreamer->emitCodeAlignment(Align(4), &getSubtargetInfo());
519 auto CurSled = OutContext.createTempSymbol("xray_sled_", true);
520 OutStreamer->emitLabel(CurSled);
521 auto Target = OutContext.createTempSymbol();
522
523 const MCExpr *TargetExpr = MCSymbolRefExpr::create(
524 Target, MCSymbolRefExpr::VariantKind::VK_None, OutContext);
525
526 // Emit "J bytes" instruction, which jumps over the nop sled to the actual
527 // start of function.
528 EmitToStreamer(
529 *OutStreamer,
530 MCInstBuilder(RISCV::JAL).addReg(RISCV::X0).addExpr(TargetExpr));
531
532 // Emit NOP instructions
533 for (int8_t I = 0; I < NoopsInSledCount; ++I)
534 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI)
535 .addReg(RISCV::X0)
536 .addReg(RISCV::X0)
537 .addImm(0));
538
539 OutStreamer->emitLabel(Target);
540 recordSled(CurSled, *MI, Kind, 2);
541}
542
543void RISCVAsmPrinter::emitStartOfAsmFile(Module &M) {
545 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
546 if (const MDString *ModuleTargetABI =
547 dyn_cast_or_null<MDString>(M.getModuleFlag("target-abi")))
548 RTS.setTargetABI(RISCVABI::getTargetABI(ModuleTargetABI->getString()));
549
550 MCSubtargetInfo SubtargetInfo = *TM.getMCSubtargetInfo();
551
552 // Use module flag to update feature bits.
553 if (auto *MD = dyn_cast_or_null<MDNode>(M.getModuleFlag("riscv-isa"))) {
554 for (auto &ISA : MD->operands()) {
555 if (auto *ISAString = dyn_cast_or_null<MDString>(ISA)) {
557 ISAString->getString(), /*EnableExperimentalExtension=*/true,
558 /*ExperimentalExtensionVersionCheck=*/true);
559 if (!errorToBool(ParseResult.takeError())) {
560 auto &ISAInfo = *ParseResult;
561 for (const auto &Feature : RISCVFeatureKV) {
562 if (ISAInfo->hasExtension(Feature.Key) &&
563 !SubtargetInfo.hasFeature(Feature.Value))
564 SubtargetInfo.ToggleFeature(Feature.Key);
565 }
566 }
567 }
568 }
569
570 RTS.setFlagsFromFeatures(SubtargetInfo);
571 }
572
573 if (TM.getTargetTriple().isOSBinFormatELF())
574 emitAttributes(SubtargetInfo);
575}
576
577void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) {
579 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
580
581 if (TM.getTargetTriple().isOSBinFormatELF())
583 EmitHwasanMemaccessSymbols(M);
584}
585
586void RISCVAsmPrinter::emitAttributes(const MCSubtargetInfo &SubtargetInfo) {
588 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
589 // Use MCSubtargetInfo from TargetMachine. Individual functions may have
590 // attributes that differ from other functions in the module and we have no
591 // way to know which function is correct.
592 RTS.emitTargetAttributes(SubtargetInfo, /*EmitStackAlign*/ true);
593}
594
595void RISCVAsmPrinter::emitFunctionEntryLabel() {
596 const auto *RMFI = MF->getInfo<RISCVMachineFunctionInfo>();
597 if (RMFI->isVectorCall()) {
598 auto &RTS =
599 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
600 RTS.emitDirectiveVariantCC(*CurrentFnSym);
601 }
603}
604
605// Force static initialization.
609}
610
611void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {
612 Register Reg = MI.getOperand(0).getReg();
613 uint32_t AccessInfo = MI.getOperand(1).getImm();
614 MCSymbol *&Sym =
615 HwasanMemaccessSymbols[HwasanMemaccessTuple(Reg, AccessInfo)];
616 if (!Sym) {
617 // FIXME: Make this work on non-ELF.
618 if (!TM.getTargetTriple().isOSBinFormatELF())
619 report_fatal_error("llvm.hwasan.check.memaccess only supported on ELF");
620
621 std::string SymName = "__hwasan_check_x" + utostr(Reg - RISCV::X0) + "_" +
622 utostr(AccessInfo) + "_short";
623 Sym = OutContext.getOrCreateSymbol(SymName);
624 }
626 auto Expr = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, OutContext);
627
628 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr));
629}
630
631void RISCVAsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {
632 Register AddrReg = MI.getOperand(0).getReg();
633 assert(std::next(MI.getIterator())->isCall() &&
634 "KCFI_CHECK not followed by a call instruction");
635 assert(std::next(MI.getIterator())->getOperand(0).getReg() == AddrReg &&
636 "KCFI_CHECK call target doesn't match call operand");
637
638 // Temporary registers for comparing the hashes. If a register is used
639 // for the call target, or reserved by the user, we can clobber another
640 // temporary register as the check is immediately followed by the
641 // call. The check defaults to X6/X7, but can fall back to X28-X31 if
642 // needed.
643 unsigned ScratchRegs[] = {RISCV::X6, RISCV::X7};
644 unsigned NextReg = RISCV::X28;
645 auto isRegAvailable = [&](unsigned Reg) {
646 return Reg != AddrReg && !STI->isRegisterReservedByUser(Reg);
647 };
648 for (auto &Reg : ScratchRegs) {
649 if (isRegAvailable(Reg))
650 continue;
651 while (!isRegAvailable(NextReg))
652 ++NextReg;
653 Reg = NextReg++;
654 if (Reg > RISCV::X31)
655 report_fatal_error("Unable to find scratch registers for KCFI_CHECK");
656 }
657
658 if (AddrReg == RISCV::X0) {
659 // Checking X0 makes no sense. Instead of emitting a load, zero
660 // ScratchRegs[0].
661 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI)
662 .addReg(ScratchRegs[0])
663 .addReg(RISCV::X0)
664 .addImm(0));
665 } else {
666 // Adjust the offset for patchable-function-prefix. This assumes that
667 // patchable-function-prefix is the same for all functions.
668 int NopSize = STI->hasStdExtCOrZca() ? 2 : 4;
669 int64_t PrefixNops = 0;
670 (void)MI.getMF()
671 ->getFunction()
672 .getFnAttribute("patchable-function-prefix")
673 .getValueAsString()
674 .getAsInteger(10, PrefixNops);
675
676 // Load the target function type hash.
677 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::LW)
678 .addReg(ScratchRegs[0])
679 .addReg(AddrReg)
680 .addImm(-(PrefixNops * NopSize + 4)));
681 }
682
683 // Load the expected 32-bit type hash.
684 const int64_t Type = MI.getOperand(1).getImm();
685 const int64_t Hi20 = ((Type + 0x800) >> 12) & 0xFFFFF;
686 const int64_t Lo12 = SignExtend64<12>(Type);
687 if (Hi20) {
688 EmitToStreamer(
689 *OutStreamer,
690 MCInstBuilder(RISCV::LUI).addReg(ScratchRegs[1]).addImm(Hi20));
691 }
692 if (Lo12 || Hi20 == 0) {
693 EmitToStreamer(*OutStreamer,
694 MCInstBuilder((STI->hasFeature(RISCV::Feature64Bit) && Hi20)
695 ? RISCV::ADDIW
696 : RISCV::ADDI)
697 .addReg(ScratchRegs[1])
698 .addReg(ScratchRegs[1])
699 .addImm(Lo12));
700 }
701
702 // Compare the hashes and trap if there's a mismatch.
703 MCSymbol *Pass = OutContext.createTempSymbol();
704 EmitToStreamer(*OutStreamer,
705 MCInstBuilder(RISCV::BEQ)
706 .addReg(ScratchRegs[0])
707 .addReg(ScratchRegs[1])
708 .addExpr(MCSymbolRefExpr::create(Pass, OutContext)));
709
710 MCSymbol *Trap = OutContext.createTempSymbol();
711 OutStreamer->emitLabel(Trap);
712 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::EBREAK));
713 emitKCFITrapEntry(*MI.getMF(), Trap);
714 OutStreamer->emitLabel(Pass);
715}
716
717void RISCVAsmPrinter::EmitHwasanMemaccessSymbols(Module &M) {
718 if (HwasanMemaccessSymbols.empty())
719 return;
720
721 assert(TM.getTargetTriple().isOSBinFormatELF());
722 // Use MCSubtargetInfo from TargetMachine. Individual functions may have
723 // attributes that differ from other functions in the module and we have no
724 // way to know which function is correct.
725 const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo();
726
727 MCSymbol *HwasanTagMismatchV2Sym =
728 OutContext.getOrCreateSymbol("__hwasan_tag_mismatch_v2");
729 // Annotate symbol as one having incompatible calling convention, so
730 // run-time linkers can instead eagerly bind this function.
731 auto &RTS =
732 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
733 RTS.emitDirectiveVariantCC(*HwasanTagMismatchV2Sym);
734
735 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
736 MCSymbolRefExpr::create(HwasanTagMismatchV2Sym, OutContext);
737 auto Expr = RISCVMCExpr::create(HwasanTagMismatchV2Ref,
738 RISCVMCExpr::VK_RISCV_CALL, OutContext);
739
740 for (auto &P : HwasanMemaccessSymbols) {
741 unsigned Reg = std::get<0>(P.first);
742 uint32_t AccessInfo = std::get<1>(P.first);
743 MCSymbol *Sym = P.second;
744
745 unsigned Size =
746 1 << ((AccessInfo >> HWASanAccessInfo::AccessSizeShift) & 0xf);
747 OutStreamer->switchSection(OutContext.getELFSection(
748 ".text.hot", ELF::SHT_PROGBITS,
750 /*IsComdat=*/true));
751
753 OutStreamer->emitSymbolAttribute(Sym, MCSA_Weak);
754 OutStreamer->emitSymbolAttribute(Sym, MCSA_Hidden);
755 OutStreamer->emitLabel(Sym);
756
757 // Extract shadow offset from ptr
758 EmitToStreamer(
759 *OutStreamer,
760 MCInstBuilder(RISCV::SLLI).addReg(RISCV::X6).addReg(Reg).addImm(8),
761 MCSTI);
762 EmitToStreamer(*OutStreamer,
763 MCInstBuilder(RISCV::SRLI)
764 .addReg(RISCV::X6)
765 .addReg(RISCV::X6)
766 .addImm(12),
767 MCSTI);
768 // load shadow tag in X6, X5 contains shadow base
769 EmitToStreamer(*OutStreamer,
770 MCInstBuilder(RISCV::ADD)
771 .addReg(RISCV::X6)
772 .addReg(RISCV::X5)
773 .addReg(RISCV::X6),
774 MCSTI);
775 EmitToStreamer(
776 *OutStreamer,
777 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
778 MCSTI);
779 // Extract tag from pointer and compare it with loaded tag from shadow
780 EmitToStreamer(
781 *OutStreamer,
782 MCInstBuilder(RISCV::SRLI).addReg(RISCV::X7).addReg(Reg).addImm(56),
783 MCSTI);
784 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
785 // X7 contains tag from the pointer, while X6 contains tag from memory
786 EmitToStreamer(*OutStreamer,
787 MCInstBuilder(RISCV::BNE)
788 .addReg(RISCV::X7)
789 .addReg(RISCV::X6)
791 HandleMismatchOrPartialSym, OutContext)),
792 MCSTI);
793 MCSymbol *ReturnSym = OutContext.createTempSymbol();
794 OutStreamer->emitLabel(ReturnSym);
795 EmitToStreamer(*OutStreamer,
796 MCInstBuilder(RISCV::JALR)
797 .addReg(RISCV::X0)
798 .addReg(RISCV::X1)
799 .addImm(0),
800 MCSTI);
801 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
802
803 EmitToStreamer(*OutStreamer,
804 MCInstBuilder(RISCV::ADDI)
805 .addReg(RISCV::X28)
806 .addReg(RISCV::X0)
807 .addImm(16),
808 MCSTI);
809 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
810 EmitToStreamer(
811 *OutStreamer,
812 MCInstBuilder(RISCV::BGEU)
813 .addReg(RISCV::X6)
814 .addReg(RISCV::X28)
815 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
816 MCSTI);
817
818 EmitToStreamer(
819 *OutStreamer,
820 MCInstBuilder(RISCV::ANDI).addReg(RISCV::X28).addReg(Reg).addImm(0xF),
821 MCSTI);
822
823 if (Size != 1)
824 EmitToStreamer(*OutStreamer,
825 MCInstBuilder(RISCV::ADDI)
826 .addReg(RISCV::X28)
827 .addReg(RISCV::X28)
828 .addImm(Size - 1),
829 MCSTI);
830 EmitToStreamer(
831 *OutStreamer,
832 MCInstBuilder(RISCV::BGE)
833 .addReg(RISCV::X28)
834 .addReg(RISCV::X6)
835 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
836 MCSTI);
837
838 EmitToStreamer(
839 *OutStreamer,
840 MCInstBuilder(RISCV::ORI).addReg(RISCV::X6).addReg(Reg).addImm(0xF),
841 MCSTI);
842 EmitToStreamer(
843 *OutStreamer,
844 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
845 MCSTI);
846 EmitToStreamer(*OutStreamer,
847 MCInstBuilder(RISCV::BEQ)
848 .addReg(RISCV::X6)
849 .addReg(RISCV::X7)
850 .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)),
851 MCSTI);
852
853 OutStreamer->emitLabel(HandleMismatchSym);
854
855 // | Previous stack frames... |
856 // +=================================+ <-- [SP + 256]
857 // | ... |
858 // | |
859 // | Stack frame space for x12 - x31.|
860 // | |
861 // | ... |
862 // +---------------------------------+ <-- [SP + 96]
863 // | Saved x11(arg1), as |
864 // | __hwasan_check_* clobbers it. |
865 // +---------------------------------+ <-- [SP + 88]
866 // | Saved x10(arg0), as |
867 // | __hwasan_check_* clobbers it. |
868 // +---------------------------------+ <-- [SP + 80]
869 // | |
870 // | Stack frame space for x9. |
871 // +---------------------------------+ <-- [SP + 72]
872 // | |
873 // | Saved x8(fp), as |
874 // | __hwasan_check_* clobbers it. |
875 // +---------------------------------+ <-- [SP + 64]
876 // | ... |
877 // | |
878 // | Stack frame space for x2 - x7. |
879 // | |
880 // | ... |
881 // +---------------------------------+ <-- [SP + 16]
882 // | Return address (x1) for caller |
883 // | of __hwasan_check_*. |
884 // +---------------------------------+ <-- [SP + 8]
885 // | Reserved place for x0, possibly |
886 // | junk, since we don't save it. |
887 // +---------------------------------+ <-- [x2 / SP]
888
889 // Adjust sp
890 EmitToStreamer(*OutStreamer,
891 MCInstBuilder(RISCV::ADDI)
892 .addReg(RISCV::X2)
893 .addReg(RISCV::X2)
894 .addImm(-256),
895 MCSTI);
896
897 // store x10(arg0) by new sp
898 EmitToStreamer(*OutStreamer,
899 MCInstBuilder(RISCV::SD)
900 .addReg(RISCV::X10)
901 .addReg(RISCV::X2)
902 .addImm(8 * 10),
903 MCSTI);
904 // store x11(arg1) by new sp
905 EmitToStreamer(*OutStreamer,
906 MCInstBuilder(RISCV::SD)
907 .addReg(RISCV::X11)
908 .addReg(RISCV::X2)
909 .addImm(8 * 11),
910 MCSTI);
911
912 // store x8(fp) by new sp
913 EmitToStreamer(
914 *OutStreamer,
915 MCInstBuilder(RISCV::SD).addReg(RISCV::X8).addReg(RISCV::X2).addImm(8 *
916 8),
917 MCSTI);
918 // store x1(ra) by new sp
919 EmitToStreamer(
920 *OutStreamer,
921 MCInstBuilder(RISCV::SD).addReg(RISCV::X1).addReg(RISCV::X2).addImm(1 *
922 8),
923 MCSTI);
924 if (Reg != RISCV::X10)
925 EmitToStreamer(
926 *OutStreamer,
927 MCInstBuilder(RISCV::ADDI).addReg(RISCV::X10).addReg(Reg).addImm(0),
928 MCSTI);
929 EmitToStreamer(*OutStreamer,
930 MCInstBuilder(RISCV::ADDI)
931 .addReg(RISCV::X11)
932 .addReg(RISCV::X0)
933 .addImm(AccessInfo & HWASanAccessInfo::RuntimeMask),
934 MCSTI);
935
936 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr),
937 MCSTI);
938 }
939}
940
942 const AsmPrinter &AP) {
943 MCContext &Ctx = AP.OutContext;
945
946 switch (MO.getTargetFlags()) {
947 default:
948 llvm_unreachable("Unknown target flag on GV operand");
949 case RISCVII::MO_None:
951 break;
952 case RISCVII::MO_CALL:
954 break;
955 case RISCVII::MO_LO:
957 break;
958 case RISCVII::MO_HI:
960 break;
963 break;
966 break;
969 break;
972 break;
975 break;
978 break;
981 break;
984 break;
987 break;
990 break;
993 break;
996 break;
997 }
998
999 const MCExpr *ME =
1001
1002 if (!MO.isJTI() && !MO.isMBB() && MO.getOffset())
1004 ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
1005
1006 if (Kind != RISCVMCExpr::VK_RISCV_None)
1007 ME = RISCVMCExpr::create(ME, Kind, Ctx);
1008 return MCOperand::createExpr(ME);
1009}
1010
1011bool RISCVAsmPrinter::lowerOperand(const MachineOperand &MO,
1012 MCOperand &MCOp) const {
1013 switch (MO.getType()) {
1014 default:
1015 report_fatal_error("lowerOperand: unknown operand type");
1017 // Ignore all implicit register operands.
1018 if (MO.isImplicit())
1019 return false;
1020 MCOp = MCOperand::createReg(MO.getReg());
1021 break;
1023 // Regmasks are like implicit defs.
1024 return false;
1026 MCOp = MCOperand::createImm(MO.getImm());
1027 break;
1029 MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), *this);
1030 break;
1032 MCOp = lowerSymbolOperand(MO, getSymbolPreferLocal(*MO.getGlobal()), *this);
1033 break;
1035 MCOp = lowerSymbolOperand(MO, GetBlockAddressSymbol(MO.getBlockAddress()),
1036 *this);
1037 break;
1039 MCOp = lowerSymbolOperand(MO, GetExternalSymbolSymbol(MO.getSymbolName()),
1040 *this);
1041 break;
1043 MCOp = lowerSymbolOperand(MO, GetCPISymbol(MO.getIndex()), *this);
1044 break;
1046 MCOp = lowerSymbolOperand(MO, GetJTISymbol(MO.getIndex()), *this);
1047 break;
1049 MCOp = lowerSymbolOperand(MO, MO.getMCSymbol(), *this);
1050 break;
1051 }
1052 return true;
1053}
1054
1056 MCInst &OutMI) {
1058 RISCVVPseudosTable::getPseudoInfo(MI->getOpcode());
1059 if (!RVV)
1060 return false;
1061
1062 OutMI.setOpcode(RVV->BaseInstr);
1063
1064 const MachineBasicBlock *MBB = MI->getParent();
1065 assert(MBB && "MI expected to be in a basic block");
1066 const MachineFunction *MF = MBB->getParent();
1067 assert(MF && "MBB expected to be in a machine function");
1068
1069 const RISCVSubtarget &Subtarget = MF->getSubtarget<RISCVSubtarget>();
1070 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
1071 const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
1072 assert(TRI && "TargetRegisterInfo expected");
1073
1074 const MCInstrDesc &MCID = MI->getDesc();
1075 uint64_t TSFlags = MCID.TSFlags;
1076 unsigned NumOps = MI->getNumExplicitOperands();
1077
1078 // Skip policy, SEW, VL, VXRM/FRM operands which are the last operands if
1079 // present.
1080 if (RISCVII::hasVecPolicyOp(TSFlags))
1081 --NumOps;
1082 if (RISCVII::hasSEWOp(TSFlags))
1083 --NumOps;
1084 if (RISCVII::hasVLOp(TSFlags))
1085 --NumOps;
1086 if (RISCVII::hasRoundModeOp(TSFlags))
1087 --NumOps;
1088
1089 bool hasVLOutput = RISCV::isFaultFirstLoad(*MI);
1090 for (unsigned OpNo = 0; OpNo != NumOps; ++OpNo) {
1091 const MachineOperand &MO = MI->getOperand(OpNo);
1092 // Skip vl ouput. It should be the second output.
1093 if (hasVLOutput && OpNo == 1)
1094 continue;
1095
1096 // Skip passthru op. It should be the first operand after the defs.
1097 if (OpNo == MI->getNumExplicitDefs() && MO.isReg() && MO.isTied()) {
1098 assert(MCID.getOperandConstraint(OpNo, MCOI::TIED_TO) == 0 &&
1099 "Expected tied to first def.");
1100 const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode());
1101 // Skip if the next operand in OutMI is not supposed to be tied. Unless it
1102 // is a _TIED instruction.
1103 if (OutMCID.getOperandConstraint(OutMI.getNumOperands(), MCOI::TIED_TO) <
1104 0 &&
1105 !RISCVII::isTiedPseudo(TSFlags))
1106 continue;
1107 }
1108
1109 MCOperand MCOp;
1110 switch (MO.getType()) {
1111 default:
1112 llvm_unreachable("Unknown operand type");
1114 Register Reg = MO.getReg();
1115
1116 if (RISCV::VRM2RegClass.contains(Reg) ||
1117 RISCV::VRM4RegClass.contains(Reg) ||
1118 RISCV::VRM8RegClass.contains(Reg)) {
1119 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0);
1120 assert(Reg && "Subregister does not exist");
1121 } else if (RISCV::FPR16RegClass.contains(Reg)) {
1122 Reg =
1123 TRI->getMatchingSuperReg(Reg, RISCV::sub_16, &RISCV::FPR32RegClass);
1124 assert(Reg && "Subregister does not exist");
1125 } else if (RISCV::FPR64RegClass.contains(Reg)) {
1126 Reg = TRI->getSubReg(Reg, RISCV::sub_32);
1127 assert(Reg && "Superregister does not exist");
1128 } else if (RISCV::VRN2M1RegClass.contains(Reg) ||
1129 RISCV::VRN2M2RegClass.contains(Reg) ||
1130 RISCV::VRN2M4RegClass.contains(Reg) ||
1131 RISCV::VRN3M1RegClass.contains(Reg) ||
1132 RISCV::VRN3M2RegClass.contains(Reg) ||
1133 RISCV::VRN4M1RegClass.contains(Reg) ||
1134 RISCV::VRN4M2RegClass.contains(Reg) ||
1135 RISCV::VRN5M1RegClass.contains(Reg) ||
1136 RISCV::VRN6M1RegClass.contains(Reg) ||
1137 RISCV::VRN7M1RegClass.contains(Reg) ||
1138 RISCV::VRN8M1RegClass.contains(Reg)) {
1139 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0);
1140 assert(Reg && "Subregister does not exist");
1141 }
1142
1143 MCOp = MCOperand::createReg(Reg);
1144 break;
1145 }
1147 MCOp = MCOperand::createImm(MO.getImm());
1148 break;
1149 }
1150 OutMI.addOperand(MCOp);
1151 }
1152
1153 // Unmasked pseudo instructions need to append dummy mask operand to
1154 // V instructions. All V instructions are modeled as the masked version.
1155 const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode());
1156 if (OutMI.getNumOperands() < OutMCID.getNumOperands()) {
1157 assert(OutMCID.operands()[OutMI.getNumOperands()].RegClass ==
1158 RISCV::VMV0RegClassID &&
1159 "Expected only mask operand to be missing");
1160 OutMI.addOperand(MCOperand::createReg(RISCV::NoRegister));
1161 }
1162
1163 assert(OutMI.getNumOperands() == OutMCID.getNumOperands());
1164 return true;
1165}
1166
1167bool RISCVAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {
1169 return false;
1170
1171 OutMI.setOpcode(MI->getOpcode());
1172
1173 for (const MachineOperand &MO : MI->operands()) {
1174 MCOperand MCOp;
1175 if (lowerOperand(MO, MCOp))
1176 OutMI.addOperand(MCOp);
1177 }
1178
1179 switch (OutMI.getOpcode()) {
1180 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
1181 const Function &F = MI->getParent()->getParent()->getFunction();
1182 if (F.hasFnAttribute("patchable-function-entry")) {
1183 unsigned Num;
1184 if (F.getFnAttribute("patchable-function-entry")
1185 .getValueAsString()
1186 .getAsInteger(10, Num))
1187 return false;
1188 emitNops(Num);
1189 return true;
1190 }
1191 break;
1192 }
1193 }
1194 return false;
1195}
1196
1197void RISCVAsmPrinter::emitMachineConstantPoolValue(
1199 auto *RCPV = static_cast<RISCVConstantPoolValue *>(MCPV);
1200 MCSymbol *MCSym;
1201
1202 if (RCPV->isGlobalValue()) {
1203 auto *GV = RCPV->getGlobalValue();
1204 MCSym = getSymbol(GV);
1205 } else {
1206 assert(RCPV->isExtSymbol() && "unrecognized constant pool type");
1207 auto Sym = RCPV->getSymbol();
1208 MCSym = GetExternalSymbolSymbol(Sym);
1209 }
1210
1211 const MCExpr *Expr =
1213 uint64_t Size = getDataLayout().getTypeAllocSize(RCPV->getType());
1214 OutStreamer->emitValue(Expr, Size);
1215}
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:128
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
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
unsigned const TargetRegisterInfo * TRI
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
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:469
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 is64Bit(const char *name)
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:428
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 emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV)
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.
The address of a basic block.
Definition: Constants.h:893
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:537
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:222
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(MCRegister 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
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:185
unsigned getNumOperands() const
Definition: MCInst.h:209
unsigned getOpcode() const
Definition: MCInst.h:199
void addOperand(const MCOperand Op)
Definition: MCInst.h:211
void setOpcode(unsigned Op)
Definition: MCInst.h:198
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:37
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:163
int64_t getImm() const
Definition: MCInst.h:81
static MCOperand createReg(MCRegister Reg)
Definition: MCInst.h:135
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:142
const MCExpr * getExpr() const
Definition: MCInst.h:115
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
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
Definition: MCStreamer.cpp:179
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
Definition: MCStreamer.cpp:420
MCTargetStreamer * getTargetStreamer()
Definition: MCStreamer.h:309
virtual void emitCodeAlignment(Align Alignment, const MCSubtargetInfo *STI, unsigned MaxBytesToEmit=0)
Emit nops until the byte alignment ByteAlignment is reached.
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:192
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:398
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.
Abstract base class for all machine specific constantpool value subclasses.
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
A RISCV-specific constant pool value.
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:81
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:937
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
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:562
void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
Definition: StackMaps.cpp:541
void recordStackMap(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a stackmap instruction.
Definition: StackMaps.cpp:531
MI-level Statepoint operands.
Definition: StackMaps.h:158
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
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...
Target - Wrapper for Target specific information.
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:1090
@ SHF_ALLOC
Definition: ELF.h:1188
@ SHF_GROUP
Definition: ELF.h:1210
@ SHF_EXECINSTR
Definition: ELF.h:1191
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:1873
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
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...
Used to provide key value pairs for feature and CPU bit flags.