aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/ExecutionEngine/JITLink/XCOFF_ppc64.cpp
blob: fd6b5f61749b5be1b3271e0aadb0981b489ed693 (plain)
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
//===------- XCOFF_ppc64.cpp -JIT linker implementation for XCOFF/ppc64
//-------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// XCOFF/ppc64 jit-link implementation.
//
//===----------------------------------------------------------------------===//

#include "llvm/ExecutionEngine/JITLink/XCOFF_ppc64.h"
#include "JITLinkGeneric.h"
#include "XCOFFLinkGraphBuilder.h"
#include "llvm/ADT/bit.h"
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
#include "llvm/ExecutionEngine/JITLink/ppc64.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/XCOFFObjectFile.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include <system_error>

using namespace llvm;

#define DEBUG_TYPE "jitlink"

namespace llvm {
namespace jitlink {

Expected<std::unique_ptr<LinkGraph>> createLinkGraphFromXCOFFObject_ppc64(
    MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP) {
  LLVM_DEBUG({
    dbgs() << "Building jitlink graph for new input "
           << ObjectBuffer.getBufferIdentifier() << "...\n";
  });

  auto Obj = object::ObjectFile::createObjectFile(ObjectBuffer);
  if (!Obj)
    return Obj.takeError();
  assert((**Obj).isXCOFF() && "Expects and XCOFF Object");

  auto Features = (*Obj)->getFeatures();
  if (!Features)
    return Features.takeError();
  LLVM_DEBUG({
    dbgs() << " Features: ";
    (*Features).print(dbgs());
  });

  return XCOFFLinkGraphBuilder(cast<object::XCOFFObjectFile>(**Obj),
                               std::move(SSP), Triple("powerpc64-ibm-aix"),
                               std::move(*Features), ppc64::getEdgeKindName)
      .buildGraph();
}

class XCOFFJITLinker_ppc64 : public JITLinker<XCOFFJITLinker_ppc64> {
  using JITLinkerBase = JITLinker<XCOFFJITLinker_ppc64>;
  friend JITLinkerBase;

public:
  XCOFFJITLinker_ppc64(std::unique_ptr<JITLinkContext> Ctx,
                       std::unique_ptr<LinkGraph> G,
                       PassConfiguration PassConfig)
      : JITLinkerBase(std::move(Ctx), std::move(G), std::move(PassConfig)) {
    // FIXME: Post allocation pass define TOC base, this is temporary to support
    // building until we can build the required toc entries
    defineTOCSymbol(getGraph());
  }

  Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
    LLVM_DEBUG(dbgs() << "  Applying fixup for " << G.getName()
                      << ", address = " << B.getAddress()
                      << ", target = " << E.getTarget().getName() << ", kind = "
                      << ppc64::getEdgeKindName(E.getKind()) << "\n");
    switch (E.getKind()) {
    case ppc64::Pointer64:
      if (auto Err = ppc64::applyFixup<endianness::big>(G, B, E, TOCSymbol))
        return Err;
      break;
    default:
      return make_error<StringError>("Unsupported relocation type",
                                     std::error_code());
    }
    return Error::success();
  }

private:
  void defineTOCSymbol(LinkGraph &G) {
    for (Symbol *S : G.defined_symbols()) {
      if (S->hasName() && *S->getName() == StringRef("TOC")) {
        TOCSymbol = S;
        return;
      }
    }
    llvm_unreachable("LinkGraph does not contan an TOC Symbol");
  }

private:
  Symbol *TOCSymbol = nullptr;
};

void link_XCOFF_ppc64(std::unique_ptr<LinkGraph> G,
                      std::unique_ptr<JITLinkContext> Ctx) {
  // Ctx->notifyFailed(make_error<StringError>(
  //     "link_XCOFF_ppc64 is not implemented", std::error_code()));

  PassConfiguration Config;

  // Pass insertions

  if (auto Err = Ctx->modifyPassConfig(*G, Config))
    return Ctx->notifyFailed(std::move(Err));

  XCOFFJITLinker_ppc64::link(std::move(Ctx), std::move(G), std::move(Config));
}

} // namespace jitlink
} // namespace llvm