xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp (revision 069ac18495ad8fde2748bc94b0f80a50250bb01d)
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 &Offset = 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 (!Offset.isImm() && !Offset.isGlobal())
234     return true;
235 
236   MCOperand MCO;
237   if (!lowerOperand(Offset, MCO))
238     return true;
239 
240   if (Offset.isImm())
241     OS << MCO.getImm();
242   else if (Offset.isGlobal())
243     OS << *MCO.getExpr();
244   OS << "(" << RISCVInstPrinter::getRegisterName(AddrReg.getReg()) << ")";
245   return false;
246 }
247 
248 bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
249   STI = &MF.getSubtarget<RISCVSubtarget>();
250 
251   SetupMachineFunction(MF);
252   emitFunctionBody();
253   return false;
254 }
255 
256 void RISCVAsmPrinter::emitStartOfAsmFile(Module &M) {
257   RISCVTargetStreamer &RTS =
258       static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
259   if (const MDString *ModuleTargetABI =
260           dyn_cast_or_null<MDString>(M.getModuleFlag("target-abi")))
261     RTS.setTargetABI(RISCVABI::getTargetABI(ModuleTargetABI->getString()));
262   if (TM.getTargetTriple().isOSBinFormatELF())
263     emitAttributes();
264 }
265 
266 void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) {
267   RISCVTargetStreamer &RTS =
268       static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
269 
270   if (TM.getTargetTriple().isOSBinFormatELF())
271     RTS.finishAttributeSection();
272   EmitHwasanMemaccessSymbols(M);
273 }
274 
275 void RISCVAsmPrinter::emitAttributes() {
276   RISCVTargetStreamer &RTS =
277       static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
278   // Use MCSubtargetInfo from TargetMachine. Individual functions may have
279   // attributes that differ from other functions in the module and we have no
280   // way to know which function is correct.
281   RTS.emitTargetAttributes(*TM.getMCSubtargetInfo(), /*EmitStackAlign*/ true);
282 }
283 
284 void RISCVAsmPrinter::emitFunctionEntryLabel() {
285   const auto *RMFI = MF->getInfo<RISCVMachineFunctionInfo>();
286   if (RMFI->isVectorCall()) {
287     auto &RTS =
288         static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
289     RTS.emitDirectiveVariantCC(*CurrentFnSym);
290   }
291   return AsmPrinter::emitFunctionEntryLabel();
292 }
293 
294 // Force static initialization.
295 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmPrinter() {
296   RegisterAsmPrinter<RISCVAsmPrinter> X(getTheRISCV32Target());
297   RegisterAsmPrinter<RISCVAsmPrinter> Y(getTheRISCV64Target());
298 }
299 
300 void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {
301   Register Reg = MI.getOperand(0).getReg();
302   uint32_t AccessInfo = MI.getOperand(1).getImm();
303   MCSymbol *&Sym =
304       HwasanMemaccessSymbols[HwasanMemaccessTuple(Reg, AccessInfo)];
305   if (!Sym) {
306     // FIXME: Make this work on non-ELF.
307     if (!TM.getTargetTriple().isOSBinFormatELF())
308       report_fatal_error("llvm.hwasan.check.memaccess only supported on ELF");
309 
310     std::string SymName = "__hwasan_check_x" + utostr(Reg - RISCV::X0) + "_" +
311                           utostr(AccessInfo) + "_short";
312     Sym = OutContext.getOrCreateSymbol(SymName);
313   }
314   auto Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, OutContext);
315   auto Expr = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, OutContext);
316 
317   EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr));
318 }
319 
320 void RISCVAsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {
321   Register AddrReg = MI.getOperand(0).getReg();
322   assert(std::next(MI.getIterator())->isCall() &&
323          "KCFI_CHECK not followed by a call instruction");
324   assert(std::next(MI.getIterator())->getOperand(0).getReg() == AddrReg &&
325          "KCFI_CHECK call target doesn't match call operand");
326 
327   // Temporary registers for comparing the hashes. If a register is used
328   // for the call target, or reserved by the user, we can clobber another
329   // temporary register as the check is immediately followed by the
330   // call. The check defaults to X6/X7, but can fall back to X28-X31 if
331   // needed.
332   unsigned ScratchRegs[] = {RISCV::X6, RISCV::X7};
333   unsigned NextReg = RISCV::X28;
334   auto isRegAvailable = [&](unsigned Reg) {
335     return Reg != AddrReg && !STI->isRegisterReservedByUser(Reg);
336   };
337   for (auto &Reg : ScratchRegs) {
338     if (isRegAvailable(Reg))
339       continue;
340     while (!isRegAvailable(NextReg))
341       ++NextReg;
342     Reg = NextReg++;
343     if (Reg > RISCV::X31)
344       report_fatal_error("Unable to find scratch registers for KCFI_CHECK");
345   }
346 
347   if (AddrReg == RISCV::X0) {
348     // Checking X0 makes no sense. Instead of emitting a load, zero
349     // ScratchRegs[0].
350     EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI)
351                                      .addReg(ScratchRegs[0])
352                                      .addReg(RISCV::X0)
353                                      .addImm(0));
354   } else {
355     // Adjust the offset for patchable-function-prefix. This assumes that
356     // patchable-function-prefix is the same for all functions.
357     int NopSize = STI->hasStdExtCOrZca() ? 2 : 4;
358     int64_t PrefixNops = 0;
359     (void)MI.getMF()
360         ->getFunction()
361         .getFnAttribute("patchable-function-prefix")
362         .getValueAsString()
363         .getAsInteger(10, PrefixNops);
364 
365     // Load the target function type hash.
366     EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::LW)
367                                      .addReg(ScratchRegs[0])
368                                      .addReg(AddrReg)
369                                      .addImm(-(PrefixNops * NopSize + 4)));
370   }
371 
372   // Load the expected 32-bit type hash.
373   const int64_t Type = MI.getOperand(1).getImm();
374   const int64_t Hi20 = ((Type + 0x800) >> 12) & 0xFFFFF;
375   const int64_t Lo12 = SignExtend64<12>(Type);
376   if (Hi20) {
377     EmitToStreamer(
378         *OutStreamer,
379         MCInstBuilder(RISCV::LUI).addReg(ScratchRegs[1]).addImm(Hi20));
380   }
381   if (Lo12 || Hi20 == 0) {
382     EmitToStreamer(*OutStreamer,
383                    MCInstBuilder((STI->hasFeature(RISCV::Feature64Bit) && Hi20)
384                                      ? RISCV::ADDIW
385                                      : RISCV::ADDI)
386                        .addReg(ScratchRegs[1])
387                        .addReg(ScratchRegs[1])
388                        .addImm(Lo12));
389   }
390 
391   // Compare the hashes and trap if there's a mismatch.
392   MCSymbol *Pass = OutContext.createTempSymbol();
393   EmitToStreamer(*OutStreamer,
394                  MCInstBuilder(RISCV::BEQ)
395                      .addReg(ScratchRegs[0])
396                      .addReg(ScratchRegs[1])
397                      .addExpr(MCSymbolRefExpr::create(Pass, OutContext)));
398 
399   MCSymbol *Trap = OutContext.createTempSymbol();
400   OutStreamer->emitLabel(Trap);
401   EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::EBREAK));
402   emitKCFITrapEntry(*MI.getMF(), Trap);
403   OutStreamer->emitLabel(Pass);
404 }
405 
406 void RISCVAsmPrinter::EmitHwasanMemaccessSymbols(Module &M) {
407   if (HwasanMemaccessSymbols.empty())
408     return;
409 
410   assert(TM.getTargetTriple().isOSBinFormatELF());
411   // Use MCSubtargetInfo from TargetMachine. Individual functions may have
412   // attributes that differ from other functions in the module and we have no
413   // way to know which function is correct.
414   const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo();
415 
416   MCSymbol *HwasanTagMismatchV2Sym =
417       OutContext.getOrCreateSymbol("__hwasan_tag_mismatch_v2");
418   // Annotate symbol as one having incompatible calling convention, so
419   // run-time linkers can instead eagerly bind this function.
420   auto &RTS =
421       static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
422   RTS.emitDirectiveVariantCC(*HwasanTagMismatchV2Sym);
423 
424   const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
425       MCSymbolRefExpr::create(HwasanTagMismatchV2Sym, OutContext);
426   auto Expr = RISCVMCExpr::create(HwasanTagMismatchV2Ref,
427                                   RISCVMCExpr::VK_RISCV_CALL, OutContext);
428 
429   for (auto &P : HwasanMemaccessSymbols) {
430     unsigned Reg = std::get<0>(P.first);
431     uint32_t AccessInfo = std::get<1>(P.first);
432     MCSymbol *Sym = P.second;
433 
434     unsigned Size =
435         1 << ((AccessInfo >> HWASanAccessInfo::AccessSizeShift) & 0xf);
436     OutStreamer->switchSection(OutContext.getELFSection(
437         ".text.hot", ELF::SHT_PROGBITS,
438         ELF::SHF_EXECINSTR | ELF::SHF_ALLOC | ELF::SHF_GROUP, 0, Sym->getName(),
439         /*IsComdat=*/true));
440 
441     OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
442     OutStreamer->emitSymbolAttribute(Sym, MCSA_Weak);
443     OutStreamer->emitSymbolAttribute(Sym, MCSA_Hidden);
444     OutStreamer->emitLabel(Sym);
445 
446     // Extract shadow offset from ptr
447     OutStreamer->emitInstruction(
448         MCInstBuilder(RISCV::SLLI).addReg(RISCV::X6).addReg(Reg).addImm(8),
449         MCSTI);
450     OutStreamer->emitInstruction(MCInstBuilder(RISCV::SRLI)
451                                      .addReg(RISCV::X6)
452                                      .addReg(RISCV::X6)
453                                      .addImm(12),
454                                  MCSTI);
455     // load shadow tag in X6, X5 contains shadow base
456     OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADD)
457                                      .addReg(RISCV::X6)
458                                      .addReg(RISCV::X5)
459                                      .addReg(RISCV::X6),
460                                  MCSTI);
461     OutStreamer->emitInstruction(
462         MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
463         MCSTI);
464     // Extract tag from X5 and compare it with loaded tag from shadow
465     OutStreamer->emitInstruction(
466         MCInstBuilder(RISCV::SRLI).addReg(RISCV::X7).addReg(Reg).addImm(56),
467         MCSTI);
468     MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
469     // X7 contains tag from memory, while X6 contains tag from the pointer
470     OutStreamer->emitInstruction(
471         MCInstBuilder(RISCV::BNE)
472             .addReg(RISCV::X7)
473             .addReg(RISCV::X6)
474             .addExpr(MCSymbolRefExpr::create(HandleMismatchOrPartialSym,
475                                              OutContext)),
476         MCSTI);
477     MCSymbol *ReturnSym = OutContext.createTempSymbol();
478     OutStreamer->emitLabel(ReturnSym);
479     OutStreamer->emitInstruction(MCInstBuilder(RISCV::JALR)
480                                      .addReg(RISCV::X0)
481                                      .addReg(RISCV::X1)
482                                      .addImm(0),
483                                  MCSTI);
484     OutStreamer->emitLabel(HandleMismatchOrPartialSym);
485 
486     OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI)
487                                      .addReg(RISCV::X28)
488                                      .addReg(RISCV::X0)
489                                      .addImm(16),
490                                  MCSTI);
491     MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
492     OutStreamer->emitInstruction(
493         MCInstBuilder(RISCV::BGEU)
494             .addReg(RISCV::X6)
495             .addReg(RISCV::X28)
496             .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
497         MCSTI);
498 
499     OutStreamer->emitInstruction(
500         MCInstBuilder(RISCV::ANDI).addReg(RISCV::X28).addReg(Reg).addImm(0xF),
501         MCSTI);
502 
503     if (Size != 1)
504       OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI)
505                                        .addReg(RISCV::X28)
506                                        .addReg(RISCV::X28)
507                                        .addImm(Size - 1),
508                                    MCSTI);
509     OutStreamer->emitInstruction(
510         MCInstBuilder(RISCV::BGE)
511             .addReg(RISCV::X28)
512             .addReg(RISCV::X6)
513             .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
514         MCSTI);
515 
516     OutStreamer->emitInstruction(
517         MCInstBuilder(RISCV::ORI).addReg(RISCV::X6).addReg(Reg).addImm(0xF),
518         MCSTI);
519     OutStreamer->emitInstruction(
520         MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
521         MCSTI);
522     OutStreamer->emitInstruction(
523         MCInstBuilder(RISCV::BEQ)
524             .addReg(RISCV::X6)
525             .addReg(RISCV::X7)
526             .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)),
527         MCSTI);
528 
529     OutStreamer->emitLabel(HandleMismatchSym);
530 
531     // | Previous stack frames...        |
532     // +=================================+ <-- [SP + 256]
533     // |              ...                |
534     // |                                 |
535     // | Stack frame space for x12 - x31.|
536     // |                                 |
537     // |              ...                |
538     // +---------------------------------+ <-- [SP + 96]
539     // | Saved x11(arg1), as             |
540     // | __hwasan_check_* clobbers it.   |
541     // +---------------------------------+ <-- [SP + 88]
542     // | Saved x10(arg0), as             |
543     // | __hwasan_check_* clobbers it.   |
544     // +---------------------------------+ <-- [SP + 80]
545     // |                                 |
546     // | Stack frame space for x9.       |
547     // +---------------------------------+ <-- [SP + 72]
548     // |                                 |
549     // | Saved x8(fp), as                |
550     // | __hwasan_check_* clobbers it.   |
551     // +---------------------------------+ <-- [SP + 64]
552     // |              ...                |
553     // |                                 |
554     // | Stack frame space for x2 - x7.  |
555     // |                                 |
556     // |              ...                |
557     // +---------------------------------+ <-- [SP + 16]
558     // | Return address (x1) for caller  |
559     // | of __hwasan_check_*.            |
560     // +---------------------------------+ <-- [SP + 8]
561     // | Reserved place for x0, possibly |
562     // | junk, since we don't save it.   |
563     // +---------------------------------+ <-- [x2 / SP]
564 
565     // Adjust sp
566     OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI)
567                                      .addReg(RISCV::X2)
568                                      .addReg(RISCV::X2)
569                                      .addImm(-256),
570                                  MCSTI);
571 
572     // store x10(arg0) by new sp
573     OutStreamer->emitInstruction(MCInstBuilder(RISCV::SD)
574                                      .addReg(RISCV::X10)
575                                      .addReg(RISCV::X2)
576                                      .addImm(8 * 10),
577                                  MCSTI);
578     // store x11(arg1) by new sp
579     OutStreamer->emitInstruction(MCInstBuilder(RISCV::SD)
580                                      .addReg(RISCV::X11)
581                                      .addReg(RISCV::X2)
582                                      .addImm(8 * 11),
583                                  MCSTI);
584 
585     // store x8(fp) by new sp
586     OutStreamer->emitInstruction(
587         MCInstBuilder(RISCV::SD).addReg(RISCV::X8).addReg(RISCV::X2).addImm(8 *
588                                                                             8),
589         MCSTI);
590     // store x1(ra) by new sp
591     OutStreamer->emitInstruction(
592         MCInstBuilder(RISCV::SD).addReg(RISCV::X1).addReg(RISCV::X2).addImm(1 *
593                                                                             8),
594         MCSTI);
595     if (Reg != RISCV::X10)
596       OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI)
597                                        .addReg(RISCV::X10)
598                                        .addReg(Reg)
599                                        .addImm(0),
600                                    MCSTI);
601     OutStreamer->emitInstruction(
602         MCInstBuilder(RISCV::ADDI)
603             .addReg(RISCV::X11)
604             .addReg(RISCV::X0)
605             .addImm(AccessInfo & HWASanAccessInfo::RuntimeMask),
606         MCSTI);
607 
608     OutStreamer->emitInstruction(MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr),
609                                  MCSTI);
610   }
611 }
612 
613 static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
614                                     const AsmPrinter &AP) {
615   MCContext &Ctx = AP.OutContext;
616   RISCVMCExpr::VariantKind Kind;
617 
618   switch (MO.getTargetFlags()) {
619   default:
620     llvm_unreachable("Unknown target flag on GV operand");
621   case RISCVII::MO_None:
622     Kind = RISCVMCExpr::VK_RISCV_None;
623     break;
624   case RISCVII::MO_CALL:
625     Kind = RISCVMCExpr::VK_RISCV_CALL;
626     break;
627   case RISCVII::MO_PLT:
628     Kind = RISCVMCExpr::VK_RISCV_CALL_PLT;
629     break;
630   case RISCVII::MO_LO:
631     Kind = RISCVMCExpr::VK_RISCV_LO;
632     break;
633   case RISCVII::MO_HI:
634     Kind = RISCVMCExpr::VK_RISCV_HI;
635     break;
636   case RISCVII::MO_PCREL_LO:
637     Kind = RISCVMCExpr::VK_RISCV_PCREL_LO;
638     break;
639   case RISCVII::MO_PCREL_HI:
640     Kind = RISCVMCExpr::VK_RISCV_PCREL_HI;
641     break;
642   case RISCVII::MO_GOT_HI:
643     Kind = RISCVMCExpr::VK_RISCV_GOT_HI;
644     break;
645   case RISCVII::MO_TPREL_LO:
646     Kind = RISCVMCExpr::VK_RISCV_TPREL_LO;
647     break;
648   case RISCVII::MO_TPREL_HI:
649     Kind = RISCVMCExpr::VK_RISCV_TPREL_HI;
650     break;
651   case RISCVII::MO_TPREL_ADD:
652     Kind = RISCVMCExpr::VK_RISCV_TPREL_ADD;
653     break;
654   case RISCVII::MO_TLS_GOT_HI:
655     Kind = RISCVMCExpr::VK_RISCV_TLS_GOT_HI;
656     break;
657   case RISCVII::MO_TLS_GD_HI:
658     Kind = RISCVMCExpr::VK_RISCV_TLS_GD_HI;
659     break;
660   }
661 
662   const MCExpr *ME =
663       MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
664 
665   if (!MO.isJTI() && !MO.isMBB() && MO.getOffset())
666     ME = MCBinaryExpr::createAdd(
667         ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
668 
669   if (Kind != RISCVMCExpr::VK_RISCV_None)
670     ME = RISCVMCExpr::create(ME, Kind, Ctx);
671   return MCOperand::createExpr(ME);
672 }
673 
674 bool RISCVAsmPrinter::lowerOperand(const MachineOperand &MO,
675                                    MCOperand &MCOp) const {
676   switch (MO.getType()) {
677   default:
678     report_fatal_error("lowerOperand: unknown operand type");
679   case MachineOperand::MO_Register:
680     // Ignore all implicit register operands.
681     if (MO.isImplicit())
682       return false;
683     MCOp = MCOperand::createReg(MO.getReg());
684     break;
685   case MachineOperand::MO_RegisterMask:
686     // Regmasks are like implicit defs.
687     return false;
688   case MachineOperand::MO_Immediate:
689     MCOp = MCOperand::createImm(MO.getImm());
690     break;
691   case MachineOperand::MO_MachineBasicBlock:
692     MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), *this);
693     break;
694   case MachineOperand::MO_GlobalAddress:
695     MCOp = lowerSymbolOperand(MO, getSymbolPreferLocal(*MO.getGlobal()), *this);
696     break;
697   case MachineOperand::MO_BlockAddress:
698     MCOp = lowerSymbolOperand(MO, GetBlockAddressSymbol(MO.getBlockAddress()),
699                               *this);
700     break;
701   case MachineOperand::MO_ExternalSymbol:
702     MCOp = lowerSymbolOperand(MO, GetExternalSymbolSymbol(MO.getSymbolName()),
703                               *this);
704     break;
705   case MachineOperand::MO_ConstantPoolIndex:
706     MCOp = lowerSymbolOperand(MO, GetCPISymbol(MO.getIndex()), *this);
707     break;
708   case MachineOperand::MO_JumpTableIndex:
709     MCOp = lowerSymbolOperand(MO, GetJTISymbol(MO.getIndex()), *this);
710     break;
711   case MachineOperand::MO_MCSymbol:
712     MCOp = lowerSymbolOperand(MO, MO.getMCSymbol(), *this);
713     break;
714   }
715   return true;
716 }
717 
718 static bool lowerRISCVVMachineInstrToMCInst(const MachineInstr *MI,
719                                             MCInst &OutMI) {
720   const RISCVVPseudosTable::PseudoInfo *RVV =
721       RISCVVPseudosTable::getPseudoInfo(MI->getOpcode());
722   if (!RVV)
723     return false;
724 
725   OutMI.setOpcode(RVV->BaseInstr);
726 
727   const MachineBasicBlock *MBB = MI->getParent();
728   assert(MBB && "MI expected to be in a basic block");
729   const MachineFunction *MF = MBB->getParent();
730   assert(MF && "MBB expected to be in a machine function");
731 
732   const RISCVSubtarget &Subtarget = MF->getSubtarget<RISCVSubtarget>();
733   const TargetInstrInfo *TII = Subtarget.getInstrInfo();
734   const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
735   assert(TRI && "TargetRegisterInfo expected");
736 
737   const MCInstrDesc &MCID = MI->getDesc();
738   uint64_t TSFlags = MCID.TSFlags;
739   unsigned NumOps = MI->getNumExplicitOperands();
740 
741   // Skip policy, VL and SEW operands which are the last operands if present.
742   if (RISCVII::hasVecPolicyOp(TSFlags))
743     --NumOps;
744   if (RISCVII::hasVLOp(TSFlags))
745     --NumOps;
746   if (RISCVII::hasSEWOp(TSFlags))
747     --NumOps;
748   if (RISCVII::hasRoundModeOp(TSFlags))
749     --NumOps;
750 
751   bool hasVLOutput = RISCV::isFaultFirstLoad(*MI);
752   for (unsigned OpNo = 0; OpNo != NumOps; ++OpNo) {
753     const MachineOperand &MO = MI->getOperand(OpNo);
754     // Skip vl ouput. It should be the second output.
755     if (hasVLOutput && OpNo == 1)
756       continue;
757 
758     // Skip merge op. It should be the first operand after the defs.
759     if (OpNo == MI->getNumExplicitDefs() && MO.isReg() && MO.isTied()) {
760       assert(MCID.getOperandConstraint(OpNo, MCOI::TIED_TO) == 0 &&
761              "Expected tied to first def.");
762       const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode());
763       // Skip if the next operand in OutMI is not supposed to be tied. Unless it
764       // is a _TIED instruction.
765       if (OutMCID.getOperandConstraint(OutMI.getNumOperands(), MCOI::TIED_TO) <
766               0 &&
767           !RISCVII::isTiedPseudo(TSFlags))
768         continue;
769     }
770 
771     MCOperand MCOp;
772     switch (MO.getType()) {
773     default:
774       llvm_unreachable("Unknown operand type");
775     case MachineOperand::MO_Register: {
776       Register Reg = MO.getReg();
777 
778       if (RISCV::VRM2RegClass.contains(Reg) ||
779           RISCV::VRM4RegClass.contains(Reg) ||
780           RISCV::VRM8RegClass.contains(Reg)) {
781         Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0);
782         assert(Reg && "Subregister does not exist");
783       } else if (RISCV::FPR16RegClass.contains(Reg)) {
784         Reg =
785             TRI->getMatchingSuperReg(Reg, RISCV::sub_16, &RISCV::FPR32RegClass);
786         assert(Reg && "Subregister does not exist");
787       } else if (RISCV::FPR64RegClass.contains(Reg)) {
788         Reg = TRI->getSubReg(Reg, RISCV::sub_32);
789         assert(Reg && "Superregister does not exist");
790       } else if (RISCV::VRN2M1RegClass.contains(Reg) ||
791                  RISCV::VRN2M2RegClass.contains(Reg) ||
792                  RISCV::VRN2M4RegClass.contains(Reg) ||
793                  RISCV::VRN3M1RegClass.contains(Reg) ||
794                  RISCV::VRN3M2RegClass.contains(Reg) ||
795                  RISCV::VRN4M1RegClass.contains(Reg) ||
796                  RISCV::VRN4M2RegClass.contains(Reg) ||
797                  RISCV::VRN5M1RegClass.contains(Reg) ||
798                  RISCV::VRN6M1RegClass.contains(Reg) ||
799                  RISCV::VRN7M1RegClass.contains(Reg) ||
800                  RISCV::VRN8M1RegClass.contains(Reg)) {
801         Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0);
802         assert(Reg && "Subregister does not exist");
803       }
804 
805       MCOp = MCOperand::createReg(Reg);
806       break;
807     }
808     case MachineOperand::MO_Immediate:
809       MCOp = MCOperand::createImm(MO.getImm());
810       break;
811     }
812     OutMI.addOperand(MCOp);
813   }
814 
815   // Unmasked pseudo instructions need to append dummy mask operand to
816   // V instructions. All V instructions are modeled as the masked version.
817   const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode());
818   if (OutMI.getNumOperands() < OutMCID.getNumOperands()) {
819     assert(OutMCID.operands()[OutMI.getNumOperands()].RegClass ==
820                RISCV::VMV0RegClassID &&
821            "Expected only mask operand to be missing");
822     OutMI.addOperand(MCOperand::createReg(RISCV::NoRegister));
823   }
824 
825   assert(OutMI.getNumOperands() == OutMCID.getNumOperands());
826   return true;
827 }
828 
829 bool RISCVAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {
830   if (lowerRISCVVMachineInstrToMCInst(MI, OutMI))
831     return false;
832 
833   OutMI.setOpcode(MI->getOpcode());
834 
835   for (const MachineOperand &MO : MI->operands()) {
836     MCOperand MCOp;
837     if (lowerOperand(MO, MCOp))
838       OutMI.addOperand(MCOp);
839   }
840 
841   switch (OutMI.getOpcode()) {
842   case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
843     const Function &F = MI->getParent()->getParent()->getFunction();
844     if (F.hasFnAttribute("patchable-function-entry")) {
845       unsigned Num;
846       if (F.getFnAttribute("patchable-function-entry")
847               .getValueAsString()
848               .getAsInteger(10, Num))
849         return false;
850       emitNops(Num);
851       return true;
852     }
853     break;
854   }
855   }
856   return false;
857 }
858