Home | History | Annotate | Line # | Download | only in X86
      1 //===-- X86AsmPrinter.h - X86 implementation of AsmPrinter ------*- C++ -*-===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 
      9 #ifndef LLVM_LIB_TARGET_X86_X86ASMPRINTER_H
     10 #define LLVM_LIB_TARGET_X86_X86ASMPRINTER_H
     11 
     12 #include "llvm/CodeGen/AsmPrinter.h"
     13 #include "llvm/CodeGen/FaultMaps.h"
     14 #include "llvm/CodeGen/StackMaps.h"
     15 
     16 // Implemented in X86MCInstLower.cpp
     17 namespace {
     18   class X86MCInstLower;
     19 }
     20 
     21 namespace llvm {
     22 class MCCodeEmitter;
     23 class MCStreamer;
     24 class X86Subtarget;
     25 class TargetMachine;
     26 
     27 class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter {
     28   const X86Subtarget *Subtarget = nullptr;
     29   StackMaps SM;
     30   FaultMaps FM;
     31   std::unique_ptr<MCCodeEmitter> CodeEmitter;
     32   bool EmitFPOData = false;
     33   bool NeedsRetpoline = false;
     34 
     35   // This utility class tracks the length of a stackmap instruction's 'shadow'.
     36   // It is used by the X86AsmPrinter to ensure that the stackmap shadow
     37   // invariants (i.e. no other stackmaps, patchpoints, or control flow within
     38   // the shadow) are met, while outputting a minimal number of NOPs for padding.
     39   //
     40   // To minimise the number of NOPs used, the shadow tracker counts the number
     41   // of instruction bytes output since the last stackmap. Only if there are too
     42   // few instruction bytes to cover the shadow are NOPs used for padding.
     43   class StackMapShadowTracker {
     44   public:
     45     void startFunction(MachineFunction &MF) {
     46       this->MF = &MF;
     47     }
     48     void count(MCInst &Inst, const MCSubtargetInfo &STI,
     49                MCCodeEmitter *CodeEmitter);
     50 
     51     // Called to signal the start of a shadow of RequiredSize bytes.
     52     void reset(unsigned RequiredSize) {
     53       RequiredShadowSize = RequiredSize;
     54       CurrentShadowSize = 0;
     55       InShadow = true;
     56     }
     57 
     58     // Called before every stackmap/patchpoint, and at the end of basic blocks,
     59     // to emit any necessary padding-NOPs.
     60     void emitShadowPadding(MCStreamer &OutStreamer, const MCSubtargetInfo &STI);
     61   private:
     62     const MachineFunction *MF = nullptr;
     63     bool InShadow = false;
     64 
     65     // RequiredShadowSize holds the length of the shadow specified in the most
     66     // recently encountered STACKMAP instruction.
     67     // CurrentShadowSize counts the number of bytes encoded since the most
     68     // recently encountered STACKMAP, stopping when that number is greater than
     69     // or equal to RequiredShadowSize.
     70     unsigned RequiredShadowSize = 0, CurrentShadowSize = 0;
     71   };
     72 
     73   StackMapShadowTracker SMShadowTracker;
     74 
     75   // All instructions emitted by the X86AsmPrinter should use this helper
     76   // method.
     77   //
     78   // This helper function invokes the SMShadowTracker on each instruction before
     79   // outputting it to the OutStream. This allows the shadow tracker to minimise
     80   // the number of NOPs used for stackmap padding.
     81   void EmitAndCountInstruction(MCInst &Inst);
     82   void LowerSTACKMAP(const MachineInstr &MI);
     83   void LowerPATCHPOINT(const MachineInstr &MI, X86MCInstLower &MCIL);
     84   void LowerSTATEPOINT(const MachineInstr &MI, X86MCInstLower &MCIL);
     85   void LowerFAULTING_OP(const MachineInstr &MI, X86MCInstLower &MCIL);
     86   void LowerPATCHABLE_OP(const MachineInstr &MI, X86MCInstLower &MCIL);
     87 
     88   void LowerTlsAddr(X86MCInstLower &MCInstLowering, const MachineInstr &MI);
     89 
     90   // XRay-specific lowering for X86.
     91   void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI,
     92                                      X86MCInstLower &MCIL);
     93   void LowerPATCHABLE_RET(const MachineInstr &MI, X86MCInstLower &MCIL);
     94   void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI, X86MCInstLower &MCIL);
     95   void LowerPATCHABLE_EVENT_CALL(const MachineInstr &MI, X86MCInstLower &MCIL);
     96   void LowerPATCHABLE_TYPED_EVENT_CALL(const MachineInstr &MI,
     97                                        X86MCInstLower &MCIL);
     98 
     99   void LowerFENTRY_CALL(const MachineInstr &MI, X86MCInstLower &MCIL);
    100 
    101   // Choose between emitting .seh_ directives and .cv_fpo_ directives.
    102   void EmitSEHInstruction(const MachineInstr *MI);
    103 
    104   void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override;
    105   void PrintOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
    106   void PrintModifiedOperand(const MachineInstr *MI, unsigned OpNo,
    107                             raw_ostream &O, const char *Modifier);
    108   void PrintPCRelImm(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
    109   void PrintLeaMemReference(const MachineInstr *MI, unsigned OpNo,
    110                             raw_ostream &O, const char *Modifier);
    111   void PrintMemReference(const MachineInstr *MI, unsigned OpNo, raw_ostream &O,
    112                          const char *Modifier);
    113   void PrintIntelMemReference(const MachineInstr *MI, unsigned OpNo,
    114                               raw_ostream &O, const char *Modifier);
    115 
    116 public:
    117   X86AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer);
    118 
    119   StringRef getPassName() const override {
    120     return "X86 Assembly Printer";
    121   }
    122 
    123   const X86Subtarget &getSubtarget() const { return *Subtarget; }
    124 
    125   void emitStartOfAsmFile(Module &M) override;
    126 
    127   void emitEndOfAsmFile(Module &M) override;
    128 
    129   void emitInstruction(const MachineInstr *MI) override;
    130 
    131   void emitBasicBlockEnd(const MachineBasicBlock &MBB) override {
    132     AsmPrinter::emitBasicBlockEnd(MBB);
    133     SMShadowTracker.emitShadowPadding(*OutStreamer, getSubtargetInfo());
    134   }
    135 
    136   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
    137                        const char *ExtraCode, raw_ostream &O) override;
    138   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
    139                              const char *ExtraCode, raw_ostream &O) override;
    140 
    141   bool doInitialization(Module &M) override {
    142     SMShadowTracker.reset(0);
    143     SM.reset();
    144     FM.reset();
    145     return AsmPrinter::doInitialization(M);
    146   }
    147 
    148   bool runOnMachineFunction(MachineFunction &MF) override;
    149   void emitFunctionBodyStart() override;
    150   void emitFunctionBodyEnd() override;
    151 };
    152 
    153 } // end namespace llvm
    154 
    155 #endif
    156