49#define DEBUG_TYPE "asm-printer"
52 "Number of RISC-V Compressed instructions emitted");
64 std::unique_ptr<MCStreamer> Streamer)
67 StringRef getPassName()
const override {
return "RISC-V Assembly Printer"; }
69 RISCVTargetStreamer &getTargetStreamer()
const {
70 return static_cast<RISCVTargetStreamer &
>(
71 *OutStreamer->getTargetStreamer());
74 void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &
SM,
75 const MachineInstr &
MI);
77 void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &
SM,
78 const MachineInstr &
MI);
80 void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &
SM,
81 const MachineInstr &
MI);
83 bool runOnMachineFunction(MachineFunction &MF)
override;
87 void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV)
override;
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;
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);
101 bool lowerPseudoInstExpansion(
const MachineInstr *
MI, MCInst &Inst);
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);
110 bool lowerOperand(
const MachineOperand &MO, MCOperand &MCOp)
const;
112 void emitStartOfAsmFile(
Module &M)
override;
113 void emitEndOfAsmFile(
Module &M)
override;
115 void emitFunctionEntryLabel()
override;
116 bool emitTargetFeaturePush(
const MCSubtargetInfo &STI)
override;
117 void emitTargetFeaturePop(
const MCSubtargetInfo &STI,
bool DidPush)
override;
119 void emitNoteGnuProperty(
const Module &M);
122 void emitAttributes(
const MCSubtargetInfo &SubtargetInfo);
124 void emitNTLHint(
const MachineInstr *
MI);
126 void emitLpadAlignedCall(
const MachineInstr &
MI);
129 void LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr *
MI);
130 void LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr *
MI);
131 void LowerPATCHABLE_TAIL_CALL(
const MachineInstr *
MI);
132 void emitSled(
const MachineInstr *
MI, SledKind Kind);
134 void lowerToMCInst(
const MachineInstr *
MI, MCInst &OutMI);
140 unsigned NOPBytes = STI->hasStdExtZca() ? 2 : 4;
141 unsigned NumNOPBytes = StackMapOpers(&
MI).getNumPatchBytes();
144 MCSymbol *MILabel = Ctx.createTempSymbol();
147 SM.recordStackMap(*MILabel,
MI);
148 assert(NumNOPBytes % NOPBytes == 0 &&
149 "Invalid number of NOP bytes requested!");
152 const MachineBasicBlock &
MBB = *
MI.getParent();
155 while (NumNOPBytes > 0) {
156 if (MII ==
MBB.
end() || MII->isCall() ||
157 MII->getOpcode() == RISCV::DBG_VALUE ||
158 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
159 MII->getOpcode() == TargetOpcode::STACKMAP)
162 NumNOPBytes -= NOPBytes;
166 emitNops(NumNOPBytes / NOPBytes);
171void RISCVAsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &
SM,
172 const MachineInstr &
MI) {
173 unsigned NOPBytes = STI->hasStdExtZca() ? 2 : 4;
176 MCSymbol *MILabel = Ctx.createTempSymbol();
178 SM.recordPatchPoint(*MILabel,
MI);
180 PatchPointOpers Opers(&
MI);
182 const MachineOperand &CalleeMO = Opers.getCallTarget();
183 unsigned EncodedBytes = 0;
185 if (CalleeMO.
isImm()) {
186 uint64_t CallTarget = CalleeMO.
getImm();
188 assert((CallTarget & 0xFFFF'FFFF'FFFF) == CallTarget &&
189 "High 16 bits of call target should be zero.");
193 for (MCInst &Inst : Seq) {
194 bool Compressed = EmitToStreamer(OutStreamer, Inst);
195 EncodedBytes += Compressed ? 2 : 4;
197 bool Compressed = EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JALR)
201 EncodedBytes += Compressed ? 2 : 4;
204 MCOperand CallTargetMCOp;
205 lowerOperand(CalleeMO, CallTargetMCOp);
206 EmitToStreamer(OutStreamer,
207 MCInstBuilder(RISCV::PseudoCALL).
addOperand(CallTargetMCOp));
212 unsigned NumBytes = Opers.getNumPatchBytes();
213 assert(NumBytes >= EncodedBytes &&
214 "Patchpoint can't request size less than the length of a call.");
215 assert((NumBytes - EncodedBytes) % NOPBytes == 0 &&
216 "Invalid number of NOP bytes requested!");
217 emitNops((NumBytes - EncodedBytes) / NOPBytes);
220void RISCVAsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &
SM,
221 const MachineInstr &
MI) {
222 unsigned NOPBytes = STI->hasStdExtZca() ? 2 : 4;
224 StatepointOpers SOpers(&
MI);
225 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
226 assert(PatchBytes % NOPBytes == 0 &&
227 "Invalid number of NOP bytes requested!");
228 emitNops(PatchBytes / NOPBytes);
231 const MachineOperand &CallTarget = SOpers.getCallTarget();
232 MCOperand CallTargetMCOp;
233 switch (CallTarget.
getType()) {
236 lowerOperand(CallTarget, CallTargetMCOp);
239 MCInstBuilder(RISCV::PseudoCALL).
addOperand(CallTargetMCOp));
243 EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JAL)
249 EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JALR)
261 MCSymbol *MILabel = Ctx.createTempSymbol();
263 SM.recordStatepoint(*MILabel,
MI);
266bool RISCVAsmPrinter::EmitToStreamer(MCStreamer &S,
const MCInst &Inst,
267 const MCSubtargetInfo &SubtargetInfo) {
271 ++RISCVNumInstrsCompressed;
278#include "RISCVGenMCPseudoLowering.inc"
285void RISCVAsmPrinter::emitLpadAlignedCall(
const MachineInstr &
MI) {
286 const MCSubtargetInfo &MCSTI = getSubtargetInfo();
287 const bool IsIndirect =
MI.getOpcode() == RISCV::PseudoCALLIndirectLpadAlign,
288 HasZca = MCSTI.
hasFeature(RISCV::FeatureStdExtZca),
289 HasRelax = MCSTI.
hasFeature(RISCV::FeatureRelax);
297 RISCVTargetStreamer &RTS = getTargetStreamer();
298 if (HasZca && HasRelax) {
306 lowerOperand(
MI.getOperand(0), MCOp);
307 CallInst = MCInstBuilder(RISCV::PseudoCALL).
addOperand(MCOp);
309 CallInst = MCInstBuilder(RISCV::JALR)
311 .addReg(
MI.getOperand(0).getReg())
315 if (HasZca && HasRelax) {
316 MCSubtargetInfo NoRelaxSTI(MCSTI);
317 NoRelaxSTI.ToggleFeature(RISCV::FeatureRelax);
318 EmitToStreamer(*OutStreamer, CallInst, NoRelaxSTI);
321 EmitToStreamer(*OutStreamer, CallInst, MCSTI);
325 MCInst LpadInst = MCInstBuilder(RISCV::AUIPC)
327 .addImm(
MI.getOperand(1).getImm());
328 EmitToStreamer(*OutStreamer, LpadInst, MCSTI);
337 lowerOperand(
MI.getOperand(0), MCOp);
343 EmitToStreamer(*OutStreamer, TmpInst, MCSTI);
351void RISCVAsmPrinter::emitNTLHint(
const MachineInstr *
MI) {
357 MachineMemOperand *MMO = *(
MI->memoperands_begin());
361 unsigned NontemporalMode = 0;
363 NontemporalMode += 0b1;
365 NontemporalMode += 0b10;
368 if (STI->hasStdExtZca())
369 Hint.setOpcode(RISCV::C_ADD);
371 Hint.setOpcode(RISCV::ADD);
377 EmitToStreamer(*OutStreamer, Hint);
380void RISCVAsmPrinter::emitInstruction(
const MachineInstr *
MI) {
381 RISCV_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->getFeatureBits());
386 if (MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
387 EmitToStreamer(*OutStreamer, OutInst);
391 switch (
MI->getOpcode()) {
392 case RISCV::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
393 LowerHWASAN_CHECK_MEMACCESS(*
MI);
395 case RISCV::KCFI_CHECK:
396 LowerKCFI_CHECK(*
MI);
398 case TargetOpcode::STACKMAP:
399 return LowerSTACKMAP(*OutStreamer,
SM, *
MI);
400 case TargetOpcode::PATCHPOINT:
401 return LowerPATCHPOINT(*OutStreamer,
SM, *
MI);
402 case TargetOpcode::STATEPOINT:
403 return LowerSTATEPOINT(*OutStreamer,
SM, *
MI);
404 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
405 const Function &
F =
MI->getParent()->getParent()->getFunction();
406 if (
F.hasFnAttribute(
"patchable-function-entry")) {
408 F.getFnAttributeAsParsedInteger(
"patchable-function-entry");
412 LowerPATCHABLE_FUNCTION_ENTER(
MI);
415 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
416 LowerPATCHABLE_FUNCTION_EXIT(
MI);
418 case TargetOpcode::PATCHABLE_TAIL_CALL:
419 LowerPATCHABLE_TAIL_CALL(
MI);
421 case RISCV::PseudoCALLLpadAlign:
422 case RISCV::PseudoCALLIndirectLpadAlign:
423 emitLpadAlignedCall(*
MI);
428 lowerToMCInst(
MI, OutInst);
429 EmitToStreamer(*OutStreamer, OutInst);
432bool RISCVAsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNo,
433 const char *ExtraCode, raw_ostream &OS) {
438 const MachineOperand &MO =
MI->getOperand(OpNo);
439 if (ExtraCode && ExtraCode[0]) {
440 if (ExtraCode[1] != 0)
443 switch (ExtraCode[0]) {
461 OS <<
TRI->getEncodingValue(MO.
getReg());
474 PrintSymbolOperand(MO, OS);
488bool RISCVAsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
490 const char *ExtraCode,
495 const MachineOperand &AddrReg =
MI->getOperand(OpNo);
496 assert(
MI->getNumOperands() > OpNo + 1 &&
"Expected additional operand");
497 const MachineOperand &
Offset =
MI->getOperand(OpNo + 1);
500 if (!AddrReg.
isReg())
507 if (!lowerOperand(
Offset, MCO))
513 MAI.printExpr(OS, *MCO.
getExpr());
516 MMI->getContext().registerInlineAsmLabel(
Offset.getMCSymbol());
517 if (
Offset.isBlockAddress()) {
519 MCSymbol *Sym = GetBlockAddressSymbol(BA);
520 MMI->getContext().registerInlineAsmLabel(Sym);
527bool RISCVAsmPrinter::emitTargetFeaturePush(
const MCSubtargetInfo &STI) {
528 RISCVTargetStreamer &RTS = getTargetStreamer();
530 const MCSubtargetInfo &MCSTI = TM.getMCSubtargetInfo();
538 auto Delta = STI.
hasFeature(Feature.Value) ? RISCVOptionArchArgType::Plus
539 : RISCVOptionArchArgType::Minus;
540 StringRef ExtName = Feature.key();
544 if (!NeedEmitStdOptionArgs.
empty()) {
553void RISCVAsmPrinter::emitTargetFeaturePop(
const MCSubtargetInfo &STI,
556 getTargetStreamer().emitDirectiveOptionPop();
559bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
562 bool EmittedOptionArch = emitTargetFeaturePush(*STI);
564 SetupMachineFunction(MF);
570 emitTargetFeaturePop(*STI, EmittedOptionArch);
574void RISCVAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr *
MI) {
575 emitSled(
MI, SledKind::FUNCTION_ENTER);
578void RISCVAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr *
MI) {
579 emitSled(
MI, SledKind::FUNCTION_EXIT);
582void RISCVAsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr *
MI) {
583 emitSled(
MI, SledKind::TAIL_CALL);
586void RISCVAsmPrinter::emitSled(
const MachineInstr *
MI, SledKind Kind) {
601 const uint8_t NoopsInSledCount = STI->is64Bit() ? 33 : 21;
604 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
606 auto Target = OutContext.createTempSymbol();
614 MCInstBuilder(RISCV::JAL).addReg(RISCV::X0).addExpr(TargetExpr));
617 for (int8_t
I = 0;
I < NoopsInSledCount; ++
I)
618 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI)
624 recordSled(CurSled, *
MI, Kind, 2);
627void RISCVAsmPrinter::emitStartOfAsmFile(
Module &M) {
629 "target streamer is uninitialized");
630 RISCVTargetStreamer &RTS = getTargetStreamer();
631 if (
const MDString *ModuleTargetABI =
635 MCSubtargetInfo SubtargetInfo = TM.getMCSubtargetInfo();
639 for (
auto &ISA : MD->operands()) {
642 ISAString->getString(),
true,
645 auto &ISAInfo = *ParseResult;
647 if (ISAInfo->hasExtension(Feature.key()) &&
658 if (TM.getTargetTriple().isOSBinFormatELF())
659 emitAttributes(SubtargetInfo);
662void RISCVAsmPrinter::emitEndOfAsmFile(
Module &M) {
663 RISCVTargetStreamer &RTS = getTargetStreamer();
665 if (TM.getTargetTriple().isOSBinFormatELF()) {
667 emitNoteGnuProperty(M);
669 EmitHwasanMemaccessSymbols(M);
672void RISCVAsmPrinter::emitAttributes(
const MCSubtargetInfo &SubtargetInfo) {
673 RISCVTargetStreamer &RTS = getTargetStreamer();
680void RISCVAsmPrinter::emitFunctionEntryLabel() {
681 const auto *RMFI = MF->getInfo<RISCVMachineFunctionInfo>();
682 if (RMFI->isVectorCall()) {
683 RISCVTargetStreamer &RTS = getTargetStreamer();
698void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
700 uint32_t AccessInfo =
MI.getOperand(1).getImm();
702 HwasanMemaccessSymbols[HwasanMemaccessTuple(
Reg, AccessInfo)];
705 if (!TM.getTargetTriple().isOSBinFormatELF())
708 std::string SymName =
"__hwasan_check_x" +
utostr(
Reg - RISCV::X0) +
"_" +
709 utostr(AccessInfo) +
"_short";
710 Sym = OutContext.getOrCreateSymbol(SymName);
715 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr));
718void RISCVAsmPrinter::LowerKCFI_CHECK(
const MachineInstr &
MI) {
720 assert(std::next(
MI.getIterator())->isCall() &&
721 "KCFI_CHECK not followed by a call instruction");
722 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
723 "KCFI_CHECK call target doesn't match call operand");
730 unsigned ScratchRegs[] = {RISCV::X6, RISCV::X7};
731 unsigned NextReg = RISCV::X28;
732 auto isRegAvailable = [&](
unsigned Reg) {
733 return Reg != AddrReg && !STI->isRegisterReservedByUser(
Reg);
735 for (
auto &
Reg : ScratchRegs) {
736 if (isRegAvailable(
Reg))
738 while (!isRegAvailable(NextReg))
741 if (
Reg > RISCV::X31)
745 if (AddrReg == RISCV::X0) {
748 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI)
749 .addReg(ScratchRegs[0])
755 int NopSize = STI->hasStdExtZca() ? 2 : 4;
757 MI.getMF()->getFunction().getFnAttributeAsParsedInteger(
758 "patchable-function-prefix");
761 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::LW)
762 .addReg(ScratchRegs[0])
764 .addImm(-(PrefixNops * NopSize + 4)));
768 const int64_t
Type =
MI.getOperand(1).getImm();
769 const int64_t Hi20 = ((
Type + 0x800) >> 12) & 0xFFFFF;
774 MCInstBuilder(RISCV::LUI).addReg(ScratchRegs[1]).addImm(Hi20));
776 if (Lo12 || Hi20 == 0) {
777 EmitToStreamer(*OutStreamer,
778 MCInstBuilder((STI->
hasFeature(RISCV::Feature64Bit) && Hi20)
781 .addReg(ScratchRegs[1])
782 .addReg(ScratchRegs[1])
788 EmitToStreamer(*OutStreamer,
789 MCInstBuilder(RISCV::BEQ)
790 .addReg(ScratchRegs[0])
791 .addReg(ScratchRegs[1])
796 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::EBREAK));
797 emitKCFITrapEntry(*
MI.getMF(),
Trap);
801void RISCVAsmPrinter::EmitHwasanMemaccessSymbols(
Module &M) {
802 if (HwasanMemaccessSymbols.empty())
805 assert(TM.getTargetTriple().isOSBinFormatELF());
809 const MCSubtargetInfo &MCSTI = TM.getMCSubtargetInfo();
812 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
815 RISCVTargetStreamer &RTS = getTargetStreamer();
818 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
823 for (
auto &
P : HwasanMemaccessSymbols) {
824 unsigned Reg = std::get<0>(
P.first);
825 uint32_t AccessInfo = std::get<1>(
P.first);
843 MCInstBuilder(RISCV::SLLI).addReg(RISCV::X6).addReg(
Reg).addImm(8),
845 EmitToStreamer(*OutStreamer,
846 MCInstBuilder(RISCV::SRLI)
852 EmitToStreamer(*OutStreamer,
853 MCInstBuilder(RISCV::ADD)
860 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
865 MCInstBuilder(RISCV::SRLI).addReg(RISCV::X7).addReg(
Reg).addImm(56),
867 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
869 EmitToStreamer(*OutStreamer,
870 MCInstBuilder(RISCV::BNE)
874 HandleMismatchOrPartialSym, OutContext)),
876 MCSymbol *ReturnSym = OutContext.createTempSymbol();
878 EmitToStreamer(*OutStreamer,
879 MCInstBuilder(RISCV::JALR)
884 OutStreamer->
emitLabel(HandleMismatchOrPartialSym);
886 EmitToStreamer(*OutStreamer,
887 MCInstBuilder(RISCV::ADDI)
892 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
895 MCInstBuilder(RISCV::BGEU)
903 MCInstBuilder(RISCV::ANDI).addReg(RISCV::X28).addReg(
Reg).addImm(0xF),
907 EmitToStreamer(*OutStreamer,
908 MCInstBuilder(RISCV::ADDI)
915 MCInstBuilder(RISCV::BGE)
923 MCInstBuilder(RISCV::ORI).addReg(RISCV::X6).addReg(
Reg).addImm(0xF),
927 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
929 EmitToStreamer(*OutStreamer,
930 MCInstBuilder(RISCV::BEQ)
936 OutStreamer->
emitLabel(HandleMismatchSym);
973 EmitToStreamer(*OutStreamer,
974 MCInstBuilder(RISCV::ADDI)
981 EmitToStreamer(*OutStreamer,
982 MCInstBuilder(RISCV::SD)
988 EmitToStreamer(*OutStreamer,
989 MCInstBuilder(RISCV::SD)
998 MCInstBuilder(RISCV::SD).addReg(RISCV::X8).addReg(RISCV::X2).addImm(8 *
1004 MCInstBuilder(RISCV::SD).addReg(RISCV::X1).addReg(RISCV::X2).addImm(1 *
1007 if (
Reg != RISCV::X10)
1010 MCInstBuilder(RISCV::ADDI).addReg(RISCV::X10).addReg(
Reg).addImm(0),
1012 EmitToStreamer(*OutStreamer,
1013 MCInstBuilder(RISCV::ADDI)
1019 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr),
1024void RISCVAsmPrinter::emitNoteGnuProperty(
const Module &M) {
1025 assert(TM.getTargetTriple().isOSBinFormatELF() &&
"invalid binary format");
1026 uint32_t GnuProps = 0;
1027 if (
const Metadata *
const Flag =
M.getModuleFlag(
"cf-protection-return");
1031 if (
const Metadata *
const Flag =
M.getModuleFlag(
"cf-protection-branch");
1033 using namespace llvm::RISCVISAUtils;
1034 const Metadata *
const CFBranchLabelSchemeFlag =
1035 M.getModuleFlag(
"cf-branch-label-scheme");
1036 assert(CFBranchLabelSchemeFlag &&
1037 "cf-protection=branch should come with cf-branch-label-scheme=... "
1038 "on RISC-V targets");
1039 const StringRef CFBranchLabelScheme =
1058 auto &RTS =
static_cast<RISCVTargetELFStreamer &
>(getTargetStreamer());
1059 RTS.emitNoteGnuPropertySection(GnuProps);
1080 Kind = ELF::R_RISCV_HI20;
1095 Kind = ELF::R_RISCV_TPREL_HI20;
1098 Kind = ELF::R_RISCV_TPREL_ADD;
1101 Kind = ELF::R_RISCV_TLS_GOT_HI20;
1104 Kind = ELF::R_RISCV_TLS_GD_HI20;
1107 Kind = ELF::R_RISCV_TLSDESC_HI20;
1110 Kind = ELF::R_RISCV_TLSDESC_LOAD_LO12;
1113 Kind = ELF::R_RISCV_TLSDESC_ADD_LO12;
1116 Kind = ELF::R_RISCV_TLSDESC_CALL;
1134bool RISCVAsmPrinter::lowerOperand(
const MachineOperand &MO,
1135 MCOperand &MCOp)
const {
1182 RISCVVPseudosTable::getPseudoInfo(
MI->getOpcode());
1190 assert(
TRI &&
"TargetRegisterInfo expected");
1194 unsigned NumOps =
MI->getNumExplicitOperands();
1213 bool hasVLOutput = RISCVInstrInfo::isFaultOnlyFirstLoad(*
MI);
1214 for (
unsigned OpNo = 0; OpNo !=
NumOps; ++OpNo) {
1217 if (hasVLOutput && OpNo == 1)
1221 if (OpNo ==
MI->getNumExplicitDefs() && MO.
isReg() && MO.
isTied()) {
1223 "Expected tied to first def.");
1243 Reg =
TRI->getSubReg(
Reg, RISCV::sub_vrm1_0);
1244 assert(
Reg &&
"Subregister does not exist");
1247 TRI->getMatchingSuperReg(
Reg, RISCV::sub_16, &RISCV::FPR32RegClass);
1248 assert(
Reg &&
"Subregister does not exist");
1250 Reg =
TRI->getSubReg(
Reg, RISCV::sub_32);
1251 assert(
Reg &&
"Superregister does not exist");
1263 Reg =
TRI->getSubReg(
Reg, RISCV::sub_vrm1_0);
1264 assert(
Reg &&
"Subregister does not exist");
1283 "Expected only mask operand to be missing");
1291void RISCVAsmPrinter::lowerToMCInst(
const MachineInstr *
MI, MCInst &OutMI) {
1297 for (
const MachineOperand &MO :
MI->operands()) {
1299 if (lowerOperand(MO, MCOp))
1304void RISCVAsmPrinter::emitMachineConstantPoolValue(
1305 MachineConstantPoolValue *MCPV) {
1306 auto *RCPV =
static_cast<RISCVConstantPoolValue *
>(MCPV);
1309 if (RCPV->isGlobalValue()) {
1310 auto *GV = RCPV->getGlobalValue();
1311 MCSym = getSymbol(GV);
1313 assert(RCPV->isExtSymbol() &&
"unrecognized constant pool type");
1314 auto Sym = RCPV->getSymbol();
1315 MCSym = GetExternalSymbolSymbol(Sym);
1319 uint64_t
Size = getDataLayout().getTypeAllocSize(RCPV->getType());
1323char RISCVAsmPrinter::ID = 0;
1325INITIALIZE_PASS(RISCVAsmPrinter,
"riscv-asm-printer",
"RISC-V Assembly Printer",
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...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_EXTERNAL_VISIBILITY
const HexagonInstrInfo * TII
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)
print mir2vec MIR2Vec Vocabulary Printer Pass
Machine Check Debug Module
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static constexpr unsigned SM(unsigned Version)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
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)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
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.
MCContext & OutContext
This is the context for the output file that we are streaming.
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())
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
Base class for the full range of assembler expressions which are needed for parsing.
Instances of this class represent a single low-level machine instruction.
unsigned getNumOperands() const
unsigned getOpcode() const
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
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.
static MCOperand createExpr(const MCExpr *Val)
static MCOperand createReg(MCRegister Reg)
static MCOperand createImm(int64_t Val)
const MCExpr * getExpr() const
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Streaming machine code generation interface.
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.
MCContext & getContext() const
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()
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())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
StringRef getName() const
getName - Get the symbol name.
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.
Representation of each machine instruction.
bool isNonTemporal() const
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() 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.
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)
virtual void emitDirectiveOptionExact()
virtual void emitDirectiveOptionPop()
void setTargetABI(RISCVABI::ABI ABI)
virtual void emitDirectiveOptionArch(ArrayRef< RISCVOptionArchArg > Args)
virtual void finishAttributeSection()
virtual void emitDirectiveOptionPush()
Wrapper class representing virtual and physical registers.
reference emplace_back(ArgTypes &&... Args)
std::string str() const
Get the contents as an std::string.
bool consume_front(char Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
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.
@ GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED
@ GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS
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)
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.
This is an optimization pass for GlobalISel generic memory operations.
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
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.
auto dyn_cast_or_null(const Y &Val)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
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.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
@ 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.
Implement std::hash so that hash_code can be used in STL containers.
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...