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