brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.5 KiB · 942e1bd Raw
309 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "AArch64WinCOFFStreamer.h"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"15#include "llvm/MC/MCWinCOFFStreamer.h"16 17using namespace llvm;18 19namespace {20 21class AArch64WinCOFFStreamer : public MCWinCOFFStreamer {22  Win64EH::ARM64UnwindEmitter EHStreamer;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) {37  MCStreamer::emitWinEHHandlerData(Loc);38 39  // We have to emit the unwind info now, because this directive40  // 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();57  emitWindowsUnwindTables();58 59  MCWinCOFFStreamer::finishImpl();60}61} // end anonymous namespace62 63// Helper function to common out unwind code setup for those codes that can64// belong to both prolog and epilog.65// There are three types of Windows ARM64 SEH codes.  They can66// 1) take no operands: SEH_Nop, SEH_PrologEnd, SEH_EpilogStart, SEH_EpilogEnd67// 2) take an offset: SEH_StackAlloc, SEH_SaveFPLR, SEH_SaveFPLR_X68// 3) take a register and an offset/size: all others69void 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 (S.isInEpilogCFI())77    S.getCurrentWinEpilog()->Instructions.push_back(Inst);78  else79    CurFrame->Instructions.push_back(Inst);80}81 82void AArch64TargetWinCOFFStreamer::emitARM64WinCFIAllocStack(unsigned Size) {83  unsigned Op = Win64EH::UOP_AllocSmall;84  if (Size >= 16384)85    Op = Win64EH::UOP_AllocLarge;86  else if (Size >= 512)87    Op = Win64EH::UOP_AllocMedium;88  emitARM64WinUnwindCode(Op, -1, Size);89}90 91void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveR19R20X(int Offset) {92  emitARM64WinUnwindCode(Win64EH::UOP_SaveR19R20X, -1, Offset);93}94 95void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveFPLR(int Offset) {96  emitARM64WinUnwindCode(Win64EH::UOP_SaveFPLR, -1, Offset);97}98 99void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveFPLRX(int Offset) {100  emitARM64WinUnwindCode(Win64EH::UOP_SaveFPLRX, -1, Offset);101}102 103void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveReg(unsigned Reg,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 110void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveRegX(unsigned Reg,111                                                           int Offset) {112  emitARM64WinUnwindCode(Win64EH::UOP_SaveRegX, Reg, Offset);113}114 115void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveRegP(unsigned Reg,116                                                           int Offset) {117  emitARM64WinUnwindCode(Win64EH::UOP_SaveRegP, Reg, Offset);118}119 120void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveRegPX(unsigned Reg,121                                                            int Offset) {122  emitARM64WinUnwindCode(Win64EH::UOP_SaveRegPX, Reg, Offset);123}124 125void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveLRPair(unsigned Reg,126                                                             int Offset) {127  emitARM64WinUnwindCode(Win64EH::UOP_SaveLRPair, Reg, Offset);128}129 130void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveFReg(unsigned Reg,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 137void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveFRegX(unsigned Reg,138                                                            int Offset) {139  emitARM64WinUnwindCode(Win64EH::UOP_SaveFRegX, Reg, Offset);140}141 142void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveFRegP(unsigned Reg,143                                                            int Offset) {144  emitARM64WinUnwindCode(Win64EH::UOP_SaveFRegP, Reg, Offset);145}146 147void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveFRegPX(unsigned Reg,148                                                             int Offset) {149  emitARM64WinUnwindCode(Win64EH::UOP_SaveFRegPX, Reg, Offset);150}151 152void AArch64TargetWinCOFFStreamer::emitARM64WinCFISetFP() {153  emitARM64WinUnwindCode(Win64EH::UOP_SetFP, -1, 0);154}155 156void AArch64TargetWinCOFFStreamer::emitARM64WinCFIAddFP(unsigned Offset) {157  assert(Offset <= 2040 && "UOP_AddFP must have offset <= 2040");158  emitARM64WinUnwindCode(Win64EH::UOP_AddFP, -1, Offset);159}160 161void AArch64TargetWinCOFFStreamer::emitARM64WinCFINop() {162  emitARM64WinUnwindCode(Win64EH::UOP_Nop, -1, 0);163}164 165void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveNext() {166  emitARM64WinUnwindCode(Win64EH::UOP_SaveNext, -1, 0);167}168 169// The functions below handle opcodes that can end up in either a prolog or170// an epilog, but not both.171void AArch64TargetWinCOFFStreamer::emitARM64WinCFIPrologEnd() {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 185void AArch64TargetWinCOFFStreamer::emitARM64WinCFIEpilogStart() {186  getStreamer().emitWinCFIBeginEpilogue();187}188 189void AArch64TargetWinCOFFStreamer::emitARM64WinCFIEpilogEnd() {190  auto &S = getStreamer();191  WinEH::FrameInfo *CurFrame = S.EnsureValidWinFrameInfo(SMLoc());192  if (!CurFrame)193    return;194 195  if (S.isInEpilogCFI()) {196    WinEH::Instruction Inst =197        WinEH::Instruction(Win64EH::UOP_End, /*Label=*/nullptr, -1, 0);198    S.getCurrentWinEpilog()->Instructions.push_back(Inst);199  }200  S.emitWinCFIEndEpilogue();201}202 203void AArch64TargetWinCOFFStreamer::emitARM64WinCFITrapFrame() {204  emitARM64WinUnwindCode(Win64EH::UOP_TrapFrame, -1, 0);205}206 207void AArch64TargetWinCOFFStreamer::emitARM64WinCFIMachineFrame() {208  emitARM64WinUnwindCode(Win64EH::UOP_PushMachFrame, -1, 0);209}210 211void AArch64TargetWinCOFFStreamer::emitARM64WinCFIContext() {212  emitARM64WinUnwindCode(Win64EH::UOP_Context, -1, 0);213}214 215void AArch64TargetWinCOFFStreamer::emitARM64WinCFIECContext() {216  emitARM64WinUnwindCode(Win64EH::UOP_ECContext, -1, 0);217}218 219void AArch64TargetWinCOFFStreamer::emitARM64WinCFIClearUnwoundToCall() {220  emitARM64WinUnwindCode(Win64EH::UOP_ClearUnwoundToCall, -1, 0);221}222 223void AArch64TargetWinCOFFStreamer::emitARM64WinCFIPACSignLR() {224  emitARM64WinUnwindCode(Win64EH::UOP_PACSignLR, -1, 0);225}226 227void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveAnyRegI(unsigned Reg,228                                                              int Offset) {229  emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegI, Reg, Offset);230}231 232void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveAnyRegIP(unsigned Reg,233                                                               int Offset) {234  emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegIP, Reg, Offset);235}236 237void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveAnyRegD(unsigned Reg,238                                                              int Offset) {239  emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegD, Reg, Offset);240}241 242void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveAnyRegDP(unsigned Reg,243                                                               int Offset) {244  emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegDP, Reg, Offset);245}246 247void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveAnyRegQ(unsigned Reg,248                                                              int Offset) {249  emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegQ, Reg, Offset);250}251 252void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveAnyRegQP(unsigned Reg,253                                                               int Offset) {254  emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegQP, Reg, Offset);255}256 257void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveAnyRegIX(unsigned Reg,258                                                               int Offset) {259  emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegIX, Reg, Offset);260}261 262void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveAnyRegIPX(unsigned Reg,263                                                                int Offset) {264  emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegIPX, Reg, Offset);265}266 267void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveAnyRegDX(unsigned Reg,268                                                               int Offset) {269  emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegDX, Reg, Offset);270}271 272void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveAnyRegDPX(unsigned Reg,273                                                                int Offset) {274  emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegDPX, Reg, Offset);275}276 277void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveAnyRegQX(unsigned Reg,278                                                               int Offset) {279  emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegQX, Reg, Offset);280}281 282void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveAnyRegQPX(unsigned Reg,283                                                                int Offset) {284  emitARM64WinUnwindCode(Win64EH::UOP_SaveAnyRegQPX, Reg, Offset);285}286 287void AArch64TargetWinCOFFStreamer::emitARM64WinCFIAllocZ(int Offset) {288  emitARM64WinUnwindCode(Win64EH::UOP_AllocZ, 0, Offset);289}290 291void AArch64TargetWinCOFFStreamer::emitARM64WinCFISaveZReg(unsigned Reg,292                                                           int Offset) {293  emitARM64WinUnwindCode(Win64EH::UOP_SaveZReg, Reg, Offset);294}295 296void AArch64TargetWinCOFFStreamer::emitARM64WinCFISavePReg(unsigned Reg,297                                                           int Offset) {298  emitARM64WinUnwindCode(Win64EH::UOP_SavePReg, Reg, Offset);299}300 301MCStreamer *302llvm::createAArch64WinCOFFStreamer(MCContext &Context,303                                   std::unique_ptr<MCAsmBackend> &&MAB,304                                   std::unique_ptr<MCObjectWriter> &&OW,305                                   std::unique_ptr<MCCodeEmitter> &&Emitter) {306  return new AArch64WinCOFFStreamer(Context, std::move(MAB), std::move(Emitter),307                                    std::move(OW));308}309