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