File: PPCXCOFFObjectWriter.cpp

package info (click to toggle)
llvm-toolchain-19 1%3A19.1.7-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,998,520 kB
  • sloc: cpp: 6,951,680; ansic: 1,486,157; asm: 913,598; python: 232,024; f90: 80,126; objc: 75,281; lisp: 37,276; pascal: 16,990; sh: 10,009; ml: 5,058; perl: 4,724; awk: 3,523; makefile: 3,167; javascript: 2,504; xml: 892; fortran: 664; cs: 573
file content (131 lines) | stat: -rw-r--r-- 5,329 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//===-- PPCXCOFFObjectWriter.cpp - PowerPC XCOFF Writer -------------------===//
//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "MCTargetDesc/PPCFixupKinds.h"
#include "MCTargetDesc/PPCMCTargetDesc.h"
#include "llvm/BinaryFormat/XCOFF.h"
#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/MCXCOFFObjectWriter.h"

using namespace llvm;

namespace {
class PPCXCOFFObjectWriter : public MCXCOFFObjectTargetWriter {
  static constexpr uint8_t SignBitMask = 0x80;

public:
  PPCXCOFFObjectWriter(bool Is64Bit);

  std::pair<uint8_t, uint8_t>
  getRelocTypeAndSignSize(const MCValue &Target, const MCFixup &Fixup,
                          bool IsPCRel) const override;
};
} // end anonymous namespace

PPCXCOFFObjectWriter::PPCXCOFFObjectWriter(bool Is64Bit)
    : MCXCOFFObjectTargetWriter(Is64Bit) {}

std::unique_ptr<MCObjectTargetWriter>
llvm::createPPCXCOFFObjectWriter(bool Is64Bit) {
  return std::make_unique<PPCXCOFFObjectWriter>(Is64Bit);
}

std::pair<uint8_t, uint8_t> PPCXCOFFObjectWriter::getRelocTypeAndSignSize(
    const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const {
  const MCSymbolRefExpr::VariantKind Modifier =
      Target.isAbsolute() ? MCSymbolRefExpr::VK_None
                          : Target.getSymA()->getKind();
  // People from AIX OS team says AIX link editor does not care about
  // the sign bit in the relocation entry "most" of the time.
  // The system assembler seems to set the sign bit on relocation entry
  // based on similar property of IsPCRel. So we will do the same here.
  // TODO: More investigation on how assembler decides to set the sign
  // bit, and we might want to match that.
  const uint8_t EncodedSignednessIndicator = IsPCRel ? SignBitMask : 0u;

  // The magic number we use in SignAndSize has a strong relationship with
  // the corresponding MCFixupKind. In most cases, it's the MCFixupKind
  // number - 1, because SignAndSize encodes the bit length being
  // relocated minus 1.
  switch ((unsigned)Fixup.getKind()) {
  default:
    report_fatal_error("Unimplemented fixup kind.");
  case PPC::fixup_ppc_half16: {
    const uint8_t SignAndSizeForHalf16 = EncodedSignednessIndicator | 15;
    switch (Modifier) {
    default:
      report_fatal_error("Unsupported modifier for half16 fixup.");
    case MCSymbolRefExpr::VK_None:
      return {XCOFF::RelocationType::R_TOC, SignAndSizeForHalf16};
    case MCSymbolRefExpr::VK_PPC_U:
      return {XCOFF::RelocationType::R_TOCU, SignAndSizeForHalf16};
    case MCSymbolRefExpr::VK_PPC_L:
      return {XCOFF::RelocationType::R_TOCL, SignAndSizeForHalf16};
    case MCSymbolRefExpr::VK_PPC_AIX_TLSLE:
      return {XCOFF::RelocationType::R_TLS_LE, SignAndSizeForHalf16};
    case MCSymbolRefExpr::VK_PPC_AIX_TLSLD:
      return {XCOFF::RelocationType::R_TLS_LD, SignAndSizeForHalf16};
    }
  } break;
  case PPC::fixup_ppc_half16ds:
  case PPC::fixup_ppc_half16dq: {
    if (IsPCRel)
      report_fatal_error("Invalid PC-relative relocation.");
    switch (Modifier) {
    default:
      llvm_unreachable("Unsupported Modifier");
    case MCSymbolRefExpr::VK_None:
      return {XCOFF::RelocationType::R_TOC, 15};
    case MCSymbolRefExpr::VK_PPC_L:
      return {XCOFF::RelocationType::R_TOCL, 15};
    case MCSymbolRefExpr::VK_PPC_AIX_TLSLE:
      return {XCOFF::RelocationType::R_TLS_LE, 15};
    case MCSymbolRefExpr::VK_PPC_AIX_TLSLD:
      return {XCOFF::RelocationType::R_TLS_LD, 15};
    }
  } break;
  case PPC::fixup_ppc_br24:
    // Branches are 4 byte aligned, so the 24 bits we encode in
    // the instruction actually represents a 26 bit offset.
    return {XCOFF::RelocationType::R_RBR, EncodedSignednessIndicator | 25};
  case PPC::fixup_ppc_br24abs:
    return {XCOFF::RelocationType::R_RBA, EncodedSignednessIndicator | 25};
  case PPC::fixup_ppc_nofixup: {
    if (Modifier == MCSymbolRefExpr::VK_None)
      return {XCOFF::RelocationType::R_REF, 0};
    else
      llvm_unreachable("Unsupported Modifier");
  } break;
  case FK_Data_4:
  case FK_Data_8:
    const uint8_t SignAndSizeForFKData =
        EncodedSignednessIndicator |
        ((unsigned)Fixup.getKind() == FK_Data_4 ? 31 : 63);
    switch (Modifier) {
    default:
      report_fatal_error("Unsupported modifier");
    case MCSymbolRefExpr::VK_PPC_AIX_TLSGD:
      return {XCOFF::RelocationType::R_TLS, SignAndSizeForFKData};
    case MCSymbolRefExpr::VK_PPC_AIX_TLSGDM:
      return {XCOFF::RelocationType::R_TLSM, SignAndSizeForFKData};
    case MCSymbolRefExpr::VK_PPC_AIX_TLSIE:
      return {XCOFF::RelocationType::R_TLS_IE, SignAndSizeForFKData};
    case MCSymbolRefExpr::VK_PPC_AIX_TLSLE:
      return {XCOFF::RelocationType::R_TLS_LE, SignAndSizeForFKData};
    case MCSymbolRefExpr::VK_PPC_AIX_TLSLD:
      return {XCOFF::RelocationType::R_TLS_LD, SignAndSizeForFKData};
    case MCSymbolRefExpr::VK_PPC_AIX_TLSML:
      return {XCOFF::RelocationType::R_TLSML, SignAndSizeForFKData};
    case MCSymbolRefExpr::VK_None:
      return {XCOFF::RelocationType::R_POS, SignAndSizeForFKData};
    }
  }
}