47#define DEBUG_TYPE "asm-printer"
50 "Number of RISC-V Compressed instructions emitted");
62 std::unique_ptr<MCStreamer> Streamer)
87 bool emitPseudoExpansionLowering(
MCStreamer &OutStreamer,
90 typedef std::tuple<unsigned, uint32_t> HwasanMemaccessTuple;
91 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
94 void EmitHwasanMemaccessSymbols(
Module &M);
103 bool emitDirectiveOptionArch();
116 unsigned NOPBytes = STI->hasStdExtCOrZca() ? 2 : 4;
120 MCSymbol *MILabel = Ctx.createTempSymbol();
124 assert(NumNOPBytes % NOPBytes == 0 &&
125 "Invalid number of NOP bytes requested!");
131 while (NumNOPBytes > 0) {
132 if (MII ==
MBB.
end() || MII->isCall() ||
133 MII->getOpcode() == RISCV::DBG_VALUE ||
134 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
135 MII->getOpcode() == TargetOpcode::STACKMAP)
142 emitNops(NumNOPBytes / NOPBytes);
149 unsigned NOPBytes = STI->hasStdExtCOrZca() ? 2 : 4;
152 MCSymbol *MILabel = Ctx.createTempSymbol();
159 unsigned EncodedBytes = 0;
161 if (CalleeMO.
isImm()) {
164 assert((CallTarget & 0xFFFF'FFFF'FFFF) == CallTarget &&
165 "High 16 bits of call target should be zero.");
169 for (
MCInst &Inst : Seq) {
170 bool Compressed = EmitToStreamer(OutStreamer, Inst);
171 EncodedBytes += Compressed ? 2 : 4;
173 bool Compressed = EmitToStreamer(OutStreamer,
MCInstBuilder(RISCV::JALR)
177 EncodedBytes += Compressed ? 2 : 4;
181 lowerOperand(CalleeMO, CallTargetMCOp);
182 EmitToStreamer(OutStreamer,
188 unsigned NumBytes = Opers.getNumPatchBytes();
189 assert(NumBytes >= EncodedBytes &&
190 "Patchpoint can't request size less than the length of a call.");
191 assert((NumBytes - EncodedBytes) % NOPBytes == 0 &&
192 "Invalid number of NOP bytes requested!");
193 emitNops((NumBytes - EncodedBytes) / NOPBytes);
198 unsigned NOPBytes = STI->hasStdExtCOrZca() ? 2 : 4;
201 if (
unsigned PatchBytes = SOpers.getNumPatchBytes()) {
202 assert(PatchBytes % NOPBytes == 0 &&
203 "Invalid number of NOP bytes requested!");
204 emitNops(PatchBytes / NOPBytes);
209 switch (CallTarget.
getType()) {
212 lowerOperand(CallTarget, CallTargetMCOp);
237 MCSymbol *MILabel = Ctx.createTempSymbol();
246 ++RISCVNumInstrsCompressed;
253#include "RISCVGenMCPseudoLowering.inc"
258 if (!STI->hasStdExtZihintntl())
261 if (
MI->memoperands_empty())
268 unsigned NontemporalMode = 0;
270 NontemporalMode += 0b1;
272 NontemporalMode += 0b10;
275 if (STI->hasStdExtCOrZca() && STI->enableRVCHintInstrs())
284 EmitToStreamer(*OutStreamer, Hint);
288 RISCV_MC::verifyInstructionPredicates(
MI->getOpcode(),
289 getSubtargetInfo().getFeatureBits());
294 if (emitPseudoExpansionLowering(*OutStreamer,
MI))
298 switch (
MI->getOpcode()) {
299 case RISCV::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
300 LowerHWASAN_CHECK_MEMACCESS(*
MI);
302 case RISCV::KCFI_CHECK:
303 LowerKCFI_CHECK(*
MI);
305 case RISCV::PseudoRVVInitUndefM1:
306 case RISCV::PseudoRVVInitUndefM2:
307 case RISCV::PseudoRVVInitUndefM4:
308 case RISCV::PseudoRVVInitUndefM8:
310 case TargetOpcode::STACKMAP:
311 return LowerSTACKMAP(*OutStreamer, SM, *
MI);
312 case TargetOpcode::PATCHPOINT:
313 return LowerPATCHPOINT(*OutStreamer, SM, *
MI);
314 case TargetOpcode::STATEPOINT:
315 return LowerSTATEPOINT(*OutStreamer, SM, *
MI);
319 if (!lowerToMCInst(
MI, OutInst))
320 EmitToStreamer(*OutStreamer, OutInst);
323bool RISCVAsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNo,
330 if (ExtraCode && ExtraCode[0]) {
331 if (ExtraCode[1] != 0)
334 switch (ExtraCode[0]) {
358 PrintSymbolOperand(MO,
OS);
372bool RISCVAsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
374 const char *ExtraCode,
380 assert(
MI->getNumOperands() > OpNo + 1 &&
"Expected additional operand");
384 if (!AddrReg.
isReg())
391 if (!lowerOperand(
Offset, MCO))
402bool RISCVAsmPrinter::emitDirectiveOptionArch() {
408 if (STI->hasFeature(Feature.Value) == MCSTI.
hasFeature(Feature.Value))
414 auto Delta = STI->hasFeature(Feature.Value) ? RISCVOptionArchArgType::Plus
415 : RISCVOptionArchArgType::Minus;
418 if (!NeedEmitStdOptionArgs.
empty()) {
432 bool EmittedOptionArch = emitDirectiveOptionArch();
434 SetupMachineFunction(MF);
437 if (EmittedOptionArch)
438 RTS.emitDirectiveOptionPop();
442void RISCVAsmPrinter::emitStartOfAsmFile(
Module &M) {
445 if (
const MDString *ModuleTargetABI =
446 dyn_cast_or_null<MDString>(
M.getModuleFlag(
"target-abi")))
452 if (
auto *MD = dyn_cast_or_null<MDNode>(
M.getModuleFlag(
"riscv-isa"))) {
453 for (
auto &ISA : MD->operands()) {
454 if (
auto *ISAString = dyn_cast_or_null<MDString>(ISA)) {
456 ISAString->getString(),
true,
459 auto &ISAInfo = *ParseResult;
461 if (ISAInfo->hasExtension(Feature.Key) &&
472 if (
TM.getTargetTriple().isOSBinFormatELF())
473 emitAttributes(SubtargetInfo);
476void RISCVAsmPrinter::emitEndOfAsmFile(
Module &M) {
480 if (
TM.getTargetTriple().isOSBinFormatELF())
482 EmitHwasanMemaccessSymbols(M);
485void RISCVAsmPrinter::emitAttributes(
const MCSubtargetInfo &SubtargetInfo) {
494void RISCVAsmPrinter::emitFunctionEntryLabel() {
496 if (RMFI->isVectorCall()) {
510void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
512 uint32_t AccessInfo =
MI.getOperand(1).getImm();
514 HwasanMemaccessSymbols[HwasanMemaccessTuple(Reg, AccessInfo)];
517 if (!
TM.getTargetTriple().isOSBinFormatELF())
520 std::string SymName =
"__hwasan_check_x" + utostr(Reg - RISCV::X0) +
"_" +
521 utostr(AccessInfo) +
"_short";
522 Sym = OutContext.getOrCreateSymbol(SymName);
527 EmitToStreamer(*OutStreamer,
MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr));
532 assert(std::next(
MI.getIterator())->isCall() &&
533 "KCFI_CHECK not followed by a call instruction");
534 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
535 "KCFI_CHECK call target doesn't match call operand");
542 unsigned ScratchRegs[] = {RISCV::X6, RISCV::X7};
543 unsigned NextReg = RISCV::X28;
544 auto isRegAvailable = [&](
unsigned Reg) {
545 return Reg != AddrReg && !STI->isRegisterReservedByUser(Reg);
547 for (
auto &Reg : ScratchRegs) {
548 if (isRegAvailable(Reg))
550 while (!isRegAvailable(NextReg))
553 if (Reg > RISCV::X31)
557 if (AddrReg == RISCV::X0) {
561 .addReg(ScratchRegs[0])
567 int NopSize = STI->hasStdExtCOrZca() ? 2 : 4;
568 int64_t PrefixNops = 0;
571 .getFnAttribute(
"patchable-function-prefix")
573 .getAsInteger(10, PrefixNops);
577 .addReg(ScratchRegs[0])
579 .addImm(-(PrefixNops * NopSize + 4)));
583 const int64_t
Type =
MI.getOperand(1).getImm();
584 const int64_t Hi20 = ((
Type + 0x800) >> 12) & 0xFFFFF;
585 const int64_t Lo12 = SignExtend64<12>(
Type);
589 MCInstBuilder(RISCV::LUI).addReg(ScratchRegs[1]).addImm(Hi20));
591 if (Lo12 || Hi20 == 0) {
592 EmitToStreamer(*OutStreamer,
603 EmitToStreamer(*OutStreamer,
605 .addReg(ScratchRegs[0])
606 .addReg(ScratchRegs[1])
612 emitKCFITrapEntry(*
MI.getMF(),
Trap);
616void RISCVAsmPrinter::EmitHwasanMemaccessSymbols(
Module &M) {
617 if (HwasanMemaccessSymbols.empty())
620 assert(
TM.getTargetTriple().isOSBinFormatELF());
627 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
639 for (
auto &
P : HwasanMemaccessSymbols) {
640 unsigned Reg = std::get<0>(
P.first);
641 uint32_t AccessInfo = std::get<1>(
P.first);
678 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
687 MCSymbol *ReturnSym = OutContext.createTempSymbol();
694 OutStreamer->
emitLabel(HandleMismatchOrPartialSym);
701 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
739 OutStreamer->
emitLabel(HandleMismatchSym);
805 if (Reg != RISCV::X10)
940 RISCVVPseudosTable::getPseudoInfo(
MI->getOpcode());
947 assert(
MBB &&
"MI expected to be in a basic block");
949 assert(MF &&
"MBB expected to be in a machine function");
954 assert(
TRI &&
"TargetRegisterInfo expected");
958 unsigned NumOps =
MI->getNumExplicitOperands();
972 for (
unsigned OpNo = 0; OpNo != NumOps; ++OpNo) {
975 if (hasVLOutput && OpNo == 1)
979 if (OpNo ==
MI->getNumExplicitDefs() && MO.
isReg() && MO.
isTied()) {
981 "Expected tied to first def.");
998 if (RISCV::VRM2RegClass.
contains(Reg) ||
999 RISCV::VRM4RegClass.
contains(Reg) ||
1000 RISCV::VRM8RegClass.
contains(Reg)) {
1001 Reg =
TRI->getSubReg(Reg, RISCV::sub_vrm1_0);
1002 assert(Reg &&
"Subregister does not exist");
1003 }
else if (RISCV::FPR16RegClass.
contains(Reg)) {
1005 TRI->getMatchingSuperReg(Reg, RISCV::sub_16, &RISCV::FPR32RegClass);
1006 assert(Reg &&
"Subregister does not exist");
1007 }
else if (RISCV::FPR64RegClass.
contains(Reg)) {
1008 Reg =
TRI->getSubReg(Reg, RISCV::sub_32);
1009 assert(Reg &&
"Superregister does not exist");
1010 }
else if (RISCV::VRN2M1RegClass.
contains(Reg) ||
1011 RISCV::VRN2M2RegClass.
contains(Reg) ||
1012 RISCV::VRN2M4RegClass.
contains(Reg) ||
1013 RISCV::VRN3M1RegClass.
contains(Reg) ||
1014 RISCV::VRN3M2RegClass.
contains(Reg) ||
1015 RISCV::VRN4M1RegClass.
contains(Reg) ||
1016 RISCV::VRN4M2RegClass.
contains(Reg) ||
1017 RISCV::VRN5M1RegClass.
contains(Reg) ||
1018 RISCV::VRN6M1RegClass.
contains(Reg) ||
1019 RISCV::VRN7M1RegClass.
contains(Reg) ||
1020 RISCV::VRN8M1RegClass.
contains(Reg)) {
1021 Reg =
TRI->getSubReg(Reg, RISCV::sub_vrm1_0);
1022 assert(Reg &&
"Subregister does not exist");
1040 RISCV::VMV0RegClassID &&
1041 "Expected only mask operand to be missing");
1057 if (lowerOperand(MO, MCOp))
1062 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
1063 const Function &
F =
MI->getParent()->getParent()->getFunction();
1064 if (
F.hasFnAttribute(
"patchable-function-entry")) {
1066 if (
F.getFnAttribute(
"patchable-function-entry")
1068 .getAsInteger(10, Num))
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
This file implements a class to represent arbitrary precision integral constant values and operations...
#define LLVM_EXTERNAL_VISIBILITY
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
const HexagonInstrInfo * TII
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
unsigned const TargetRegisterInfo * TRI
Module.h This file contains the declarations for the Module class.
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
const char LLVMTargetMachineRef TM
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmPrinter()
static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym, const AsmPrinter &AP)
static bool lowerRISCVVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This class is intended to be used as a driving class for all asm writers.
virtual void emitInstruction(const MachineInstr *)
Targets should implement this to emit instructions.
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
virtual void emitStartOfAsmFile(Module &)
This virtual method can be overridden by targets that want to emit something at the start of their fi...
virtual void emitEndOfAsmFile(Module &)
This virtual method can be overridden by targets that want to emit something at the end of their file...
MCContext & OutContext
This is the context for the output file that we are streaming.
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)
static 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.
MCInstBuilder & addReg(unsigned Reg)
Add a new register operand.
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
MCInstBuilder & addExpr(const MCExpr *Val)
Add a new MCExpr operand.
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 createReg(unsigned Reg)
static MCOperand createExpr(const MCExpr *Val)
static MCOperand createImm(int64_t Val)
const MCExpr * getExpr() const
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.
MCContext & getContext() const
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.
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
FeatureBitset ToggleFeature(uint64_t FB)
Toggle a feature and return the re-computed feature bits.
Represent a reference to a symbol from inside an expression.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
const MachineFunction * getParent() const
Return the MachineFunction containing 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.
A description of a memory reference used in the backend.
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.
Pass interface - Implemented by all 'passes'.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
MI-level patchpoint operands.
static bool isSupportedExtensionFeature(StringRef Ext)
static llvm::Expected< std::unique_ptr< RISCVISAInfo > > parseArchString(StringRef Arch, bool EnableExperimentalExtension, bool ExperimentalExtensionVersionCheck=true, bool IgnoreUnknown=false)
Parse RISC-V ISA info from arch string.
static const char * getRegisterName(MCRegister Reg)
static const RISCVMCExpr * create(const MCExpr *Expr, VariantKind Kind, MCContext &Ctx)
@ VK_RISCV_TLSDESC_ADD_LO
@ VK_RISCV_TLSDESC_LOAD_LO
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
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)
virtual void finishAttributeSection()
virtual void emitDirectiveOptionPush()
Wrapper class representing virtual and physical registers.
reference emplace_back(ArgTypes &&... Args)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
MI-level stackmap operands.
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given stackmap should emit.
void recordStatepoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a statepoint instruction.
void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
void recordStackMap(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a stackmap instruction.
MI-level Statepoint operands.
StringRef - Represent a constant reference to a string, i.e.
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...
The instances of the Type class are immutable: once they are created, they are never changed.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
ABI getTargetABI(StringRef ABIName)
static bool hasRoundModeOp(uint64_t TSFlags)
static bool isTiedPseudo(uint64_t TSFlags)
static bool hasVLOp(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)
bool isFaultFirstLoad(const MachineInstr &MI)
Reg
All possible values of the reg field in the ModR/M byte.
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
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Target & getTheRISCV64Target()
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures]
@ MCSA_ELF_TypeFunction
.type _foo, STT_FUNC # aka @function
@ MCSA_Hidden
.hidden (ELF)
Implement std::hash so that hash_code can be used in STL containers.
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...
Used to provide key value pairs for feature and CPU bit flags.