xref: /freebsd/contrib/llvm-project/llvm/lib/Target/X86/X86AsmPrinter.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 public:
29   static char ID;
30 
31 private:
32   const X86Subtarget *Subtarget = nullptr;
33   FaultMaps FM;
34   std::unique_ptr<MCCodeEmitter> CodeEmitter;
35   bool EmitFPOData = false;
36   bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags = false;
37   bool IndCSPrefix = false;
38   bool EnableImportCallOptimization = false;
39 
40   enum ImportCallKind : unsigned {
41     IMAGE_RETPOLINE_AMD64_IMPORT_BR = 0x02,
42     IMAGE_RETPOLINE_AMD64_IMPORT_CALL = 0x03,
43     IMAGE_RETPOLINE_AMD64_INDIR_BR = 0x04,
44     IMAGE_RETPOLINE_AMD64_INDIR_CALL = 0x05,
45     IMAGE_RETPOLINE_AMD64_INDIR_BR_REX = 0x06,
46     IMAGE_RETPOLINE_AMD64_CFG_BR = 0x08,
47     IMAGE_RETPOLINE_AMD64_CFG_CALL = 0x09,
48     IMAGE_RETPOLINE_AMD64_CFG_BR_REX = 0x0A,
49     IMAGE_RETPOLINE_AMD64_SWITCHTABLE_FIRST = 0x010,
50     IMAGE_RETPOLINE_AMD64_SWITCHTABLE_LAST = 0x01F,
51   };
52   struct ImportCallInfo {
53     MCSymbol *CalleeSymbol;
54     ImportCallKind Kind;
55   };
56   DenseMap<MCSection *, std::vector<ImportCallInfo>>
57       SectionToImportedFunctionCalls;
58 
59   // This utility class tracks the length of a stackmap instruction's 'shadow'.
60   // It is used by the X86AsmPrinter to ensure that the stackmap shadow
61   // invariants (i.e. no other stackmaps, patchpoints, or control flow within
62   // the shadow) are met, while outputting a minimal number of NOPs for padding.
63   //
64   // To minimise the number of NOPs used, the shadow tracker counts the number
65   // of instruction bytes output since the last stackmap. Only if there are too
66   // few instruction bytes to cover the shadow are NOPs used for padding.
67   class StackMapShadowTracker {
68   public:
startFunction(MachineFunction & MF)69     void startFunction(MachineFunction &MF) {
70       this->MF = &MF;
71     }
72     void count(const MCInst &Inst, const MCSubtargetInfo &STI,
73                MCCodeEmitter *CodeEmitter);
74 
75     // Called to signal the start of a shadow of RequiredSize bytes.
reset(unsigned RequiredSize)76     void reset(unsigned RequiredSize) {
77       RequiredShadowSize = RequiredSize;
78       CurrentShadowSize = 0;
79       InShadow = true;
80     }
81 
82     // Called before every stackmap/patchpoint, and at the end of basic blocks,
83     // to emit any necessary padding-NOPs.
84     void emitShadowPadding(MCStreamer &OutStreamer, const MCSubtargetInfo &STI);
85   private:
86     const MachineFunction *MF = nullptr;
87     bool InShadow = false;
88 
89     // RequiredShadowSize holds the length of the shadow specified in the most
90     // recently encountered STACKMAP instruction.
91     // CurrentShadowSize counts the number of bytes encoded since the most
92     // recently encountered STACKMAP, stopping when that number is greater than
93     // or equal to RequiredShadowSize.
94     unsigned RequiredShadowSize = 0, CurrentShadowSize = 0;
95   };
96 
97   StackMapShadowTracker SMShadowTracker;
98 
99   // All instructions emitted by the X86AsmPrinter should use this helper
100   // method.
101   //
102   // This helper function invokes the SMShadowTracker on each instruction before
103   // outputting it to the OutStream. This allows the shadow tracker to minimise
104   // the number of NOPs used for stackmap padding.
105   void EmitAndCountInstruction(MCInst &Inst);
106   void LowerSTACKMAP(const MachineInstr &MI);
107   void LowerPATCHPOINT(const MachineInstr &MI, X86MCInstLower &MCIL);
108   void LowerSTATEPOINT(const MachineInstr &MI, X86MCInstLower &MCIL);
109   void LowerFAULTING_OP(const MachineInstr &MI, X86MCInstLower &MCIL);
110   void LowerPATCHABLE_OP(const MachineInstr &MI, X86MCInstLower &MCIL);
111 
112   void LowerTlsAddr(X86MCInstLower &MCInstLowering, const MachineInstr &MI);
113 
114   // XRay-specific lowering for X86.
115   void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI,
116                                      X86MCInstLower &MCIL);
117   void LowerPATCHABLE_RET(const MachineInstr &MI, X86MCInstLower &MCIL);
118   void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI, X86MCInstLower &MCIL);
119   void LowerPATCHABLE_EVENT_CALL(const MachineInstr &MI, X86MCInstLower &MCIL);
120   void LowerPATCHABLE_TYPED_EVENT_CALL(const MachineInstr &MI,
121                                        X86MCInstLower &MCIL);
122 
123   void LowerFENTRY_CALL(const MachineInstr &MI, X86MCInstLower &MCIL);
124 
125   // KCFI specific lowering for X86.
126   uint32_t MaskKCFIType(uint32_t Value);
127   void EmitKCFITypePadding(const MachineFunction &MF, bool HasType = true);
128   void LowerKCFI_CHECK(const MachineInstr &MI);
129 
130   // Address sanitizer specific lowering for X86.
131   void LowerASAN_CHECK_MEMACCESS(const MachineInstr &MI);
132 
133   // Choose between emitting .seh_ directives and .cv_fpo_ directives.
134   void EmitSEHInstruction(const MachineInstr *MI);
135 
136   void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override;
137   void PrintOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
138   void PrintModifiedOperand(const MachineInstr *MI, unsigned OpNo,
139                             raw_ostream &O, StringRef Modifier = {});
140   void PrintPCRelImm(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
141   void PrintLeaMemReference(const MachineInstr *MI, unsigned OpNo,
142                             raw_ostream &O, StringRef Modifier = {});
143   void PrintMemReference(const MachineInstr *MI, unsigned OpNo, raw_ostream &O,
144                          StringRef Modifier = {});
145   void PrintIntelMemReference(const MachineInstr *MI, unsigned OpNo,
146                               raw_ostream &O, StringRef Modifier = {});
147   const MCSubtargetInfo *getIFuncMCSubtargetInfo() const override;
148   void emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
149                               MCSymbol *LazyPointer) override;
150   void emitMachOIFuncStubHelperBody(Module &M, const GlobalIFunc &GI,
151                                     MCSymbol *LazyPointer) override;
152 
153   void emitCallInstruction(const llvm::MCInst &MCI);
154 
155   // Emits a label to mark the next instruction as being relevant to Import Call
156   // Optimization.
157   void emitLabelAndRecordForImportCallOptimization(ImportCallKind Kind);
158 
159 public:
160   X86AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer);
161 
getPassName()162   StringRef getPassName() const override {
163     return "X86 Assembly Printer";
164   }
165 
getSubtarget()166   const X86Subtarget &getSubtarget() const { return *Subtarget; }
167 
168   void emitStartOfAsmFile(Module &M) override;
169 
170   void emitEndOfAsmFile(Module &M) override;
171 
172   void emitInstruction(const MachineInstr *MI) override;
173 
174   void emitBasicBlockEnd(const MachineBasicBlock &MBB) override;
175 
176   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
177                        const char *ExtraCode, raw_ostream &O) override;
178   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
179                              const char *ExtraCode, raw_ostream &O) override;
180 
doInitialization(Module & M)181   bool doInitialization(Module &M) override {
182     SMShadowTracker.reset(0);
183     SM.reset();
184     FM.reset();
185     return AsmPrinter::doInitialization(M);
186   }
187 
188   bool runOnMachineFunction(MachineFunction &MF) override;
189   void emitFunctionBodyStart() override;
190   void emitFunctionBodyEnd() override;
191   void emitKCFITypeId(const MachineFunction &MF) override;
192 
shouldEmitWeakSwiftAsyncExtendedFramePointerFlags()193   bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags() const override {
194     return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags;
195   }
196 };
197 
198 } // end namespace llvm
199 
200 #endif
201