LLVM  14.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/MCCodeEmitter.h"
12 #include "llvm/MC/MCObjectWriter.h"
13 #include "llvm/MC/MCWin64EH.h"
15 
16 using namespace llvm;
17 
18 namespace {
19 
20 class AArch64WinCOFFStreamer : public MCWinCOFFStreamer {
22 
23 public:
24  AArch64WinCOFFStreamer(MCContext &C, std::unique_ptr<MCAsmBackend> AB,
25  std::unique_ptr<MCCodeEmitter> CE,
26  std::unique_ptr<MCObjectWriter> OW)
27  : MCWinCOFFStreamer(C, std::move(AB), std::move(CE), std::move(OW)) {}
28 
29  void EmitWinEHHandlerData(SMLoc Loc) override;
30  void EmitWindowsUnwindTables() override;
31  void EmitWindowsUnwindTables(WinEH::FrameInfo *Frame) override;
32  void finishImpl() override;
33 };
34 
35 void AArch64WinCOFFStreamer::EmitWinEHHandlerData(SMLoc Loc) {
37 
38  // We have to emit the unwind info now, because this directive
39  // actually switches to the .xdata section!
40  EHStreamer.EmitUnwindInfo(*this, getCurrentWinFrameInfo(),
41  /* HandlerData = */ true);
42 }
43 
44 void AArch64WinCOFFStreamer::EmitWindowsUnwindTables(WinEH::FrameInfo *Frame) {
45  EHStreamer.EmitUnwindInfo(*this, Frame, /* HandlerData = */ false);
46 }
47 
48 void AArch64WinCOFFStreamer::EmitWindowsUnwindTables() {
49  if (!getNumWinFrameInfos())
50  return;
51  EHStreamer.Emit(*this);
52 }
53 
54 void AArch64WinCOFFStreamer::finishImpl() {
55  emitFrames(nullptr);
56  EmitWindowsUnwindTables();
57 
59 }
60 } // end anonymous namespace
61 
62 // Helper function to common out unwind code setup for those codes that can
63 // belong to both prolog and epilog.
64 // There are three types of Windows ARM64 SEH codes. They can
65 // 1) take no operands: SEH_Nop, SEH_PrologEnd, SEH_EpilogStart, SEH_EpilogEnd
66 // 2) take an offset: SEH_StackAlloc, SEH_SaveFPLR, SEH_SaveFPLR_X
67 // 3) take a register and an offset/size: all others
68 void AArch64TargetWinCOFFStreamer::emitARM64WinUnwindCode(unsigned UnwindCode,
69  int Reg, int Offset) {
70  auto &S = getStreamer();
71  WinEH::FrameInfo *CurFrame = S.EnsureValidWinFrameInfo(SMLoc());
72  if (!CurFrame)
73  return;
74  MCSymbol *Label = S.emitCFILabel();
75  auto Inst = WinEH::Instruction(UnwindCode, Label, 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;
180  auto it = CurFrame->Instructions.begin();
181  CurFrame->Instructions.insert(it, Inst);
182 }
183 
185  auto &S = getStreamer();
186  WinEH::FrameInfo *CurFrame = S.EnsureValidWinFrameInfo(SMLoc());
187  if (!CurFrame)
188  return;
189 
190  InEpilogCFI = true;
191  CurrentEpilog = S.emitCFILabel();
192 }
193 
195  auto &S = getStreamer();
196  WinEH::FrameInfo *CurFrame = S.EnsureValidWinFrameInfo(SMLoc());
197  if (!CurFrame)
198  return;
199 
200  InEpilogCFI = false;
201  MCSymbol *Label = S.emitCFILabel();
203  CurFrame->EpilogMap[CurrentEpilog].push_back(Inst);
204  CurrentEpilog = nullptr;
205 }
206 
208  emitARM64WinUnwindCode(Win64EH::UOP_TrapFrame, -1, 0);
209 }
210 
212  emitARM64WinUnwindCode(Win64EH::UOP_PushMachFrame, -1, 0);
213 }
214 
216  emitARM64WinUnwindCode(Win64EH::UOP_Context, -1, 0);
217 }
218 
220  emitARM64WinUnwindCode(Win64EH::UOP_ClearUnwoundToCall, -1, 0);
221 }
222 
224  MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
225  std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter,
226  bool RelaxAll, bool IncrementalLinkerCompatible) {
227  auto *S = new AArch64WinCOFFStreamer(Context, std::move(MAB),
228  std::move(Emitter), std::move(OW));
229  S->getAssembler().setIncrementalLinkerCompatible(IncrementalLinkerCompatible);
230  return S;
231 }
llvm::Check::Size
@ Size
Definition: FileCheck.h:73
llvm::MCTargetStreamer::getStreamer
MCStreamer & getStreamer()
Definition: MCStreamer.h:99
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:219
llvm
This file implements support for optimizing divisions by a constant.
Definition: AllocatorList.h:23
Reg
unsigned Reg
Definition: MachineSink.cpp:1566
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:789
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFIAddFP
void emitARM64WinCFIAddFP(unsigned Size) override
Definition: AArch64WinCOFFStreamer.cpp:156
llvm::MCContext
Context object for machine code objects.
Definition: MCContext.h:72
llvm::EHStreamer
Emits exception handling directives.
Definition: EHStreamer.h:30
MCCodeEmitter.h
llvm::Win64EH::UOP_SaveFRegP
@ UOP_SaveFRegP
Definition: Win64EH.h:51
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
llvm::Win64EH::UOP_SaveNext
@ UOP_SaveNext
Definition: Win64EH.h:57
llvm::Win64EH::UOP_SaveLRPair
@ UOP_SaveLRPair
Definition: Win64EH.h:48
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:81
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:211
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFITrapFrame
void emitARM64WinCFITrapFrame() override
Definition: AArch64WinCOFFStreamer.cpp:207
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:194
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveFPLR
void emitARM64WinCFISaveFPLR(int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:95
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFIContext
void emitARM64WinCFIContext() override
Definition: AArch64WinCOFFStreamer.cpp:215
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:223
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:1609
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:184
llvm::AArch64TargetWinCOFFStreamer::emitARM64WinCFINop
void emitARM64WinCFINop() override
Definition: AArch64WinCOFFStreamer.cpp:161
llvm::MCWinCOFFStreamer::finishImpl
void finishImpl() override
Streamer specific finalization.
Definition: MCWinCOFFStreamer.cpp:364
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
llvm::pdb::PDB_SymType::Label
@ Label
std
Definition: BitVector.h:838
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:324
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