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