xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFObjectWriter.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
10b57cec5SDimitry Andric //= AArch64WinCOFFObjectWriter.cpp - AArch64 Windows COFF Object Writer C++ =//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===---------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
9fe6060f1SDimitry Andric #include "AArch64MCTargetDesc.h"
100b57cec5SDimitry Andric #include "MCTargetDesc/AArch64FixupKinds.h"
110b57cec5SDimitry Andric #include "MCTargetDesc/AArch64MCExpr.h"
120b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
130b57cec5SDimitry Andric #include "llvm/BinaryFormat/COFF.h"
140b57cec5SDimitry Andric #include "llvm/MC/MCAsmBackend.h"
151106035dSDimitry Andric #include "llvm/MC/MCContext.h"
160b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCFixup.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCFixupKindInfo.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCValue.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCWinCOFFObjectWriter.h"
2281ad6265SDimitry Andric #include "llvm/Support/Casting.h"
230b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
240b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
250b57cec5SDimitry Andric #include <cassert>
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric using namespace llvm;
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric namespace {
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric class AArch64WinCOFFObjectWriter : public MCWinCOFFObjectTargetWriter {
320b57cec5SDimitry Andric public:
AArch64WinCOFFObjectWriter(const Triple & TheTriple)33*bdd1243dSDimitry Andric   AArch64WinCOFFObjectWriter(const Triple &TheTriple)
34*bdd1243dSDimitry Andric       : MCWinCOFFObjectTargetWriter(TheTriple.isWindowsArm64EC()
35*bdd1243dSDimitry Andric                                         ? COFF::IMAGE_FILE_MACHINE_ARM64EC
36*bdd1243dSDimitry Andric                                         : COFF::IMAGE_FILE_MACHINE_ARM64) {}
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric   ~AArch64WinCOFFObjectWriter() override = default;
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric   unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
410b57cec5SDimitry Andric                         const MCFixup &Fixup, bool IsCrossSection,
420b57cec5SDimitry Andric                         const MCAsmBackend &MAB) const override;
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric   bool recordRelocation(const MCFixup &) const override;
450b57cec5SDimitry Andric };
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric } // end anonymous namespace
480b57cec5SDimitry Andric 
getRelocType(MCContext & Ctx,const MCValue & Target,const MCFixup & Fixup,bool IsCrossSection,const MCAsmBackend & MAB) const490b57cec5SDimitry Andric unsigned AArch64WinCOFFObjectWriter::getRelocType(
500b57cec5SDimitry Andric     MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup,
510b57cec5SDimitry Andric     bool IsCrossSection, const MCAsmBackend &MAB) const {
52fe6060f1SDimitry Andric   unsigned FixupKind = Fixup.getKind();
53fe6060f1SDimitry Andric   if (IsCrossSection) {
54fe6060f1SDimitry Andric     // IMAGE_REL_ARM64_REL64 does not exist. We treat FK_Data_8 as FK_PCRel_4 so
55fe6060f1SDimitry Andric     // that .xword a-b can lower to IMAGE_REL_ARM64_REL32. This allows generic
56fe6060f1SDimitry Andric     // instrumentation to not bother with the COFF limitation. A negative value
57fe6060f1SDimitry Andric     // needs attention.
58fe6060f1SDimitry Andric     if (FixupKind != FK_Data_4 && FixupKind != FK_Data_8) {
59fe6060f1SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "Cannot represent this expression");
60fe6060f1SDimitry Andric       return COFF::IMAGE_REL_ARM64_ADDR32;
61fe6060f1SDimitry Andric     }
62fe6060f1SDimitry Andric     FixupKind = FK_PCRel_4;
63fe6060f1SDimitry Andric   }
64fe6060f1SDimitry Andric 
650b57cec5SDimitry Andric   auto Modifier = Target.isAbsolute() ? MCSymbolRefExpr::VK_None
660b57cec5SDimitry Andric                                       : Target.getSymA()->getKind();
670b57cec5SDimitry Andric   const MCExpr *Expr = Fixup.getValue();
680b57cec5SDimitry Andric 
691106035dSDimitry Andric   if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) {
701106035dSDimitry Andric     AArch64MCExpr::VariantKind RefKind = A64E->getKind();
711106035dSDimitry Andric     switch (AArch64MCExpr::getSymbolLoc(RefKind)) {
721106035dSDimitry Andric     case AArch64MCExpr::VK_ABS:
731106035dSDimitry Andric     case AArch64MCExpr::VK_SECREL:
741106035dSDimitry Andric       // Supported
751106035dSDimitry Andric       break;
761106035dSDimitry Andric     default:
771106035dSDimitry Andric       Ctx.reportError(Fixup.getLoc(), "relocation variant " +
781106035dSDimitry Andric                                           A64E->getVariantKindName() +
791106035dSDimitry Andric                                           " unsupported on COFF targets");
801106035dSDimitry Andric       return COFF::IMAGE_REL_ARM64_ABSOLUTE; // Dummy return value
811106035dSDimitry Andric     }
821106035dSDimitry Andric   }
831106035dSDimitry Andric 
84fe6060f1SDimitry Andric   switch (FixupKind) {
850b57cec5SDimitry Andric   default: {
861106035dSDimitry Andric     if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) {
871106035dSDimitry Andric       Ctx.reportError(Fixup.getLoc(), "relocation type " +
881106035dSDimitry Andric                                           A64E->getVariantKindName() +
891106035dSDimitry Andric                                           " unsupported on COFF targets");
901106035dSDimitry Andric     } else {
910b57cec5SDimitry Andric       const MCFixupKindInfo &Info = MAB.getFixupKindInfo(Fixup.getKind());
921106035dSDimitry Andric       Ctx.reportError(Fixup.getLoc(), Twine("relocation type ") + Info.Name +
931106035dSDimitry Andric                                           " unsupported on COFF targets");
941106035dSDimitry Andric     }
951106035dSDimitry Andric     return COFF::IMAGE_REL_ARM64_ABSOLUTE; // Dummy return value
960b57cec5SDimitry Andric   }
970b57cec5SDimitry Andric 
98fe6060f1SDimitry Andric   case FK_PCRel_4:
99fe6060f1SDimitry Andric     return COFF::IMAGE_REL_ARM64_REL32;
100fe6060f1SDimitry Andric 
1010b57cec5SDimitry Andric   case FK_Data_4:
1020b57cec5SDimitry Andric     switch (Modifier) {
1030b57cec5SDimitry Andric     default:
1040b57cec5SDimitry Andric       return COFF::IMAGE_REL_ARM64_ADDR32;
1050b57cec5SDimitry Andric     case MCSymbolRefExpr::VK_COFF_IMGREL32:
1060b57cec5SDimitry Andric       return COFF::IMAGE_REL_ARM64_ADDR32NB;
1070b57cec5SDimitry Andric     case MCSymbolRefExpr::VK_SECREL:
1080b57cec5SDimitry Andric       return COFF::IMAGE_REL_ARM64_SECREL;
1090b57cec5SDimitry Andric     }
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   case FK_Data_8:
1120b57cec5SDimitry Andric     return COFF::IMAGE_REL_ARM64_ADDR64;
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   case FK_SecRel_2:
1150b57cec5SDimitry Andric     return COFF::IMAGE_REL_ARM64_SECTION;
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   case FK_SecRel_4:
1180b57cec5SDimitry Andric     return COFF::IMAGE_REL_ARM64_SECREL;
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   case AArch64::fixup_aarch64_add_imm12:
1210b57cec5SDimitry Andric     if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) {
1220b57cec5SDimitry Andric       AArch64MCExpr::VariantKind RefKind = A64E->getKind();
1230b57cec5SDimitry Andric       if (RefKind == AArch64MCExpr::VK_SECREL_LO12)
1240b57cec5SDimitry Andric         return COFF::IMAGE_REL_ARM64_SECREL_LOW12A;
1250b57cec5SDimitry Andric       if (RefKind == AArch64MCExpr::VK_SECREL_HI12)
1260b57cec5SDimitry Andric         return COFF::IMAGE_REL_ARM64_SECREL_HIGH12A;
1270b57cec5SDimitry Andric     }
1280b57cec5SDimitry Andric     return COFF::IMAGE_REL_ARM64_PAGEOFFSET_12A;
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   case AArch64::fixup_aarch64_ldst_imm12_scale1:
1310b57cec5SDimitry Andric   case AArch64::fixup_aarch64_ldst_imm12_scale2:
1320b57cec5SDimitry Andric   case AArch64::fixup_aarch64_ldst_imm12_scale4:
1330b57cec5SDimitry Andric   case AArch64::fixup_aarch64_ldst_imm12_scale8:
1340b57cec5SDimitry Andric   case AArch64::fixup_aarch64_ldst_imm12_scale16:
1350b57cec5SDimitry Andric     if (const AArch64MCExpr *A64E = dyn_cast<AArch64MCExpr>(Expr)) {
1360b57cec5SDimitry Andric       AArch64MCExpr::VariantKind RefKind = A64E->getKind();
1370b57cec5SDimitry Andric       if (RefKind == AArch64MCExpr::VK_SECREL_LO12)
1380b57cec5SDimitry Andric         return COFF::IMAGE_REL_ARM64_SECREL_LOW12L;
1390b57cec5SDimitry Andric     }
1400b57cec5SDimitry Andric     return COFF::IMAGE_REL_ARM64_PAGEOFFSET_12L;
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric   case AArch64::fixup_aarch64_pcrel_adr_imm21:
1430b57cec5SDimitry Andric     return COFF::IMAGE_REL_ARM64_REL21;
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric   case AArch64::fixup_aarch64_pcrel_adrp_imm21:
1460b57cec5SDimitry Andric     return COFF::IMAGE_REL_ARM64_PAGEBASE_REL21;
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   case AArch64::fixup_aarch64_pcrel_branch14:
1490b57cec5SDimitry Andric     return COFF::IMAGE_REL_ARM64_BRANCH14;
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   case AArch64::fixup_aarch64_pcrel_branch19:
1520b57cec5SDimitry Andric     return COFF::IMAGE_REL_ARM64_BRANCH19;
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   case AArch64::fixup_aarch64_pcrel_branch26:
1550b57cec5SDimitry Andric   case AArch64::fixup_aarch64_pcrel_call26:
1560b57cec5SDimitry Andric     return COFF::IMAGE_REL_ARM64_BRANCH26;
1570b57cec5SDimitry Andric   }
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric 
recordRelocation(const MCFixup & Fixup) const1600b57cec5SDimitry Andric bool AArch64WinCOFFObjectWriter::recordRelocation(const MCFixup &Fixup) const {
1610b57cec5SDimitry Andric   return true;
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric 
164*bdd1243dSDimitry Andric std::unique_ptr<MCObjectTargetWriter>
createAArch64WinCOFFObjectWriter(const Triple & TheTriple)165*bdd1243dSDimitry Andric llvm::createAArch64WinCOFFObjectWriter(const Triple &TheTriple) {
166*bdd1243dSDimitry Andric   return std::make_unique<AArch64WinCOFFObjectWriter>(TheTriple);
1670b57cec5SDimitry Andric }
168