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