52#define DEBUG_TYPE "asm-printer"
55 "Number of RISC-V Compressed instructions emitted");
67 std::unique_ptr<MCStreamer> Streamer)
70 StringRef getPassName()
const override {
return "RISC-V Assembly Printer"; }
72 RISCVTargetStreamer &getTargetStreamer()
const {
73 return static_cast<RISCVTargetStreamer &
>(
74 *OutStreamer->getTargetStreamer());
77 void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
78 const MachineInstr &
MI);
80 void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
81 const MachineInstr &
MI);
83 void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
84 const MachineInstr &
MI);
86 bool runOnMachineFunction(MachineFunction &MF)
override;
90 void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV)
override;
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;
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);
104 bool lowerPseudoInstExpansion(
const MachineInstr *
MI, MCInst &Inst);
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);
113 bool lowerOperand(
const MachineOperand &MO, MCOperand &MCOp)
const;
115 void emitStartOfAsmFile(
Module &M)
override;
116 void emitEndOfAsmFile(
Module &M)
override;
118 void emitFunctionEntryLabel()
override;
119 bool emitTargetFeaturePush(
const MCSubtargetInfo &STI)
override;
120 void emitTargetFeaturePop(
const MCSubtargetInfo &STI,
bool DidPush)
override;
122 void emitNoteGnuProperty(
const Module &M);
125 void emitAttributes(
const MCSubtargetInfo &SubtargetInfo);
127 void emitNTLHint(
const MachineInstr *
MI);
129 void emitLpadAlignedCall(
const MachineInstr &
MI);
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);
137 void lowerToMCInst(
const MachineInstr *
MI, MCInst &OutMI);
143 unsigned NOPBytes = STI->hasStdExtZca() ? 2 : 4;
144 unsigned NumNOPBytes = StackMapOpers(&
MI).getNumPatchBytes();
147 MCSymbol *MILabel = Ctx.createTempSymbol();
151 assert(NumNOPBytes % NOPBytes == 0 &&
152 "Invalid number of NOP bytes requested!");
155 const MachineBasicBlock &
MBB = *
MI.getParent();
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)
165 NumNOPBytes -= NOPBytes;
169 emitNops(NumNOPBytes / NOPBytes);
174void RISCVAsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
175 const MachineInstr &
MI) {
176 unsigned NOPBytes = STI->hasStdExtZca() ? 2 : 4;
179 MCSymbol *MILabel = Ctx.createTempSymbol();
183 PatchPointOpers Opers(&
MI);
185 const MachineOperand &CalleeMO = Opers.getCallTarget();
186 unsigned EncodedBytes = 0;
188 if (CalleeMO.
isImm()) {
189 uint64_t CallTarget = CalleeMO.
getImm();
191 assert((CallTarget & 0xFFFF'FFFF'FFFF) == CallTarget &&
192 "High 16 bits of call target should be zero.");
196 for (MCInst &Inst : Seq) {
197 bool Compressed = EmitToStreamer(OutStreamer, Inst);
198 EncodedBytes += Compressed ? 2 : 4;
200 bool Compressed = EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JALR)
204 EncodedBytes += Compressed ? 2 : 4;
207 MCOperand CallTargetMCOp;
208 lowerOperand(CalleeMO, CallTargetMCOp);
209 EmitToStreamer(OutStreamer,
210 MCInstBuilder(RISCV::PseudoCALL).
addOperand(CallTargetMCOp));
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);
223void RISCVAsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
224 const MachineInstr &
MI) {
225 unsigned NOPBytes = STI->hasStdExtZca() ? 2 : 4;
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);
234 const MachineOperand &CallTarget = SOpers.getCallTarget();
235 MCOperand CallTargetMCOp;
236 switch (CallTarget.
getType()) {
239 lowerOperand(CallTarget, CallTargetMCOp);
242 MCInstBuilder(RISCV::PseudoCALL).
addOperand(CallTargetMCOp));
246 EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JAL)
252 EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JALR)
264 MCSymbol *MILabel = Ctx.createTempSymbol();
269bool RISCVAsmPrinter::EmitToStreamer(MCStreamer &S,
const MCInst &Inst,
270 const MCSubtargetInfo &SubtargetInfo) {
274 ++RISCVNumInstrsCompressed;
281#include "RISCVGenMCPseudoLowering.inc"
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);
300 RISCVTargetStreamer &RTS = getTargetStreamer();
301 if (HasZca && HasRelax) {
309 lowerOperand(
MI.getOperand(0), MCOp);
310 CallInst = MCInstBuilder(RISCV::PseudoCALL).
addOperand(MCOp);
312 CallInst = MCInstBuilder(RISCV::JALR)
314 .addReg(
MI.getOperand(0).getReg())
318 if (HasZca && HasRelax) {
319 MCSubtargetInfo NoRelaxSTI(MCSTI);
320 NoRelaxSTI.ToggleFeature(RISCV::FeatureRelax);
321 EmitToStreamer(*OutStreamer, CallInst, NoRelaxSTI);
324 EmitToStreamer(*OutStreamer, CallInst, MCSTI);
328 MCInst LpadInst = MCInstBuilder(RISCV::AUIPC)
330 .addImm(
MI.getOperand(1).getImm());
331 EmitToStreamer(*OutStreamer, LpadInst, MCSTI);
340 lowerOperand(
MI.getOperand(0), MCOp);
346 EmitToStreamer(*OutStreamer, TmpInst, MCSTI);
354void RISCVAsmPrinter::emitNTLHint(
const MachineInstr *
MI) {
360 MachineMemOperand *MMO = *(
MI->memoperands_begin());
364 unsigned NontemporalMode = 0;
366 NontemporalMode += 0b1;
368 NontemporalMode += 0b10;
371 if (STI->hasStdExtZca())
372 Hint.setOpcode(RISCV::C_ADD);
374 Hint.setOpcode(RISCV::ADD);
380 EmitToStreamer(*OutStreamer, Hint);
383void RISCVAsmPrinter::emitInstruction(
const MachineInstr *
MI) {
384 RISCV_MC::verifyInstructionPredicates(
MI->getOpcode(), STI->getFeatureBits());
389 if (MCInst OutInst; lowerPseudoInstExpansion(
MI, OutInst)) {
390 EmitToStreamer(*OutStreamer, OutInst);
394 switch (
MI->getOpcode()) {
395 case RISCV::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
396 LowerHWASAN_CHECK_MEMACCESS(*
MI);
398 case RISCV::KCFI_CHECK:
399 LowerKCFI_CHECK(*
MI);
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")) {
411 F.getFnAttributeAsParsedInteger(
"patchable-function-entry");
415 LowerPATCHABLE_FUNCTION_ENTER(
MI);
418 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
419 LowerPATCHABLE_FUNCTION_EXIT(
MI);
421 case TargetOpcode::PATCHABLE_TAIL_CALL:
422 LowerPATCHABLE_TAIL_CALL(
MI);
424 case RISCV::PseudoCALLLpadAlign:
425 case RISCV::PseudoCALLIndirectLpadAlign:
426 emitLpadAlignedCall(*
MI);
431 lowerToMCInst(
MI, OutInst);
432 EmitToStreamer(*OutStreamer, OutInst);
435bool RISCVAsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNo,
436 const char *ExtraCode, raw_ostream &OS) {
441 const MachineOperand &MO =
MI->getOperand(OpNo);
442 if (ExtraCode && ExtraCode[0]) {
443 if (ExtraCode[1] != 0)
446 switch (ExtraCode[0]) {
464 OS <<
TRI->getEncodingValue(MO.
getReg());
477 PrintSymbolOperand(MO, OS);
491bool RISCVAsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
493 const char *ExtraCode,
498 const MachineOperand &AddrReg =
MI->getOperand(OpNo);
499 assert(
MI->getNumOperands() > OpNo + 1 &&
"Expected additional operand");
500 const MachineOperand &
Offset =
MI->getOperand(OpNo + 1);
503 if (!AddrReg.
isReg())
510 if (!lowerOperand(
Offset, MCO))
516 MAI.printExpr(OS, *MCO.
getExpr());
519 MMI->getContext().registerInlineAsmLabel(
Offset.getMCSymbol());
520 if (
Offset.isBlockAddress()) {
522 MCSymbol *Sym = GetBlockAddressSymbol(BA);
523 MMI->getContext().registerInlineAsmLabel(Sym);
530bool RISCVAsmPrinter::emitTargetFeaturePush(
const MCSubtargetInfo &STI) {
531 RISCVTargetStreamer &RTS = getTargetStreamer();
533 const MCSubtargetInfo &MCSTI = TM.getMCSubtargetInfo();
541 auto Delta = STI.
hasFeature(Feature.Value) ? RISCVOptionArchArgType::Plus
542 : RISCVOptionArchArgType::Minus;
543 StringRef ExtName = Feature.key();
547 if (!NeedEmitStdOptionArgs.
empty()) {
556void RISCVAsmPrinter::emitTargetFeaturePop(
const MCSubtargetInfo &STI,
559 getTargetStreamer().emitDirectiveOptionPop();
562bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
565 bool EmittedOptionArch = emitTargetFeaturePush(*STI);
567 SetupMachineFunction(MF);
573 emitTargetFeaturePop(*STI, EmittedOptionArch);
577void RISCVAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const MachineInstr *
MI) {
578 emitSled(
MI, SledKind::FUNCTION_ENTER);
581void RISCVAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(
const MachineInstr *
MI) {
582 emitSled(
MI, SledKind::FUNCTION_EXIT);
585void RISCVAsmPrinter::LowerPATCHABLE_TAIL_CALL(
const MachineInstr *
MI) {
586 emitSled(
MI, SledKind::TAIL_CALL);
589void RISCVAsmPrinter::emitSled(
const MachineInstr *
MI, SledKind Kind) {
604 const uint8_t NoopsInSledCount = STI->is64Bit() ? 33 : 21;
607 auto CurSled = OutContext.createTempSymbol(
"xray_sled_",
true);
609 auto Target = OutContext.createTempSymbol();
617 MCInstBuilder(RISCV::JAL).addReg(RISCV::X0).addExpr(TargetExpr));
620 for (int8_t
I = 0;
I < NoopsInSledCount; ++
I)
621 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI)
627 recordSled(CurSled, *
MI, Kind, 2);
630void RISCVAsmPrinter::emitStartOfAsmFile(
Module &M) {
632 "target streamer is uninitialized");
633 RISCVTargetStreamer &RTS = getTargetStreamer();
634 if (
const MDString *ModuleTargetABI =
638 MCSubtargetInfo SubtargetInfo = TM.getMCSubtargetInfo();
642 for (
auto &ISA : MD->operands()) {
645 ISAString->getString(),
true,
648 auto &ISAInfo = *ParseResult;
650 if (ISAInfo->hasExtension(Feature.key()) &&
661 if (TM.getTargetTriple().isOSBinFormatELF())
662 emitAttributes(SubtargetInfo);
665void RISCVAsmPrinter::emitEndOfAsmFile(
Module &M) {
666 RISCVTargetStreamer &RTS = getTargetStreamer();
668 if (TM.getTargetTriple().isOSBinFormatELF()) {
670 emitNoteGnuProperty(M);
672 EmitHwasanMemaccessSymbols(M);
675void RISCVAsmPrinter::emitAttributes(
const MCSubtargetInfo &SubtargetInfo) {
676 RISCVTargetStreamer &RTS = getTargetStreamer();
683void RISCVAsmPrinter::emitFunctionEntryLabel() {
684 const auto *RMFI = MF->getInfo<RISCVMachineFunctionInfo>();
685 if (RMFI->isVectorCall()) {
686 RISCVTargetStreamer &RTS = getTargetStreamer();
701void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
703 uint32_t AccessInfo =
MI.getOperand(1).getImm();
705 HwasanMemaccessSymbols[HwasanMemaccessTuple(
Reg, AccessInfo)];
708 if (!TM.getTargetTriple().isOSBinFormatELF())
711 std::string SymName =
"__hwasan_check_x" +
utostr(
Reg - RISCV::X0) +
"_" +
712 utostr(AccessInfo) +
"_short";
713 Sym = OutContext.getOrCreateSymbol(SymName);
718 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr));
721void RISCVAsmPrinter::LowerKCFI_CHECK(
const MachineInstr &
MI) {
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");
733 unsigned ScratchRegs[] = {RISCV::X6, RISCV::X7};
734 unsigned NextReg = RISCV::X28;
735 auto isRegAvailable = [&](
unsigned Reg) {
736 return Reg != AddrReg && !STI->isRegisterReservedByUser(
Reg);
738 for (
auto &
Reg : ScratchRegs) {
739 if (isRegAvailable(
Reg))
741 while (!isRegAvailable(NextReg))
744 if (
Reg > RISCV::X31)
748 if (AddrReg == RISCV::X0) {
751 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI)
752 .addReg(ScratchRegs[0])
758 int NopSize = STI->hasStdExtZca() ? 2 : 4;
760 MI.getMF()->getFunction().getFnAttributeAsParsedInteger(
761 "patchable-function-prefix");
764 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::LW)
765 .addReg(ScratchRegs[0])
767 .addImm(-(PrefixNops * NopSize + 4)));
771 const int64_t
Type =
MI.getOperand(1).getImm();
772 const int64_t Hi20 = ((
Type + 0x800) >> 12) & 0xFFFFF;
777 MCInstBuilder(RISCV::LUI).addReg(ScratchRegs[1]).addImm(Hi20));
779 if (Lo12 || Hi20 == 0) {
780 EmitToStreamer(*OutStreamer,
781 MCInstBuilder((STI->
hasFeature(RISCV::Feature64Bit) && Hi20)
784 .addReg(ScratchRegs[1])
785 .addReg(ScratchRegs[1])
791 EmitToStreamer(*OutStreamer,
792 MCInstBuilder(RISCV::BEQ)
793 .addReg(ScratchRegs[0])
794 .addReg(ScratchRegs[1])
799 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::EBREAK));
800 emitKCFITrapEntry(*
MI.getMF(),
Trap);
804void RISCVAsmPrinter::EmitHwasanMemaccessSymbols(
Module &M) {
805 if (HwasanMemaccessSymbols.empty())
808 assert(TM.getTargetTriple().isOSBinFormatELF());
812 const MCSubtargetInfo &MCSTI = TM.getMCSubtargetInfo();
815 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
818 RISCVTargetStreamer &RTS = getTargetStreamer();
821 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
826 for (
auto &
P : HwasanMemaccessSymbols) {
827 unsigned Reg = std::get<0>(
P.first);
828 uint32_t AccessInfo = std::get<1>(
P.first);
846 MCInstBuilder(RISCV::SLLI).addReg(RISCV::X6).addReg(
Reg).addImm(8),
848 EmitToStreamer(*OutStreamer,
849 MCInstBuilder(RISCV::SRLI)
855 EmitToStreamer(*OutStreamer,
856 MCInstBuilder(RISCV::ADD)
863 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
868 MCInstBuilder(RISCV::SRLI).addReg(RISCV::X7).addReg(
Reg).addImm(56),
870 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
872 EmitToStreamer(*OutStreamer,
873 MCInstBuilder(RISCV::BNE)
877 HandleMismatchOrPartialSym, OutContext)),
879 MCSymbol *ReturnSym = OutContext.createTempSymbol();
881 EmitToStreamer(*OutStreamer,
882 MCInstBuilder(RISCV::JALR)
887 OutStreamer->
emitLabel(HandleMismatchOrPartialSym);
889 EmitToStreamer(*OutStreamer,
890 MCInstBuilder(RISCV::ADDI)
895 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
898 MCInstBuilder(RISCV::BGEU)
906 MCInstBuilder(RISCV::ANDI).addReg(RISCV::X28).addReg(
Reg).addImm(0xF),
910 EmitToStreamer(*OutStreamer,
911 MCInstBuilder(RISCV::ADDI)
918 MCInstBuilder(RISCV::BGE)
926 MCInstBuilder(RISCV::ORI).addReg(RISCV::X6).addReg(
Reg).addImm(0xF),
930 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
932 EmitToStreamer(*OutStreamer,
933 MCInstBuilder(RISCV::BEQ)
939 OutStreamer->
emitLabel(HandleMismatchSym);
976 EmitToStreamer(*OutStreamer,
977 MCInstBuilder(RISCV::ADDI)
984 EmitToStreamer(*OutStreamer,
985 MCInstBuilder(RISCV::SD)
991 EmitToStreamer(*OutStreamer,
992 MCInstBuilder(RISCV::SD)
1001 MCInstBuilder(RISCV::SD).addReg(RISCV::X8).addReg(RISCV::X2).addImm(8 *
1007 MCInstBuilder(RISCV::SD).addReg(RISCV::X1).addReg(RISCV::X2).addImm(1 *
1010 if (
Reg != RISCV::X10)
1013 MCInstBuilder(RISCV::ADDI).addReg(RISCV::X10).addReg(
Reg).addImm(0),
1015 EmitToStreamer(*OutStreamer,
1016 MCInstBuilder(RISCV::ADDI)
1022 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr),
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");
1034 if (
const Metadata *
const Flag =
M.getModuleFlag(
"cf-protection-branch");
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 =
1061 auto &RTS =
static_cast<RISCVTargetELFStreamer &
>(getTargetStreamer());
1062 RTS.emitNoteGnuPropertySection(GnuProps);
1083 Kind = ELF::R_RISCV_HI20;
1098 Kind = ELF::R_RISCV_TPREL_HI20;
1101 Kind = ELF::R_RISCV_TPREL_ADD;
1104 Kind = ELF::R_RISCV_TLS_GOT_HI20;
1107 Kind = ELF::R_RISCV_TLS_GD_HI20;
1110 Kind = ELF::R_RISCV_TLSDESC_HI20;
1113 Kind = ELF::R_RISCV_TLSDESC_LOAD_LO12;
1116 Kind = ELF::R_RISCV_TLSDESC_ADD_LO12;
1119 Kind = ELF::R_RISCV_TLSDESC_CALL;
1137bool RISCVAsmPrinter::lowerOperand(
const MachineOperand &MO,
1138 MCOperand &MCOp)
const {
1185 RISCVVPseudosTable::getPseudoInfo(
MI->getOpcode());
1193 assert(
TRI &&
"TargetRegisterInfo expected");
1197 unsigned NumOps =
MI->getNumExplicitOperands();
1216 bool hasVLOutput = RISCVInstrInfo::isFaultOnlyFirstLoad(*
MI);
1217 for (
unsigned OpNo = 0; OpNo !=
NumOps; ++OpNo) {
1220 if (hasVLOutput && OpNo == 1)
1224 if (OpNo ==
MI->getNumExplicitDefs() && MO.
isReg() && MO.
isTied()) {
1226 "Expected tied to first def.");
1246 Reg =
TRI->getSubReg(
Reg, RISCV::sub_vrm1_0);
1247 assert(
Reg &&
"Subregister does not exist");
1250 TRI->getMatchingSuperReg(
Reg, RISCV::sub_16, &RISCV::FPR32RegClass);
1251 assert(
Reg &&
"Subregister does not exist");
1253 Reg =
TRI->getSubReg(
Reg, RISCV::sub_32);
1254 assert(
Reg &&
"Superregister does not exist");
1266 Reg =
TRI->getSubReg(
Reg, RISCV::sub_vrm1_0);
1267 assert(
Reg &&
"Subregister does not exist");
1286 "Expected only mask operand to be missing");
1294void RISCVAsmPrinter::lowerToMCInst(
const MachineInstr *
MI, MCInst &OutMI) {
1300 for (
const MachineOperand &MO :
MI->operands()) {
1302 if (lowerOperand(MO, MCOp))
1307void RISCVAsmPrinter::emitMachineConstantPoolValue(
1308 MachineConstantPoolValue *MCPV) {
1309 auto *RCPV =
static_cast<RISCVConstantPoolValue *
>(MCPV);
1312 if (RCPV->isGlobalValue()) {
1313 auto *GV = RCPV->getGlobalValue();
1314 MCSym = getSymbol(GV);
1316 assert(RCPV->isExtSymbol() &&
"unrecognized constant pool type");
1317 auto Sym = RCPV->getSymbol();
1318 MCSym = GetExternalSymbolSymbol(Sym);
1322 uint64_t
Size = getDataLayout().getTypeAllocSize(RCPV->getType());
1326char RISCVAsmPrinter::ID = 0;
1333 RISCVAsmPrinter &
AsmPrinter =
static_cast<RISCVAsmPrinter &
>(
1343 RISCVAsmPrinter &
AsmPrinter =
static_cast<RISCVAsmPrinter &
>(
1354 RISCVAsmPrinter &
AsmPrinter =
static_cast<RISCVAsmPrinter &
>(
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 const Function * getParent(const Value *V)
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
ModuleAnalysisManager MAM
#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")
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.
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.
bool doFinalization(Module &M) override
Shut down the asmprinter.
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
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.
Function & getFunction()
Return the LLVM function that this machine code represents.
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.
A Module instance is used to store all the information related to an LLVM module.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
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)
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)
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.
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.
@ 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
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.
auto dyn_cast_or_null(const Y &Val)
LLVM_ABI void setupModuleAsmPrinter(Module &M, ModuleAnalysisManager &MAM, AsmPrinter &AsmPrinter)
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.
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.
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()
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
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,...