LLVM 22.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
20#include "RISCV.h"
23#include "RISCVRegisterInfo.h"
25#include "llvm/ADT/APInt.h"
26#include "llvm/ADT/Statistic.h"
32#include "llvm/IR/Module.h"
33#include "llvm/MC/MCAsmInfo.h"
34#include "llvm/MC/MCContext.h"
35#include "llvm/MC/MCInst.h"
39#include "llvm/MC/MCStreamer.h"
40#include "llvm/MC/MCSymbol.h"
46
47using namespace llvm;
48
49#define DEBUG_TYPE "asm-printer"
50
51STATISTIC(RISCVNumInstrsCompressed,
52 "Number of RISC-V Compressed instructions emitted");
53
54namespace llvm {
55extern const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures];
56} // namespace llvm
57
58namespace {
59class RISCVAsmPrinter : public AsmPrinter {
60public:
61 static char ID;
62
63private:
64 const RISCVSubtarget *STI;
65
66public:
67 explicit RISCVAsmPrinter(TargetMachine &TM,
68 std::unique_ptr<MCStreamer> Streamer)
69 : AsmPrinter(TM, std::move(Streamer), ID) {}
70
71 StringRef getPassName() const override { return "RISC-V Assembly Printer"; }
72
73 void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
74 const MachineInstr &MI);
75
76 void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
77 const MachineInstr &MI);
78
79 void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
80 const MachineInstr &MI);
81
82 bool runOnMachineFunction(MachineFunction &MF) override;
83
84 void emitInstruction(const MachineInstr *MI) override;
85
86 void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override;
87
88 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
89 const char *ExtraCode, raw_ostream &OS) override;
90 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
91 const char *ExtraCode, raw_ostream &OS) override;
92
93 // Returns whether Inst is compressed.
94 bool EmitToStreamer(MCStreamer &S, const MCInst &Inst,
95 const MCSubtargetInfo &SubtargetInfo);
96 bool EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
97 return EmitToStreamer(S, Inst, *STI);
98 }
99
100 bool lowerPseudoInstExpansion(const MachineInstr *MI, MCInst &Inst);
101
102 typedef std::tuple<unsigned, uint32_t> HwasanMemaccessTuple;
103 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
104 void LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI);
105 void LowerKCFI_CHECK(const MachineInstr &MI);
106 void EmitHwasanMemaccessSymbols(Module &M);
107
108 // Wrapper needed for tblgenned pseudo lowering.
109 bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const;
110
111 void emitStartOfAsmFile(Module &M) override;
112 void emitEndOfAsmFile(Module &M) override;
113
114 void emitFunctionEntryLabel() override;
115 bool emitDirectiveOptionArch();
116
117 void emitNoteGnuProperty(const Module &M);
118
119private:
120 void emitAttributes(const MCSubtargetInfo &SubtargetInfo);
121
122 void emitNTLHint(const MachineInstr *MI);
123
124 // XRay Support
125 void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr *MI);
126 void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr *MI);
127 void LowerPATCHABLE_TAIL_CALL(const MachineInstr *MI);
128 void emitSled(const MachineInstr *MI, SledKind Kind);
129
130 void lowerToMCInst(const MachineInstr *MI, MCInst &OutMI);
131};
132}
133
134void RISCVAsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
135 const MachineInstr &MI) {
136 unsigned NOPBytes = STI->hasStdExtZca() ? 2 : 4;
137 unsigned NumNOPBytes = StackMapOpers(&MI).getNumPatchBytes();
138
139 auto &Ctx = OutStreamer.getContext();
140 MCSymbol *MILabel = Ctx.createTempSymbol();
141 OutStreamer.emitLabel(MILabel);
142
143 SM.recordStackMap(*MILabel, MI);
144 assert(NumNOPBytes % NOPBytes == 0 &&
145 "Invalid number of NOP bytes requested!");
146
147 // Scan ahead to trim the shadow.
148 const MachineBasicBlock &MBB = *MI.getParent();
150 ++MII;
151 while (NumNOPBytes > 0) {
152 if (MII == MBB.end() || MII->isCall() ||
153 MII->getOpcode() == RISCV::DBG_VALUE ||
154 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
155 MII->getOpcode() == TargetOpcode::STACKMAP)
156 break;
157 ++MII;
158 NumNOPBytes -= 4;
159 }
160
161 // Emit nops.
162 emitNops(NumNOPBytes / NOPBytes);
163}
164
165// Lower a patchpoint of the form:
166// [<def>], <id>, <numBytes>, <target>, <numArgs>
167void RISCVAsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
168 const MachineInstr &MI) {
169 unsigned NOPBytes = STI->hasStdExtZca() ? 2 : 4;
170
171 auto &Ctx = OutStreamer.getContext();
172 MCSymbol *MILabel = Ctx.createTempSymbol();
173 OutStreamer.emitLabel(MILabel);
174 SM.recordPatchPoint(*MILabel, MI);
175
176 PatchPointOpers Opers(&MI);
177
178 const MachineOperand &CalleeMO = Opers.getCallTarget();
179 unsigned EncodedBytes = 0;
180
181 if (CalleeMO.isImm()) {
182 uint64_t CallTarget = CalleeMO.getImm();
183 if (CallTarget) {
184 assert((CallTarget & 0xFFFF'FFFF'FFFF) == CallTarget &&
185 "High 16 bits of call target should be zero.");
186 // Materialize the jump address:
188 RISCVMatInt::generateMCInstSeq(CallTarget, *STI, RISCV::X1, Seq);
189 for (MCInst &Inst : Seq) {
190 bool Compressed = EmitToStreamer(OutStreamer, Inst);
191 EncodedBytes += Compressed ? 2 : 4;
192 }
193 bool Compressed = EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JALR)
194 .addReg(RISCV::X1)
195 .addReg(RISCV::X1)
196 .addImm(0));
197 EncodedBytes += Compressed ? 2 : 4;
198 }
199 } else if (CalleeMO.isGlobal()) {
200 MCOperand CallTargetMCOp;
201 lowerOperand(CalleeMO, CallTargetMCOp);
202 EmitToStreamer(OutStreamer,
203 MCInstBuilder(RISCV::PseudoCALL).addOperand(CallTargetMCOp));
204 EncodedBytes += 8;
205 }
206
207 // Emit padding.
208 unsigned NumBytes = Opers.getNumPatchBytes();
209 assert(NumBytes >= EncodedBytes &&
210 "Patchpoint can't request size less than the length of a call.");
211 assert((NumBytes - EncodedBytes) % NOPBytes == 0 &&
212 "Invalid number of NOP bytes requested!");
213 emitNops((NumBytes - EncodedBytes) / NOPBytes);
214}
215
216void RISCVAsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
217 const MachineInstr &MI) {
218 unsigned NOPBytes = STI->hasStdExtZca() ? 2 : 4;
219
220 StatepointOpers SOpers(&MI);
221 if (unsigned PatchBytes = SOpers.getNumPatchBytes()) {
222 assert(PatchBytes % NOPBytes == 0 &&
223 "Invalid number of NOP bytes requested!");
224 emitNops(PatchBytes / NOPBytes);
225 } else {
226 // Lower call target and choose correct opcode
227 const MachineOperand &CallTarget = SOpers.getCallTarget();
228 MCOperand CallTargetMCOp;
229 switch (CallTarget.getType()) {
232 lowerOperand(CallTarget, CallTargetMCOp);
233 EmitToStreamer(
234 OutStreamer,
235 MCInstBuilder(RISCV::PseudoCALL).addOperand(CallTargetMCOp));
236 break;
238 CallTargetMCOp = MCOperand::createImm(CallTarget.getImm());
239 EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JAL)
240 .addReg(RISCV::X1)
241 .addOperand(CallTargetMCOp));
242 break;
244 CallTargetMCOp = MCOperand::createReg(CallTarget.getReg());
245 EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JALR)
246 .addReg(RISCV::X1)
247 .addOperand(CallTargetMCOp)
248 .addImm(0));
249 break;
250 default:
251 llvm_unreachable("Unsupported operand type in statepoint call target");
252 break;
253 }
254 }
255
256 auto &Ctx = OutStreamer.getContext();
257 MCSymbol *MILabel = Ctx.createTempSymbol();
258 OutStreamer.emitLabel(MILabel);
259 SM.recordStatepoint(*MILabel, MI);
260}
261
262bool RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst,
263 const MCSubtargetInfo &SubtargetInfo) {
264 MCInst CInst;
265 bool Res = RISCVRVC::compress(CInst, Inst, SubtargetInfo);
266 if (Res)
267 ++RISCVNumInstrsCompressed;
268 S.emitInstruction(Res ? CInst : Inst, SubtargetInfo);
269 return Res;
270}
271
272// Simple pseudo-instructions have their lowering (with expansion to real
273// instructions) auto-generated.
274#include "RISCVGenMCPseudoLowering.inc"
275
276// If the target supports Zihintntl and the instruction has a nontemporal
277// MachineMemOperand, emit an NTLH hint instruction before it.
278void RISCVAsmPrinter::emitNTLHint(const MachineInstr *MI) {
279 if (!STI->hasStdExtZihintntl())
280 return;
281
282 if (MI->memoperands_empty())
283 return;
284
285 MachineMemOperand *MMO = *(MI->memoperands_begin());
286 if (!MMO->isNonTemporal())
287 return;
288
289 unsigned NontemporalMode = 0;
290 if (MMO->getFlags() & MONontemporalBit0)
291 NontemporalMode += 0b1;
292 if (MMO->getFlags() & MONontemporalBit1)
293 NontemporalMode += 0b10;
294
295 MCInst Hint;
296 if (STI->hasStdExtZca())
297 Hint.setOpcode(RISCV::C_ADD);
298 else
299 Hint.setOpcode(RISCV::ADD);
300
301 Hint.addOperand(MCOperand::createReg(RISCV::X0));
302 Hint.addOperand(MCOperand::createReg(RISCV::X0));
303 Hint.addOperand(MCOperand::createReg(RISCV::X2 + NontemporalMode));
304
305 EmitToStreamer(*OutStreamer, Hint);
306}
307
308void RISCVAsmPrinter::emitInstruction(const MachineInstr *MI) {
309 RISCV_MC::verifyInstructionPredicates(MI->getOpcode(), STI->getFeatureBits());
310
311 emitNTLHint(MI);
312
313 // Do any auto-generated pseudo lowerings.
314 if (MCInst OutInst; lowerPseudoInstExpansion(MI, OutInst)) {
315 EmitToStreamer(*OutStreamer, OutInst);
316 return;
317 }
318
319 switch (MI->getOpcode()) {
320 case RISCV::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
321 LowerHWASAN_CHECK_MEMACCESS(*MI);
322 return;
323 case RISCV::KCFI_CHECK:
324 LowerKCFI_CHECK(*MI);
325 return;
326 case TargetOpcode::STACKMAP:
327 return LowerSTACKMAP(*OutStreamer, SM, *MI);
328 case TargetOpcode::PATCHPOINT:
329 return LowerPATCHPOINT(*OutStreamer, SM, *MI);
330 case TargetOpcode::STATEPOINT:
331 return LowerSTATEPOINT(*OutStreamer, SM, *MI);
332 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
333 const Function &F = MI->getParent()->getParent()->getFunction();
334 if (F.hasFnAttribute("patchable-function-entry")) {
335 unsigned Num;
336 [[maybe_unused]] bool Result =
337 F.getFnAttribute("patchable-function-entry")
338 .getValueAsString()
339 .getAsInteger(10, Num);
340 assert(!Result && "Enforced by the verifier");
341 emitNops(Num);
342 return;
343 }
344 LowerPATCHABLE_FUNCTION_ENTER(MI);
345 return;
346 }
347 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
348 LowerPATCHABLE_FUNCTION_EXIT(MI);
349 return;
350 case TargetOpcode::PATCHABLE_TAIL_CALL:
351 LowerPATCHABLE_TAIL_CALL(MI);
352 return;
353 }
354
355 MCInst OutInst;
356 lowerToMCInst(MI, OutInst);
357 EmitToStreamer(*OutStreamer, OutInst);
358}
359
360bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
361 const char *ExtraCode, raw_ostream &OS) {
362 // First try the generic code, which knows about modifiers like 'c' and 'n'.
363 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
364 return false;
365
366 const MachineOperand &MO = MI->getOperand(OpNo);
367 if (ExtraCode && ExtraCode[0]) {
368 if (ExtraCode[1] != 0)
369 return true; // Unknown modifier.
370
371 switch (ExtraCode[0]) {
372 default:
373 return true; // Unknown modifier.
374 case 'z': // Print zero register if zero, regular printing otherwise.
375 if (MO.isImm() && MO.getImm() == 0) {
376 OS << RISCVInstPrinter::getRegisterName(RISCV::X0);
377 return false;
378 }
379 break;
380 case 'i': // Literal 'i' if operand is not a register.
381 if (!MO.isReg())
382 OS << 'i';
383 return false;
384 case 'N': // Print the register encoding as an integer (0-31)
385 if (!MO.isReg())
386 return true;
387
388 const RISCVRegisterInfo *TRI = STI->getRegisterInfo();
389 OS << TRI->getEncodingValue(MO.getReg());
390 return false;
391 }
392 }
393
394 switch (MO.getType()) {
396 OS << MO.getImm();
397 return false;
400 return false;
402 PrintSymbolOperand(MO, OS);
403 return false;
405 MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());
406 Sym->print(OS, MAI);
407 return false;
408 }
409 default:
410 break;
411 }
412
413 return true;
414}
415
416bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
417 unsigned OpNo,
418 const char *ExtraCode,
419 raw_ostream &OS) {
420 if (ExtraCode)
421 return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
422
423 const MachineOperand &AddrReg = MI->getOperand(OpNo);
424 assert(MI->getNumOperands() > OpNo + 1 && "Expected additional operand");
425 const MachineOperand &Offset = MI->getOperand(OpNo + 1);
426 // All memory operands should have a register and an immediate operand (see
427 // RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand).
428 if (!AddrReg.isReg())
429 return true;
430 if (!Offset.isImm() && !Offset.isGlobal() && !Offset.isBlockAddress() &&
431 !Offset.isMCSymbol())
432 return true;
433
434 MCOperand MCO;
435 if (!lowerOperand(Offset, MCO))
436 return true;
437
438 if (Offset.isImm())
439 OS << MCO.getImm();
440 else if (Offset.isGlobal() || Offset.isBlockAddress() || Offset.isMCSymbol())
441 MAI->printExpr(OS, *MCO.getExpr());
442
443 if (Offset.isMCSymbol())
444 MMI->getContext().registerInlineAsmLabel(Offset.getMCSymbol());
445 if (Offset.isBlockAddress()) {
446 const BlockAddress *BA = Offset.getBlockAddress();
447 MCSymbol *Sym = GetBlockAddressSymbol(BA);
448 MMI->getContext().registerInlineAsmLabel(Sym);
449 }
450
451 OS << "(" << RISCVInstPrinter::getRegisterName(AddrReg.getReg()) << ")";
452 return false;
453}
454
455bool RISCVAsmPrinter::emitDirectiveOptionArch() {
456 RISCVTargetStreamer &RTS =
457 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
458 SmallVector<RISCVOptionArchArg> NeedEmitStdOptionArgs;
459 const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo();
460 for (const auto &Feature : RISCVFeatureKV) {
461 if (STI->hasFeature(Feature.Value) == MCSTI.hasFeature(Feature.Value))
462 continue;
463
465 continue;
466
467 auto Delta = STI->hasFeature(Feature.Value) ? RISCVOptionArchArgType::Plus
468 : RISCVOptionArchArgType::Minus;
469 NeedEmitStdOptionArgs.emplace_back(Delta, Feature.Key);
470 }
471 if (!NeedEmitStdOptionArgs.empty()) {
473 RTS.emitDirectiveOptionArch(NeedEmitStdOptionArgs);
474 return true;
475 }
476
477 return false;
478}
479
480bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
481 STI = &MF.getSubtarget<RISCVSubtarget>();
482 RISCVTargetStreamer &RTS =
483 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
484
485 bool EmittedOptionArch = emitDirectiveOptionArch();
486
487 SetupMachineFunction(MF);
488 emitFunctionBody();
489
490 // Emit the XRay table
491 emitXRayTable();
492
493 if (EmittedOptionArch)
494 RTS.emitDirectiveOptionPop();
495 return false;
496}
497
498void RISCVAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr *MI) {
499 emitSled(MI, SledKind::FUNCTION_ENTER);
500}
501
502void RISCVAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr *MI) {
503 emitSled(MI, SledKind::FUNCTION_EXIT);
504}
505
506void RISCVAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr *MI) {
507 emitSled(MI, SledKind::TAIL_CALL);
508}
509
510void RISCVAsmPrinter::emitSled(const MachineInstr *MI, SledKind Kind) {
511 // We want to emit the jump instruction and the nops constituting the sled.
512 // The format is as follows:
513 // .Lxray_sled_N
514 // ALIGN
515 // J .tmpN
516 // 21 or 33 C.NOP instructions
517 // .tmpN
518
519 // The following variable holds the count of the number of NOPs to be patched
520 // in for XRay instrumentation during compilation.
521 // Note that RV64 and RV32 each has a sled of 68 and 44 bytes, respectively.
522 // Assuming we're using JAL to jump to .tmpN, then we only need
523 // (68 - 4)/2 = 32 NOPs for RV64 and (44 - 4)/2 = 20 for RV32. However, there
524 // is a chance that we'll use C.JAL instead, so an additional NOP is needed.
525 const uint8_t NoopsInSledCount = STI->is64Bit() ? 33 : 21;
526
527 OutStreamer->emitCodeAlignment(Align(4), STI);
528 auto CurSled = OutContext.createTempSymbol("xray_sled_", true);
529 OutStreamer->emitLabel(CurSled);
530 auto Target = OutContext.createTempSymbol();
531
532 const MCExpr *TargetExpr = MCSymbolRefExpr::create(Target, OutContext);
533
534 // Emit "J bytes" instruction, which jumps over the nop sled to the actual
535 // start of function.
536 EmitToStreamer(
537 *OutStreamer,
538 MCInstBuilder(RISCV::JAL).addReg(RISCV::X0).addExpr(TargetExpr));
539
540 // Emit NOP instructions
541 for (int8_t I = 0; I < NoopsInSledCount; ++I)
542 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI)
543 .addReg(RISCV::X0)
544 .addReg(RISCV::X0)
545 .addImm(0));
546
547 OutStreamer->emitLabel(Target);
548 recordSled(CurSled, *MI, Kind, 2);
549}
550
551void RISCVAsmPrinter::emitStartOfAsmFile(Module &M) {
552 assert(OutStreamer->getTargetStreamer() &&
553 "target streamer is uninitialized");
554 RISCVTargetStreamer &RTS =
555 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
556 if (const MDString *ModuleTargetABI =
557 dyn_cast_or_null<MDString>(M.getModuleFlag("target-abi")))
558 RTS.setTargetABI(RISCVABI::getTargetABI(ModuleTargetABI->getString()));
559
560 MCSubtargetInfo SubtargetInfo = *TM.getMCSubtargetInfo();
561
562 // Use module flag to update feature bits.
563 if (auto *MD = dyn_cast_or_null<MDNode>(M.getModuleFlag("riscv-isa"))) {
564 for (auto &ISA : MD->operands()) {
565 if (auto *ISAString = dyn_cast_or_null<MDString>(ISA)) {
566 auto ParseResult = llvm::RISCVISAInfo::parseArchString(
567 ISAString->getString(), /*EnableExperimentalExtension=*/true,
568 /*ExperimentalExtensionVersionCheck=*/true);
569 if (!errorToBool(ParseResult.takeError())) {
570 auto &ISAInfo = *ParseResult;
571 for (const auto &Feature : RISCVFeatureKV) {
572 if (ISAInfo->hasExtension(Feature.Key) &&
573 !SubtargetInfo.hasFeature(Feature.Value))
574 SubtargetInfo.ToggleFeature(Feature.Key);
575 }
576 }
577 }
578 }
579
580 RTS.setFlagsFromFeatures(SubtargetInfo);
581 }
582
583 if (TM.getTargetTriple().isOSBinFormatELF())
584 emitAttributes(SubtargetInfo);
585}
586
587void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) {
588 RISCVTargetStreamer &RTS =
589 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
590
591 if (TM.getTargetTriple().isOSBinFormatELF()) {
593 emitNoteGnuProperty(M);
594 }
595 EmitHwasanMemaccessSymbols(M);
596}
597
598void RISCVAsmPrinter::emitAttributes(const MCSubtargetInfo &SubtargetInfo) {
599 RISCVTargetStreamer &RTS =
600 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
601 // Use MCSubtargetInfo from TargetMachine. Individual functions may have
602 // attributes that differ from other functions in the module and we have no
603 // way to know which function is correct.
604 RTS.emitTargetAttributes(SubtargetInfo, /*EmitStackAlign*/ true);
605}
606
607void RISCVAsmPrinter::emitFunctionEntryLabel() {
608 const auto *RMFI = MF->getInfo<RISCVMachineFunctionInfo>();
609 if (RMFI->isVectorCall()) {
610 auto &RTS =
611 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
612 RTS.emitDirectiveVariantCC(*CurrentFnSym);
613 }
615}
616
617// Force static initialization.
625
626void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {
627 Register Reg = MI.getOperand(0).getReg();
628 uint32_t AccessInfo = MI.getOperand(1).getImm();
629 MCSymbol *&Sym =
630 HwasanMemaccessSymbols[HwasanMemaccessTuple(Reg, AccessInfo)];
631 if (!Sym) {
632 // FIXME: Make this work on non-ELF.
633 if (!TM.getTargetTriple().isOSBinFormatELF())
634 report_fatal_error("llvm.hwasan.check.memaccess only supported on ELF");
635
636 std::string SymName = "__hwasan_check_x" + utostr(Reg - RISCV::X0) + "_" +
637 utostr(AccessInfo) + "_short";
638 Sym = OutContext.getOrCreateSymbol(SymName);
639 }
640 auto Res = MCSymbolRefExpr::create(Sym, OutContext);
641 auto Expr = MCSpecifierExpr::create(Res, ELF::R_RISCV_CALL_PLT, OutContext);
642
643 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr));
644}
645
646void RISCVAsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {
647 Register AddrReg = MI.getOperand(0).getReg();
648 assert(std::next(MI.getIterator())->isCall() &&
649 "KCFI_CHECK not followed by a call instruction");
650 assert(std::next(MI.getIterator())->getOperand(0).getReg() == AddrReg &&
651 "KCFI_CHECK call target doesn't match call operand");
652
653 // Temporary registers for comparing the hashes. If a register is used
654 // for the call target, or reserved by the user, we can clobber another
655 // temporary register as the check is immediately followed by the
656 // call. The check defaults to X6/X7, but can fall back to X28-X31 if
657 // needed.
658 unsigned ScratchRegs[] = {RISCV::X6, RISCV::X7};
659 unsigned NextReg = RISCV::X28;
660 auto isRegAvailable = [&](unsigned Reg) {
661 return Reg != AddrReg && !STI->isRegisterReservedByUser(Reg);
662 };
663 for (auto &Reg : ScratchRegs) {
664 if (isRegAvailable(Reg))
665 continue;
666 while (!isRegAvailable(NextReg))
667 ++NextReg;
668 Reg = NextReg++;
669 if (Reg > RISCV::X31)
670 report_fatal_error("Unable to find scratch registers for KCFI_CHECK");
671 }
672
673 if (AddrReg == RISCV::X0) {
674 // Checking X0 makes no sense. Instead of emitting a load, zero
675 // ScratchRegs[0].
676 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI)
677 .addReg(ScratchRegs[0])
678 .addReg(RISCV::X0)
679 .addImm(0));
680 } else {
681 // Adjust the offset for patchable-function-prefix. This assumes that
682 // patchable-function-prefix is the same for all functions.
683 int NopSize = STI->hasStdExtZca() ? 2 : 4;
684 int64_t PrefixNops = 0;
685 (void)MI.getMF()
686 ->getFunction()
687 .getFnAttribute("patchable-function-prefix")
688 .getValueAsString()
689 .getAsInteger(10, PrefixNops);
690
691 // Load the target function type hash.
692 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::LW)
693 .addReg(ScratchRegs[0])
694 .addReg(AddrReg)
695 .addImm(-(PrefixNops * NopSize + 4)));
696 }
697
698 // Load the expected 32-bit type hash.
699 const int64_t Type = MI.getOperand(1).getImm();
700 const int64_t Hi20 = ((Type + 0x800) >> 12) & 0xFFFFF;
701 const int64_t Lo12 = SignExtend64<12>(Type);
702 if (Hi20) {
703 EmitToStreamer(
704 *OutStreamer,
705 MCInstBuilder(RISCV::LUI).addReg(ScratchRegs[1]).addImm(Hi20));
706 }
707 if (Lo12 || Hi20 == 0) {
708 EmitToStreamer(*OutStreamer,
709 MCInstBuilder((STI->hasFeature(RISCV::Feature64Bit) && Hi20)
710 ? RISCV::ADDIW
711 : RISCV::ADDI)
712 .addReg(ScratchRegs[1])
713 .addReg(ScratchRegs[1])
714 .addImm(Lo12));
715 }
716
717 // Compare the hashes and trap if there's a mismatch.
718 MCSymbol *Pass = OutContext.createTempSymbol();
719 EmitToStreamer(*OutStreamer,
720 MCInstBuilder(RISCV::BEQ)
721 .addReg(ScratchRegs[0])
722 .addReg(ScratchRegs[1])
723 .addExpr(MCSymbolRefExpr::create(Pass, OutContext)));
724
725 MCSymbol *Trap = OutContext.createTempSymbol();
726 OutStreamer->emitLabel(Trap);
727 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::EBREAK));
728 emitKCFITrapEntry(*MI.getMF(), Trap);
729 OutStreamer->emitLabel(Pass);
730}
731
732void RISCVAsmPrinter::EmitHwasanMemaccessSymbols(Module &M) {
733 if (HwasanMemaccessSymbols.empty())
734 return;
735
736 assert(TM.getTargetTriple().isOSBinFormatELF());
737 // Use MCSubtargetInfo from TargetMachine. Individual functions may have
738 // attributes that differ from other functions in the module and we have no
739 // way to know which function is correct.
740 const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo();
741
742 MCSymbol *HwasanTagMismatchV2Sym =
743 OutContext.getOrCreateSymbol("__hwasan_tag_mismatch_v2");
744 // Annotate symbol as one having incompatible calling convention, so
745 // run-time linkers can instead eagerly bind this function.
746 auto &RTS =
747 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
748 RTS.emitDirectiveVariantCC(*HwasanTagMismatchV2Sym);
749
750 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
751 MCSymbolRefExpr::create(HwasanTagMismatchV2Sym, OutContext);
752 auto Expr = MCSpecifierExpr::create(HwasanTagMismatchV2Ref,
753 ELF::R_RISCV_CALL_PLT, OutContext);
754
755 for (auto &P : HwasanMemaccessSymbols) {
756 unsigned Reg = std::get<0>(P.first);
757 uint32_t AccessInfo = std::get<1>(P.first);
758 MCSymbol *Sym = P.second;
759
760 unsigned Size =
761 1 << ((AccessInfo >> HWASanAccessInfo::AccessSizeShift) & 0xf);
762 OutStreamer->switchSection(OutContext.getELFSection(
763 ".text.hot", ELF::SHT_PROGBITS,
765 /*IsComdat=*/true));
766
768 OutStreamer->emitSymbolAttribute(Sym, MCSA_Weak);
769 OutStreamer->emitSymbolAttribute(Sym, MCSA_Hidden);
770 OutStreamer->emitLabel(Sym);
771
772 // Extract shadow offset from ptr
773 EmitToStreamer(
774 *OutStreamer,
775 MCInstBuilder(RISCV::SLLI).addReg(RISCV::X6).addReg(Reg).addImm(8),
776 MCSTI);
777 EmitToStreamer(*OutStreamer,
778 MCInstBuilder(RISCV::SRLI)
779 .addReg(RISCV::X6)
780 .addReg(RISCV::X6)
781 .addImm(12),
782 MCSTI);
783 // load shadow tag in X6, X5 contains shadow base
784 EmitToStreamer(*OutStreamer,
785 MCInstBuilder(RISCV::ADD)
786 .addReg(RISCV::X6)
787 .addReg(RISCV::X5)
788 .addReg(RISCV::X6),
789 MCSTI);
790 EmitToStreamer(
791 *OutStreamer,
792 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
793 MCSTI);
794 // Extract tag from pointer and compare it with loaded tag from shadow
795 EmitToStreamer(
796 *OutStreamer,
797 MCInstBuilder(RISCV::SRLI).addReg(RISCV::X7).addReg(Reg).addImm(56),
798 MCSTI);
799 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
800 // X7 contains tag from the pointer, while X6 contains tag from memory
801 EmitToStreamer(*OutStreamer,
802 MCInstBuilder(RISCV::BNE)
803 .addReg(RISCV::X7)
804 .addReg(RISCV::X6)
806 HandleMismatchOrPartialSym, OutContext)),
807 MCSTI);
808 MCSymbol *ReturnSym = OutContext.createTempSymbol();
809 OutStreamer->emitLabel(ReturnSym);
810 EmitToStreamer(*OutStreamer,
811 MCInstBuilder(RISCV::JALR)
812 .addReg(RISCV::X0)
813 .addReg(RISCV::X1)
814 .addImm(0),
815 MCSTI);
816 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
817
818 EmitToStreamer(*OutStreamer,
819 MCInstBuilder(RISCV::ADDI)
820 .addReg(RISCV::X28)
821 .addReg(RISCV::X0)
822 .addImm(16),
823 MCSTI);
824 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
825 EmitToStreamer(
826 *OutStreamer,
827 MCInstBuilder(RISCV::BGEU)
828 .addReg(RISCV::X6)
829 .addReg(RISCV::X28)
830 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
831 MCSTI);
832
833 EmitToStreamer(
834 *OutStreamer,
835 MCInstBuilder(RISCV::ANDI).addReg(RISCV::X28).addReg(Reg).addImm(0xF),
836 MCSTI);
837
838 if (Size != 1)
839 EmitToStreamer(*OutStreamer,
840 MCInstBuilder(RISCV::ADDI)
841 .addReg(RISCV::X28)
842 .addReg(RISCV::X28)
843 .addImm(Size - 1),
844 MCSTI);
845 EmitToStreamer(
846 *OutStreamer,
847 MCInstBuilder(RISCV::BGE)
848 .addReg(RISCV::X28)
849 .addReg(RISCV::X6)
850 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
851 MCSTI);
852
853 EmitToStreamer(
854 *OutStreamer,
855 MCInstBuilder(RISCV::ORI).addReg(RISCV::X6).addReg(Reg).addImm(0xF),
856 MCSTI);
857 EmitToStreamer(
858 *OutStreamer,
859 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
860 MCSTI);
861 EmitToStreamer(*OutStreamer,
862 MCInstBuilder(RISCV::BEQ)
863 .addReg(RISCV::X6)
864 .addReg(RISCV::X7)
865 .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)),
866 MCSTI);
867
868 OutStreamer->emitLabel(HandleMismatchSym);
869
870 // | Previous stack frames... |
871 // +=================================+ <-- [SP + 256]
872 // | ... |
873 // | |
874 // | Stack frame space for x12 - x31.|
875 // | |
876 // | ... |
877 // +---------------------------------+ <-- [SP + 96]
878 // | Saved x11(arg1), as |
879 // | __hwasan_check_* clobbers it. |
880 // +---------------------------------+ <-- [SP + 88]
881 // | Saved x10(arg0), as |
882 // | __hwasan_check_* clobbers it. |
883 // +---------------------------------+ <-- [SP + 80]
884 // | |
885 // | Stack frame space for x9. |
886 // +---------------------------------+ <-- [SP + 72]
887 // | |
888 // | Saved x8(fp), as |
889 // | __hwasan_check_* clobbers it. |
890 // +---------------------------------+ <-- [SP + 64]
891 // | ... |
892 // | |
893 // | Stack frame space for x2 - x7. |
894 // | |
895 // | ... |
896 // +---------------------------------+ <-- [SP + 16]
897 // | Return address (x1) for caller |
898 // | of __hwasan_check_*. |
899 // +---------------------------------+ <-- [SP + 8]
900 // | Reserved place for x0, possibly |
901 // | junk, since we don't save it. |
902 // +---------------------------------+ <-- [x2 / SP]
903
904 // Adjust sp
905 EmitToStreamer(*OutStreamer,
906 MCInstBuilder(RISCV::ADDI)
907 .addReg(RISCV::X2)
908 .addReg(RISCV::X2)
909 .addImm(-256),
910 MCSTI);
911
912 // store x10(arg0) by new sp
913 EmitToStreamer(*OutStreamer,
914 MCInstBuilder(RISCV::SD)
915 .addReg(RISCV::X10)
916 .addReg(RISCV::X2)
917 .addImm(8 * 10),
918 MCSTI);
919 // store x11(arg1) by new sp
920 EmitToStreamer(*OutStreamer,
921 MCInstBuilder(RISCV::SD)
922 .addReg(RISCV::X11)
923 .addReg(RISCV::X2)
924 .addImm(8 * 11),
925 MCSTI);
926
927 // store x8(fp) by new sp
928 EmitToStreamer(
929 *OutStreamer,
930 MCInstBuilder(RISCV::SD).addReg(RISCV::X8).addReg(RISCV::X2).addImm(8 *
931 8),
932 MCSTI);
933 // store x1(ra) by new sp
934 EmitToStreamer(
935 *OutStreamer,
936 MCInstBuilder(RISCV::SD).addReg(RISCV::X1).addReg(RISCV::X2).addImm(1 *
937 8),
938 MCSTI);
939 if (Reg != RISCV::X10)
940 EmitToStreamer(
941 *OutStreamer,
942 MCInstBuilder(RISCV::ADDI).addReg(RISCV::X10).addReg(Reg).addImm(0),
943 MCSTI);
944 EmitToStreamer(*OutStreamer,
945 MCInstBuilder(RISCV::ADDI)
946 .addReg(RISCV::X11)
947 .addReg(RISCV::X0)
948 .addImm(AccessInfo & HWASanAccessInfo::RuntimeMask),
949 MCSTI);
950
951 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr),
952 MCSTI);
953 }
954}
955
956void RISCVAsmPrinter::emitNoteGnuProperty(const Module &M) {
957 assert(TM.getTargetTriple().isOSBinFormatELF() && "invalid binary format");
958 if (const Metadata *const Flag = M.getModuleFlag("cf-protection-return");
959 Flag && !mdconst::extract<ConstantInt>(Flag)->isZero()) {
960 RISCVTargetELFStreamer &RTS = static_cast<RISCVTargetELFStreamer &>(
961 *OutStreamer->getTargetStreamer());
963 }
964}
965
967 const AsmPrinter &AP) {
968 MCContext &Ctx = AP.OutContext;
969 RISCV::Specifier Kind;
970
971 switch (MO.getTargetFlags()) {
972 default:
973 llvm_unreachable("Unknown target flag on GV operand");
974 case RISCVII::MO_None:
975 Kind = RISCV::S_None;
976 break;
977 case RISCVII::MO_CALL:
978 Kind = ELF::R_RISCV_CALL_PLT;
979 break;
980 case RISCVII::MO_LO:
981 Kind = RISCV::S_LO;
982 break;
983 case RISCVII::MO_HI:
984 Kind = ELF::R_RISCV_HI20;
985 break;
987 Kind = RISCV::S_PCREL_LO;
988 break;
990 Kind = ELF::R_RISCV_PCREL_HI20;
991 break;
993 Kind = ELF::R_RISCV_GOT_HI20;
994 break;
996 Kind = RISCV::S_TPREL_LO;
997 break;
999 Kind = ELF::R_RISCV_TPREL_HI20;
1000 break;
1002 Kind = ELF::R_RISCV_TPREL_ADD;
1003 break;
1005 Kind = ELF::R_RISCV_TLS_GOT_HI20;
1006 break;
1008 Kind = ELF::R_RISCV_TLS_GD_HI20;
1009 break;
1011 Kind = ELF::R_RISCV_TLSDESC_HI20;
1012 break;
1014 Kind = ELF::R_RISCV_TLSDESC_LOAD_LO12;
1015 break;
1017 Kind = ELF::R_RISCV_TLSDESC_ADD_LO12;
1018 break;
1020 Kind = ELF::R_RISCV_TLSDESC_CALL;
1021 break;
1022 }
1023
1024 const MCExpr *ME = MCSymbolRefExpr::create(Sym, Ctx);
1025
1026 if (!MO.isJTI() && !MO.isMBB() && MO.getOffset())
1028 ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
1029
1030 if (Kind != RISCV::S_None)
1031 ME = MCSpecifierExpr::create(ME, Kind, Ctx);
1032 return MCOperand::createExpr(ME);
1033}
1034
1035bool RISCVAsmPrinter::lowerOperand(const MachineOperand &MO,
1036 MCOperand &MCOp) const {
1037 switch (MO.getType()) {
1038 default:
1039 report_fatal_error("lowerOperand: unknown operand type");
1041 // Ignore all implicit register operands.
1042 if (MO.isImplicit())
1043 return false;
1044 MCOp = MCOperand::createReg(MO.getReg());
1045 break;
1047 // Regmasks are like implicit defs.
1048 return false;
1050 MCOp = MCOperand::createImm(MO.getImm());
1051 break;
1053 MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), *this);
1054 break;
1056 MCOp = lowerSymbolOperand(MO, getSymbolPreferLocal(*MO.getGlobal()), *this);
1057 break;
1059 MCOp = lowerSymbolOperand(MO, GetBlockAddressSymbol(MO.getBlockAddress()),
1060 *this);
1061 break;
1063 MCOp = lowerSymbolOperand(MO, GetExternalSymbolSymbol(MO.getSymbolName()),
1064 *this);
1065 break;
1067 MCOp = lowerSymbolOperand(MO, GetCPISymbol(MO.getIndex()), *this);
1068 break;
1070 MCOp = lowerSymbolOperand(MO, GetJTISymbol(MO.getIndex()), *this);
1071 break;
1073 MCOp = lowerSymbolOperand(MO, MO.getMCSymbol(), *this);
1074 break;
1075 }
1076 return true;
1077}
1078
1080 MCInst &OutMI,
1081 const RISCVSubtarget *STI) {
1083 RISCVVPseudosTable::getPseudoInfo(MI->getOpcode());
1084 if (!RVV)
1085 return false;
1086
1087 OutMI.setOpcode(RVV->BaseInstr);
1088
1089 const TargetInstrInfo *TII = STI->getInstrInfo();
1090 const TargetRegisterInfo *TRI = STI->getRegisterInfo();
1091 assert(TRI && "TargetRegisterInfo expected");
1092
1093 const MCInstrDesc &MCID = MI->getDesc();
1094 uint64_t TSFlags = MCID.TSFlags;
1095 unsigned NumOps = MI->getNumExplicitOperands();
1096
1097 // Skip policy, SEW, VL, VXRM/FRM operands which are the last operands if
1098 // present.
1099 if (RISCVII::hasVecPolicyOp(TSFlags))
1100 --NumOps;
1101 if (RISCVII::hasSEWOp(TSFlags))
1102 --NumOps;
1103 if (RISCVII::hasVLOp(TSFlags))
1104 --NumOps;
1105 if (RISCVII::hasRoundModeOp(TSFlags))
1106 --NumOps;
1107 if (RISCVII::hasTWidenOp(TSFlags))
1108 --NumOps;
1109 if (RISCVII::hasTMOp(TSFlags))
1110 --NumOps;
1111 if (RISCVII::hasTKOp(TSFlags))
1112 --NumOps;
1113
1114 bool hasVLOutput = RISCVInstrInfo::isFaultOnlyFirstLoad(*MI);
1115 for (unsigned OpNo = 0; OpNo != NumOps; ++OpNo) {
1116 const MachineOperand &MO = MI->getOperand(OpNo);
1117 // Skip vl output. It should be the second output.
1118 if (hasVLOutput && OpNo == 1)
1119 continue;
1120
1121 // Skip passthru op. It should be the first operand after the defs.
1122 if (OpNo == MI->getNumExplicitDefs() && MO.isReg() && MO.isTied()) {
1123 assert(MCID.getOperandConstraint(OpNo, MCOI::TIED_TO) == 0 &&
1124 "Expected tied to first def.");
1125 const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode());
1126 // Skip if the next operand in OutMI is not supposed to be tied. Unless it
1127 // is a _TIED instruction.
1128 if (OutMCID.getOperandConstraint(OutMI.getNumOperands(), MCOI::TIED_TO) <
1129 0 &&
1130 !RISCVII::isTiedPseudo(TSFlags))
1131 continue;
1132 }
1133
1134 MCOperand MCOp;
1135 switch (MO.getType()) {
1136 default:
1137 llvm_unreachable("Unknown operand type");
1139 Register Reg = MO.getReg();
1140
1141 if (RISCV::VRM2RegClass.contains(Reg) ||
1142 RISCV::VRM4RegClass.contains(Reg) ||
1143 RISCV::VRM8RegClass.contains(Reg)) {
1144 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0);
1145 assert(Reg && "Subregister does not exist");
1146 } else if (RISCV::FPR16RegClass.contains(Reg)) {
1147 Reg =
1148 TRI->getMatchingSuperReg(Reg, RISCV::sub_16, &RISCV::FPR32RegClass);
1149 assert(Reg && "Subregister does not exist");
1150 } else if (RISCV::FPR64RegClass.contains(Reg)) {
1151 Reg = TRI->getSubReg(Reg, RISCV::sub_32);
1152 assert(Reg && "Superregister does not exist");
1153 } else if (RISCV::VRN2M1RegClass.contains(Reg) ||
1154 RISCV::VRN2M2RegClass.contains(Reg) ||
1155 RISCV::VRN2M4RegClass.contains(Reg) ||
1156 RISCV::VRN3M1RegClass.contains(Reg) ||
1157 RISCV::VRN3M2RegClass.contains(Reg) ||
1158 RISCV::VRN4M1RegClass.contains(Reg) ||
1159 RISCV::VRN4M2RegClass.contains(Reg) ||
1160 RISCV::VRN5M1RegClass.contains(Reg) ||
1161 RISCV::VRN6M1RegClass.contains(Reg) ||
1162 RISCV::VRN7M1RegClass.contains(Reg) ||
1163 RISCV::VRN8M1RegClass.contains(Reg)) {
1164 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0);
1165 assert(Reg && "Subregister does not exist");
1166 }
1167
1168 MCOp = MCOperand::createReg(Reg);
1169 break;
1170 }
1172 MCOp = MCOperand::createImm(MO.getImm());
1173 break;
1174 }
1175 OutMI.addOperand(MCOp);
1176 }
1177
1178 // Unmasked pseudo instructions need to append dummy mask operand to
1179 // V instructions. All V instructions are modeled as the masked version.
1180 const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode());
1181 if (OutMI.getNumOperands() < OutMCID.getNumOperands()) {
1182 assert(OutMCID.operands()[OutMI.getNumOperands()].OperandType ==
1184 "Expected only mask operand to be missing");
1185 OutMI.addOperand(MCOperand::createReg(RISCV::NoRegister));
1186 }
1187
1188 assert(OutMI.getNumOperands() == OutMCID.getNumOperands());
1189 return true;
1190}
1191
1192void RISCVAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {
1193 if (lowerRISCVVMachineInstrToMCInst(MI, OutMI, STI))
1194 return;
1195
1196 OutMI.setOpcode(MI->getOpcode());
1197
1198 for (const MachineOperand &MO : MI->operands()) {
1199 MCOperand MCOp;
1200 if (lowerOperand(MO, MCOp))
1201 OutMI.addOperand(MCOp);
1202 }
1203}
1204
1205void RISCVAsmPrinter::emitMachineConstantPoolValue(
1206 MachineConstantPoolValue *MCPV) {
1207 auto *RCPV = static_cast<RISCVConstantPoolValue *>(MCPV);
1208 MCSymbol *MCSym;
1209
1210 if (RCPV->isGlobalValue()) {
1211 auto *GV = RCPV->getGlobalValue();
1212 MCSym = getSymbol(GV);
1213 } else {
1214 assert(RCPV->isExtSymbol() && "unrecognized constant pool type");
1215 auto Sym = RCPV->getSymbol();
1216 MCSym = GetExternalSymbolSymbol(Sym);
1217 }
1218
1219 const MCExpr *Expr = MCSymbolRefExpr::create(MCSym, OutContext);
1220 uint64_t Size = getDataLayout().getTypeAllocSize(RCPV->getType());
1221 OutStreamer->emitValue(Expr, Size);
1222}
1223
1224char RISCVAsmPrinter::ID = 0;
1225
1226INITIALIZE_PASS(RISCVAsmPrinter, "riscv-asm-printer", "RISC-V Assembly Printer",
1227 false, false)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock & MBB
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_ABI
Definition Compiler.h:213
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
dxil translate DXIL Translate Metadata
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym, const AsmPrinter &AP)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
print mir2vec MIR2Vec Vocabulary Printer Pass
Definition MIR2Vec.cpp:593
Machine Check Debug Module
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define P(N)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static bool lowerRISCVVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, const RISCVSubtarget *STI)
LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmPrinter()
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:487
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
This class is intended to be used as a driving class for all asm writers.
Definition AsmPrinter.h:91
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition AsmPrinter.h:101
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, SMLoc Loc=SMLoc())
Definition MCExpr.h:343
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Context object for machine code objects.
Definition MCContext.h:83
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
unsigned getNumOperands() const
Definition MCInst.h:212
unsigned getOpcode() const
Definition MCInst.h:202
void addOperand(const MCOperand Op)
Definition MCInst.h:215
void setOpcode(unsigned Op)
Definition MCInst.h:201
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specified operand constraint if it is present.
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
static MCOperand createExpr(const MCExpr *Val)
Definition MCInst.h:166
int64_t getImm() const
Definition MCInst.h:84
static MCOperand createReg(MCRegister Reg)
Definition MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
const MCExpr * getExpr() const
Definition MCInst.h:118
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.cpp:743
Streaming machine code generation interface.
Definition MCStreamer.h:220
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:314
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
MCTargetStreamer * getTargetStreamer()
Definition MCStreamer.h:324
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.
bool hasFeature(unsigned Feature) const
FeatureBitset ToggleFeature(uint64_t FB)
Toggle a feature and return the re-computed feature bits.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:214
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition MCSymbol.cpp:59
StringRef getName() const
getName - Get the symbol name.
Definition MCSymbol.h:188
MachineInstrBundleIterator< const MachineInstr > const_iterator
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
const 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.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isJTI() const
isJTI - Tests if this is a MO_JumpTableIndex operand.
const BlockAddress * getBlockAddress() const
unsigned getTargetFlags() const
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
MCSymbol * getMCSymbol() const
@ MO_Immediate
Immediate operand.
@ MO_ConstantPoolIndex
Address of indexed Constant in Constant Pool.
@ MO_MCSymbol
MCSymbol reference (for debug/eh info)
@ MO_GlobalAddress
Address of a global value.
@ MO_RegisterMask
Mask of preserved registers.
@ MO_BlockAddress
Address of a basic block.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
@ MO_JumpTableIndex
Address of indexed Jump Table for switch.
int64_t getOffset() const
Return the offset from the symbol in this operand.
bool isMBB() const
isMBB - Tests if this is a MO_MachineBasicBlock operand.
static LLVM_ABI bool isSupportedExtensionFeature(StringRef Ext)
static LLVM_ABI llvm::Expected< std::unique_ptr< RISCVISAInfo > > parseArchString(StringRef Arch, bool EnableExperimentalExtension, bool ExperimentalExtensionVersionCheck=true)
Parse RISC-V ISA info from arch string.
static const char * getRegisterName(MCRegister Reg)
bool isRegisterReservedByUser(Register i) const override
const RISCVRegisterInfo * getRegisterInfo() const override
const RISCVInstrInfo * getInstrInfo() const override
void emitNoteGnuPropertySection(const uint32_t Feature1And)
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:20
reference emplace_back(ArgTypes &&... Args)
LLVM_ABI void recordStatepoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a statepoint instruction.
LLVM_ABI void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
LLVM_ABI void recordStackMap(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a stackmap instruction.
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ SHF_ALLOC
Definition ELF.h:1248
@ SHF_GROUP
Definition ELF.h:1270
@ SHF_EXECINSTR
Definition ELF.h:1251
@ SHT_PROGBITS
Definition ELF.h:1147
@ GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS
Definition ELF.h:1913
ABI getTargetABI(StringRef ABIName)
static bool hasRoundModeOp(uint64_t TSFlags)
static bool hasTWidenOp(uint64_t TSFlags)
static bool isTiedPseudo(uint64_t TSFlags)
static bool hasTKOp(uint64_t TSFlags)
static bool hasVLOp(uint64_t TSFlags)
static bool hasTMOp(uint64_t TSFlags)
static bool hasVecPolicyOp(uint64_t TSFlags)
static bool hasSEWOp(uint64_t TSFlags)
void generateMCInstSeq(int64_t Val, const MCSubtargetInfo &STI, MCRegister DestReg, SmallVectorImpl< MCInst > &Insts)
bool compress(MCInst &OutInst, const MCInst &MI, const MCSubtargetInfo &STI)
uint16_t Specifier
void emitInstruction(MCObjectStreamer &, const MCInst &Inst, const MCSubtargetInfo &STI)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
Definition Metadata.h:667
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
Definition Error.h:1113
@ Offset
Definition DWP.cpp:532
static const MachineMemOperand::Flags MONontemporalBit1
Target & getTheRISCV32Target()
static const MachineMemOperand::Flags MONontemporalBit0
std::string utostr(uint64_t X, bool isNeg=false)
Target & getTheRISCV64beTarget()
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:167
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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:1915
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:572
const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures]
@ MCSA_Weak
.weak
@ MCSA_ELF_TypeFunction
.type _foo, STT_FUNC # aka @function
@ MCSA_Hidden
.hidden (ELF)
Target & getTheRISCV32beTarget()
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...
Used to provide key value pairs for feature and CPU bit flags.