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   FaultMaps FM;
30   std::unique_ptr<MCCodeEmitter> CodeEmitter;
31   bool EmitFPOData = false;
32   bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags = false;
33   bool IndCSPrefix = 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   // KCFI specific lowering for X86.
102   uint32_t MaskKCFIType(uint32_t Value);
103   void EmitKCFITypePadding(const MachineFunction &MF, bool HasType = true);
104   void LowerKCFI_CHECK(const MachineInstr &MI);
105 
106   // Address sanitizer specific lowering for X86.
107   void LowerASAN_CHECK_MEMACCESS(const MachineInstr &MI);
108 
109   // Choose between emitting .seh_ directives and .cv_fpo_ directives.
110   void EmitSEHInstruction(const MachineInstr *MI);
111 
112   void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override;
113   void PrintOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
114   void PrintModifiedOperand(const MachineInstr *MI, unsigned OpNo,
115                             raw_ostream &O, const char *Modifier);
116   void PrintPCRelImm(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
117   void PrintLeaMemReference(const MachineInstr *MI, unsigned OpNo,
118                             raw_ostream &O, const char *Modifier);
119   void PrintMemReference(const MachineInstr *MI, unsigned OpNo, raw_ostream &O,
120                          const char *Modifier);
121   void PrintIntelMemReference(const MachineInstr *MI, unsigned OpNo,
122                               raw_ostream &O, const char *Modifier);
123 
124 public:
125   X86AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer);
126 
127   StringRef getPassName() const override {
128     return "X86 Assembly Printer";
129   }
130 
131   const X86Subtarget &getSubtarget() const { return *Subtarget; }
132 
133   void emitStartOfAsmFile(Module &M) override;
134 
135   void emitEndOfAsmFile(Module &M) override;
136 
137   void emitInstruction(const MachineInstr *MI) override;
138 
139   void emitBasicBlockEnd(const MachineBasicBlock &MBB) override;
140 
141   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
142                        const char *ExtraCode, raw_ostream &O) override;
143   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
144                              const char *ExtraCode, raw_ostream &O) override;
145 
146   bool doInitialization(Module &M) override {
147     SMShadowTracker.reset(0);
148     SM.reset();
149     FM.reset();
150     return AsmPrinter::doInitialization(M);
151   }
152 
153   bool runOnMachineFunction(MachineFunction &MF) override;
154   void emitFunctionBodyStart() override;
155   void emitFunctionBodyEnd() override;
156   void emitKCFITypeId(const MachineFunction &MF) override;
157 
158   bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags() const override {
159     return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
160   }
161 };
162 
163 } // end namespace llvm
164 
165 #endif
166