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