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