xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1 //===-- RISCVAsmPrinter.cpp - RISC-V LLVM assembly writer -----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains a printer that converts from our internal representation
10 // of machine-dependent LLVM code to the RISC-V assembly language.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "MCTargetDesc/RISCVBaseInfo.h"
15 #include "MCTargetDesc/RISCVInstPrinter.h"
16 #include "MCTargetDesc/RISCVMCExpr.h"
17 #include "MCTargetDesc/RISCVTargetStreamer.h"
18 #include "RISCV.h"
19 #include "RISCVMachineFunctionInfo.h"
20 #include "RISCVTargetMachine.h"
21 #include "TargetInfo/RISCVTargetInfo.h"
22 #include "llvm/ADT/APInt.h"
23 #include "llvm/ADT/Statistic.h"
24 #include "llvm/BinaryFormat/ELF.h"
25 #include "llvm/CodeGen/AsmPrinter.h"
26 #include "llvm/CodeGen/MachineConstantPool.h"
27 #include "llvm/CodeGen/MachineFunctionPass.h"
28 #include "llvm/CodeGen/MachineInstr.h"
29 #include "llvm/CodeGen/MachineModuleInfo.h"
30 #include "llvm/MC/MCAsmInfo.h"
31 #include "llvm/MC/MCContext.h"
32 #include "llvm/MC/MCInst.h"
33 #include "llvm/MC/MCInstBuilder.h"
34 #include "llvm/MC/MCObjectFileInfo.h"
35 #include "llvm/MC/MCSectionELF.h"
36 #include "llvm/MC/MCStreamer.h"
37 #include "llvm/MC/MCSymbol.h"
38 #include "llvm/MC/TargetRegistry.h"
39 #include "llvm/Support/raw_ostream.h"
40 #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
41 
42 using namespace llvm;
43 
44 #define DEBUG_TYPE "asm-printer"
45 
46 STATISTIC(RISCVNumInstrsCompressed,
47           "Number of RISC-V Compressed instructions emitted");
48 
49 namespace {
50 class RISCVAsmPrinter : public AsmPrinter {
51   const RISCVSubtarget *STI;
52 
53 public:
54   explicit RISCVAsmPrinter(TargetMachine &TM,
55                            std::unique_ptr<MCStreamer> Streamer)
56       : AsmPrinter(TM, std::move(Streamer)) {}
57 
58   StringRef getPassName() const override { return "RISC-V Assembly Printer"; }
59 
60   bool runOnMachineFunction(MachineFunction &MF) override;
61 
62   void emitInstruction(const MachineInstr *MI) override;
63 
64   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
65                        const char *ExtraCode, raw_ostream &OS) override;
66   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
67                              const char *ExtraCode, raw_ostream &OS) override;
68 
69   void EmitToStreamer(MCStreamer &S, const MCInst &Inst);
70   bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
71                                    const MachineInstr *MI);
72 
73   typedef std::tuple<unsigned, uint32_t> HwasanMemaccessTuple;
74   std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
75   void LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI);
76   void LowerKCFI_CHECK(const MachineInstr &MI);
77   void EmitHwasanMemaccessSymbols(Module &M);
78 
79   // Wrapper needed for tblgenned pseudo lowering.
80   bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const;
81 
82   void emitStartOfAsmFile(Module &M) override;
83   void emitEndOfAsmFile(Module &M) override;
84 
85   void emitFunctionEntryLabel() override;
86 
87 private:
88   void emitAttributes();
89 
90   void emitNTLHint(const MachineInstr *MI);
91 
92   bool lowerToMCInst(const MachineInstr *MI, MCInst &OutMI);
93 };
94 }
95 
96 void RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
97   MCInst CInst;
98   bool Res = RISCVRVC::compress(CInst, Inst, *STI);
99   if (Res)
100     ++RISCVNumInstrsCompressed;
101   AsmPrinter::EmitToStreamer(*OutStreamer, Res ? CInst : Inst);
102 }
103 
104 // Simple pseudo-instructions have their lowering (with expansion to real
105 // instructions) auto-generated.
106 #include "RISCVGenMCPseudoLowering.inc"
107 
108 // If the target supports Zihintntl and the instruction has a nontemporal
109 // MachineMemOperand, emit an NTLH hint instruction before it.
110 void RISCVAsmPrinter::emitNTLHint(const MachineInstr *MI) {
111   if (!STI->hasStdExtZihintntl())
112     return;
113 
114   if (MI->memoperands_empty())
115     return;
116 
117   MachineMemOperand *MMO = *(MI->memoperands_begin());
118   if (!MMO->isNonTemporal())
119     return;
120 
121   unsigned NontemporalMode = 0;
122   if (MMO->getFlags() & MONontemporalBit0)
123     NontemporalMode += 0b1;
124   if (MMO->getFlags() & MONontemporalBit1)
125     NontemporalMode += 0b10;
126 
127   MCInst Hint;
128   if (STI->hasStdExtCOrZca() && STI->enableRVCHintInstrs())
129     Hint.setOpcode(RISCV::C_ADD_HINT);
130   else
131     Hint.setOpcode(RISCV::ADD);
132 
133   Hint.addOperand(MCOperand::createReg(RISCV::X0));
134   Hint.addOperand(MCOperand::createReg(RISCV::X0));
135   Hint.addOperand(MCOperand::createReg(RISCV::X2 + NontemporalMode));
136 
137   EmitToStreamer(*OutStreamer, Hint);
138 }
139 
140 void RISCVAsmPrinter::emitInstruction(const MachineInstr *MI) {
141   RISCV_MC::verifyInstructionPredicates(MI->getOpcode(),
142                                         getSubtargetInfo().getFeatureBits());
143 
144   emitNTLHint(MI);
145 
146   // Do any auto-generated pseudo lowerings.
147   if (emitPseudoExpansionLowering(*OutStreamer, MI))
148     return;
149 
150 
151   switch (MI->getOpcode()) {
152   case RISCV::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
153     LowerHWASAN_CHECK_MEMACCESS(*MI);
154     return;
155   case RISCV::KCFI_CHECK:
156     LowerKCFI_CHECK(*MI);
157     return;
158   case RISCV::PseudoRVVInitUndefM1:
159   case RISCV::PseudoRVVInitUndefM2:
160   case RISCV::PseudoRVVInitUndefM4:
161   case RISCV::PseudoRVVInitUndefM8:
162     return;
163   }
164 
165   MCInst OutInst;
166   if (!lowerToMCInst(MI, OutInst))
167     EmitToStreamer(*OutStreamer, OutInst);
168 }
169 
170 bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
171                                       const char *ExtraCode, raw_ostream &OS) {
172   // First try the generic code, which knows about modifiers like 'c' and 'n'.
173   if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
174     return false;
175 
176   const MachineOperand &MO = MI->getOperand(OpNo);
177   if (ExtraCode && ExtraCode[0]) {
178     if (ExtraCode[1] != 0)
179       return true; // Unknown modifier.
180 
181     switch (ExtraCode[0]) {
182     default:
183       return true; // Unknown modifier.
184     case 'z':      // Print zero register if zero, regular printing otherwise.
185       if (MO.isImm() && MO.getImm() == 0) {
186         OS << RISCVInstPrinter::getRegisterName(RISCV::X0);
187         return false;
188       }
189       break;
190     case 'i': // Literal 'i' if operand is not a register.
191       if (!MO.isReg())
192         OS << 'i';
193       return false;
194     }
195   }
196 
197   switch (MO.getType()) {
198   case MachineOperand::MO_Immediate:
199     OS << MO.getImm();
200     return false;
201   case MachineOperand::MO_Register:
202     OS << RISCVInstPrinter::getRegisterName(MO.getReg());
203     return false;
204   case MachineOperand::MO_GlobalAddress:
205     PrintSymbolOperand(MO, OS);
206     return false;
207   case MachineOperand::MO_BlockAddress: {
208     MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());
209     Sym->print(OS, MAI);
210     return false;
211   }
212   default:
213     break;
214   }
215 
216   return true;
217 }
218 
219 bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
220                                             unsigned OpNo,
221                                             const char *ExtraCode,
222                                             raw_ostream &OS) {
223   if (ExtraCode)
224     return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
225 
226   const MachineOperand &AddrReg = MI->getOperand(OpNo);
227   assert(MI->getNumOperands() > OpNo + 1 && "Expected additional operand");
228   const MachineOperand &DispImm = MI->getOperand(OpNo + 1);
229   // All memory operands should have a register and an immediate operand (see
230   // RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand).
231   if (!AddrReg.isReg())
232     return true;
233   if (!DispImm.isImm())
234     return true;
235 
236   OS << DispImm.getImm() << "("
237      << RISCVInstPrinter::getRegisterName(AddrReg.getReg()) << ")";
238   return false;
239 }
240 
241 bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
242   STI = &MF.getSubtarget<RISCVSubtarget>();
243 
244   SetupMachineFunction(MF);
245   emitFunctionBody();
246   return false;
247 }
248 
249 void RISCVAsmPrinter::emitStartOfAsmFile(Module &M) {
250   RISCVTargetStreamer &RTS =
251       static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
252   if (const MDString *ModuleTargetABI =
253           dyn_cast_or_null<MDString>(M.getModuleFlag("target-abi")))
254     RTS.setTargetABI(RISCVABI::getTargetABI(ModuleTargetABI->getString()));
255   if (TM.getTargetTriple().isOSBinFormatELF())
256     emitAttributes();
257 }
258 
259 void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) {
260   RISCVTargetStreamer &RTS =
261       static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
262 
263   if (TM.getTargetTriple().isOSBinFormatELF())
264     RTS.finishAttributeSection();
265   EmitHwasanMemaccessSymbols(M);
266 }
267 
268 void RISCVAsmPrinter::emitAttributes() {
269   RISCVTargetStreamer &RTS =
270       static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
271   // Use MCSubtargetInfo from TargetMachine. Individual functions may have
272   // attributes that differ from other functions in the module and we have no
273   // way to know which function is correct.
274   RTS.emitTargetAttributes(*TM.getMCSubtargetInfo(), /*EmitStackAlign*/ true);
275 }
276 
277 void RISCVAsmPrinter::emitFunctionEntryLabel() {
278   const auto *RMFI = MF->getInfo<RISCVMachineFunctionInfo>();
279   if (RMFI->isVectorCall()) {
280     auto &RTS =
281         static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
282     RTS.emitDirectiveVariantCC(*CurrentFnSym);
283   }
284   return AsmPrinter::emitFunctionEntryLabel();
285 }
286 
287 // Force static initialization.
288 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmPrinter() {
289   RegisterAsmPrinter<RISCVAsmPrinter> X(getTheRISCV32Target());
290   RegisterAsmPrinter<RISCVAsmPrinter> Y(getTheRISCV64Target());
291 }
292 
293 void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {
294   Register Reg = MI.getOperand(0).getReg();
295   uint32_t AccessInfo = MI.getOperand(1).getImm();
296   MCSymbol *&Sym =
297       HwasanMemaccessSymbols[HwasanMemaccessTuple(Reg, AccessInfo)];
298   if (!Sym) {
299     // FIXME: Make this work on non-ELF.
300     if (!TM.getTargetTriple().isOSBinFormatELF())
301       report_fatal_error("llvm.hwasan.check.memaccess only supported on ELF");
302 
303     std::string SymName = "__hwasan_check_x" + utostr(Reg - RISCV::X0) + "_" +
304                           utostr(AccessInfo) + "_short";
305     Sym = OutContext.getOrCreateSymbol(SymName);
306   }
307   auto Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, OutContext);
308   auto Expr = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, OutContext);
309 
310   EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr));
311 }
312 
313 void RISCVAsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {
314   Register AddrReg = MI.getOperand(0).getReg();
315   assert(std::next(MI.getIterator())->isCall() &&
316          "KCFI_CHECK not followed by a call instruction");
317   assert(std::next(MI.getIterator())->getOperand(0).getReg() == AddrReg &&
318          "KCFI_CHECK call target doesn't match call operand");
319 
320   // Temporary registers for comparing the hashes. If a register is used
321   // for the call target, or reserved by the user, we can clobber another
322   // temporary register as the check is immediately followed by the
323   // call. The check defaults to X6/X7, but can fall back to X28-X31 if
324   // needed.
325   unsigned ScratchRegs[] = {RISCV::X6, RISCV::X7};
326   unsigned NextReg = RISCV::X28;
327   auto isRegAvailable = [&](unsigned Reg) {
328     return Reg != AddrReg && !STI->isRegisterReservedByUser(Reg);
329   };
330   for (auto &Reg : ScratchRegs) {
331     if (isRegAvailable(Reg))
332       continue;
333     while (!isRegAvailable(NextReg))
334       ++NextReg;
335     Reg = NextReg++;
336     if (Reg > RISCV::X31)
337       report_fatal_error("Unable to find scratch registers for KCFI_CHECK");
338   }
339 
340   if (AddrReg == RISCV::X0) {
341     // Checking X0 makes no sense. Instead of emitting a load, zero
342     // ScratchRegs[0].
343     EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI)
344                                      .addReg(ScratchRegs[0])
345                                      .addReg(RISCV::X0)
346                                      .addImm(0));
347   } else {
348     // Adjust the offset for patchable-function-prefix. This assumes that
349     // patchable-function-prefix is the same for all functions.
350     int NopSize = STI->hasStdExtCOrZca() ? 2 : 4;
351     int64_t PrefixNops = 0;
352     (void)MI.getMF()
353         ->getFunction()
354         .getFnAttribute("patchable-function-prefix")
355         .getValueAsString()
356         .getAsInteger(10, PrefixNops);
357 
358     // Load the target function type hash.
359     EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::LW)
360                                      .addReg(ScratchRegs[0])
361                                      .addReg(AddrReg)
362                                      .addImm(-(PrefixNops * NopSize + 4)));
363   }
364 
365   // Load the expected 32-bit type hash.
366   const int64_t Type = MI.getOperand(1).getImm();
367   const int64_t Hi20 = ((Type + 0x800) >> 12) & 0xFFFFF;
368   const int64_t Lo12 = SignExtend64<12>(Type);
369   if (Hi20) {
370     EmitToStreamer(
371         *OutStreamer,
372         MCInstBuilder(RISCV::LUI).addReg(ScratchRegs[1]).addImm(Hi20));
373   }
374   if (Lo12 || Hi20 == 0) {
375     EmitToStreamer(*OutStreamer,
376                    MCInstBuilder((STI->hasFeature(RISCV::Feature64Bit) && Hi20)
377                                      ? RISCV::ADDIW
378                                      : RISCV::ADDI)
379                        .addReg(ScratchRegs[1])
380                        .addReg(ScratchRegs[1])
381                        .addImm(Lo12));
382   }
383 
384   // Compare the hashes and trap if there's a mismatch.
385   MCSymbol *Pass = OutContext.createTempSymbol();
386   EmitToStreamer(*OutStreamer,
387                  MCInstBuilder(RISCV::BEQ)
388                      .addReg(ScratchRegs[0])
389                      .addReg(ScratchRegs[1])
390                      .addExpr(MCSymbolRefExpr::create(Pass, OutContext)));
391 
392   MCSymbol *Trap = OutContext.createTempSymbol();
393   OutStreamer->emitLabel(Trap);
394   EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::EBREAK));
395   emitKCFITrapEntry(*MI.getMF(), Trap);
396   OutStreamer->emitLabel(Pass);
397 }
398 
399 void RISCVAsmPrinter::EmitHwasanMemaccessSymbols(Module &M) {
400   if (HwasanMemaccessSymbols.empty())
401     return;
402 
403   assert(TM.getTargetTriple().isOSBinFormatELF());
404   // Use MCSubtargetInfo from TargetMachine. Individual functions may have
405   // attributes that differ from other functions in the module and we have no
406   // way to know which function is correct.
407   const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo();
408 
409   MCSymbol *HwasanTagMismatchV2Sym =
410       OutContext.getOrCreateSymbol("__hwasan_tag_mismatch_v2");
411   // Annotate symbol as one having incompatible calling convention, so
412   // run-time linkers can instead eagerly bind this function.
413   auto &RTS =
414       static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
415   RTS.emitDirectiveVariantCC(*HwasanTagMismatchV2Sym);
416 
417   const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
418       MCSymbolRefExpr::create(HwasanTagMismatchV2Sym, OutContext);
419   auto Expr = RISCVMCExpr::create(HwasanTagMismatchV2Ref,
420                                   RISCVMCExpr::VK_RISCV_CALL, OutContext);
421 
422   for (auto &P : HwasanMemaccessSymbols) {
423     unsigned Reg = std::get<0>(P.first);
424     uint32_t AccessInfo = std::get<1>(P.first);
425     MCSymbol *Sym = P.second;
426 
427     unsigned Size =
428         1 << ((AccessInfo >> HWASanAccessInfo::AccessSizeShift) & 0xf);
429     OutStreamer->switchSection(OutContext.getELFSection(
430         ".text.hot", ELF::SHT_PROGBITS,
431         ELF::SHF_EXECINSTR | ELF::SHF_ALLOC | ELF::SHF_GROUP, 0, Sym->getName(),
432         /*IsComdat=*/true));
433 
434     OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
435     OutStreamer->emitSymbolAttribute(Sym, MCSA_Weak);
436     OutStreamer->emitSymbolAttribute(Sym, MCSA_Hidden);
437     OutStreamer->emitLabel(Sym);
438 
439     // Extract shadow offset from ptr
440     OutStreamer->emitInstruction(
441         MCInstBuilder(RISCV::SLLI).addReg(RISCV::X6).addReg(Reg).addImm(8),
442         MCSTI);
443     OutStreamer->emitInstruction(MCInstBuilder(RISCV::SRLI)
444                                      .addReg(RISCV::X6)
445                                      .addReg(RISCV::X6)
446                                      .addImm(12),
447                                  MCSTI);
448     // load shadow tag in X6, X5 contains shadow base
449     OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADD)
450                                      .addReg(RISCV::X6)
451                                      .addReg(RISCV::X5)
452                                      .addReg(RISCV::X6),
453                                  MCSTI);
454     OutStreamer->emitInstruction(
455         MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
456         MCSTI);
457     // Extract tag from X5 and compare it with loaded tag from shadow
458     OutStreamer->emitInstruction(
459         MCInstBuilder(RISCV::SRLI).addReg(RISCV::X7).addReg(Reg).addImm(56),
460         MCSTI);
461     MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
462     // X7 contains tag from memory, while X6 contains tag from the pointer
463     OutStreamer->emitInstruction(
464         MCInstBuilder(RISCV::BNE)
465             .addReg(RISCV::X7)
466             .addReg(RISCV::X6)
467             .addExpr(MCSymbolRefExpr::create(HandleMismatchOrPartialSym,
468                                              OutContext)),
469         MCSTI);
470     MCSymbol *ReturnSym = OutContext.createTempSymbol();
471     OutStreamer->emitLabel(ReturnSym);
472     OutStreamer->emitInstruction(MCInstBuilder(RISCV::JALR)
473                                      .addReg(RISCV::X0)
474                                      .addReg(RISCV::X1)
475                                      .addImm(0),
476                                  MCSTI);
477     OutStreamer->emitLabel(HandleMismatchOrPartialSym);
478 
479     OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI)
480                                      .addReg(RISCV::X28)
481                                      .addReg(RISCV::X0)
482                                      .addImm(16),
483                                  MCSTI);
484     MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
485     OutStreamer->emitInstruction(
486         MCInstBuilder(RISCV::BGEU)
487             .addReg(RISCV::X6)
488             .addReg(RISCV::X28)
489             .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
490         MCSTI);
491 
492     OutStreamer->emitInstruction(
493         MCInstBuilder(RISCV::ANDI).addReg(RISCV::X28).addReg(Reg).addImm(0xF),
494         MCSTI);
495 
496     if (Size != 1)
497       OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI)
498                                        .addReg(RISCV::X28)
499                                        .addReg(RISCV::X28)
500                                        .addImm(Size - 1),
501                                    MCSTI);
502     OutStreamer->emitInstruction(
503         MCInstBuilder(RISCV::BGE)
504             .addReg(RISCV::X28)
505             .addReg(RISCV::X6)
506             .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
507         MCSTI);
508 
509     OutStreamer->emitInstruction(
510         MCInstBuilder(RISCV::ORI).addReg(RISCV::X6).addReg(Reg).addImm(0xF),
511         MCSTI);
512     OutStreamer->emitInstruction(
513         MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
514         MCSTI);
515     OutStreamer->emitInstruction(
516         MCInstBuilder(RISCV::BEQ)
517             .addReg(RISCV::X6)
518             .addReg(RISCV::X7)
519             .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)),
520         MCSTI);
521 
522     OutStreamer->emitLabel(HandleMismatchSym);
523 
524     // | Previous stack frames...        |
525     // +=================================+ <-- [SP + 256]
526     // |              ...                |
527     // |                                 |
528     // | Stack frame space for x12 - x31.|
529     // |                                 |
530     // |              ...                |
531     // +---------------------------------+ <-- [SP + 96]
532     // | Saved x11(arg1), as             |
533     // | __hwasan_check_* clobbers it.   |
534     // +---------------------------------+ <-- [SP + 88]
535     // | Saved x10(arg0), as             |
536     // | __hwasan_check_* clobbers it.   |
537     // +---------------------------------+ <-- [SP + 80]
538     // |                                 |
539     // | Stack frame space for x9.       |
540     // +---------------------------------+ <-- [SP + 72]
541     // |                                 |
542     // | Saved x8(fp), as                |
543     // | __hwasan_check_* clobbers it.   |
544     // +---------------------------------+ <-- [SP + 64]
545     // |              ...                |
546     // |                                 |
547     // | Stack frame space for x2 - x7.  |
548     // |                                 |
549     // |              ...                |
550     // +---------------------------------+ <-- [SP + 16]
551     // | Return address (x1) for caller  |
552     // | of __hwasan_check_*.            |
553     // +---------------------------------+ <-- [SP + 8]
554     // | Reserved place for x0, possibly |
555     // | junk, since we don't save it.   |
556     // +---------------------------------+ <-- [x2 / SP]
557 
558     // Adjust sp
559     OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI)
560                                      .addReg(RISCV::X2)
561                                      .addReg(RISCV::X2)
562                                      .addImm(-256),
563                                  MCSTI);
564 
565     // store x10(arg0) by new sp
566     OutStreamer->emitInstruction(MCInstBuilder(RISCV::SD)
567                                      .addReg(RISCV::X10)
568                                      .addReg(RISCV::X2)
569                                      .addImm(8 * 10),
570                                  MCSTI);
571     // store x11(arg1) by new sp
572     OutStreamer->emitInstruction(MCInstBuilder(RISCV::SD)
573                                      .addReg(RISCV::X11)
574                                      .addReg(RISCV::X2)
575                                      .addImm(8 * 11),
576                                  MCSTI);
577 
578     // store x8(fp) by new sp
579     OutStreamer->emitInstruction(
580         MCInstBuilder(RISCV::SD).addReg(RISCV::X8).addReg(RISCV::X2).addImm(8 *
581                                                                             8),
582         MCSTI);
583     // store x1(ra) by new sp
584     OutStreamer->emitInstruction(
585         MCInstBuilder(RISCV::SD).addReg(RISCV::X1).addReg(RISCV::X2).addImm(1 *
586                                                                             8),
587         MCSTI);
588     if (Reg != RISCV::X10)
589       OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI)
590                                        .addReg(RISCV::X10)
591                                        .addReg(Reg)
592                                        .addImm(0),
593                                    MCSTI);
594     OutStreamer->emitInstruction(
595         MCInstBuilder(RISCV::ADDI)
596             .addReg(RISCV::X11)
597             .addReg(RISCV::X0)
598             .addImm(AccessInfo & HWASanAccessInfo::RuntimeMask),
599         MCSTI);
600 
601     OutStreamer->emitInstruction(MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr),
602                                  MCSTI);
603   }
604 }
605 
606 static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
607                                     const AsmPrinter &AP) {
608   MCContext &Ctx = AP.OutContext;
609   RISCVMCExpr::VariantKind Kind;
610 
611   switch (MO.getTargetFlags()) {
612   default:
613     llvm_unreachable("Unknown target flag on GV operand");
614   case RISCVII::MO_None:
615     Kind = RISCVMCExpr::VK_RISCV_None;
616     break;
617   case RISCVII::MO_CALL:
618     Kind = RISCVMCExpr::VK_RISCV_CALL;
619     break;
620   case RISCVII::MO_PLT:
621     Kind = RISCVMCExpr::VK_RISCV_CALL_PLT;
622     break;
623   case RISCVII::MO_LO:
624     Kind = RISCVMCExpr::VK_RISCV_LO;
625     break;
626   case RISCVII::MO_HI:
627     Kind = RISCVMCExpr::VK_RISCV_HI;
628     break;
629   case RISCVII::MO_PCREL_LO:
630     Kind = RISCVMCExpr::VK_RISCV_PCREL_LO;
631     break;
632   case RISCVII::MO_PCREL_HI:
633     Kind = RISCVMCExpr::VK_RISCV_PCREL_HI;
634     break;
635   case RISCVII::MO_GOT_HI:
636     Kind = RISCVMCExpr::VK_RISCV_GOT_HI;
637     break;
638   case RISCVII::MO_TPREL_LO:
639     Kind = RISCVMCExpr::VK_RISCV_TPREL_LO;
640     break;
641   case RISCVII::MO_TPREL_HI:
642     Kind = RISCVMCExpr::VK_RISCV_TPREL_HI;
643     break;
644   case RISCVII::MO_TPREL_ADD:
645     Kind = RISCVMCExpr::VK_RISCV_TPREL_ADD;
646     break;
647   case RISCVII::MO_TLS_GOT_HI:
648     Kind = RISCVMCExpr::VK_RISCV_TLS_GOT_HI;
649     break;
650   case RISCVII::MO_TLS_GD_HI:
651     Kind = RISCVMCExpr::VK_RISCV_TLS_GD_HI;
652     break;
653   }
654 
655   const MCExpr *ME =
656       MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
657 
658   if (!MO.isJTI() && !MO.isMBB() && MO.getOffset())
659     ME = MCBinaryExpr::createAdd(
660         ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
661 
662   if (Kind != RISCVMCExpr::VK_RISCV_None)
663     ME = RISCVMCExpr::create(ME, Kind, Ctx);
664   return MCOperand::createExpr(ME);
665 }
666 
667 bool RISCVAsmPrinter::lowerOperand(const MachineOperand &MO,
668                                    MCOperand &MCOp) const {
669   switch (MO.getType()) {
670   default:
671     report_fatal_error("lowerOperand: unknown operand type");
672   case MachineOperand::MO_Register:
673     // Ignore all implicit register operands.
674     if (MO.isImplicit())
675       return false;
676     MCOp = MCOperand::createReg(MO.getReg());
677     break;
678   case MachineOperand::MO_RegisterMask:
679     // Regmasks are like implicit defs.
680     return false;
681   case MachineOperand::MO_Immediate:
682     MCOp = MCOperand::createImm(MO.getImm());
683     break;
684   case MachineOperand::MO_MachineBasicBlock:
685     MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), *this);
686     break;
687   case MachineOperand::MO_GlobalAddress:
688     MCOp = lowerSymbolOperand(MO, getSymbolPreferLocal(*MO.getGlobal()), *this);
689     break;
690   case MachineOperand::MO_BlockAddress:
691     MCOp = lowerSymbolOperand(MO, GetBlockAddressSymbol(MO.getBlockAddress()),
692                               *this);
693     break;
694   case MachineOperand::MO_ExternalSymbol:
695     MCOp = lowerSymbolOperand(MO, GetExternalSymbolSymbol(MO.getSymbolName()),
696                               *this);
697     break;
698   case MachineOperand::MO_ConstantPoolIndex:
699     MCOp = lowerSymbolOperand(MO, GetCPISymbol(MO.getIndex()), *this);
700     break;
701   case MachineOperand::MO_JumpTableIndex:
702     MCOp = lowerSymbolOperand(MO, GetJTISymbol(MO.getIndex()), *this);
703     break;
704   case MachineOperand::MO_MCSymbol:
705     MCOp = lowerSymbolOperand(MO, MO.getMCSymbol(), *this);
706     break;
707   }
708   return true;
709 }
710 
711 static bool lowerRISCVVMachineInstrToMCInst(const MachineInstr *MI,
712                                             MCInst &OutMI) {
713   const RISCVVPseudosTable::PseudoInfo *RVV =
714       RISCVVPseudosTable::getPseudoInfo(MI->getOpcode());
715   if (!RVV)
716     return false;
717 
718   OutMI.setOpcode(RVV->BaseInstr);
719 
720   const MachineBasicBlock *MBB = MI->getParent();
721   assert(MBB && "MI expected to be in a basic block");
722   const MachineFunction *MF = MBB->getParent();
723   assert(MF && "MBB expected to be in a machine function");
724 
725   const RISCVSubtarget &Subtarget = MF->getSubtarget<RISCVSubtarget>();
726   const TargetInstrInfo *TII = Subtarget.getInstrInfo();
727   const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
728   assert(TRI && "TargetRegisterInfo expected");
729 
730   const MCInstrDesc &MCID = MI->getDesc();
731   uint64_t TSFlags = MCID.TSFlags;
732   unsigned NumOps = MI->getNumExplicitOperands();
733 
734   // Skip policy, VL and SEW operands which are the last operands if present.
735   if (RISCVII::hasVecPolicyOp(TSFlags))
736     --NumOps;
737   if (RISCVII::hasVLOp(TSFlags))
738     --NumOps;
739   if (RISCVII::hasSEWOp(TSFlags))
740     --NumOps;
741   if (RISCVII::hasRoundModeOp(TSFlags))
742     --NumOps;
743 
744   bool hasVLOutput = RISCV::isFaultFirstLoad(*MI);
745   for (unsigned OpNo = 0; OpNo != NumOps; ++OpNo) {
746     const MachineOperand &MO = MI->getOperand(OpNo);
747     // Skip vl ouput. It should be the second output.
748     if (hasVLOutput && OpNo == 1)
749       continue;
750 
751     // Skip merge op. It should be the first operand after the defs.
752     if (OpNo == MI->getNumExplicitDefs() && MO.isReg() && MO.isTied()) {
753       assert(MCID.getOperandConstraint(OpNo, MCOI::TIED_TO) == 0 &&
754              "Expected tied to first def.");
755       const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode());
756       // Skip if the next operand in OutMI is not supposed to be tied. Unless it
757       // is a _TIED instruction.
758       if (OutMCID.getOperandConstraint(OutMI.getNumOperands(), MCOI::TIED_TO) <
759               0 &&
760           !RISCVII::isTiedPseudo(TSFlags))
761         continue;
762     }
763 
764     MCOperand MCOp;
765     switch (MO.getType()) {
766     default:
767       llvm_unreachable("Unknown operand type");
768     case MachineOperand::MO_Register: {
769       Register Reg = MO.getReg();
770 
771       if (RISCV::VRM2RegClass.contains(Reg) ||
772           RISCV::VRM4RegClass.contains(Reg) ||
773           RISCV::VRM8RegClass.contains(Reg)) {
774         Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0);
775         assert(Reg && "Subregister does not exist");
776       } else if (RISCV::FPR16RegClass.contains(Reg)) {
777         Reg =
778             TRI->getMatchingSuperReg(Reg, RISCV::sub_16, &RISCV::FPR32RegClass);
779         assert(Reg && "Subregister does not exist");
780       } else if (RISCV::FPR64RegClass.contains(Reg)) {
781         Reg = TRI->getSubReg(Reg, RISCV::sub_32);
782         assert(Reg && "Superregister does not exist");
783       } else if (RISCV::VRN2M1RegClass.contains(Reg) ||
784                  RISCV::VRN2M2RegClass.contains(Reg) ||
785                  RISCV::VRN2M4RegClass.contains(Reg) ||
786                  RISCV::VRN3M1RegClass.contains(Reg) ||
787                  RISCV::VRN3M2RegClass.contains(Reg) ||
788                  RISCV::VRN4M1RegClass.contains(Reg) ||
789                  RISCV::VRN4M2RegClass.contains(Reg) ||
790                  RISCV::VRN5M1RegClass.contains(Reg) ||
791                  RISCV::VRN6M1RegClass.contains(Reg) ||
792                  RISCV::VRN7M1RegClass.contains(Reg) ||
793                  RISCV::VRN8M1RegClass.contains(Reg)) {
794         Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0);
795         assert(Reg && "Subregister does not exist");
796       }
797 
798       MCOp = MCOperand::createReg(Reg);
799       break;
800     }
801     case MachineOperand::MO_Immediate:
802       MCOp = MCOperand::createImm(MO.getImm());
803       break;
804     }
805     OutMI.addOperand(MCOp);
806   }
807 
808   // Unmasked pseudo instructions need to append dummy mask operand to
809   // V instructions. All V instructions are modeled as the masked version.
810   const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode());
811   if (OutMI.getNumOperands() < OutMCID.getNumOperands()) {
812     assert(OutMCID.operands()[OutMI.getNumOperands()].RegClass ==
813                RISCV::VMV0RegClassID &&
814            "Expected only mask operand to be missing");
815     OutMI.addOperand(MCOperand::createReg(RISCV::NoRegister));
816   }
817 
818   assert(OutMI.getNumOperands() == OutMCID.getNumOperands());
819   return true;
820 }
821 
822 bool RISCVAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {
823   if (lowerRISCVVMachineInstrToMCInst(MI, OutMI))
824     return false;
825 
826   OutMI.setOpcode(MI->getOpcode());
827 
828   for (const MachineOperand &MO : MI->operands()) {
829     MCOperand MCOp;
830     if (lowerOperand(MO, MCOp))
831       OutMI.addOperand(MCOp);
832   }
833 
834   switch (OutMI.getOpcode()) {
835   case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
836     const Function &F = MI->getParent()->getParent()->getFunction();
837     if (F.hasFnAttribute("patchable-function-entry")) {
838       unsigned Num;
839       if (F.getFnAttribute("patchable-function-entry")
840               .getValueAsString()
841               .getAsInteger(10, Num))
842         return false;
843       emitNops(Num);
844       return true;
845     }
846     break;
847   }
848   }
849   return false;
850 }
851