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