AArch64WinCOFFObjectWriter.cpp revision 360784
1//= AArch64WinCOFFObjectWriter.cpp - AArch64 Windows COFF Object Writer 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
9#include "MCTargetDesc/AArch64FixupKinds.h"
10#include "MCTargetDesc/AArch64MCExpr.h"
11#include "llvm/ADT/Twine.h"
12#include "llvm/BinaryFormat/COFF.h"
13#include "llvm/MC/MCAsmBackend.h"
14#include "llvm/MC/MCExpr.h"
15#include "llvm/MC/MCFixup.h"
16#include "llvm/MC/MCFixupKindInfo.h"
17#include "llvm/MC/MCObjectWriter.h"
18#include "llvm/MC/MCValue.h"
19#include "llvm/MC/MCWinCOFFObjectWriter.h"
20#include "llvm/Support/ErrorHandling.h"
21#include "llvm/Support/raw_ostream.h"
22#include <cassert>
23
24using namespace llvm;
25
26namespace {
27
28class AArch64WinCOFFObjectWriter : public MCWinCOFFObjectTargetWriter {
29public:
30  AArch64WinCOFFObjectWriter()
31      : MCWinCOFFObjectTargetWriter(COFF::IMAGE_FILE_MACHINE_ARM64) {}
32
33  ~AArch64WinCOFFObjectWriter() override = default;
34
35  unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
36                        const MCFixup &Fixup, bool IsCrossSection,
37                        const MCAsmBackend &MAB) const override;
38
39  bool recordRelocation(const MCFixup &) const override;
40};
41
42} // end anonymous namespace
43
44unsigned AArch64WinCOFFObjectWriter::getRelocType(
45    MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup,
46    bool IsCrossSection, const MCAsmBackend &MAB) const {
47  auto Modifier = Target.isAbsolute() ? MCSymbolRefExpr::VK_None
48                                      : Target.getSymA()->getKind();
49  const MCExpr *Expr = Fixup.getValue();
50
51  switch (static_cast<unsigned>(Fixup.getKind())) {
52  default: {
53    const MCFixupKindInfo &Info = MAB.getFixupKindInfo(Fixup.getKind());
54    report_fatal_error(Twine("unsupported relocation type: ") + Info.Name);
55  }
56
57  case FK_Data_4:
58    switch (Modifier) {
59    default:
60      return COFF::IMAGE_REL_ARM64_ADDR32;
61    case MCSymbolRefExpr::VK_COFF_IMGREL32:
62      return COFF::IMAGE_REL_ARM64_ADDR32NB;
63    case MCSymbolRefExpr::VK_SECREL:
64      return COFF::IMAGE_REL_ARM64_SECREL;
65    }
66
67  case FK_Data_8:
68    return COFF::IMAGE_REL_ARM64_ADDR64;
69
70  case FK_SecRel_2:
71    return COFF::IMAGE_REL_ARM64_SECTION;
72
73  case FK_SecRel_4:
74    return COFF::IMAGE_REL_ARM64_SECREL;
75
76  case AArch64::fixup_aarch64_add_imm12:
77    if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) {
78      AArch64MCExpr::VariantKind RefKind = A64E->getKind();
79      if (RefKind == AArch64MCExpr::VK_SECREL_LO12)
80        return COFF::IMAGE_REL_ARM64_SECREL_LOW12A;
81      if (RefKind == AArch64MCExpr::VK_SECREL_HI12)
82        return COFF::IMAGE_REL_ARM64_SECREL_HIGH12A;
83    }
84    return COFF::IMAGE_REL_ARM64_PAGEOFFSET_12A;
85
86  case AArch64::fixup_aarch64_ldst_imm12_scale1:
87  case AArch64::fixup_aarch64_ldst_imm12_scale2:
88  case AArch64::fixup_aarch64_ldst_imm12_scale4:
89  case AArch64::fixup_aarch64_ldst_imm12_scale8:
90  case AArch64::fixup_aarch64_ldst_imm12_scale16:
91    if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) {
92      AArch64MCExpr::VariantKind RefKind = A64E->getKind();
93      if (RefKind == AArch64MCExpr::VK_SECREL_LO12)
94        return COFF::IMAGE_REL_ARM64_SECREL_LOW12L;
95    }
96    return COFF::IMAGE_REL_ARM64_PAGEOFFSET_12L;
97
98  case AArch64::fixup_aarch64_pcrel_adr_imm21:
99    return COFF::IMAGE_REL_ARM64_REL21;
100
101  case AArch64::fixup_aarch64_pcrel_adrp_imm21:
102    return COFF::IMAGE_REL_ARM64_PAGEBASE_REL21;
103
104  case AArch64::fixup_aarch64_pcrel_branch14:
105    return COFF::IMAGE_REL_ARM64_BRANCH14;
106
107  case AArch64::fixup_aarch64_pcrel_branch19:
108    return COFF::IMAGE_REL_ARM64_BRANCH19;
109
110  case AArch64::fixup_aarch64_pcrel_branch26:
111  case AArch64::fixup_aarch64_pcrel_call26:
112    return COFF::IMAGE_REL_ARM64_BRANCH26;
113  }
114}
115
116bool AArch64WinCOFFObjectWriter::recordRelocation(const MCFixup &Fixup) const {
117  return true;
118}
119
120namespace llvm {
121
122std::unique_ptr<MCObjectTargetWriter> createAArch64WinCOFFObjectWriter() {
123  return std::make_unique<AArch64WinCOFFObjectWriter>();
124}
125
126} // end namespace llvm
127