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