LLVM 20.0.0git
ELF_loongarch.cpp
Go to the documentation of this file.
1//===--- ELF_loongarch.cpp - JIT linker implementation for ELF/loongarch --===//
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// ELF/loongarch jit-link implementation.
10//
11//===----------------------------------------------------------------------===//
12
18#include "llvm/Object/ELF.h"
20
21#include "EHFrameSupportImpl.h"
22#include "ELFLinkGraphBuilder.h"
23#include "JITLinkGeneric.h"
24
25#define DEBUG_TYPE "jitlink"
26
27using namespace llvm;
28using namespace llvm::jitlink;
29using namespace llvm::jitlink::loongarch;
30
31namespace {
32
33class ELFJITLinker_loongarch : public JITLinker<ELFJITLinker_loongarch> {
34 friend class JITLinker<ELFJITLinker_loongarch>;
35
36public:
37 ELFJITLinker_loongarch(std::unique_ptr<JITLinkContext> Ctx,
38 std::unique_ptr<LinkGraph> G,
39 PassConfiguration PassConfig)
40 : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
41
42private:
43 Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
44 return loongarch::applyFixup(G, B, E);
45 }
46};
47
48template <typename ELFT>
49class ELFLinkGraphBuilder_loongarch : public ELFLinkGraphBuilder<ELFT> {
50private:
52 getRelocationKind(const uint32_t Type) {
53 using namespace loongarch;
54 switch (Type) {
55 case ELF::R_LARCH_64:
56 return Pointer64;
57 case ELF::R_LARCH_32:
58 return Pointer32;
59 case ELF::R_LARCH_32_PCREL:
60 return Delta32;
61 case ELF::R_LARCH_B16:
62 return Branch16PCRel;
63 case ELF::R_LARCH_B21:
64 return Branch21PCRel;
65 case ELF::R_LARCH_B26:
66 return Branch26PCRel;
67 case ELF::R_LARCH_PCALA_HI20:
68 return Page20;
69 case ELF::R_LARCH_PCALA_LO12:
70 return PageOffset12;
71 case ELF::R_LARCH_GOT_PC_HI20:
73 case ELF::R_LARCH_GOT_PC_LO12:
75 case ELF::R_LARCH_CALL36:
76 return Call36PCRel;
77 }
78
79 return make_error<JITLinkError>(
80 "Unsupported loongarch relocation:" + formatv("{0:d}: ", Type) +
82 }
83
84 Error addRelocations() override {
85 LLVM_DEBUG(dbgs() << "Processing relocations:\n");
86
88 using Self = ELFLinkGraphBuilder_loongarch<ELFT>;
89 for (const auto &RelSect : Base::Sections)
90 if (Error Err = Base::forEachRelaRelocation(RelSect, this,
91 &Self::addSingleRelocation))
92 return Err;
93
94 return Error::success();
95 }
96
97 Error addSingleRelocation(const typename ELFT::Rela &Rel,
98 const typename ELFT::Shdr &FixupSect,
99 Block &BlockToFix) {
101
102 uint32_t SymbolIndex = Rel.getSymbol(false);
103 auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
104 if (!ObjSymbol)
105 return ObjSymbol.takeError();
106
107 Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
108 if (!GraphSymbol)
109 return make_error<StringError>(
110 formatv("Could not find symbol at given index, did you add it to "
111 "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
112 SymbolIndex, (*ObjSymbol)->st_shndx,
113 Base::GraphSymbols.size()),
115
116 uint32_t Type = Rel.getType(false);
117 Expected<loongarch::EdgeKind_loongarch> Kind = getRelocationKind(Type);
118 if (!Kind)
119 return Kind.takeError();
120
121 int64_t Addend = Rel.r_addend;
122 auto FixupAddress = orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset;
123 Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
124 Edge GE(*Kind, Offset, *GraphSymbol, Addend);
125 LLVM_DEBUG({
126 dbgs() << " ";
127 printEdge(dbgs(), BlockToFix, GE, loongarch::getEdgeKindName(*Kind));
128 dbgs() << "\n";
129 });
130
131 BlockToFix.addEdge(std::move(GE));
132
133 return Error::success();
134 }
135
136public:
137 ELFLinkGraphBuilder_loongarch(StringRef FileName,
138 const object::ELFFile<ELFT> &Obj,
139 std::shared_ptr<orc::SymbolStringPool> SSP,
140 Triple TT, SubtargetFeatures Features)
141 : ELFLinkGraphBuilder<ELFT>(Obj, std::move(SSP), std::move(TT),
142 std::move(Features), FileName,
144};
145
146Error buildTables_ELF_loongarch(LinkGraph &G) {
147 LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
148
149 GOTTableManager GOT;
150 PLTTableManager PLT(GOT);
151 visitExistingEdges(G, GOT, PLT);
152 return Error::success();
153}
154
155} // namespace
156
157namespace llvm {
158namespace jitlink {
159
161 MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP) {
162 LLVM_DEBUG({
163 dbgs() << "Building jitlink graph for new input "
164 << ObjectBuffer.getBufferIdentifier() << "...\n";
165 });
166
167 auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer);
168 if (!ELFObj)
169 return ELFObj.takeError();
170
171 auto Features = (*ELFObj)->getFeatures();
172 if (!Features)
173 return Features.takeError();
174
175 if ((*ELFObj)->getArch() == Triple::loongarch64) {
176 auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64LE>>(**ELFObj);
177 return ELFLinkGraphBuilder_loongarch<object::ELF64LE>(
178 (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
179 std::move(SSP), (*ELFObj)->makeTriple(), std::move(*Features))
180 .buildGraph();
181 }
182
183 assert((*ELFObj)->getArch() == Triple::loongarch32 &&
184 "Invalid triple for LoongArch ELF object file");
185 auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF32LE>>(**ELFObj);
186 return ELFLinkGraphBuilder_loongarch<object::ELF32LE>(
187 (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), std::move(SSP),
188 (*ELFObj)->makeTriple(), std::move(*Features))
189 .buildGraph();
190}
191
192void link_ELF_loongarch(std::unique_ptr<LinkGraph> G,
193 std::unique_ptr<JITLinkContext> Ctx) {
195 const Triple &TT = G->getTargetTriple();
196 if (Ctx->shouldAddDefaultTargetPasses(TT)) {
197 // Add eh-frame passes.
198 Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame"));
199 Config.PrePrunePasses.push_back(
200 EHFrameEdgeFixer(".eh_frame", G->getPointerSize(), Pointer32, Pointer64,
202 Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame"));
203
204 // Add a mark-live pass.
205 if (auto MarkLive = Ctx->getMarkLivePass(TT))
206 Config.PrePrunePasses.push_back(std::move(MarkLive));
207 else
208 Config.PrePrunePasses.push_back(markAllSymbolsLive);
209
210 // Add an in-place GOT/PLTStubs build pass.
211 Config.PostPrunePasses.push_back(buildTables_ELF_loongarch);
212 }
213
214 if (auto Err = Ctx->modifyPassConfig(*G, Config))
215 return Ctx->notifyFailed(std::move(Err));
216
217 ELFJITLinker_loongarch::link(std::move(Ctx), std::move(G), std::move(Config));
218}
219
220} // namespace jitlink
221} // namespace llvm
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_DEBUG(...)
Definition: Debug.h:106
RelaxConfig Config
Definition: ELF_riscv.cpp:506
#define G(x, y, z)
Definition: MD5.cpp:56
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
Tagged union holding either a T or a Error.
Definition: Error.h:481
StringRef getBufferIdentifier() const
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
Manages the enabling and disabling of subtarget specific features.
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
@ loongarch32
Definition: Triple.h:61
@ loongarch64
Definition: Triple.h:62
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
static Expected< std::unique_ptr< ObjectFile > > createELFObjectFile(MemoryBufferRef Object, bool InitContent=true)
Represents an address in the executor process.
@ EM_LOONGARCH
Definition: ELF.h:325
StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type)
Definition: ELF.cpp:24
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:98
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163