45#define DEBUG_TYPE "asm-printer"
48 "Number of RISC-V Compressed instructions emitted");
60 std::unique_ptr<MCStreamer> Streamer)
75 bool emitPseudoExpansionLowering(
MCStreamer &OutStreamer,
78 typedef std::tuple<unsigned, uint32_t> HwasanMemaccessTuple;
79 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
82 void EmitHwasanMemaccessSymbols(
Module &M);
91 bool emitDirectiveOptionArch();
94 void emitAttributes();
106 ++RISCVNumInstrsCompressed;
112#include "RISCVGenMCPseudoLowering.inc"
117 if (!STI->hasStdExtZihintntl())
120 if (
MI->memoperands_empty())
127 unsigned NontemporalMode = 0;
129 NontemporalMode += 0b1;
131 NontemporalMode += 0b10;
134 if (STI->hasStdExtCOrZca() && STI->enableRVCHintInstrs())
143 EmitToStreamer(*OutStreamer, Hint);
147 RISCV_MC::verifyInstructionPredicates(
MI->getOpcode(),
148 getSubtargetInfo().getFeatureBits());
153 if (emitPseudoExpansionLowering(*OutStreamer,
MI))
157 switch (
MI->getOpcode()) {
158 case RISCV::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
159 LowerHWASAN_CHECK_MEMACCESS(*
MI);
161 case RISCV::KCFI_CHECK:
162 LowerKCFI_CHECK(*
MI);
164 case RISCV::PseudoRVVInitUndefM1:
165 case RISCV::PseudoRVVInitUndefM2:
166 case RISCV::PseudoRVVInitUndefM4:
167 case RISCV::PseudoRVVInitUndefM8:
172 if (!lowerToMCInst(
MI, OutInst))
173 EmitToStreamer(*OutStreamer, OutInst);
176bool RISCVAsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNo,
183 if (ExtraCode && ExtraCode[0]) {
184 if (ExtraCode[1] != 0)
187 switch (ExtraCode[0]) {
211 PrintSymbolOperand(MO,
OS);
225bool RISCVAsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
227 const char *ExtraCode,
233 assert(
MI->getNumOperands() > OpNo + 1 &&
"Expected additional operand");
237 if (!AddrReg.
isReg())
243 if (!lowerOperand(
Offset, MCO))
254bool RISCVAsmPrinter::emitDirectiveOptionArch() {
260 if (STI->hasFeature(Feature.Value) == MCSTI.
hasFeature(Feature.Value))
266 auto Delta = STI->hasFeature(Feature.Value) ? RISCVOptionArchArgType::Plus
267 : RISCVOptionArchArgType::Minus;
270 if (!NeedEmitStdOptionArgs.
empty()) {
284 bool EmittedOptionArch = emitDirectiveOptionArch();
286 SetupMachineFunction(MF);
289 if (EmittedOptionArch)
290 RTS.emitDirectiveOptionPop();
294void RISCVAsmPrinter::emitStartOfAsmFile(
Module &M) {
297 if (
const MDString *ModuleTargetABI =
298 dyn_cast_or_null<MDString>(
M.getModuleFlag(
"target-abi")))
300 if (
TM.getTargetTriple().isOSBinFormatELF())
304void RISCVAsmPrinter::emitEndOfAsmFile(
Module &M) {
308 if (
TM.getTargetTriple().isOSBinFormatELF())
310 EmitHwasanMemaccessSymbols(M);
313void RISCVAsmPrinter::emitAttributes() {
322void RISCVAsmPrinter::emitFunctionEntryLabel() {
324 if (RMFI->isVectorCall()) {
338void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(
const MachineInstr &
MI) {
340 uint32_t AccessInfo =
MI.getOperand(1).getImm();
342 HwasanMemaccessSymbols[HwasanMemaccessTuple(Reg, AccessInfo)];
345 if (!
TM.getTargetTriple().isOSBinFormatELF())
348 std::string SymName =
"__hwasan_check_x" + utostr(Reg - RISCV::X0) +
"_" +
349 utostr(AccessInfo) +
"_short";
350 Sym = OutContext.getOrCreateSymbol(SymName);
355 EmitToStreamer(*OutStreamer,
MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr));
360 assert(std::next(
MI.getIterator())->isCall() &&
361 "KCFI_CHECK not followed by a call instruction");
362 assert(std::next(
MI.getIterator())->getOperand(0).getReg() == AddrReg &&
363 "KCFI_CHECK call target doesn't match call operand");
370 unsigned ScratchRegs[] = {RISCV::X6, RISCV::X7};
371 unsigned NextReg = RISCV::X28;
372 auto isRegAvailable = [&](
unsigned Reg) {
373 return Reg != AddrReg && !STI->isRegisterReservedByUser(Reg);
375 for (
auto &Reg : ScratchRegs) {
376 if (isRegAvailable(Reg))
378 while (!isRegAvailable(NextReg))
381 if (Reg > RISCV::X31)
385 if (AddrReg == RISCV::X0) {
389 .addReg(ScratchRegs[0])
395 int NopSize = STI->hasStdExtCOrZca() ? 2 : 4;
396 int64_t PrefixNops = 0;
399 .getFnAttribute(
"patchable-function-prefix")
401 .getAsInteger(10, PrefixNops);
405 .addReg(ScratchRegs[0])
407 .addImm(-(PrefixNops * NopSize + 4)));
411 const int64_t
Type =
MI.getOperand(1).getImm();
412 const int64_t Hi20 = ((
Type + 0x800) >> 12) & 0xFFFFF;
413 const int64_t Lo12 = SignExtend64<12>(
Type);
417 MCInstBuilder(RISCV::LUI).addReg(ScratchRegs[1]).addImm(Hi20));
419 if (Lo12 || Hi20 == 0) {
420 EmitToStreamer(*OutStreamer,
431 EmitToStreamer(*OutStreamer,
433 .addReg(ScratchRegs[0])
434 .addReg(ScratchRegs[1])
438 OutStreamer->emitLabel(
Trap);
440 emitKCFITrapEntry(*
MI.getMF(),
Trap);
441 OutStreamer->emitLabel(
Pass);
444void RISCVAsmPrinter::EmitHwasanMemaccessSymbols(
Module &M) {
445 if (HwasanMemaccessSymbols.empty())
448 assert(
TM.getTargetTriple().isOSBinFormatELF());
455 OutContext.getOrCreateSymbol(
"__hwasan_tag_mismatch_v2");
467 for (
auto &
P : HwasanMemaccessSymbols) {
468 unsigned Reg = std::get<0>(
P.first);
469 uint32_t AccessInfo = std::get<1>(
P.first);
474 OutStreamer->switchSection(OutContext.getELFSection(
482 OutStreamer->emitLabel(
Sym);
485 OutStreamer->emitInstruction(
499 OutStreamer->emitInstruction(
503 OutStreamer->emitInstruction(
506 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
508 OutStreamer->emitInstruction(
515 MCSymbol *ReturnSym = OutContext.createTempSymbol();
516 OutStreamer->emitLabel(ReturnSym);
522 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
529 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
530 OutStreamer->emitInstruction(
537 OutStreamer->emitInstruction(
547 OutStreamer->emitInstruction(
554 OutStreamer->emitInstruction(
557 OutStreamer->emitInstruction(
560 OutStreamer->emitInstruction(
567 OutStreamer->emitLabel(HandleMismatchSym);
624 OutStreamer->emitInstruction(
629 OutStreamer->emitInstruction(
633 if (Reg != RISCV::X10)
639 OutStreamer->emitInstruction(
759 RISCVVPseudosTable::getPseudoInfo(
MI->getOpcode());
766 assert(
MBB &&
"MI expected to be in a basic block");
768 assert(MF &&
"MBB expected to be in a machine function");
773 assert(
TRI &&
"TargetRegisterInfo expected");
777 unsigned NumOps =
MI->getNumExplicitOperands();
791 for (
unsigned OpNo = 0; OpNo != NumOps; ++OpNo) {
794 if (hasVLOutput && OpNo == 1)
798 if (OpNo ==
MI->getNumExplicitDefs() && MO.
isReg() && MO.
isTied()) {
800 "Expected tied to first def.");
817 if (RISCV::VRM2RegClass.
contains(Reg) ||
818 RISCV::VRM4RegClass.
contains(Reg) ||
819 RISCV::VRM8RegClass.
contains(Reg)) {
820 Reg =
TRI->getSubReg(Reg, RISCV::sub_vrm1_0);
821 assert(Reg &&
"Subregister does not exist");
822 }
else if (RISCV::FPR16RegClass.
contains(Reg)) {
824 TRI->getMatchingSuperReg(Reg, RISCV::sub_16, &RISCV::FPR32RegClass);
825 assert(Reg &&
"Subregister does not exist");
826 }
else if (RISCV::FPR64RegClass.
contains(Reg)) {
827 Reg =
TRI->getSubReg(Reg, RISCV::sub_32);
828 assert(Reg &&
"Superregister does not exist");
829 }
else if (RISCV::VRN2M1RegClass.
contains(Reg) ||
830 RISCV::VRN2M2RegClass.
contains(Reg) ||
831 RISCV::VRN2M4RegClass.
contains(Reg) ||
832 RISCV::VRN3M1RegClass.
contains(Reg) ||
833 RISCV::VRN3M2RegClass.
contains(Reg) ||
834 RISCV::VRN4M1RegClass.
contains(Reg) ||
835 RISCV::VRN4M2RegClass.
contains(Reg) ||
836 RISCV::VRN5M1RegClass.
contains(Reg) ||
837 RISCV::VRN6M1RegClass.
contains(Reg) ||
838 RISCV::VRN7M1RegClass.
contains(Reg) ||
839 RISCV::VRN8M1RegClass.
contains(Reg)) {
840 Reg =
TRI->getSubReg(Reg, RISCV::sub_vrm1_0);
841 assert(Reg &&
"Subregister does not exist");
859 RISCV::VMV0RegClassID &&
860 "Expected only mask operand to be missing");
876 if (lowerOperand(MO, MCOp))
881 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
882 const Function &
F =
MI->getParent()->getParent()->getFunction();
883 if (
F.hasFnAttribute(
"patchable-function-entry")) {
885 if (
F.getFnAttribute(
"patchable-function-entry")
887 .getAsInteger(10, Num))
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
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.
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
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
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.
static bool isSupportedExtensionFeature(StringRef Ext)
static const char * getRegisterName(MCRegister Reg)
static const RISCVMCExpr * create(const MCExpr *Expr, VariantKind Kind, MCContext &Ctx)
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 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.
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)
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.
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.