LLVM  15.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 
10 #include "llvm/MC/MCAsmBackend.h"
11 #include "llvm/MC/MCAssembler.h"
12 #include "llvm/MC/MCCodeEmitter.h"
13 #include "llvm/MC/MCObjectWriter.h"
14 #include "llvm/MC/MCWin64EH.h"
16 
17 using namespace llvm;
18 
19 namespace {
20 
21 class AArch64WinCOFFStreamer : public MCWinCOFFStreamer {
23 
24 public:
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 
36 void 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 
45 void AArch64WinCOFFStreamer::EmitWindowsUnwindTables(WinEH::FrameInfo *Frame) {
46  EHStreamer.EmitUnwindInfo(*this, Frame, /* HandlerData = */ false);
47 }
48 
49 void AArch64WinCOFFStreamer::EmitWindowsUnwindTables() {
50  if (!getNumWinFrameInfos())
51  return;
52  EHStreamer.Emit(*this);
53 }
54 
55 void 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
69 void 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].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].push_back(Inst);
205  CurrentEpilog = nullptr;
206 }
207 
209  emitARM64WinUnwindCode(Win64EH::UOP_TrapFrame, -1, 0);
210 }
211 
213  emitARM64WinUnwindCode(Win64EH::UOP_PushMachFrame, -1, 0);
214 }
215 
217  emitARM64WinUnwindCode(Win64EH::UOP_Context, -1, 0);
218 }
219 
221  emitARM64WinUnwindCode(Win64EH::UOP_ClearUnwoundToCall, -1, 0);
222 }
223 
225  MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
226  std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter,
227  bool RelaxAll, bool IncrementalLinkerCompatible) {
228  auto *S = new AArch64WinCOFFStreamer(Context, std::move(MAB),
229  std::move(Emitter), std::move(OW));
230  S->getAssembler().setIncrementalLinkerCompatible(IncrementalLinkerCompatible);
231  return S;
232 }
llvm::MCTargetStreamer::getStreamer
MCStreamer & getStreamer()
Definition: MCStreamer.h:101
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveReg
void emitARM64WinCFISaveReg(unsigned Reg, int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:103
llvm::Win64EH::UOP_AllocMedium
@ UOP_AllocMedium
Definition: Win64EH.h:40
llvm::MCWinCOFFStreamer
Definition: MCWinCOFFStreamer.h:27
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFIClearUnwoundToCall
void emitARM64WinCFIClearUnwoundToCall() override
Definition: AArch64WinCOFFStreamer.cpp:220
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::MCSymbol
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
it
into xmm2 addss xmm2 xmm1 xmm3 addss xmm3 movaps xmm0 unpcklps xmm0 ret seems silly when it could just be one addps Expand libm rounding functions main should enable SSE DAZ mode and other fast SSE modes Think about doing i64 math in SSE regs on x86 This testcase should have no SSE instructions in it
Definition: README-SSE.txt:81
llvm::MCStreamer::EmitWinEHHandlerData
virtual void EmitWinEHHandlerData(SMLoc Loc=SMLoc())
Definition: MCStreamer.cpp:793
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFIAddFP
void emitARM64WinCFIAddFP(unsigned Size) override
Definition: AArch64WinCOFFStreamer.cpp:156
llvm::MCContext
Context object for machine code objects.
Definition: MCContext.h:74
llvm::EHStreamer
Emits exception handling directives.
Definition: EHStreamer.h:30
MCCodeEmitter.h
llvm::Win64EH::UOP_SaveFRegP
@ UOP_SaveFRegP
Definition: Win64EH.h:51
llvm::X86Disassembler::Reg
Reg
All possible values of the reg field in the ModR/M byte.
Definition: X86DisassemblerDecoder.h:462
llvm::Win64EH::UOP_SaveRegPX
@ UOP_SaveRegPX
Definition: Win64EH.h:47
llvm::WinEH::FrameInfo::EpilogMap
MapVector< MCSymbol *, std::vector< Instruction > > EpilogMap
Definition: MCWinEH.h:57
llvm::X86::SecondMacroFusionInstKind::AB
@ AB
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveFRegP
void emitARM64WinCFISaveFRegP(unsigned Reg, int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:142
MCAssembler.h
llvm::Win64EH::UOP_SaveNext
@ UOP_SaveNext
Definition: Win64EH.h:57
llvm::Win64EH::UOP_SaveLRPair
@ UOP_SaveLRPair
Definition: Win64EH.h:48
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveFRegX
void emitARM64WinCFISaveFRegX(unsigned Reg, int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:137
llvm::Win64EH::UOP_TrapFrame
@ UOP_TrapFrame
Definition: Win64EH.h:58
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveRegP
void emitARM64WinCFISaveRegP(unsigned Reg, int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:115
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveRegX
void emitARM64WinCFISaveRegX(unsigned Reg, int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:110
llvm::Win64EH::UOP_Nop
@ UOP_Nop
Definition: Win64EH.h:55
Context
LLVMContext & Context
Definition: NVVMIntrRange.cpp:66
llvm::Win64EH::UOP_AddFP
@ UOP_AddFP
Definition: Win64EH.h:54
MCAsmBackend.h
llvm::SMLoc
Represents a location in source code.
Definition: SMLoc.h:23
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFIMachineFrame
void emitARM64WinCFIMachineFrame() override
Definition: AArch64WinCOFFStreamer.cpp:212
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFITrapFrame
void emitARM64WinCFITrapFrame() override
Definition: AArch64WinCOFFStreamer.cpp:208
llvm::Win64EH::UOP_SaveRegX
@ UOP_SaveRegX
Definition: Win64EH.h:45
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveR19R20X
void emitARM64WinCFISaveR19R20X(int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:91
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::Win64EH::UOP_SaveReg
@ UOP_SaveReg
Definition: Win64EH.h:44
llvm::Win64EH::UOP_SaveFRegX
@ UOP_SaveFRegX
Definition: Win64EH.h:50
llvm::Win64EH::UOP_SetFP
@ UOP_SetFP
Definition: Win64EH.h:53
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFIEpilogEnd
void emitARM64WinCFIEpilogEnd() override
Definition: AArch64WinCOFFStreamer.cpp:195
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveFPLR
void emitARM64WinCFISaveFPLR(int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:95
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFIContext
void emitARM64WinCFIContext() override
Definition: AArch64WinCOFFStreamer.cpp:216
llvm::createAArch64WinCOFFStreamer
MCWinCOFFStreamer * createAArch64WinCOFFStreamer(MCContext &Context, std::unique_ptr< MCAsmBackend > TAB, std::unique_ptr< MCObjectWriter > OW, std::unique_ptr< MCCodeEmitter > Emitter, bool RelaxAll, bool IncrementalLinkerCompatible)
Definition: AArch64WinCOFFStreamer.cpp:224
llvm::Win64EH::UOP_SaveFPLRX
@ UOP_SaveFPLRX
Definition: Win64EH.h:42
llvm::Win64EH::UOP_End
@ UOP_End
Definition: Win64EH.h:56
llvm::Win64EH::UOP_AllocSmall
@ UOP_AllocSmall
Definition: Win64EH.h:29
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFIAllocStack
void emitARM64WinCFIAllocStack(unsigned Size) override
Definition: AArch64WinCOFFStreamer.cpp:82
llvm::WinEH::FrameInfo::PrologEnd
const MCSymbol * PrologEnd
Definition: MCWinEH.h:45
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::Win64EH::UOP_Context
@ UOP_Context
Definition: Win64EH.h:59
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::Win64EH::UOP_SaveFReg
@ UOP_SaveFReg
Definition: Win64EH.h:49
llvm::move
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:1663
llvm::WinEH::EncodingType::CE
@ CE
Windows NT (Windows on ARM)
llvm::Win64EH::UOP_SaveFRegPX
@ UOP_SaveFRegPX
Definition: Win64EH.h:52
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFIEpilogStart
void emitARM64WinCFIEpilogStart() override
Definition: AArch64WinCOFFStreamer.cpp:185
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFINop
void emitARM64WinCFINop() override
Definition: AArch64WinCOFFStreamer.cpp:161
llvm::MCWinCOFFStreamer::finishImpl
void finishImpl() override
Streamer specific finalization.
Definition: MCWinCOFFStreamer.cpp:363
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
MCWinCOFFStreamer.h
MCObjectWriter.h
llvm::Win64EH::UOP_ClearUnwoundToCall
@ UOP_ClearUnwoundToCall
Definition: Win64EH.h:60
llvm::Win64EH::ARM64UnwindEmitter
Definition: MCWin64EH.h:60
std
Definition: BitVector.h:851
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:326
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveNext
void emitARM64WinCFISaveNext() override
Definition: AArch64WinCOFFStreamer.cpp:165
llvm::Win64EH::UOP_SaveR19R20X
@ UOP_SaveR19R20X
Definition: Win64EH.h:41
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveFPLRX
void emitARM64WinCFISaveFPLRX(int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:99
llvm::WinEH::FrameInfo
Definition: MCWinEH.h:39
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveRegPX
void emitARM64WinCFISaveRegPX(unsigned Reg, int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:120
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveFReg
void emitARM64WinCFISaveFReg(unsigned Reg, int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:130
llvm::Win64EH::UOP_SaveRegP
@ UOP_SaveRegP
Definition: Win64EH.h:46
llvm::Win64EH::UOP_SaveFPLR
@ UOP_SaveFPLR
Definition: Win64EH.h:43
llvm::WinEH::Instruction
Definition: MCWinEH.h:21
AArch64WinCOFFStreamer.h
llvm::WinEH::FrameInfo::Instructions
std::vector< Instruction > Instructions
Definition: MCWinEH.h:56
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveLRPair
void emitARM64WinCFISaveLRPair(unsigned Reg, int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:125
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFIPrologEnd
void emitARM64WinCFIPrologEnd() override
Definition: AArch64WinCOFFStreamer.cpp:171
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFISetFP
void emitARM64WinCFISetFP() override
Definition: AArch64WinCOFFStreamer.cpp:152
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveFRegPX
void emitARM64WinCFISaveFRegPX(unsigned Reg, int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:147
llvm::Win64EH::UOP_PushMachFrame
@ UOP_PushMachFrame
Definition: Win64EH.h:37
MCWin64EH.h
llvm::Win64EH::UOP_AllocLarge
@ UOP_AllocLarge
Definition: Win64EH.h:28