1*9880d681SAndroid Build Coastguard Worker //===-- X86AsmPrinter.h - X86 implementation of AsmPrinter ------*- C++ -*-===// 2*9880d681SAndroid Build Coastguard Worker // 3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure 4*9880d681SAndroid Build Coastguard Worker // 5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source 6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details. 7*9880d681SAndroid Build Coastguard Worker // 8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*9880d681SAndroid Build Coastguard Worker 10*9880d681SAndroid Build Coastguard Worker #ifndef LLVM_LIB_TARGET_X86_X86ASMPRINTER_H 11*9880d681SAndroid Build Coastguard Worker #define LLVM_LIB_TARGET_X86_X86ASMPRINTER_H 12*9880d681SAndroid Build Coastguard Worker 13*9880d681SAndroid Build Coastguard Worker #include "X86Subtarget.h" 14*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/AsmPrinter.h" 15*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/FaultMaps.h" 16*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/StackMaps.h" 17*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetMachine.h" 18*9880d681SAndroid Build Coastguard Worker 19*9880d681SAndroid Build Coastguard Worker // Implemented in X86MCInstLower.cpp 20*9880d681SAndroid Build Coastguard Worker namespace { 21*9880d681SAndroid Build Coastguard Worker class X86MCInstLower; 22*9880d681SAndroid Build Coastguard Worker } 23*9880d681SAndroid Build Coastguard Worker 24*9880d681SAndroid Build Coastguard Worker namespace llvm { 25*9880d681SAndroid Build Coastguard Worker class MCStreamer; 26*9880d681SAndroid Build Coastguard Worker class MCSymbol; 27*9880d681SAndroid Build Coastguard Worker 28*9880d681SAndroid Build Coastguard Worker class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter { 29*9880d681SAndroid Build Coastguard Worker const X86Subtarget *Subtarget; 30*9880d681SAndroid Build Coastguard Worker StackMaps SM; 31*9880d681SAndroid Build Coastguard Worker FaultMaps FM; 32*9880d681SAndroid Build Coastguard Worker std::unique_ptr<MCCodeEmitter> CodeEmitter; 33*9880d681SAndroid Build Coastguard Worker 34*9880d681SAndroid Build Coastguard Worker // This utility class tracks the length of a stackmap instruction's 'shadow'. 35*9880d681SAndroid Build Coastguard Worker // It is used by the X86AsmPrinter to ensure that the stackmap shadow 36*9880d681SAndroid Build Coastguard Worker // invariants (i.e. no other stackmaps, patchpoints, or control flow within 37*9880d681SAndroid Build Coastguard Worker // the shadow) are met, while outputting a minimal number of NOPs for padding. 38*9880d681SAndroid Build Coastguard Worker // 39*9880d681SAndroid Build Coastguard Worker // To minimise the number of NOPs used, the shadow tracker counts the number 40*9880d681SAndroid Build Coastguard Worker // of instruction bytes output since the last stackmap. Only if there are too 41*9880d681SAndroid Build Coastguard Worker // few instruction bytes to cover the shadow are NOPs used for padding. 42*9880d681SAndroid Build Coastguard Worker class StackMapShadowTracker { 43*9880d681SAndroid Build Coastguard Worker public: startFunction(MachineFunction & MF)44*9880d681SAndroid Build Coastguard Worker void startFunction(MachineFunction &MF) { 45*9880d681SAndroid Build Coastguard Worker this->MF = &MF; 46*9880d681SAndroid Build Coastguard Worker } 47*9880d681SAndroid Build Coastguard Worker void count(MCInst &Inst, const MCSubtargetInfo &STI, 48*9880d681SAndroid Build Coastguard Worker MCCodeEmitter *CodeEmitter); 49*9880d681SAndroid Build Coastguard Worker 50*9880d681SAndroid Build Coastguard Worker // Called to signal the start of a shadow of RequiredSize bytes. reset(unsigned RequiredSize)51*9880d681SAndroid Build Coastguard Worker void reset(unsigned RequiredSize) { 52*9880d681SAndroid Build Coastguard Worker RequiredShadowSize = RequiredSize; 53*9880d681SAndroid Build Coastguard Worker CurrentShadowSize = 0; 54*9880d681SAndroid Build Coastguard Worker InShadow = true; 55*9880d681SAndroid Build Coastguard Worker } 56*9880d681SAndroid Build Coastguard Worker 57*9880d681SAndroid Build Coastguard Worker // Called before every stackmap/patchpoint, and at the end of basic blocks, 58*9880d681SAndroid Build Coastguard Worker // to emit any necessary padding-NOPs. 59*9880d681SAndroid Build Coastguard Worker void emitShadowPadding(MCStreamer &OutStreamer, const MCSubtargetInfo &STI); 60*9880d681SAndroid Build Coastguard Worker private: 61*9880d681SAndroid Build Coastguard Worker const MachineFunction *MF; 62*9880d681SAndroid Build Coastguard Worker bool InShadow = false; 63*9880d681SAndroid Build Coastguard Worker 64*9880d681SAndroid Build Coastguard Worker // RequiredShadowSize holds the length of the shadow specified in the most 65*9880d681SAndroid Build Coastguard Worker // recently encountered STACKMAP instruction. 66*9880d681SAndroid Build Coastguard Worker // CurrentShadowSize counts the number of bytes encoded since the most 67*9880d681SAndroid Build Coastguard Worker // recently encountered STACKMAP, stopping when that number is greater than 68*9880d681SAndroid Build Coastguard Worker // or equal to RequiredShadowSize. 69*9880d681SAndroid Build Coastguard Worker unsigned RequiredShadowSize = 0, CurrentShadowSize = 0; 70*9880d681SAndroid Build Coastguard Worker }; 71*9880d681SAndroid Build Coastguard Worker 72*9880d681SAndroid Build Coastguard Worker StackMapShadowTracker SMShadowTracker; 73*9880d681SAndroid Build Coastguard Worker 74*9880d681SAndroid Build Coastguard Worker // This describes the kind of sled we're storing in the XRay table. 75*9880d681SAndroid Build Coastguard Worker enum class SledKind : uint8_t { 76*9880d681SAndroid Build Coastguard Worker FUNCTION_ENTER = 0, 77*9880d681SAndroid Build Coastguard Worker FUNCTION_EXIT = 1, 78*9880d681SAndroid Build Coastguard Worker TAIL_CALL = 2, 79*9880d681SAndroid Build Coastguard Worker }; 80*9880d681SAndroid Build Coastguard Worker 81*9880d681SAndroid Build Coastguard Worker // The table will contain these structs that point to the sled, the function 82*9880d681SAndroid Build Coastguard Worker // containing the sled, and what kind of sled (and whether they should always 83*9880d681SAndroid Build Coastguard Worker // be instrumented). 84*9880d681SAndroid Build Coastguard Worker struct XRayFunctionEntry { 85*9880d681SAndroid Build Coastguard Worker const MCSymbol *Sled; 86*9880d681SAndroid Build Coastguard Worker const MCSymbol *Function; 87*9880d681SAndroid Build Coastguard Worker SledKind Kind; 88*9880d681SAndroid Build Coastguard Worker bool AlwaysInstrument; 89*9880d681SAndroid Build Coastguard Worker const class Function *Fn; 90*9880d681SAndroid Build Coastguard Worker }; 91*9880d681SAndroid Build Coastguard Worker 92*9880d681SAndroid Build Coastguard Worker // All the sleds to be emitted. 93*9880d681SAndroid Build Coastguard Worker std::vector<XRayFunctionEntry> Sleds; 94*9880d681SAndroid Build Coastguard Worker 95*9880d681SAndroid Build Coastguard Worker // All instructions emitted by the X86AsmPrinter should use this helper 96*9880d681SAndroid Build Coastguard Worker // method. 97*9880d681SAndroid Build Coastguard Worker // 98*9880d681SAndroid Build Coastguard Worker // This helper function invokes the SMShadowTracker on each instruction before 99*9880d681SAndroid Build Coastguard Worker // outputting it to the OutStream. This allows the shadow tracker to minimise 100*9880d681SAndroid Build Coastguard Worker // the number of NOPs used for stackmap padding. 101*9880d681SAndroid Build Coastguard Worker void EmitAndCountInstruction(MCInst &Inst); 102*9880d681SAndroid Build Coastguard Worker void LowerSTACKMAP(const MachineInstr &MI); 103*9880d681SAndroid Build Coastguard Worker void LowerPATCHPOINT(const MachineInstr &MI, X86MCInstLower &MCIL); 104*9880d681SAndroid Build Coastguard Worker void LowerSTATEPOINT(const MachineInstr &MI, X86MCInstLower &MCIL); 105*9880d681SAndroid Build Coastguard Worker void LowerFAULTING_LOAD_OP(const MachineInstr &MI, X86MCInstLower &MCIL); 106*9880d681SAndroid Build Coastguard Worker void LowerPATCHABLE_OP(const MachineInstr &MI, X86MCInstLower &MCIL); 107*9880d681SAndroid Build Coastguard Worker 108*9880d681SAndroid Build Coastguard Worker void LowerTlsAddr(X86MCInstLower &MCInstLowering, const MachineInstr &MI); 109*9880d681SAndroid Build Coastguard Worker 110*9880d681SAndroid Build Coastguard Worker // XRay-specific lowering for X86. 111*9880d681SAndroid Build Coastguard Worker void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI, 112*9880d681SAndroid Build Coastguard Worker X86MCInstLower &MCIL); 113*9880d681SAndroid Build Coastguard Worker void LowerPATCHABLE_RET(const MachineInstr &MI, X86MCInstLower &MCIL); 114*9880d681SAndroid Build Coastguard Worker void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI, X86MCInstLower &MCIL); 115*9880d681SAndroid Build Coastguard Worker 116*9880d681SAndroid Build Coastguard Worker // Helper function that emits the XRay sleds we've collected for a particular 117*9880d681SAndroid Build Coastguard Worker // function. 118*9880d681SAndroid Build Coastguard Worker void EmitXRayTable(); 119*9880d681SAndroid Build Coastguard Worker 120*9880d681SAndroid Build Coastguard Worker // Helper function to record a given XRay sled. 121*9880d681SAndroid Build Coastguard Worker void recordSled(MCSymbol *Sled, const MachineInstr &MI, SledKind Kind); 122*9880d681SAndroid Build Coastguard Worker public: X86AsmPrinter(TargetMachine & TM,std::unique_ptr<MCStreamer> Streamer)123*9880d681SAndroid Build Coastguard Worker explicit X86AsmPrinter(TargetMachine &TM, 124*9880d681SAndroid Build Coastguard Worker std::unique_ptr<MCStreamer> Streamer) 125*9880d681SAndroid Build Coastguard Worker : AsmPrinter(TM, std::move(Streamer)), SM(*this), FM(*this) {} 126*9880d681SAndroid Build Coastguard Worker getPassName()127*9880d681SAndroid Build Coastguard Worker const char *getPassName() const override { 128*9880d681SAndroid Build Coastguard Worker return "X86 Assembly / Object Emitter"; 129*9880d681SAndroid Build Coastguard Worker } 130*9880d681SAndroid Build Coastguard Worker getSubtarget()131*9880d681SAndroid Build Coastguard Worker const X86Subtarget &getSubtarget() const { return *Subtarget; } 132*9880d681SAndroid Build Coastguard Worker 133*9880d681SAndroid Build Coastguard Worker void EmitStartOfAsmFile(Module &M) override; 134*9880d681SAndroid Build Coastguard Worker 135*9880d681SAndroid Build Coastguard Worker void EmitEndOfAsmFile(Module &M) override; 136*9880d681SAndroid Build Coastguard Worker 137*9880d681SAndroid Build Coastguard Worker void EmitInstruction(const MachineInstr *MI) override; 138*9880d681SAndroid Build Coastguard Worker EmitBasicBlockEnd(const MachineBasicBlock & MBB)139*9880d681SAndroid Build Coastguard Worker void EmitBasicBlockEnd(const MachineBasicBlock &MBB) override { 140*9880d681SAndroid Build Coastguard Worker SMShadowTracker.emitShadowPadding(*OutStreamer, getSubtargetInfo()); 141*9880d681SAndroid Build Coastguard Worker } 142*9880d681SAndroid Build Coastguard Worker 143*9880d681SAndroid Build Coastguard Worker bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 144*9880d681SAndroid Build Coastguard Worker unsigned AsmVariant, const char *ExtraCode, 145*9880d681SAndroid Build Coastguard Worker raw_ostream &OS) override; 146*9880d681SAndroid Build Coastguard Worker bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, 147*9880d681SAndroid Build Coastguard Worker unsigned AsmVariant, const char *ExtraCode, 148*9880d681SAndroid Build Coastguard Worker raw_ostream &OS) override; 149*9880d681SAndroid Build Coastguard Worker 150*9880d681SAndroid Build Coastguard Worker /// \brief Return the symbol for the specified constant pool entry. 151*9880d681SAndroid Build Coastguard Worker MCSymbol *GetCPISymbol(unsigned CPID) const override; 152*9880d681SAndroid Build Coastguard Worker doInitialization(Module & M)153*9880d681SAndroid Build Coastguard Worker bool doInitialization(Module &M) override { 154*9880d681SAndroid Build Coastguard Worker SMShadowTracker.reset(0); 155*9880d681SAndroid Build Coastguard Worker SM.reset(); 156*9880d681SAndroid Build Coastguard Worker return AsmPrinter::doInitialization(M); 157*9880d681SAndroid Build Coastguard Worker } 158*9880d681SAndroid Build Coastguard Worker 159*9880d681SAndroid Build Coastguard Worker bool runOnMachineFunction(MachineFunction &F) override; 160*9880d681SAndroid Build Coastguard Worker }; 161*9880d681SAndroid Build Coastguard Worker 162*9880d681SAndroid Build Coastguard Worker } // end namespace llvm 163*9880d681SAndroid Build Coastguard Worker 164*9880d681SAndroid Build Coastguard Worker #endif 165