LLVM 24.0.0git
RISCVAsmPrinter.cpp
Go to the documentation of this file.
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 "RISCVAsmPrinter.h"
21#include "RISCV.h"
24#include "RISCVRegisterInfo.h"
26#include "llvm/ADT/APInt.h"
27#include "llvm/ADT/Statistic.h"
35#include "llvm/IR/Module.h"
36#include "llvm/MC/MCAsmInfo.h"
37#include "llvm/MC/MCContext.h"
38#include "llvm/MC/MCInst.h"
42#include "llvm/MC/MCStreamer.h"
43#include "llvm/MC/MCSymbol.h"
49
50using namespace llvm;
51
52#define DEBUG_TYPE "asm-printer"
53
54STATISTIC(RISCVNumInstrsCompressed,
55 "Number of RISC-V Compressed instructions emitted");
56
57namespace {
58class RISCVAsmPrinter : public AsmPrinter {
59public:
60 static char ID;
61
62private:
63 const RISCVSubtarget *STI;
64
65public:
66 explicit RISCVAsmPrinter(TargetMachine &TM,
67 std::unique_ptr<MCStreamer> Streamer)
68 : AsmPrinter(TM, std::move(Streamer), ID) {}
69
70 StringRef getPassName() const override { return "RISC-V Assembly Printer"; }
71
72 RISCVTargetStreamer &getTargetStreamer() const {
73 return static_cast<RISCVTargetStreamer &>(
74 *OutStreamer->getTargetStreamer());
75 }
76
77 void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
78 const MachineInstr &MI);
79
80 void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
81 const MachineInstr &MI);
82
83 void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
84 const MachineInstr &MI);
85
86 bool runOnMachineFunction(MachineFunction &MF) override;
87
88 void emitInstruction(const MachineInstr *MI) override;
89
90 void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override;
91
92 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
93 const char *ExtraCode, raw_ostream &OS) override;
94 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
95 const char *ExtraCode, raw_ostream &OS) override;
96
97 // Returns whether Inst is compressed.
98 bool EmitToStreamer(MCStreamer &S, const MCInst &Inst,
99 const MCSubtargetInfo &SubtargetInfo);
100 bool EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
101 return EmitToStreamer(S, Inst, *STI);
102 }
103
104 bool lowerPseudoInstExpansion(const MachineInstr *MI, MCInst &Inst);
105
106 typedef std::tuple<unsigned, uint32_t> HwasanMemaccessTuple;
107 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
108 void LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI);
109 void LowerKCFI_CHECK(const MachineInstr &MI);
110 void EmitHwasanMemaccessSymbols(Module &M);
111
112 // Wrapper needed for tblgenned pseudo lowering.
113 bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const;
114
115 void emitStartOfAsmFile(Module &M) override;
116 void emitEndOfAsmFile(Module &M) override;
117
118 void emitFunctionEntryLabel() override;
119 bool emitTargetFeaturePush(const MCSubtargetInfo &STI) override;
120 void emitTargetFeaturePop(const MCSubtargetInfo &STI, bool DidPush) override;
121
122 void emitNoteGnuProperty(const Module &M);
123
124private:
125 void emitAttributes(const MCSubtargetInfo &SubtargetInfo);
126
127 void emitNTLHint(const MachineInstr *MI);
128
129 void emitLpadAlignedCall(const MachineInstr &MI);
130
131 // XRay Support
132 void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr *MI);
133 void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr *MI);
134 void LowerPATCHABLE_TAIL_CALL(const MachineInstr *MI);
135 void emitSled(const MachineInstr *MI, SledKind Kind);
136
137 void lowerToMCInst(const MachineInstr *MI, MCInst &OutMI);
138};
139} // namespace
140
141void RISCVAsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
142 const MachineInstr &MI) {
143 unsigned NOPBytes = STI->hasStdExtZca() ? 2 : 4;
144 unsigned NumNOPBytes = StackMapOpers(&MI).getNumPatchBytes();
145
146 auto &Ctx = OutStreamer.getContext();
147 MCSymbol *MILabel = Ctx.createTempSymbol();
148 OutStreamer.emitLabel(MILabel);
149
150 SM.recordStackMap(*MILabel, MI);
151 assert(NumNOPBytes % NOPBytes == 0 &&
152 "Invalid number of NOP bytes requested!");
153
154 // Scan ahead to trim the shadow.
155 const MachineBasicBlock &MBB = *MI.getParent();
157 ++MII;
158 while (NumNOPBytes > 0) {
159 if (MII == MBB.end() || MII->isCall() ||
160 MII->getOpcode() == RISCV::DBG_VALUE ||
161 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
162 MII->getOpcode() == TargetOpcode::STACKMAP)
163 break;
164 ++MII;
165 NumNOPBytes -= NOPBytes;
166 }
167
168 // Emit nops.
169 emitNops(NumNOPBytes / NOPBytes);
170}
171
172// Lower a patchpoint of the form:
173// [<def>], <id>, <numBytes>, <target>, <numArgs>
174void RISCVAsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
175 const MachineInstr &MI) {
176 unsigned NOPBytes = STI->hasStdExtZca() ? 2 : 4;
177
178 auto &Ctx = OutStreamer.getContext();
179 MCSymbol *MILabel = Ctx.createTempSymbol();
180 OutStreamer.emitLabel(MILabel);
181 SM.recordPatchPoint(*MILabel, MI);
182
183 PatchPointOpers Opers(&MI);
184
185 const MachineOperand &CalleeMO = Opers.getCallTarget();
186 unsigned EncodedBytes = 0;
187
188 if (CalleeMO.isImm()) {
189 uint64_t CallTarget = CalleeMO.getImm();
190 if (CallTarget) {
191 assert((CallTarget & 0xFFFF'FFFF'FFFF) == CallTarget &&
192 "High 16 bits of call target should be zero.");
193 // Materialize the jump address:
195 RISCVMatInt::generateMCInstSeq(CallTarget, *STI, RISCV::X1, Seq);
196 for (MCInst &Inst : Seq) {
197 bool Compressed = EmitToStreamer(OutStreamer, Inst);
198 EncodedBytes += Compressed ? 2 : 4;
199 }
200 bool Compressed = EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JALR)
201 .addReg(RISCV::X1)
202 .addReg(RISCV::X1)
203 .addImm(0));
204 EncodedBytes += Compressed ? 2 : 4;
205 }
206 } else if (CalleeMO.isGlobal()) {
207 MCOperand CallTargetMCOp;
208 lowerOperand(CalleeMO, CallTargetMCOp);
209 EmitToStreamer(OutStreamer,
210 MCInstBuilder(RISCV::PseudoCALL).addOperand(CallTargetMCOp));
211 EncodedBytes += 8;
212 }
213
214 // Emit padding.
215 unsigned NumBytes = Opers.getNumPatchBytes();
216 assert(NumBytes >= EncodedBytes &&
217 "Patchpoint can't request size less than the length of a call.");
218 assert((NumBytes - EncodedBytes) % NOPBytes == 0 &&
219 "Invalid number of NOP bytes requested!");
220 emitNops((NumBytes - EncodedBytes) / NOPBytes);
221}
222
223void RISCVAsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
224 const MachineInstr &MI) {
225 unsigned NOPBytes = STI->hasStdExtZca() ? 2 : 4;
226
227 StatepointOpers SOpers(&MI);
228 if (unsigned PatchBytes = SOpers.getNumPatchBytes()) {
229 assert(PatchBytes % NOPBytes == 0 &&
230 "Invalid number of NOP bytes requested!");
231 emitNops(PatchBytes / NOPBytes);
232 } else {
233 // Lower call target and choose correct opcode
234 const MachineOperand &CallTarget = SOpers.getCallTarget();
235 MCOperand CallTargetMCOp;
236 switch (CallTarget.getType()) {
239 lowerOperand(CallTarget, CallTargetMCOp);
240 EmitToStreamer(
241 OutStreamer,
242 MCInstBuilder(RISCV::PseudoCALL).addOperand(CallTargetMCOp));
243 break;
245 CallTargetMCOp = MCOperand::createImm(CallTarget.getImm());
246 EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JAL)
247 .addReg(RISCV::X1)
248 .addOperand(CallTargetMCOp));
249 break;
251 CallTargetMCOp = MCOperand::createReg(CallTarget.getReg());
252 EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JALR)
253 .addReg(RISCV::X1)
254 .addOperand(CallTargetMCOp)
255 .addImm(0));
256 break;
257 default:
258 llvm_unreachable("Unsupported operand type in statepoint call target");
259 break;
260 }
261 }
262
263 auto &Ctx = OutStreamer.getContext();
264 MCSymbol *MILabel = Ctx.createTempSymbol();
265 OutStreamer.emitLabel(MILabel);
266 SM.recordStatepoint(*MILabel, MI);
267}
268
269bool RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst,
270 const MCSubtargetInfo &SubtargetInfo) {
271 MCInst CInst;
272 bool Res = RISCVRVC::compress(CInst, Inst, SubtargetInfo);
273 if (Res)
274 ++RISCVNumInstrsCompressed;
275 S.emitInstruction(Res ? CInst : Inst, SubtargetInfo);
276 return Res;
277}
278
279// Simple pseudo-instructions have their lowering (with expansion to real
280// instructions) auto-generated.
281#include "RISCVGenMCPseudoLowering.inc"
282
283// Emit a call to a returns_twice function with LPAD.
284// When Zca is enabled, emit .p2align 2 before the call to ensure the
285// following LPAD is 4-byte aligned. For assembly output, wrap with
286// .option push/exact/pop to prevent relaxation. For object output,
287// emit the pseudo directly so MCCodeEmitter handles it without R_RISCV_RELAX.
288void RISCVAsmPrinter::emitLpadAlignedCall(const MachineInstr &MI) {
289 const MCSubtargetInfo &MCSTI = getSubtargetInfo();
290 const bool IsIndirect = MI.getOpcode() == RISCV::PseudoCALLIndirectLpadAlign,
291 HasZca = MCSTI.hasFeature(RISCV::FeatureStdExtZca),
292 HasRelax = MCSTI.hasFeature(RISCV::FeatureRelax);
293
294 if (HasZca)
295 OutStreamer->emitCodeAlignment(Align(4), MCSTI);
296
297 if (OutStreamer->hasRawTextSupport()) {
298 // Assembly path: wrap call with .option push/exact/pop and emit LPAD
299 // separately so the output is human-readable.
300 RISCVTargetStreamer &RTS = getTargetStreamer();
301 if (HasZca && HasRelax) {
304 }
305
306 MCInst CallInst;
307 if (!IsIndirect) {
308 MCOperand MCOp;
309 lowerOperand(MI.getOperand(0), MCOp);
310 CallInst = MCInstBuilder(RISCV::PseudoCALL).addOperand(MCOp);
311 } else {
312 CallInst = MCInstBuilder(RISCV::JALR)
313 .addReg(RISCV::X1)
314 .addReg(MI.getOperand(0).getReg())
315 .addImm(0);
316 }
317
318 if (HasZca && HasRelax) {
319 MCSubtargetInfo NoRelaxSTI(MCSTI);
320 NoRelaxSTI.ToggleFeature(RISCV::FeatureRelax);
321 EmitToStreamer(*OutStreamer, CallInst, NoRelaxSTI);
323 } else {
324 EmitToStreamer(*OutStreamer, CallInst, MCSTI);
325 }
326
327 // LPAD is encoded as AUIPC X0, label.
328 MCInst LpadInst = MCInstBuilder(RISCV::AUIPC)
329 .addReg(RISCV::X0)
330 .addImm(MI.getOperand(1).getImm());
331 EmitToStreamer(*OutStreamer, LpadInst, MCSTI);
332 } else {
333 // Object path: emit PseudoCALL(Indirect)LpadAlign directly.
334 // MCCodeEmitter::expandFunctionCallLpad expands to AUIPC+JALR+LPAD
335 // without emitting R_RISCV_RELAX on the call fixup.
336 MCInst TmpInst;
337 TmpInst.setOpcode(MI.getOpcode());
338 if (!IsIndirect) {
339 MCOperand MCOp;
340 lowerOperand(MI.getOperand(0), MCOp);
341 TmpInst.addOperand(MCOp);
342 } else {
343 TmpInst.addOperand(MCOperand::createReg(MI.getOperand(0).getReg()));
344 }
345 TmpInst.addOperand(MCOperand::createImm(MI.getOperand(1).getImm()));
346 EmitToStreamer(*OutStreamer, TmpInst, MCSTI);
347 }
348}
349
350// If the instruction has a nontemporal MachineMemOperand, emit an NTL hint
351// instruction before it. NTL hints are always safe to emit since they use
352// HINT encodings that are guaranteed not to trap
353// (riscv-non-isa/riscv-elf-psabi-doc#474).
354void RISCVAsmPrinter::emitNTLHint(const MachineInstr *MI) {
355 if (!STI->getInstrInfo()->requiresNTLHint(*MI))
356 return;
357
358 assert(!MI->memoperands_empty());
359
360 MachineMemOperand *MMO = *(MI->memoperands_begin());
361
362 assert(MMO->isNonTemporal());
363
364 unsigned NontemporalMode = 0;
365 if (MMO->getFlags() & MONontemporalBit0)
366 NontemporalMode += 0b1;
367 if (MMO->getFlags() & MONontemporalBit1)
368 NontemporalMode += 0b10;
369
370 MCInst Hint;
371 if (STI->hasStdExtZca())
372 Hint.setOpcode(RISCV::C_ADD);
373 else
374 Hint.setOpcode(RISCV::ADD);
375
376 Hint.addOperand(MCOperand::createReg(RISCV::X0));
377 Hint.addOperand(MCOperand::createReg(RISCV::X0));
378 Hint.addOperand(MCOperand::createReg(RISCV::X2 + NontemporalMode));
379
380 EmitToStreamer(*OutStreamer, Hint);
381}
382
383void RISCVAsmPrinter::emitInstruction(const MachineInstr *MI) {
384 RISCV_MC::verifyInstructionPredicates(MI->getOpcode(), STI->getFeatureBits());
385
386 emitNTLHint(MI);
387
388 // Do any auto-generated pseudo lowerings.
389 if (MCInst OutInst; lowerPseudoInstExpansion(MI, OutInst)) {
390 EmitToStreamer(*OutStreamer, OutInst);
391 return;
392 }
393
394 switch (MI->getOpcode()) {
395 case RISCV::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
396 LowerHWASAN_CHECK_MEMACCESS(*MI);
397 return;
398 case RISCV::KCFI_CHECK:
399 LowerKCFI_CHECK(*MI);
400 return;
401 case TargetOpcode::STACKMAP:
402 return LowerSTACKMAP(*OutStreamer, SM, *MI);
403 case TargetOpcode::PATCHPOINT:
404 return LowerPATCHPOINT(*OutStreamer, SM, *MI);
405 case TargetOpcode::STATEPOINT:
406 return LowerSTATEPOINT(*OutStreamer, SM, *MI);
407 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
408 const Function &F = MI->getParent()->getParent()->getFunction();
409 if (F.hasFnAttribute("patchable-function-entry")) {
410 unsigned Num =
411 F.getFnAttributeAsParsedInteger("patchable-function-entry");
412 emitNops(Num);
413 return;
414 }
415 LowerPATCHABLE_FUNCTION_ENTER(MI);
416 return;
417 }
418 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
419 LowerPATCHABLE_FUNCTION_EXIT(MI);
420 return;
421 case TargetOpcode::PATCHABLE_TAIL_CALL:
422 LowerPATCHABLE_TAIL_CALL(MI);
423 return;
424 case RISCV::PseudoCALLLpadAlign:
425 case RISCV::PseudoCALLIndirectLpadAlign:
426 emitLpadAlignedCall(*MI);
427 return;
428 }
429
430 MCInst OutInst;
431 lowerToMCInst(MI, OutInst);
432 EmitToStreamer(*OutStreamer, OutInst);
433}
434
435bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
436 const char *ExtraCode, raw_ostream &OS) {
437 // First try the generic code, which knows about modifiers like 'c' and 'n'.
438 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
439 return false;
440
441 const MachineOperand &MO = MI->getOperand(OpNo);
442 if (ExtraCode && ExtraCode[0]) {
443 if (ExtraCode[1] != 0)
444 return true; // Unknown modifier.
445
446 switch (ExtraCode[0]) {
447 default:
448 return true; // Unknown modifier.
449 case 'z': // Print zero register if zero, regular printing otherwise.
450 if (MO.isImm() && MO.getImm() == 0) {
451 OS << RISCVInstPrinter::getRegisterName(RISCV::X0);
452 return false;
453 }
454 break;
455 case 'i': // Literal 'i' if operand is not a register.
456 if (!MO.isReg())
457 OS << 'i';
458 return false;
459 case 'N': // Print the register encoding as an integer (0-31)
460 if (!MO.isReg())
461 return true;
462
463 const RISCVRegisterInfo *TRI = STI->getRegisterInfo();
464 OS << TRI->getEncodingValue(MO.getReg());
465 return false;
466 }
467 }
468
469 switch (MO.getType()) {
471 OS << MO.getImm();
472 return false;
475 return false;
477 PrintSymbolOperand(MO, OS);
478 return false;
480 MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());
481 Sym->print(OS, MAI);
482 return false;
483 }
484 default:
485 break;
486 }
487
488 return true;
489}
490
491bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
492 unsigned OpNo,
493 const char *ExtraCode,
494 raw_ostream &OS) {
495 if (ExtraCode)
496 return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
497
498 const MachineOperand &AddrReg = MI->getOperand(OpNo);
499 assert(MI->getNumOperands() > OpNo + 1 && "Expected additional operand");
500 const MachineOperand &Offset = MI->getOperand(OpNo + 1);
501 // All memory operands should have a register and an immediate operand (see
502 // RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand).
503 if (!AddrReg.isReg())
504 return true;
505 if (!Offset.isImm() && !Offset.isGlobal() && !Offset.isBlockAddress() &&
506 !Offset.isMCSymbol())
507 return true;
508
509 MCOperand MCO;
510 if (!lowerOperand(Offset, MCO))
511 return true;
512
513 if (Offset.isImm())
514 OS << MCO.getImm();
515 else if (Offset.isGlobal() || Offset.isBlockAddress() || Offset.isMCSymbol())
516 MAI.printExpr(OS, *MCO.getExpr());
517
518 if (Offset.isMCSymbol())
519 MMI->getContext().registerInlineAsmLabel(Offset.getMCSymbol());
520 if (Offset.isBlockAddress()) {
521 const BlockAddress *BA = Offset.getBlockAddress();
522 MCSymbol *Sym = GetBlockAddressSymbol(BA);
523 MMI->getContext().registerInlineAsmLabel(Sym);
524 }
525
526 OS << "(" << RISCVInstPrinter::getRegisterName(AddrReg.getReg()) << ")";
527 return false;
528}
529
530bool RISCVAsmPrinter::emitTargetFeaturePush(const MCSubtargetInfo &STI) {
531 RISCVTargetStreamer &RTS = getTargetStreamer();
532 SmallVector<RISCVOptionArchArg> NeedEmitStdOptionArgs;
533 const MCSubtargetInfo &MCSTI = TM.getMCSubtargetInfo();
534 for (const auto &Feature : MCSTI.getAllProcessorFeatures()) {
535 if (STI.hasFeature(Feature.Value) == MCSTI.hasFeature(Feature.Value))
536 continue;
537
539 continue;
540
541 auto Delta = STI.hasFeature(Feature.Value) ? RISCVOptionArchArgType::Plus
542 : RISCVOptionArchArgType::Minus;
543 StringRef ExtName = Feature.key();
544 ExtName.consume_front("experimental-");
545 NeedEmitStdOptionArgs.emplace_back(Delta, ExtName.str());
546 }
547 if (!NeedEmitStdOptionArgs.empty()) {
549 RTS.emitDirectiveOptionArch(NeedEmitStdOptionArgs);
550 return true;
551 }
552
553 return false;
554}
555
556void RISCVAsmPrinter::emitTargetFeaturePop(const MCSubtargetInfo &STI,
557 bool DidPush) {
558 if (DidPush)
559 getTargetStreamer().emitDirectiveOptionPop();
560}
561
562bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
563 STI = &MF.getSubtarget<RISCVSubtarget>();
564
565 bool EmittedOptionArch = emitTargetFeaturePush(*STI);
566
567 SetupMachineFunction(MF);
568 emitFunctionBody();
569
570 // Emit the XRay table
571 emitXRayTable();
572
573 emitTargetFeaturePop(*STI, EmittedOptionArch);
574 return false;
575}
576
577void RISCVAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr *MI) {
578 emitSled(MI, SledKind::FUNCTION_ENTER);
579}
580
581void RISCVAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr *MI) {
582 emitSled(MI, SledKind::FUNCTION_EXIT);
583}
584
585void RISCVAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr *MI) {
586 emitSled(MI, SledKind::TAIL_CALL);
587}
588
589void RISCVAsmPrinter::emitSled(const MachineInstr *MI, SledKind Kind) {
590 // We want to emit the jump instruction and the nops constituting the sled.
591 // The format is as follows:
592 // .Lxray_sled_N
593 // ALIGN
594 // J .tmpN
595 // 21 or 33 C.NOP instructions
596 // .tmpN
597
598 // The following variable holds the count of the number of NOPs to be patched
599 // in for XRay instrumentation during compilation.
600 // Note that RV64 and RV32 each has a sled of 68 and 44 bytes, respectively.
601 // Assuming we're using JAL to jump to .tmpN, then we only need
602 // (68 - 4)/2 = 32 NOPs for RV64 and (44 - 4)/2 = 20 for RV32. However, there
603 // is a chance that we'll use C.JAL instead, so an additional NOP is needed.
604 const uint8_t NoopsInSledCount = STI->is64Bit() ? 33 : 21;
605
606 OutStreamer->emitCodeAlignment(Align(4), *STI);
607 auto CurSled = OutContext.createTempSymbol("xray_sled_", true);
608 OutStreamer->emitLabel(CurSled);
609 auto Target = OutContext.createTempSymbol();
610
611 const MCExpr *TargetExpr = MCSymbolRefExpr::create(Target, OutContext);
612
613 // Emit "J bytes" instruction, which jumps over the nop sled to the actual
614 // start of function.
615 EmitToStreamer(
616 *OutStreamer,
617 MCInstBuilder(RISCV::JAL).addReg(RISCV::X0).addExpr(TargetExpr));
618
619 // Emit NOP instructions
620 for (int8_t I = 0; I < NoopsInSledCount; ++I)
621 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI)
622 .addReg(RISCV::X0)
623 .addReg(RISCV::X0)
624 .addImm(0));
625
626 OutStreamer->emitLabel(Target);
627 recordSled(CurSled, *MI, Kind, 2);
628}
629
630void RISCVAsmPrinter::emitStartOfAsmFile(Module &M) {
631 assert(OutStreamer->getTargetStreamer() &&
632 "target streamer is uninitialized");
633 RISCVTargetStreamer &RTS = getTargetStreamer();
634 if (const MDString *ModuleTargetABI =
635 dyn_cast_or_null<MDString>(M.getModuleFlag("target-abi")))
636 RTS.setTargetABI(RISCVABI::getTargetABI(ModuleTargetABI->getString()));
637
638 MCSubtargetInfo SubtargetInfo = TM.getMCSubtargetInfo();
639
640 // Use module flag to update feature bits.
641 if (auto *MD = dyn_cast_or_null<MDNode>(M.getModuleFlag("riscv-isa"))) {
642 for (auto &ISA : MD->operands()) {
643 if (auto *ISAString = dyn_cast_or_null<MDString>(ISA)) {
644 auto ParseResult = llvm::RISCVISAInfo::parseArchString(
645 ISAString->getString(), /*EnableExperimentalExtension=*/true,
646 /*ExperimentalExtensionVersionCheck=*/true);
647 if (!errorToBool(ParseResult.takeError())) {
648 auto &ISAInfo = *ParseResult;
649 for (const auto &Feature : SubtargetInfo.getAllProcessorFeatures()) {
650 if (ISAInfo->hasExtension(Feature.key()) &&
651 !SubtargetInfo.hasFeature(Feature.Value))
652 SubtargetInfo.ToggleFeature(Feature.key());
653 }
654 }
655 }
656 }
657
658 RTS.setFlagsFromFeatures(SubtargetInfo);
659 }
660
661 if (TM.getTargetTriple().isOSBinFormatELF())
662 emitAttributes(SubtargetInfo);
663}
664
665void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) {
666 RISCVTargetStreamer &RTS = getTargetStreamer();
667
668 if (TM.getTargetTriple().isOSBinFormatELF()) {
670 emitNoteGnuProperty(M);
671 }
672 EmitHwasanMemaccessSymbols(M);
673}
674
675void RISCVAsmPrinter::emitAttributes(const MCSubtargetInfo &SubtargetInfo) {
676 RISCVTargetStreamer &RTS = getTargetStreamer();
677 // Use MCSubtargetInfo from TargetMachine. Individual functions may have
678 // attributes that differ from other functions in the module and we have no
679 // way to know which function is correct.
680 RTS.emitTargetAttributes(SubtargetInfo, /*EmitStackAlign*/ true);
681}
682
683void RISCVAsmPrinter::emitFunctionEntryLabel() {
684 const auto *RMFI = MF->getInfo<RISCVMachineFunctionInfo>();
685 if (RMFI->isVectorCall()) {
686 RISCVTargetStreamer &RTS = getTargetStreamer();
687 RTS.emitDirectiveVariantCC(*CurrentFnSym);
688 }
690}
691
692// Force static initialization.
700
701void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {
702 Register Reg = MI.getOperand(0).getReg();
703 uint32_t AccessInfo = MI.getOperand(1).getImm();
704 MCSymbol *&Sym =
705 HwasanMemaccessSymbols[HwasanMemaccessTuple(Reg, AccessInfo)];
706 if (!Sym) {
707 // FIXME: Make this work on non-ELF.
708 if (!TM.getTargetTriple().isOSBinFormatELF())
709 report_fatal_error("llvm.hwasan.check.memaccess only supported on ELF");
710
711 std::string SymName = "__hwasan_check_x" + utostr(Reg - RISCV::X0) + "_" +
712 utostr(AccessInfo) + "_short";
713 Sym = OutContext.getOrCreateSymbol(SymName);
714 }
715 auto Res = MCSymbolRefExpr::create(Sym, OutContext);
716 auto Expr = MCSpecifierExpr::create(Res, RISCV::S_CALL_PLT, OutContext);
717
718 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr));
719}
720
721void RISCVAsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {
722 Register AddrReg = MI.getOperand(0).getReg();
723 assert(std::next(MI.getIterator())->isCall() &&
724 "KCFI_CHECK not followed by a call instruction");
725 assert(std::next(MI.getIterator())->getOperand(0).getReg() == AddrReg &&
726 "KCFI_CHECK call target doesn't match call operand");
727
728 // Temporary registers for comparing the hashes. If a register is used
729 // for the call target, or reserved by the user, we can clobber another
730 // temporary register as the check is immediately followed by the
731 // call. The check defaults to X6/X7, but can fall back to X28-X31 if
732 // needed.
733 unsigned ScratchRegs[] = {RISCV::X6, RISCV::X7};
734 unsigned NextReg = RISCV::X28;
735 auto isRegAvailable = [&](unsigned Reg) {
736 return Reg != AddrReg && !STI->isRegisterReservedByUser(Reg);
737 };
738 for (auto &Reg : ScratchRegs) {
739 if (isRegAvailable(Reg))
740 continue;
741 while (!isRegAvailable(NextReg))
742 ++NextReg;
743 Reg = NextReg++;
744 if (Reg > RISCV::X31)
745 report_fatal_error("Unable to find scratch registers for KCFI_CHECK");
746 }
747
748 if (AddrReg == RISCV::X0) {
749 // Checking X0 makes no sense. Instead of emitting a load, zero
750 // ScratchRegs[0].
751 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI)
752 .addReg(ScratchRegs[0])
753 .addReg(RISCV::X0)
754 .addImm(0));
755 } else {
756 // Adjust the offset for patchable-function-prefix. This assumes that
757 // patchable-function-prefix is the same for all functions.
758 int NopSize = STI->hasStdExtZca() ? 2 : 4;
759 int64_t PrefixNops =
760 MI.getMF()->getFunction().getFnAttributeAsParsedInteger(
761 "patchable-function-prefix");
762
763 // Load the target function type hash.
764 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::LW)
765 .addReg(ScratchRegs[0])
766 .addReg(AddrReg)
767 .addImm(-(PrefixNops * NopSize + 4)));
768 }
769
770 // Load the expected 32-bit type hash.
771 const int64_t Type = MI.getOperand(1).getImm();
772 const int64_t Hi20 = ((Type + 0x800) >> 12) & 0xFFFFF;
773 const int64_t Lo12 = SignExtend64<12>(Type);
774 if (Hi20) {
775 EmitToStreamer(
776 *OutStreamer,
777 MCInstBuilder(RISCV::LUI).addReg(ScratchRegs[1]).addImm(Hi20));
778 }
779 if (Lo12 || Hi20 == 0) {
780 EmitToStreamer(*OutStreamer,
781 MCInstBuilder((STI->hasFeature(RISCV::Feature64Bit) && Hi20)
782 ? RISCV::ADDIW
783 : RISCV::ADDI)
784 .addReg(ScratchRegs[1])
785 .addReg(ScratchRegs[1])
786 .addImm(Lo12));
787 }
788
789 // Compare the hashes and trap if there's a mismatch.
790 MCSymbol *Pass = OutContext.createTempSymbol();
791 EmitToStreamer(*OutStreamer,
792 MCInstBuilder(RISCV::BEQ)
793 .addReg(ScratchRegs[0])
794 .addReg(ScratchRegs[1])
795 .addExpr(MCSymbolRefExpr::create(Pass, OutContext)));
796
797 MCSymbol *Trap = OutContext.createTempSymbol();
798 OutStreamer->emitLabel(Trap);
799 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::EBREAK));
800 emitKCFITrapEntry(*MI.getMF(), Trap);
801 OutStreamer->emitLabel(Pass);
802}
803
804void RISCVAsmPrinter::EmitHwasanMemaccessSymbols(Module &M) {
805 if (HwasanMemaccessSymbols.empty())
806 return;
807
808 assert(TM.getTargetTriple().isOSBinFormatELF());
809 // Use MCSubtargetInfo from TargetMachine. Individual functions may have
810 // attributes that differ from other functions in the module and we have no
811 // way to know which function is correct.
812 const MCSubtargetInfo &MCSTI = TM.getMCSubtargetInfo();
813
814 MCSymbol *HwasanTagMismatchV2Sym =
815 OutContext.getOrCreateSymbol("__hwasan_tag_mismatch_v2");
816 // Annotate symbol as one having incompatible calling convention, so
817 // run-time linkers can instead eagerly bind this function.
818 RISCVTargetStreamer &RTS = getTargetStreamer();
819 RTS.emitDirectiveVariantCC(*HwasanTagMismatchV2Sym);
820
821 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
822 MCSymbolRefExpr::create(HwasanTagMismatchV2Sym, OutContext);
823 auto Expr = MCSpecifierExpr::create(HwasanTagMismatchV2Ref, RISCV::S_CALL_PLT,
824 OutContext);
825
826 for (auto &P : HwasanMemaccessSymbols) {
827 unsigned Reg = std::get<0>(P.first);
828 uint32_t AccessInfo = std::get<1>(P.first);
829 MCSymbol *Sym = P.second;
830
831 unsigned Size =
832 1 << ((AccessInfo >> HWASanAccessInfo::AccessSizeShift) & 0xf);
833 OutStreamer->switchSection(OutContext.getELFSection(
834 ".text.hot", ELF::SHT_PROGBITS,
836 /*IsComdat=*/true));
837
839 OutStreamer->emitSymbolAttribute(Sym, MCSA_Weak);
840 OutStreamer->emitSymbolAttribute(Sym, MCSA_Hidden);
841 OutStreamer->emitLabel(Sym);
842
843 // Extract shadow offset from ptr
844 EmitToStreamer(
845 *OutStreamer,
846 MCInstBuilder(RISCV::SLLI).addReg(RISCV::X6).addReg(Reg).addImm(8),
847 MCSTI);
848 EmitToStreamer(*OutStreamer,
849 MCInstBuilder(RISCV::SRLI)
850 .addReg(RISCV::X6)
851 .addReg(RISCV::X6)
852 .addImm(12),
853 MCSTI);
854 // load shadow tag in X6, X5 contains shadow base
855 EmitToStreamer(*OutStreamer,
856 MCInstBuilder(RISCV::ADD)
857 .addReg(RISCV::X6)
858 .addReg(RISCV::X5)
859 .addReg(RISCV::X6),
860 MCSTI);
861 EmitToStreamer(
862 *OutStreamer,
863 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
864 MCSTI);
865 // Extract tag from pointer and compare it with loaded tag from shadow
866 EmitToStreamer(
867 *OutStreamer,
868 MCInstBuilder(RISCV::SRLI).addReg(RISCV::X7).addReg(Reg).addImm(56),
869 MCSTI);
870 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
871 // X7 contains tag from the pointer, while X6 contains tag from memory
872 EmitToStreamer(*OutStreamer,
873 MCInstBuilder(RISCV::BNE)
874 .addReg(RISCV::X7)
875 .addReg(RISCV::X6)
877 HandleMismatchOrPartialSym, OutContext)),
878 MCSTI);
879 MCSymbol *ReturnSym = OutContext.createTempSymbol();
880 OutStreamer->emitLabel(ReturnSym);
881 EmitToStreamer(*OutStreamer,
882 MCInstBuilder(RISCV::JALR)
883 .addReg(RISCV::X0)
884 .addReg(RISCV::X1)
885 .addImm(0),
886 MCSTI);
887 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
888
889 EmitToStreamer(*OutStreamer,
890 MCInstBuilder(RISCV::ADDI)
891 .addReg(RISCV::X28)
892 .addReg(RISCV::X0)
893 .addImm(16),
894 MCSTI);
895 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
896 EmitToStreamer(
897 *OutStreamer,
898 MCInstBuilder(RISCV::BGEU)
899 .addReg(RISCV::X6)
900 .addReg(RISCV::X28)
901 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
902 MCSTI);
903
904 EmitToStreamer(
905 *OutStreamer,
906 MCInstBuilder(RISCV::ANDI).addReg(RISCV::X28).addReg(Reg).addImm(0xF),
907 MCSTI);
908
909 if (Size != 1)
910 EmitToStreamer(*OutStreamer,
911 MCInstBuilder(RISCV::ADDI)
912 .addReg(RISCV::X28)
913 .addReg(RISCV::X28)
914 .addImm(Size - 1),
915 MCSTI);
916 EmitToStreamer(
917 *OutStreamer,
918 MCInstBuilder(RISCV::BGE)
919 .addReg(RISCV::X28)
920 .addReg(RISCV::X6)
921 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
922 MCSTI);
923
924 EmitToStreamer(
925 *OutStreamer,
926 MCInstBuilder(RISCV::ORI).addReg(RISCV::X6).addReg(Reg).addImm(0xF),
927 MCSTI);
928 EmitToStreamer(
929 *OutStreamer,
930 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
931 MCSTI);
932 EmitToStreamer(*OutStreamer,
933 MCInstBuilder(RISCV::BEQ)
934 .addReg(RISCV::X6)
935 .addReg(RISCV::X7)
936 .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)),
937 MCSTI);
938
939 OutStreamer->emitLabel(HandleMismatchSym);
940
941 // | Previous stack frames... |
942 // +=================================+ <-- [SP + 256]
943 // | ... |
944 // | |
945 // | Stack frame space for x12 - x31.|
946 // | |
947 // | ... |
948 // +---------------------------------+ <-- [SP + 96]
949 // | Saved x11(arg1), as |
950 // | __hwasan_check_* clobbers it. |
951 // +---------------------------------+ <-- [SP + 88]
952 // | Saved x10(arg0), as |
953 // | __hwasan_check_* clobbers it. |
954 // +---------------------------------+ <-- [SP + 80]
955 // | |
956 // | Stack frame space for x9. |
957 // +---------------------------------+ <-- [SP + 72]
958 // | |
959 // | Saved x8(fp), as |
960 // | __hwasan_check_* clobbers it. |
961 // +---------------------------------+ <-- [SP + 64]
962 // | ... |
963 // | |
964 // | Stack frame space for x2 - x7. |
965 // | |
966 // | ... |
967 // +---------------------------------+ <-- [SP + 16]
968 // | Return address (x1) for caller |
969 // | of __hwasan_check_*. |
970 // +---------------------------------+ <-- [SP + 8]
971 // | Reserved place for x0, possibly |
972 // | junk, since we don't save it. |
973 // +---------------------------------+ <-- [x2 / SP]
974
975 // Adjust sp
976 EmitToStreamer(*OutStreamer,
977 MCInstBuilder(RISCV::ADDI)
978 .addReg(RISCV::X2)
979 .addReg(RISCV::X2)
980 .addImm(-256),
981 MCSTI);
982
983 // store x10(arg0) by new sp
984 EmitToStreamer(*OutStreamer,
985 MCInstBuilder(RISCV::SD)
986 .addReg(RISCV::X10)
987 .addReg(RISCV::X2)
988 .addImm(8 * 10),
989 MCSTI);
990 // store x11(arg1) by new sp
991 EmitToStreamer(*OutStreamer,
992 MCInstBuilder(RISCV::SD)
993 .addReg(RISCV::X11)
994 .addReg(RISCV::X2)
995 .addImm(8 * 11),
996 MCSTI);
997
998 // store x8(fp) by new sp
999 EmitToStreamer(
1000 *OutStreamer,
1001 MCInstBuilder(RISCV::SD).addReg(RISCV::X8).addReg(RISCV::X2).addImm(8 *
1002 8),
1003 MCSTI);
1004 // store x1(ra) by new sp
1005 EmitToStreamer(
1006 *OutStreamer,
1007 MCInstBuilder(RISCV::SD).addReg(RISCV::X1).addReg(RISCV::X2).addImm(1 *
1008 8),
1009 MCSTI);
1010 if (Reg != RISCV::X10)
1011 EmitToStreamer(
1012 *OutStreamer,
1013 MCInstBuilder(RISCV::ADDI).addReg(RISCV::X10).addReg(Reg).addImm(0),
1014 MCSTI);
1015 EmitToStreamer(*OutStreamer,
1016 MCInstBuilder(RISCV::ADDI)
1017 .addReg(RISCV::X11)
1018 .addReg(RISCV::X0)
1019 .addImm(AccessInfo & HWASanAccessInfo::RuntimeMask),
1020 MCSTI);
1021
1022 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr),
1023 MCSTI);
1024 }
1025}
1026
1027void RISCVAsmPrinter::emitNoteGnuProperty(const Module &M) {
1028 assert(TM.getTargetTriple().isOSBinFormatELF() && "invalid binary format");
1029 uint32_t GnuProps = 0;
1030 if (const Metadata *const Flag = M.getModuleFlag("cf-protection-return");
1031 Flag && !mdconst::extract<ConstantInt>(Flag)->isZero())
1033
1034 if (const Metadata *const Flag = M.getModuleFlag("cf-protection-branch");
1035 Flag && !mdconst::extract<ConstantInt>(Flag)->isZero()) {
1036 using namespace llvm::RISCVISAUtils;
1037 const Metadata *const CFBranchLabelSchemeFlag =
1038 M.getModuleFlag("cf-branch-label-scheme");
1039 assert(CFBranchLabelSchemeFlag &&
1040 "cf-protection=branch should come with cf-branch-label-scheme=... "
1041 "on RISC-V targets");
1042 const StringRef CFBranchLabelScheme =
1043 cast<MDString>(CFBranchLabelSchemeFlag)->getString();
1044 switch (llvm::RISCVCFI::getZicfilpLabelScheme(CFBranchLabelScheme)) {
1046 reportFatalInternalError("invalid RISC-V Zicfilp label scheme");
1049 break;
1051 // TODO: Emit the func-sig bit after the feature is implemented
1052 reportFatalUsageError("the complete func-sig label scheme feature is not "
1053 "implemented yet");
1054 break;
1055 }
1056 }
1057
1058 if (!GnuProps)
1059 return;
1060
1061 auto &RTS = static_cast<RISCVTargetELFStreamer &>(getTargetStreamer());
1062 RTS.emitNoteGnuPropertySection(GnuProps);
1063}
1064
1066 const AsmPrinter &AP) {
1067 MCContext &Ctx = AP.OutContext;
1068 RISCV::Specifier Kind;
1069
1070 switch (MO.getTargetFlags()) {
1071 default:
1072 llvm_unreachable("Unknown target flag on GV operand");
1073 case RISCVII::MO_None:
1074 Kind = RISCV::S_None;
1075 break;
1076 case RISCVII::MO_CALL:
1077 Kind = RISCV::S_CALL_PLT;
1078 break;
1079 case RISCVII::MO_LO:
1080 Kind = RISCV::S_LO;
1081 break;
1082 case RISCVII::MO_HI:
1083 Kind = ELF::R_RISCV_HI20;
1084 break;
1086 Kind = RISCV::S_PCREL_LO;
1087 break;
1089 Kind = RISCV::S_PCREL_HI;
1090 break;
1091 case RISCVII::MO_GOT_HI:
1092 Kind = RISCV::S_GOT_HI;
1093 break;
1095 Kind = RISCV::S_TPREL_LO;
1096 break;
1098 Kind = ELF::R_RISCV_TPREL_HI20;
1099 break;
1101 Kind = ELF::R_RISCV_TPREL_ADD;
1102 break;
1104 Kind = ELF::R_RISCV_TLS_GOT_HI20;
1105 break;
1107 Kind = ELF::R_RISCV_TLS_GD_HI20;
1108 break;
1110 Kind = ELF::R_RISCV_TLSDESC_HI20;
1111 break;
1113 Kind = ELF::R_RISCV_TLSDESC_LOAD_LO12;
1114 break;
1116 Kind = ELF::R_RISCV_TLSDESC_ADD_LO12;
1117 break;
1119 Kind = ELF::R_RISCV_TLSDESC_CALL;
1120 break;
1122 Kind = RISCV::S_QC_ACCESS;
1123 break;
1124 }
1125
1126 const MCExpr *ME = MCSymbolRefExpr::create(Sym, Ctx);
1127
1128 if (!MO.isJTI() && !MO.isMBB() && MO.getOffset())
1130 ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
1131
1132 if (Kind != RISCV::S_None)
1133 ME = MCSpecifierExpr::create(ME, Kind, Ctx);
1134 return MCOperand::createExpr(ME);
1135}
1136
1137bool RISCVAsmPrinter::lowerOperand(const MachineOperand &MO,
1138 MCOperand &MCOp) const {
1139 switch (MO.getType()) {
1140 default:
1141 report_fatal_error("lowerOperand: unknown operand type");
1143 // Ignore all implicit register operands.
1144 if (MO.isImplicit())
1145 return false;
1146 MCOp = MCOperand::createReg(MO.getReg());
1147 break;
1149 // Regmasks are like implicit defs.
1150 return false;
1152 MCOp = MCOperand::createImm(MO.getImm());
1153 break;
1155 MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), *this);
1156 break;
1158 MCOp = lowerSymbolOperand(MO, getSymbolPreferLocal(*MO.getGlobal()), *this);
1159 break;
1161 MCOp = lowerSymbolOperand(MO, GetBlockAddressSymbol(MO.getBlockAddress()),
1162 *this);
1163 break;
1165 MCOp = lowerSymbolOperand(MO, GetExternalSymbolSymbol(MO.getSymbolName()),
1166 *this);
1167 break;
1169 MCOp = lowerSymbolOperand(MO, GetCPISymbol(MO.getIndex()), *this);
1170 break;
1172 MCOp = lowerSymbolOperand(MO, GetJTISymbol(MO.getIndex()), *this);
1173 break;
1175 MCOp = lowerSymbolOperand(MO, MO.getMCSymbol(), *this);
1176 break;
1177 }
1178 return true;
1179}
1180
1182 MCInst &OutMI,
1183 const RISCVSubtarget *STI) {
1185 RISCVVPseudosTable::getPseudoInfo(MI->getOpcode());
1186 if (!RVV)
1187 return false;
1188
1189 OutMI.setOpcode(RVV->BaseInstr);
1190
1191 const TargetInstrInfo *TII = STI->getInstrInfo();
1192 const TargetRegisterInfo *TRI = STI->getRegisterInfo();
1193 assert(TRI && "TargetRegisterInfo expected");
1194
1195 const MCInstrDesc &MCID = MI->getDesc();
1196 uint64_t TSFlags = MCID.TSFlags;
1197 unsigned NumOps = MI->getNumExplicitOperands();
1198
1199 // Skip policy, SEW, VL, VXRM/FRM operands which are the last operands if
1200 // present.
1201 if (RISCVII::hasVecPolicyOp(TSFlags))
1202 --NumOps;
1203 if (RISCVII::hasSEWOp(TSFlags))
1204 --NumOps;
1205 if (RISCVII::hasVLOp(TSFlags))
1206 --NumOps;
1207 if (RISCVII::hasRoundModeOp(TSFlags))
1208 --NumOps;
1209 if (RISCVII::hasTWidenOp(TSFlags))
1210 --NumOps;
1211 if (RISCVII::hasTMOp(TSFlags))
1212 --NumOps;
1213 if (RISCVII::hasTKOp(TSFlags))
1214 --NumOps;
1215
1216 bool hasVLOutput = RISCVInstrInfo::isFaultOnlyFirstLoad(*MI);
1217 for (unsigned OpNo = 0; OpNo != NumOps; ++OpNo) {
1218 const MachineOperand &MO = MI->getOperand(OpNo);
1219 // Skip vl output. It should be the second output.
1220 if (hasVLOutput && OpNo == 1)
1221 continue;
1222
1223 // Skip passthru op. It should be the first operand after the defs.
1224 if (OpNo == MI->getNumExplicitDefs() && MO.isReg() && MO.isTied()) {
1225 assert(MCID.getOperandConstraint(OpNo, MCOI::TIED_TO) == 0 &&
1226 "Expected tied to first def.");
1227 const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode());
1228 // Skip if the next operand in OutMI is not supposed to be tied. Unless it
1229 // is a _TIED instruction.
1230 if (OutMCID.getOperandConstraint(OutMI.getNumOperands(), MCOI::TIED_TO) <
1231 0 &&
1232 !RISCVII::isTiedPseudo(TSFlags))
1233 continue;
1234 }
1235
1236 MCOperand MCOp;
1237 switch (MO.getType()) {
1238 default:
1239 llvm_unreachable("Unknown operand type");
1241 Register Reg = MO.getReg();
1242
1243 if (RISCV::VRM2RegClass.contains(Reg) ||
1244 RISCV::VRM4RegClass.contains(Reg) ||
1245 RISCV::VRM8RegClass.contains(Reg)) {
1246 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0);
1247 assert(Reg && "Subregister does not exist");
1248 } else if (RISCV::FPR16RegClass.contains(Reg)) {
1249 Reg =
1250 TRI->getMatchingSuperReg(Reg, RISCV::sub_16, &RISCV::FPR32RegClass);
1251 assert(Reg && "Subregister does not exist");
1252 } else if (RISCV::FPR64RegClass.contains(Reg)) {
1253 Reg = TRI->getSubReg(Reg, RISCV::sub_32);
1254 assert(Reg && "Superregister does not exist");
1255 } else if (RISCV::VRN2M1RegClass.contains(Reg) ||
1256 RISCV::VRN2M2RegClass.contains(Reg) ||
1257 RISCV::VRN2M4RegClass.contains(Reg) ||
1258 RISCV::VRN3M1RegClass.contains(Reg) ||
1259 RISCV::VRN3M2RegClass.contains(Reg) ||
1260 RISCV::VRN4M1RegClass.contains(Reg) ||
1261 RISCV::VRN4M2RegClass.contains(Reg) ||
1262 RISCV::VRN5M1RegClass.contains(Reg) ||
1263 RISCV::VRN6M1RegClass.contains(Reg) ||
1264 RISCV::VRN7M1RegClass.contains(Reg) ||
1265 RISCV::VRN8M1RegClass.contains(Reg)) {
1266 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0);
1267 assert(Reg && "Subregister does not exist");
1268 }
1269
1270 MCOp = MCOperand::createReg(Reg);
1271 break;
1272 }
1274 MCOp = MCOperand::createImm(MO.getImm());
1275 break;
1276 }
1277 OutMI.addOperand(MCOp);
1278 }
1279
1280 // Unmasked pseudo instructions need to append dummy mask operand to
1281 // V instructions. All V instructions are modeled as the masked version.
1282 const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode());
1283 if (OutMI.getNumOperands() < OutMCID.getNumOperands()) {
1284 assert(OutMCID.operands()[OutMI.getNumOperands()].OperandType ==
1286 "Expected only mask operand to be missing");
1287 OutMI.addOperand(MCOperand::createReg(RISCV::NoRegister));
1288 }
1289
1290 assert(OutMI.getNumOperands() == OutMCID.getNumOperands());
1291 return true;
1292}
1293
1294void RISCVAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {
1295 if (lowerRISCVVMachineInstrToMCInst(MI, OutMI, STI))
1296 return;
1297
1298 OutMI.setOpcode(MI->getOpcode());
1299
1300 for (const MachineOperand &MO : MI->operands()) {
1301 MCOperand MCOp;
1302 if (lowerOperand(MO, MCOp))
1303 OutMI.addOperand(MCOp);
1304 }
1305}
1306
1307void RISCVAsmPrinter::emitMachineConstantPoolValue(
1308 MachineConstantPoolValue *MCPV) {
1309 auto *RCPV = static_cast<RISCVConstantPoolValue *>(MCPV);
1310 MCSymbol *MCSym;
1311
1312 if (RCPV->isGlobalValue()) {
1313 auto *GV = RCPV->getGlobalValue();
1314 MCSym = getSymbol(GV);
1315 } else {
1316 assert(RCPV->isExtSymbol() && "unrecognized constant pool type");
1317 auto Sym = RCPV->getSymbol();
1318 MCSym = GetExternalSymbolSymbol(Sym);
1319 }
1320
1321 const MCExpr *Expr = MCSymbolRefExpr::create(MCSym, OutContext);
1322 uint64_t Size = getDataLayout().getTypeAllocSize(RCPV->getType());
1323 OutStreamer->emitValue(Expr, Size);
1324}
1325
1326char RISCVAsmPrinter::ID = 0;
1327
1328INITIALIZE_PASS(RISCVAsmPrinter, "riscv-asm-printer", "RISC-V Assembly Printer",
1329 false, false)
1330
1333 RISCVAsmPrinter &AsmPrinter = static_cast<RISCVAsmPrinter &>(
1334 MAM.getResult<AsmPrinterAnalysis>(M).getPrinter());
1337 return PreservedAnalyses::all();
1338}
1339
1340PreservedAnalyses
1343 RISCVAsmPrinter &AsmPrinter = static_cast<RISCVAsmPrinter &>(
1345 .getCachedResult<AsmPrinterAnalysis>(*MF.getFunction().getParent())
1346 ->getPrinter());
1349 return PreservedAnalyses::all();
1350}
1351
1354 RISCVAsmPrinter &AsmPrinter = static_cast<RISCVAsmPrinter &>(
1355 MAM.getResult<AsmPrinterAnalysis>(M).getPrinter());
1358 return PreservedAnalyses::all();
1359}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock & MBB
static const Function * getParent(const Value *V)
#define X(NUM, ENUM, NAME)
Definition ELF.h:856
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_ABI
Definition Compiler.h:215
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
dxil translate DXIL Translate Metadata
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym, const AsmPrinter &AP)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
print mir2vec MIR2Vec Vocabulary Printer Pass
Definition MIR2Vec.cpp:621
Machine Check Debug Module
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define P(N)
ModuleAnalysisManager MAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static bool lowerRISCVVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, const RISCVSubtarget *STI)
LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmPrinter()
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class is intended to be used as a driving class for all asm writers.
Definition AsmPrinter.h:91
bool doInitialization(Module &M) override
Set up the AsmPrinter when we are working on a new module.
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition AsmPrinter.h:101
bool doFinalization(Module &M) override
Shut down the asmprinter.
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
Definition AsmPrinter.h:453
virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant as...
virtual void emitFunctionEntryLabel()
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:342
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Context object for machine code objects.
Definition MCContext.h:83
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
unsigned getNumOperands() const
Definition MCInst.h:212
unsigned getOpcode() const
Definition MCInst.h:202
void addOperand(const MCOperand Op)
Definition MCInst.h:215
void setOpcode(unsigned Op)
Definition MCInst.h:201
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specified operand constraint if it is present.
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
static MCOperand createExpr(const MCExpr *Val)
Definition MCInst.h:166
int64_t getImm() const
Definition MCInst.h:84
static MCOperand createReg(MCRegister Reg)
Definition MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
const MCExpr * getExpr() const
Definition MCInst.h:118
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.cpp:743
Streaming machine code generation interface.
Definition MCStreamer.h:222
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
virtual bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute)=0
Add the given Attribute to Symbol.
virtual void emitCodeAlignment(Align Alignment, const MCSubtargetInfo &STI, unsigned MaxBytesToEmit=0)
Emit nops until the byte alignment ByteAlignment is reached.
virtual bool hasRawTextSupport() const
Return true if this asm streamer supports emitting unformatted text to the .s file with EmitRawText.
Definition MCStreamer.h:385
MCContext & getContext() const
Definition MCStreamer.h:326
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
MCTargetStreamer * getTargetStreamer()
Definition MCStreamer.h:336
virtual void switchSection(MCSection *Section, uint32_t Subsec=0)
Set the current section where code is being emitted to Section.
bool hasFeature(unsigned Feature) const
const FeatureBitset & ToggleFeature(uint64_t FB)
Toggle a feature and return the re-computed feature bits.
ArrayRef< SubtargetFeatureKV > getAllProcessorFeatures() const
Return processor features.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition MCSymbol.cpp:59
StringRef getName() const
getName - Get the symbol name.
Definition MCSymbol.h:188
MachineInstrBundleIterator< const MachineInstr > const_iterator
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isJTI() const
isJTI - Tests if this is a MO_JumpTableIndex operand.
const BlockAddress * getBlockAddress() const
unsigned getTargetFlags() const
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
MCSymbol * getMCSymbol() const
@ MO_Immediate
Immediate operand.
@ MO_ConstantPoolIndex
Address of indexed Constant in Constant Pool.
@ MO_MCSymbol
MCSymbol reference (for debug/eh info)
@ MO_GlobalAddress
Address of a global value.
@ MO_RegisterMask
Mask of preserved registers.
@ MO_BlockAddress
Address of a basic block.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
@ MO_JumpTableIndex
Address of indexed Jump Table for switch.
int64_t getOffset() const
Return the offset from the symbol in this operand.
bool isMBB() const
isMBB - Tests if this is a MO_MachineBasicBlock operand.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
static LLVM_ABI bool isSupportedExtensionFeature(StringRef Ext)
static LLVM_ABI llvm::Expected< std::unique_ptr< RISCVISAInfo > > parseArchString(StringRef Arch, bool EnableExperimentalExtension, bool ExperimentalExtensionVersionCheck=true)
Parse RISC-V ISA info from arch string.
static const char * getRegisterName(MCRegister Reg)
bool requiresNTLHint(const MachineInstr &MI) const
Return true if the instruction requires an NTL hint to be emitted.
const RISCVRegisterInfo * getRegisterInfo() const override
const RISCVInstrInfo * getInstrInfo() const override
virtual void emitDirectiveVariantCC(MCSymbol &Symbol)
void emitTargetAttributes(const MCSubtargetInfo &STI, bool EmitStackAlign)
void setFlagsFromFeatures(const MCSubtargetInfo &STI)
void setTargetABI(RISCVABI::ABI ABI)
virtual void emitDirectiveOptionArch(ArrayRef< RISCVOptionArchArg > Args)
Wrapper class representing virtual and physical registers.
Definition Register.h:20
reference emplace_back(ArgTypes &&... Args)
LLVM_ABI void recordStatepoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a statepoint instruction.
LLVM_ABI void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
LLVM_ABI void recordStackMap(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a stackmap instruction.
std::string str() const
Get the contents as an std::string.
Definition StringRef.h:222
bool consume_front(char Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
Definition StringRef.h:661
TargetInstrInfo - Interface to description of machine instruction set.
Primary interface to the complete machine description for the target machine.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ SHF_ALLOC
Definition ELF.h:1258
@ SHF_GROUP
Definition ELF.h:1280
@ SHF_EXECINSTR
Definition ELF.h:1261
@ SHT_PROGBITS
Definition ELF.h:1156
@ GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED
Definition ELF.h:1923
@ GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS
Definition ELF.h:1924
ABI getTargetABI(StringRef ABIName)
ZicfilpLabelSchemeKind getZicfilpLabelScheme(const StringRef CFBranchLabelScheme)
static bool hasRoundModeOp(uint64_t TSFlags)
static bool hasTWidenOp(uint64_t TSFlags)
static bool isTiedPseudo(uint64_t TSFlags)
static bool hasTKOp(uint64_t TSFlags)
static bool hasVLOp(uint64_t TSFlags)
static bool hasTMOp(uint64_t TSFlags)
static bool hasVecPolicyOp(uint64_t TSFlags)
static bool hasSEWOp(uint64_t TSFlags)
void generateMCInstSeq(int64_t Val, const MCSubtargetInfo &STI, MCRegister DestReg, SmallVectorImpl< MCInst > &Insts)
bool compress(MCInst &OutInst, const MCInst &MI, const MCSubtargetInfo &STI)
uint16_t Specifier
void emitInstruction(MCObjectStreamer &, const MCInst &Inst, const MCSubtargetInfo &STI)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
Definition Metadata.h:668
This is an optimization pass for GlobalISel generic memory operations.
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
Definition Error.h:1129
@ Offset
Definition DWP.cpp:578
static const MachineMemOperand::Flags MONontemporalBit1
OuterAnalysisManagerProxy< ModuleAnalysisManager, MachineFunction > ModuleAnalysisManagerMachineFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
Target & getTheRISCV32Target()
static const MachineMemOperand::Flags MONontemporalBit0
std::string utostr(uint64_t X, bool isNeg=false)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
Target & getTheRISCV64beTarget()
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
Definition Error.cpp:173
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
LLVM_ABI void setupModuleAsmPrinter(Module &M, ModuleAnalysisManager &MAM, AsmPrinter &AsmPrinter)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
Target & getTheRISCV64Target()
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1917
LLVM_ABI void setupMachineFunctionAsmPrinter(MachineFunctionAnalysisManager &MFAM, MachineFunction &MF, AsmPrinter &AsmPrinter)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:573
@ MCSA_Weak
.weak
@ MCSA_ELF_TypeFunction
.type _foo, STT_FUNC # aka @function
@ MCSA_Hidden
.hidden (ELF)
Target & getTheRISCV32beTarget()
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:177
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...