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: |
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. |
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 | |
162 | StringRef getPassName() const override { |
163 | return "X86 Assembly Printer" ; |
164 | } |
165 | |
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 *, raw_ostream &O) override; |
178 | bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, |
179 | const char *, raw_ostream &O) override; |
180 | |
181 | bool doInitialization(Module &M) override { |
182 | SMShadowTracker.reset(RequiredSize: 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 | |
193 | bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags() const override { |
194 | return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags; |
195 | } |
196 | }; |
197 | |
198 | } // end namespace llvm |
199 | |
200 | #endif |
201 | |