LLVM  13.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,
70  int Offset) {
71  auto &S = getStreamer();
72  WinEH::FrameInfo *CurFrame = S.EnsureValidWinFrameInfo(SMLoc());
73  if (!CurFrame)
74  return;
75  MCSymbol *Label = S.emitCFILabel();
76  auto Inst = WinEH::Instruction(UnwindCode, Label, Reg, Offset);
77  if (InEpilogCFI)
78  CurFrame->EpilogMap[CurrentEpilog].push_back(Inst);
79  else
80  CurFrame->Instructions.push_back(Inst);
81 }
82 
84  unsigned Op = Win64EH::UOP_AllocSmall;
85  if (Size >= 16384)
87  else if (Size >= 512)
89  EmitARM64WinUnwindCode(Op, -1, Size);
90 }
91 
93  EmitARM64WinUnwindCode(Win64EH::UOP_SaveR19R20X, -1, Offset);
94 }
95 
97  EmitARM64WinUnwindCode(Win64EH::UOP_SaveFPLR, -1, Offset);
98 }
99 
101  EmitARM64WinUnwindCode(Win64EH::UOP_SaveFPLRX, -1, Offset);
102 }
103 
105  int Offset) {
106  assert(Offset >= 0 && Offset <= 504 &&
107  "Offset for save reg should be >= 0 && <= 504");
108  EmitARM64WinUnwindCode(Win64EH::UOP_SaveReg, Reg, Offset);
109 }
110 
112  int Offset) {
113  EmitARM64WinUnwindCode(Win64EH::UOP_SaveRegX, Reg, Offset);
114 }
115 
117  int Offset) {
118  EmitARM64WinUnwindCode(Win64EH::UOP_SaveRegP, Reg, Offset);
119 }
120 
122  int Offset) {
123  EmitARM64WinUnwindCode(Win64EH::UOP_SaveRegPX, Reg, Offset);
124 }
125 
127  int Offset) {
128  EmitARM64WinUnwindCode(Win64EH::UOP_SaveLRPair, Reg, Offset);
129 }
130 
132  int Offset) {
133  assert(Offset >= 0 && Offset <= 504 &&
134  "Offset for save reg should be >= 0 && <= 504");
135  EmitARM64WinUnwindCode(Win64EH::UOP_SaveFReg, Reg, Offset);
136 }
137 
139  int Offset) {
140  EmitARM64WinUnwindCode(Win64EH::UOP_SaveFRegX, Reg, Offset);
141 }
142 
144  int Offset) {
145  EmitARM64WinUnwindCode(Win64EH::UOP_SaveFRegP, Reg, Offset);
146 }
147 
149  int Offset) {
150  EmitARM64WinUnwindCode(Win64EH::UOP_SaveFRegPX, Reg, Offset);
151 }
152 
154  EmitARM64WinUnwindCode(Win64EH::UOP_SetFP, -1, 0);
155 }
156 
158  assert(Offset <= 2040 && "UOP_AddFP must have offset <= 2040");
159  EmitARM64WinUnwindCode(Win64EH::UOP_AddFP, -1, Offset);
160 }
161 
163  EmitARM64WinUnwindCode(Win64EH::UOP_Nop, -1, 0);
164 }
165 
167  EmitARM64WinUnwindCode(Win64EH::UOP_SaveNext, -1, 0);
168 }
169 
170 // The functions below handle opcodes that can end up in either a prolog or
171 // an epilog, but not both.
173  auto &S = getStreamer();
174  WinEH::FrameInfo *CurFrame = S.EnsureValidWinFrameInfo(SMLoc());
175  if (!CurFrame)
176  return;
177 
178  MCSymbol *Label = S.emitCFILabel();
179  CurFrame->PrologEnd = Label;
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  MCSymbol *Label = S.emitCFILabel();
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::Check::Size
@ Size
Definition: FileCheck.h:73
llvm::MCTargetStreamer::getStreamer
MCStreamer & getStreamer()
Definition: MCStreamer.h:99
llvm::Win64EH::UOP_AllocMedium
@ UOP_AllocMedium
Definition: Win64EH.h:40
llvm::MCWinCOFFStreamer
Definition: MCWinCOFFStreamer.h:27
llvm
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
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFIEpilogStart
void EmitARM64WinCFIEpilogStart() override
Definition: AArch64WinCOFFStreamer.cpp:185
llvm::MCStreamer::EmitWinEHHandlerData
virtual void EmitWinEHHandlerData(SMLoc Loc=SMLoc())
Definition: MCStreamer.cpp:774
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFISaveRegPX
void EmitARM64WinCFISaveRegPX(unsigned Reg, int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:121
llvm::MCContext
Context object for machine code objects.
Definition: MCContext.h:71
llvm::EHStreamer
Emits exception handling directives.
Definition: EHStreamer.h:30
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFIPrologEnd
void EmitARM64WinCFIPrologEnd() override
Definition: AArch64WinCOFFStreamer.cpp:172
MCCodeEmitter.h
it
Reference model for inliner Oz decision policy Note this model is also referenced by test Transforms Inline ML tests if replacing it
Definition: README.txt:3
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::EmitARM64WinCFISetFP
void EmitARM64WinCFISetFP() override
Definition: AArch64WinCOFFStreamer.cpp:153
llvm::Win64EH::UOP_SaveNext
@ UOP_SaveNext
Definition: Win64EH.h:57
llvm::Win64EH::UOP_SaveLRPair
@ UOP_SaveLRPair
Definition: Win64EH.h:48
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFINop
void EmitARM64WinCFINop() override
Definition: AArch64WinCOFFStreamer.cpp:162
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:81
llvm::Win64EH::UOP_TrapFrame
@ UOP_TrapFrame
Definition: Win64EH.h:58
llvm::Win64EH::UOP_Nop
@ UOP_Nop
Definition: Win64EH.h:55
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFISaveFRegX
void EmitARM64WinCFISaveFRegX(unsigned Reg, int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:138
Context
LLVMContext & Context
Definition: NVVMIntrRange.cpp:66
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFIAllocStack
void EmitARM64WinCFIAllocStack(unsigned Size) override
Definition: AArch64WinCOFFStreamer.cpp:83
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFIContext
void EmitARM64WinCFIContext() override
Definition: AArch64WinCOFFStreamer.cpp:216
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::Win64EH::UOP_SaveRegX
@ UOP_SaveRegX
Definition: Win64EH.h:45
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::Win64EH::UOP_SaveReg
@ UOP_SaveReg
Definition: Win64EH.h:44
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFISaveFPLR
void EmitARM64WinCFISaveFPLR(int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:96
llvm::Win64EH::UOP_SaveFRegX
@ UOP_SaveFRegX
Definition: Win64EH.h:50
llvm::Win64EH::UOP_SetFP
@ UOP_SetFP
Definition: Win64EH.h:53
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::AArch64TargetWinCOFFStreamer::EmitARM64WinCFIClearUnwoundToCall
void EmitARM64WinCFIClearUnwoundToCall() override
Definition: AArch64WinCOFFStreamer.cpp:220
llvm::Win64EH::UOP_End
@ UOP_End
Definition: Win64EH.h:56
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFISaveFRegP
void EmitARM64WinCFISaveFRegP(unsigned Reg, int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:143
llvm::Win64EH::UOP_AllocSmall
@ UOP_AllocSmall
Definition: Win64EH.h:29
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:1540
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFISaveFRegPX
void EmitARM64WinCFISaveFRegPX(unsigned Reg, int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:148
llvm::WinEH::EncodingType::CE
@ CE
Windows NT (Windows on ARM)
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFISaveFPLRX
void EmitARM64WinCFISaveFPLRX(int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:100
llvm::Win64EH::UOP_SaveFRegPX
@ UOP_SaveFRegPX
Definition: Win64EH.h:52
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
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFISaveR19R20X
void EmitARM64WinCFISaveR19R20X(int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:92
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFIMachineFrame
void EmitARM64WinCFIMachineFrame() override
Definition: AArch64WinCOFFStreamer.cpp:212
MCObjectWriter.h
llvm::Win64EH::UOP_ClearUnwoundToCall
@ UOP_ClearUnwoundToCall
Definition: Win64EH.h:60
llvm::Win64EH::ARM64UnwindEmitter
Definition: MCWin64EH.h:60
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFIAddFP
void EmitARM64WinCFIAddFP(unsigned Size) override
Definition: AArch64WinCOFFStreamer.cpp:157
llvm::pdb::PDB_SymType::Label
@ Label
std
Definition: BitVector.h:838
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFIEpilogEnd
void EmitARM64WinCFIEpilogEnd() override
Definition: AArch64WinCOFFStreamer.cpp:195
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:314
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFISaveLRPair
void EmitARM64WinCFISaveLRPair(unsigned Reg, int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:126
llvm::Win64EH::UOP_SaveR19R20X
@ UOP_SaveR19R20X
Definition: Win64EH.h:41
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFISaveFReg
void EmitARM64WinCFISaveFReg(unsigned Reg, int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:131
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFISaveNext
void EmitARM64WinCFISaveNext() override
Definition: AArch64WinCOFFStreamer.cpp:166
llvm::WinEH::FrameInfo
Definition: MCWinEH.h:39
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFISaveRegP
void EmitARM64WinCFISaveRegP(unsigned Reg, int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:116
llvm::Win64EH::UOP_SaveRegP
@ UOP_SaveRegP
Definition: Win64EH.h:46
llvm::Win64EH::UOP_SaveFPLR
@ UOP_SaveFPLR
Definition: Win64EH.h:43
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFISaveRegX
void EmitARM64WinCFISaveRegX(unsigned Reg, int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:111
llvm::WinEH::Instruction
Definition: MCWinEH.h:21
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFITrapFrame
void EmitARM64WinCFITrapFrame() override
Definition: AArch64WinCOFFStreamer.cpp:208
AArch64WinCOFFStreamer.h
llvm::WinEH::FrameInfo::Instructions
std::vector< Instruction > Instructions
Definition: MCWinEH.h:56
llvm::AArch64TargetWinCOFFStreamer::EmitARM64WinCFISaveReg
void EmitARM64WinCFISaveReg(unsigned Reg, int Offset) override
Definition: AArch64WinCOFFStreamer.cpp:104
llvm::Win64EH::UOP_PushMachFrame
@ UOP_PushMachFrame
Definition: Win64EH.h:37
MCWin64EH.h
llvm::Win64EH::UOP_AllocLarge
@ UOP_AllocLarge
Definition: Win64EH.h:28