LLVM 19.0.0git
AArch64WinCOFFStreamer.cpp
Go to the documentation of this file.
1//===-- AArch64WinCOFFStreamer.cpp - ARM Target WinCOFF Streamer ----*- 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
11#include "llvm/MC/MCAssembler.h"
14#include "llvm/MC/MCWin64EH.h"
16
17using namespace llvm;
18
19namespace {
20
21class AArch64WinCOFFStreamer : public MCWinCOFFStreamer {
23
24public:
25 AArch64WinCOFFStreamer(MCContext &C, std::unique_ptr<MCAsmBackend> AB,
26 std::unique_ptr<MCCodeEmitter> CE,
27 std::unique_ptr<MCObjectWriter> OW)
28 : MCWinCOFFStreamer(C, std::move(AB), std::move(CE), std::move(OW)) {}
29
30 void emitWinEHHandlerData(SMLoc Loc) override;
31 void emitWindowsUnwindTables() override;
32 void emitWindowsUnwindTables(WinEH::FrameInfo *Frame) override;
33 void finishImpl() override;
34};
35
36void AArch64WinCOFFStreamer::emitWinEHHandlerData(SMLoc Loc) {
38
39 // We have to emit the unwind info now, because this directive
40 // actually switches to the .xdata section!
41 EHStreamer.EmitUnwindInfo(*this, getCurrentWinFrameInfo(),
42 /* HandlerData = */ true);
43}
44
45void AArch64WinCOFFStreamer::emitWindowsUnwindTables(WinEH::FrameInfo *Frame) {
46 EHStreamer.EmitUnwindInfo(*this, Frame, /* HandlerData = */ false);
47}
48
49void AArch64WinCOFFStreamer::emitWindowsUnwindTables() {
50 if (!getNumWinFrameInfos())
51 return;
52 EHStreamer.Emit(*this);
53}
54
55void AArch64WinCOFFStreamer::finishImpl() {
56 emitFrames(nullptr);
57 emitWindowsUnwindTables();
58
60}
61} // end anonymous namespace
62
63// Helper function to common out unwind code setup for those codes that can
64// belong to both prolog and epilog.
65// There are three types of Windows ARM64 SEH codes. They can
66// 1) take no operands: SEH_Nop, SEH_PrologEnd, SEH_EpilogStart, SEH_EpilogEnd
67// 2) take an offset: SEH_StackAlloc, SEH_SaveFPLR, SEH_SaveFPLR_X
68// 3) take a register and an offset/size: all others
69void AArch64TargetWinCOFFStreamer::emitARM64WinUnwindCode(unsigned UnwindCode,
70 int Reg, int Offset) {
71 auto &S = getStreamer();
72 WinEH::FrameInfo *CurFrame = S.EnsureValidWinFrameInfo(SMLoc());
73 if (!CurFrame)
74 return;
75 auto Inst = WinEH::Instruction(UnwindCode, /*Label=*/nullptr, Reg, Offset);
76 if (InEpilogCFI)
77 CurFrame->EpilogMap[CurrentEpilog].Instructions.push_back(Inst);
78 else
79 CurFrame->Instructions.push_back(Inst);
80}
81
83 unsigned Op = Win64EH::UOP_AllocSmall;
84 if (Size >= 16384)
86 else if (Size >= 512)
88 emitARM64WinUnwindCode(Op, -1, Size);
89}
90
92 emitARM64WinUnwindCode(Win64EH::UOP_SaveR19R20X, -1, Offset);
93}
94
96 emitARM64WinUnwindCode(Win64EH::UOP_SaveFPLR, -1, Offset);
97}
98
100 emitARM64WinUnwindCode(Win64EH::UOP_SaveFPLRX, -1, Offset);
101}
102
104 int Offset) {
105 assert(Offset >= 0 && Offset <= 504 &&
106 "Offset for save reg should be >= 0 && <= 504");
107 emitARM64WinUnwindCode(Win64EH::UOP_SaveReg, Reg, Offset);
108}
109
111 int Offset) {
112 emitARM64WinUnwindCode(Win64EH::UOP_SaveRegX, Reg, Offset);
113}
114
116 int Offset) {
117 emitARM64WinUnwindCode(Win64EH::UOP_SaveRegP, Reg, Offset);
118}
119
121 int Offset) {
122 emitARM64WinUnwindCode(Win64EH::UOP_SaveRegPX, Reg, Offset);
123}
124
126 int Offset) {
127 emitARM64WinUnwindCode(Win64EH::UOP_SaveLRPair, Reg, Offset);
128}
129
131 int Offset) {
132 assert(Offset >= 0 && Offset <= 504 &&
133 "Offset for save reg should be >= 0 && <= 504");
134 emitARM64WinUnwindCode(Win64EH::UOP_SaveFReg, Reg, Offset);
135}
136
138 int Offset) {
139 emitARM64WinUnwindCode(Win64EH::UOP_SaveFRegX, Reg, Offset);
140}
141
143 int Offset) {
144 emitARM64WinUnwindCode(Win64EH::UOP_SaveFRegP, Reg, Offset);
145}
146
148 int Offset) {
149 emitARM64WinUnwindCode(Win64EH::UOP_SaveFRegPX, Reg, Offset);
150}
151
153 emitARM64WinUnwindCode(Win64EH::UOP_SetFP, -1, 0);
154}
155
157 assert(Offset <= 2040 && "UOP_AddFP must have offset <= 2040");
158 emitARM64WinUnwindCode(Win64EH::UOP_AddFP, -1, Offset);
159}
160
162 emitARM64WinUnwindCode(Win64EH::UOP_Nop, -1, 0);
163}
164
166 emitARM64WinUnwindCode(Win64EH::UOP_SaveNext, -1, 0);
167}
168
169// The functions below handle opcodes that can end up in either a prolog or
170// an epilog, but not both.
172 auto &S = getStreamer();
173 WinEH::FrameInfo *CurFrame = S.EnsureValidWinFrameInfo(SMLoc());
174 if (!CurFrame)
175 return;
176
177 MCSymbol *Label = S.emitCFILabel();
178 CurFrame->PrologEnd = Label;
179 WinEH::Instruction Inst =
180 WinEH::Instruction(Win64EH::UOP_End, /*Label=*/nullptr, -1, 0);
181 auto it = CurFrame->Instructions.begin();
182 CurFrame->Instructions.insert(it, Inst);
183}
184
186 auto &S = getStreamer();
187 WinEH::FrameInfo *CurFrame = S.EnsureValidWinFrameInfo(SMLoc());
188 if (!CurFrame)
189 return;
190
191 InEpilogCFI = true;
192 CurrentEpilog = S.emitCFILabel();
193}
194
196 auto &S = getStreamer();
197 WinEH::FrameInfo *CurFrame = S.EnsureValidWinFrameInfo(SMLoc());
198 if (!CurFrame)
199 return;
200
201 InEpilogCFI = false;
202 WinEH::Instruction Inst =
203 WinEH::Instruction(Win64EH::UOP_End, /*Label=*/nullptr, -1, 0);
204 CurFrame->EpilogMap[CurrentEpilog].Instructions.push_back(Inst);
205 MCSymbol *Label = S.emitCFILabel();
206 CurFrame->EpilogMap[CurrentEpilog].End = Label;
207 CurrentEpilog = nullptr;
208}
209
211 emitARM64WinUnwindCode(Win64EH::UOP_TrapFrame, -1, 0);
212}
213
215 emitARM64WinUnwindCode(Win64EH::UOP_PushMachFrame, -1, 0);
216}
217
219 emitARM64WinUnwindCode(Win64EH::UOP_Context, -1, 0);
220}
221
223 emitARM64WinUnwindCode(Win64EH::UOP_ECContext, -1, 0);
224}
225
227 emitARM64WinUnwindCode(Win64EH::UOP_ClearUnwoundToCall, -1, 0);
228}
229
231 emitARM64WinUnwindCode(Win64EH::UOP_PACSignLR, -1, 0);
232}
233
235 int Offset) {
236 emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegI, Reg, Offset);
237}
238
240 int Offset) {
241 emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegIP, Reg, Offset);
242}
243
245 int Offset) {
246 emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegD, Reg, Offset);
247}
248
250 int Offset) {
251 emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegDP, Reg, Offset);
252}
253
255 int Offset) {
256 emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegQ, Reg, Offset);
257}
258
260 int Offset) {
261 emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegQP, Reg, Offset);
262}
263
265 int Offset) {
266 emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegIX, Reg, Offset);
267}
268
270 int Offset) {
271 emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegIPX, Reg, Offset);
272}
273
275 int Offset) {
276 emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegDX, Reg, Offset);
277}
278
280 int Offset) {
281 emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegDPX, Reg, Offset);
282}
283
285 int Offset) {
286 emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegQX, Reg, Offset);
287}
288
290 int Offset) {
291 emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegQPX, Reg, Offset);
292}
293
295 MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
296 std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter,
297 bool RelaxAll, bool IncrementalLinkerCompatible) {
298 auto *S = new AArch64WinCOFFStreamer(Context, std::move(MAB),
299 std::move(Emitter), std::move(OW));
300 S->getAssembler().setIncrementalLinkerCompatible(IncrementalLinkerCompatible);
301 return S;
302}
dxil DXContainer Global Emitter
uint64_t Size
LLVMContext & Context
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void emitARM64WinCFISaveAnyRegQX(unsigned Reg, int Offset) override
void emitARM64WinCFISaveAnyRegDX(unsigned Reg, int Offset) override
void emitARM64WinCFISaveAnyRegIP(unsigned Reg, int Offset) override
void emitARM64WinCFISaveAnyRegQ(unsigned Reg, int Offset) override
void emitARM64WinCFISaveFRegP(unsigned Reg, int Offset) override
void emitARM64WinCFISaveFRegPX(unsigned Reg, int Offset) override
void emitARM64WinCFISaveRegP(unsigned Reg, int Offset) override
void emitARM64WinCFISaveR19R20X(int Offset) override
void emitARM64WinCFISaveRegPX(unsigned Reg, int Offset) override
void emitARM64WinCFISaveRegX(unsigned Reg, int Offset) override
void emitARM64WinCFISaveAnyRegQPX(unsigned Reg, int Offset) override
void emitARM64WinCFISaveAnyRegIPX(unsigned Reg, int Offset) override
void emitARM64WinCFISaveFPLR(int Offset) override
void emitARM64WinCFISaveFRegX(unsigned Reg, int Offset) override
void emitARM64WinCFISaveAnyRegDPX(unsigned Reg, int Offset) override
void emitARM64WinCFIAllocStack(unsigned Size) override
void emitARM64WinCFISaveAnyRegD(unsigned Reg, int Offset) override
void emitARM64WinCFISaveAnyRegI(unsigned Reg, int Offset) override
void emitARM64WinCFISaveFReg(unsigned Reg, int Offset) override
void emitARM64WinCFISaveAnyRegIX(unsigned Reg, int Offset) override
void emitARM64WinCFISaveFPLRX(int Offset) override
void emitARM64WinCFISaveReg(unsigned Reg, int Offset) override
void emitARM64WinCFIAddFP(unsigned Size) override
void emitARM64WinCFISaveAnyRegDP(unsigned Reg, int Offset) override
void emitARM64WinCFISaveLRPair(unsigned Reg, int Offset) override
void emitARM64WinCFISaveAnyRegQP(unsigned Reg, int Offset) override
This class represents an Operation in the Expression.
Emits exception handling directives.
Definition: EHStreamer.h:30
Context object for machine code objects.
Definition: MCContext.h:81
virtual void emitWindowsUnwindTables()
virtual void emitWinEHHandlerData(SMLoc Loc=SMLoc())
Definition: MCStreamer.cpp:808
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:40
MCStreamer & getStreamer()
Definition: MCStreamer.h:101
void finishImpl() override
Streamer specific finalization.
void emitWinEHHandlerData(SMLoc Loc) override
Represents a location in source code.
Definition: SMLoc.h:23
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
@ UOP_SaveFRegP
Definition: Win64EH.h:54
@ UOP_SaveFReg
Definition: Win64EH.h:52
@ UOP_SaveAnyRegDPX
Definition: Win64EH.h:75
@ UOP_SaveFRegPX
Definition: Win64EH.h:55
@ UOP_SaveFPLRX
Definition: Win64EH.h:45
@ UOP_ClearUnwoundToCall
Definition: Win64EH.h:64
@ UOP_SaveAnyRegDX
Definition: Win64EH.h:74
@ UOP_SaveAnyRegQP
Definition: Win64EH.h:71
@ UOP_SaveAnyRegD
Definition: Win64EH.h:68
@ UOP_SaveFPLR
Definition: Win64EH.h:46
@ UOP_SaveAnyRegIPX
Definition: Win64EH.h:73
@ UOP_SaveRegX
Definition: Win64EH.h:48
@ UOP_SaveAnyRegQX
Definition: Win64EH.h:76
@ UOP_AllocLarge
Definition: Win64EH.h:31
@ UOP_SaveLRPair
Definition: Win64EH.h:51
@ UOP_SaveAnyRegIX
Definition: Win64EH.h:72
@ UOP_AllocSmall
Definition: Win64EH.h:32
@ UOP_SaveRegP
Definition: Win64EH.h:49
@ UOP_SaveRegPX
Definition: Win64EH.h:50
@ UOP_SaveAnyRegQ
Definition: Win64EH.h:70
@ UOP_SaveNext
Definition: Win64EH.h:60
@ UOP_SaveAnyRegDP
Definition: Win64EH.h:69
@ UOP_PushMachFrame
Definition: Win64EH.h:40
@ UOP_SaveR19R20X
Definition: Win64EH.h:44
@ UOP_SaveAnyRegQPX
Definition: Win64EH.h:77
@ UOP_PACSignLR
Definition: Win64EH.h:65
@ UOP_ECContext
Definition: Win64EH.h:63
@ UOP_AllocMedium
Definition: Win64EH.h:43
@ UOP_SaveAnyRegIP
Definition: Win64EH.h:67
@ UOP_TrapFrame
Definition: Win64EH.h:61
@ UOP_SaveFRegX
Definition: Win64EH.h:53
@ UOP_SaveAnyRegI
Definition: Win64EH.h:66
@ CE
Windows NT (Windows on ARM)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:456
MCWinCOFFStreamer * createAArch64WinCOFFStreamer(MCContext &Context, std::unique_ptr< MCAsmBackend > TAB, std::unique_ptr< MCObjectWriter > OW, std::unique_ptr< MCCodeEmitter > Emitter, bool RelaxAll, bool IncrementalLinkerCompatible)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1849
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
std::vector< Instruction > Instructions
Definition: MCWinEH.h:58
const MCSymbol * PrologEnd
Definition: MCWinEH.h:45
MapVector< MCSymbol *, Epilog > EpilogMap
Definition: MCWinEH.h:64