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:
startFunction(MachineFunction & MF)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.
reset(unsigned RequiredSize)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 
getPassName()119   StringRef getPassName() const override {
120     return "X86 Assembly Printer";
121   }
122 
getSubtarget()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 
emitBasicBlockEnd(const MachineBasicBlock & MBB)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 
doInitialization(Module & M)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