10b57cec5SDimitry Andric //===-- X86AsmPrinter.h - X86 implementation of AsmPrinter ------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_X86_X86ASMPRINTER_H 100b57cec5SDimitry Andric #define LLVM_LIB_TARGET_X86_X86ASMPRINTER_H 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h" 130b57cec5SDimitry Andric #include "llvm/CodeGen/FaultMaps.h" 140b57cec5SDimitry Andric #include "llvm/CodeGen/StackMaps.h" 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric // Implemented in X86MCInstLower.cpp 170b57cec5SDimitry Andric namespace { 180b57cec5SDimitry Andric class X86MCInstLower; 190b57cec5SDimitry Andric } 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric namespace llvm { 225ffd83dbSDimitry Andric class MCCodeEmitter; 230b57cec5SDimitry Andric class MCStreamer; 245ffd83dbSDimitry Andric class X86Subtarget; 255ffd83dbSDimitry Andric class TargetMachine; 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter { 28480093f4SDimitry Andric const X86Subtarget *Subtarget = nullptr; 290b57cec5SDimitry Andric FaultMaps FM; 300b57cec5SDimitry Andric std::unique_ptr<MCCodeEmitter> CodeEmitter; 310b57cec5SDimitry Andric bool EmitFPOData = false; 320eae32dcSDimitry Andric bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags = false; 33bdd1243dSDimitry Andric bool IndCSPrefix = false; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric // This utility class tracks the length of a stackmap instruction's 'shadow'. 360b57cec5SDimitry Andric // It is used by the X86AsmPrinter to ensure that the stackmap shadow 370b57cec5SDimitry Andric // invariants (i.e. no other stackmaps, patchpoints, or control flow within 380b57cec5SDimitry Andric // the shadow) are met, while outputting a minimal number of NOPs for padding. 390b57cec5SDimitry Andric // 400b57cec5SDimitry Andric // To minimise the number of NOPs used, the shadow tracker counts the number 410b57cec5SDimitry Andric // of instruction bytes output since the last stackmap. Only if there are too 420b57cec5SDimitry Andric // few instruction bytes to cover the shadow are NOPs used for padding. 430b57cec5SDimitry Andric class StackMapShadowTracker { 440b57cec5SDimitry Andric public: 450b57cec5SDimitry Andric void startFunction(MachineFunction &MF) { 460b57cec5SDimitry Andric this->MF = &MF; 470b57cec5SDimitry Andric } 480b57cec5SDimitry Andric void count(MCInst &Inst, const MCSubtargetInfo &STI, 490b57cec5SDimitry Andric MCCodeEmitter *CodeEmitter); 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric // Called to signal the start of a shadow of RequiredSize bytes. 520b57cec5SDimitry Andric void reset(unsigned RequiredSize) { 530b57cec5SDimitry Andric RequiredShadowSize = RequiredSize; 540b57cec5SDimitry Andric CurrentShadowSize = 0; 550b57cec5SDimitry Andric InShadow = true; 560b57cec5SDimitry Andric } 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric // Called before every stackmap/patchpoint, and at the end of basic blocks, 590b57cec5SDimitry Andric // to emit any necessary padding-NOPs. 600b57cec5SDimitry Andric void emitShadowPadding(MCStreamer &OutStreamer, const MCSubtargetInfo &STI); 610b57cec5SDimitry Andric private: 62480093f4SDimitry Andric const MachineFunction *MF = nullptr; 630b57cec5SDimitry Andric bool InShadow = false; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric // RequiredShadowSize holds the length of the shadow specified in the most 660b57cec5SDimitry Andric // recently encountered STACKMAP instruction. 670b57cec5SDimitry Andric // CurrentShadowSize counts the number of bytes encoded since the most 680b57cec5SDimitry Andric // recently encountered STACKMAP, stopping when that number is greater than 690b57cec5SDimitry Andric // or equal to RequiredShadowSize. 700b57cec5SDimitry Andric unsigned RequiredShadowSize = 0, CurrentShadowSize = 0; 710b57cec5SDimitry Andric }; 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric StackMapShadowTracker SMShadowTracker; 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric // All instructions emitted by the X86AsmPrinter should use this helper 760b57cec5SDimitry Andric // method. 770b57cec5SDimitry Andric // 780b57cec5SDimitry Andric // This helper function invokes the SMShadowTracker on each instruction before 790b57cec5SDimitry Andric // outputting it to the OutStream. This allows the shadow tracker to minimise 800b57cec5SDimitry Andric // the number of NOPs used for stackmap padding. 810b57cec5SDimitry Andric void EmitAndCountInstruction(MCInst &Inst); 820b57cec5SDimitry Andric void LowerSTACKMAP(const MachineInstr &MI); 830b57cec5SDimitry Andric void LowerPATCHPOINT(const MachineInstr &MI, X86MCInstLower &MCIL); 840b57cec5SDimitry Andric void LowerSTATEPOINT(const MachineInstr &MI, X86MCInstLower &MCIL); 850b57cec5SDimitry Andric void LowerFAULTING_OP(const MachineInstr &MI, X86MCInstLower &MCIL); 860b57cec5SDimitry Andric void LowerPATCHABLE_OP(const MachineInstr &MI, X86MCInstLower &MCIL); 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric void LowerTlsAddr(X86MCInstLower &MCInstLowering, const MachineInstr &MI); 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric // XRay-specific lowering for X86. 910b57cec5SDimitry Andric void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI, 920b57cec5SDimitry Andric X86MCInstLower &MCIL); 930b57cec5SDimitry Andric void LowerPATCHABLE_RET(const MachineInstr &MI, X86MCInstLower &MCIL); 940b57cec5SDimitry Andric void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI, X86MCInstLower &MCIL); 950b57cec5SDimitry Andric void LowerPATCHABLE_EVENT_CALL(const MachineInstr &MI, X86MCInstLower &MCIL); 960b57cec5SDimitry Andric void LowerPATCHABLE_TYPED_EVENT_CALL(const MachineInstr &MI, 970b57cec5SDimitry Andric X86MCInstLower &MCIL); 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric void LowerFENTRY_CALL(const MachineInstr &MI, X86MCInstLower &MCIL); 1000b57cec5SDimitry Andric 101bdd1243dSDimitry Andric // KCFI specific lowering for X86. 102bdd1243dSDimitry Andric uint32_t MaskKCFIType(uint32_t Value); 103bdd1243dSDimitry Andric void EmitKCFITypePadding(const MachineFunction &MF, bool HasType = true); 104bdd1243dSDimitry Andric void LowerKCFI_CHECK(const MachineInstr &MI); 105bdd1243dSDimitry Andric 106349cc55cSDimitry Andric // Address sanitizer specific lowering for X86. 107349cc55cSDimitry Andric void LowerASAN_CHECK_MEMACCESS(const MachineInstr &MI); 108349cc55cSDimitry Andric 1090b57cec5SDimitry Andric // Choose between emitting .seh_ directives and .cv_fpo_ directives. 1100b57cec5SDimitry Andric void EmitSEHInstruction(const MachineInstr *MI); 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override; 1130b57cec5SDimitry Andric void PrintOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O); 1140b57cec5SDimitry Andric void PrintModifiedOperand(const MachineInstr *MI, unsigned OpNo, 1150b57cec5SDimitry Andric raw_ostream &O, const char *Modifier); 1160b57cec5SDimitry Andric void PrintPCRelImm(const MachineInstr *MI, unsigned OpNo, raw_ostream &O); 1170b57cec5SDimitry Andric void PrintLeaMemReference(const MachineInstr *MI, unsigned OpNo, 1180b57cec5SDimitry Andric raw_ostream &O, const char *Modifier); 1190b57cec5SDimitry Andric void PrintMemReference(const MachineInstr *MI, unsigned OpNo, raw_ostream &O, 1200b57cec5SDimitry Andric const char *Modifier); 1210b57cec5SDimitry Andric void PrintIntelMemReference(const MachineInstr *MI, unsigned OpNo, 122480093f4SDimitry Andric raw_ostream &O, const char *Modifier); 123*5f757f3fSDimitry Andric const MCSubtargetInfo *getIFuncMCSubtargetInfo() const override; 124*5f757f3fSDimitry Andric void emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI, 125*5f757f3fSDimitry Andric MCSymbol *LazyPointer) override; 126*5f757f3fSDimitry Andric void emitMachOIFuncStubHelperBody(Module &M, const GlobalIFunc &GI, 127*5f757f3fSDimitry Andric MCSymbol *LazyPointer) override; 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric public: 1300b57cec5SDimitry Andric X86AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer); 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric StringRef getPassName() const override { 1330b57cec5SDimitry Andric return "X86 Assembly Printer"; 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric const X86Subtarget &getSubtarget() const { return *Subtarget; } 1370b57cec5SDimitry Andric 1385ffd83dbSDimitry Andric void emitStartOfAsmFile(Module &M) override; 1390b57cec5SDimitry Andric 1405ffd83dbSDimitry Andric void emitEndOfAsmFile(Module &M) override; 1410b57cec5SDimitry Andric 1425ffd83dbSDimitry Andric void emitInstruction(const MachineInstr *MI) override; 1430b57cec5SDimitry Andric 14481ad6265SDimitry Andric void emitBasicBlockEnd(const MachineBasicBlock &MBB) override; 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 147e8d8bef9SDimitry Andric const char *ExtraCode, raw_ostream &O) override; 1480b57cec5SDimitry Andric bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, 149e8d8bef9SDimitry Andric const char *ExtraCode, raw_ostream &O) override; 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric bool doInitialization(Module &M) override { 1520b57cec5SDimitry Andric SMShadowTracker.reset(0); 1530b57cec5SDimitry Andric SM.reset(); 1540b57cec5SDimitry Andric FM.reset(); 1550b57cec5SDimitry Andric return AsmPrinter::doInitialization(M); 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric 158e8d8bef9SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 1595ffd83dbSDimitry Andric void emitFunctionBodyStart() override; 1605ffd83dbSDimitry Andric void emitFunctionBodyEnd() override; 161bdd1243dSDimitry Andric void emitKCFITypeId(const MachineFunction &MF) override; 1620eae32dcSDimitry Andric 1630eae32dcSDimitry Andric bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags() const override { 1640eae32dcSDimitry Andric return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags; 1650eae32dcSDimitry Andric } 1660b57cec5SDimitry Andric }; 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric } // end namespace llvm 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric #endif 171