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 | const MCSubtargetInfo *getIFuncMCSubtargetInfo() const override; |
124 | void emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI, |
125 | MCSymbol *LazyPointer) override; |
126 | void emitMachOIFuncStubHelperBody(Module &M, const GlobalIFunc &GI, |
127 | MCSymbol *LazyPointer) override; |
128 | |
129 | public: |
130 | X86AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer); |
131 | |
132 | StringRef getPassName() const override { |
133 | return "X86 Assembly Printer" ; |
134 | } |
135 | |
136 | const X86Subtarget &getSubtarget() const { return *Subtarget; } |
137 | |
138 | void emitStartOfAsmFile(Module &M) override; |
139 | |
140 | void emitEndOfAsmFile(Module &M) override; |
141 | |
142 | void emitInstruction(const MachineInstr *MI) override; |
143 | |
144 | void emitBasicBlockEnd(const MachineBasicBlock &MBB) override; |
145 | |
146 | bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, |
147 | const char *, raw_ostream &O) override; |
148 | bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, |
149 | const char *, raw_ostream &O) override; |
150 | |
151 | bool doInitialization(Module &M) override { |
152 | SMShadowTracker.reset(RequiredSize: 0); |
153 | SM.reset(); |
154 | FM.reset(); |
155 | return AsmPrinter::doInitialization(M); |
156 | } |
157 | |
158 | bool runOnMachineFunction(MachineFunction &MF) override; |
159 | void emitFunctionBodyStart() override; |
160 | void emitFunctionBodyEnd() override; |
161 | void emitKCFITypeId(const MachineFunction &MF) override; |
162 | |
163 | bool shouldEmitWeakSwiftAsyncExtendedFramePointerFlags() const override { |
164 | return ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags; |
165 | } |
166 | }; |
167 | |
168 | } // end namespace llvm |
169 | |
170 | #endif |
171 | |