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
17namespace {
18 class X86MCInstLower;
19}
20
21namespace llvm {
22class MCCodeEmitter;
23class MCStreamer;
24class X86Subtarget;
25class TargetMachine;
26
27class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter {
28public:
29 static char ID;
30
31private:
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
159public:
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 *ExtraCode, raw_ostream &O) override;
178 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
179 const char *ExtraCode, 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