106f32e7eSjoerg //===-- PPCXCOFFObjectWriter.cpp - PowerPC XCOFF Writer -------------------===//
206f32e7eSjoerg //
306f32e7eSjoerg //
406f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
506f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
606f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
706f32e7eSjoerg //
806f32e7eSjoerg //===----------------------------------------------------------------------===//
906f32e7eSjoerg
10*da58b97aSjoerg #include "MCTargetDesc/PPCFixupKinds.h"
11*da58b97aSjoerg #include "MCTargetDesc/PPCMCTargetDesc.h"
12*da58b97aSjoerg #include "llvm/BinaryFormat/XCOFF.h"
13*da58b97aSjoerg #include "llvm/MC/MCFixup.h"
14*da58b97aSjoerg #include "llvm/MC/MCFixupKindInfo.h"
15*da58b97aSjoerg #include "llvm/MC/MCValue.h"
1606f32e7eSjoerg #include "llvm/MC/MCXCOFFObjectWriter.h"
1706f32e7eSjoerg
1806f32e7eSjoerg using namespace llvm;
1906f32e7eSjoerg
2006f32e7eSjoerg namespace {
2106f32e7eSjoerg class PPCXCOFFObjectWriter : public MCXCOFFObjectTargetWriter {
22*da58b97aSjoerg static constexpr uint8_t SignBitMask = 0x80;
2306f32e7eSjoerg
2406f32e7eSjoerg public:
2506f32e7eSjoerg PPCXCOFFObjectWriter(bool Is64Bit);
26*da58b97aSjoerg
27*da58b97aSjoerg std::pair<uint8_t, uint8_t>
28*da58b97aSjoerg getRelocTypeAndSignSize(const MCValue &Target, const MCFixup &Fixup,
29*da58b97aSjoerg bool IsPCRel) const override;
3006f32e7eSjoerg };
3106f32e7eSjoerg } // end anonymous namespace
3206f32e7eSjoerg
PPCXCOFFObjectWriter(bool Is64Bit)3306f32e7eSjoerg PPCXCOFFObjectWriter::PPCXCOFFObjectWriter(bool Is64Bit)
3406f32e7eSjoerg : MCXCOFFObjectTargetWriter(Is64Bit) {}
3506f32e7eSjoerg
3606f32e7eSjoerg std::unique_ptr<MCObjectTargetWriter>
createPPCXCOFFObjectWriter(bool Is64Bit)3706f32e7eSjoerg llvm::createPPCXCOFFObjectWriter(bool Is64Bit) {
3806f32e7eSjoerg return std::make_unique<PPCXCOFFObjectWriter>(Is64Bit);
3906f32e7eSjoerg }
40*da58b97aSjoerg
getRelocTypeAndSignSize(const MCValue & Target,const MCFixup & Fixup,bool IsPCRel) const41*da58b97aSjoerg std::pair<uint8_t, uint8_t> PPCXCOFFObjectWriter::getRelocTypeAndSignSize(
42*da58b97aSjoerg const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const {
43*da58b97aSjoerg const MCSymbolRefExpr::VariantKind Modifier =
44*da58b97aSjoerg Target.isAbsolute() ? MCSymbolRefExpr::VK_None
45*da58b97aSjoerg : Target.getSymA()->getKind();
46*da58b97aSjoerg // People from AIX OS team says AIX link editor does not care about
47*da58b97aSjoerg // the sign bit in the relocation entry "most" of the time.
48*da58b97aSjoerg // The system assembler seems to set the sign bit on relocation entry
49*da58b97aSjoerg // based on similar property of IsPCRel. So we will do the same here.
50*da58b97aSjoerg // TODO: More investigation on how assembler decides to set the sign
51*da58b97aSjoerg // bit, and we might want to match that.
52*da58b97aSjoerg const uint8_t EncodedSignednessIndicator = IsPCRel ? SignBitMask : 0u;
53*da58b97aSjoerg
54*da58b97aSjoerg // The magic number we use in SignAndSize has a strong relationship with
55*da58b97aSjoerg // the corresponding MCFixupKind. In most cases, it's the MCFixupKind
56*da58b97aSjoerg // number - 1, because SignAndSize encodes the bit length being
57*da58b97aSjoerg // relocated minus 1.
58*da58b97aSjoerg switch ((unsigned)Fixup.getKind()) {
59*da58b97aSjoerg default:
60*da58b97aSjoerg report_fatal_error("Unimplemented fixup kind.");
61*da58b97aSjoerg case PPC::fixup_ppc_half16: {
62*da58b97aSjoerg const uint8_t SignAndSizeForHalf16 = EncodedSignednessIndicator | 15;
63*da58b97aSjoerg switch (Modifier) {
64*da58b97aSjoerg default:
65*da58b97aSjoerg report_fatal_error("Unsupported modifier for half16 fixup.");
66*da58b97aSjoerg case MCSymbolRefExpr::VK_None:
67*da58b97aSjoerg return {XCOFF::RelocationType::R_TOC, SignAndSizeForHalf16};
68*da58b97aSjoerg case MCSymbolRefExpr::VK_PPC_U:
69*da58b97aSjoerg return {XCOFF::RelocationType::R_TOCU, SignAndSizeForHalf16};
70*da58b97aSjoerg case MCSymbolRefExpr::VK_PPC_L:
71*da58b97aSjoerg return {XCOFF::RelocationType::R_TOCL, SignAndSizeForHalf16};
72*da58b97aSjoerg }
73*da58b97aSjoerg } break;
74*da58b97aSjoerg case PPC::fixup_ppc_br24:
75*da58b97aSjoerg // Branches are 4 byte aligned, so the 24 bits we encode in
76*da58b97aSjoerg // the instruction actually represents a 26 bit offset.
77*da58b97aSjoerg return {XCOFF::RelocationType::R_RBR, EncodedSignednessIndicator | 25};
78*da58b97aSjoerg case PPC::fixup_ppc_br24abs:
79*da58b97aSjoerg return {XCOFF::RelocationType::R_RBA, EncodedSignednessIndicator | 25};
80*da58b97aSjoerg case FK_Data_4:
81*da58b97aSjoerg switch (Modifier) {
82*da58b97aSjoerg default:
83*da58b97aSjoerg report_fatal_error("Unsupported modifier");
84*da58b97aSjoerg case MCSymbolRefExpr::VK_PPC_AIX_TLSGD:
85*da58b97aSjoerg return {XCOFF::RelocationType::R_TLS, EncodedSignednessIndicator | 31};
86*da58b97aSjoerg case MCSymbolRefExpr::VK_PPC_AIX_TLSGDM:
87*da58b97aSjoerg return {XCOFF::RelocationType::R_TLSM, EncodedSignednessIndicator | 31};
88*da58b97aSjoerg case MCSymbolRefExpr::VK_None:
89*da58b97aSjoerg return {XCOFF::RelocationType::R_POS, EncodedSignednessIndicator | 31};
90*da58b97aSjoerg }
91*da58b97aSjoerg }
92*da58b97aSjoerg }
93