LLVM 24.0.0git
mips.h
Go to the documentation of this file.
1//===-- mips.h - Generic JITLink MIPS edge kinds and utilities -*- C++ -*-===//
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// Generic utilities for graphs representing MIPS objects.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_EXECUTIONENGINE_JITLINK_MIPS_H
14#define LLVM_EXECUTIONENGINE_JITLINK_MIPS_H
15
18#include "llvm/Support/Endian.h"
20
21namespace llvm {
22namespace jitlink {
23namespace mips {
24
25/// MIPS fixup and table-request edge kinds.
26enum EdgeKind_mips : Edge::Kind {
27 /// Fixup <- Target + Addend, checked as an unsigned 32-bit pointer.
28 Pointer32 = Edge::FirstRelocation,
29 /// Fixup <- Target + Addend : uint64.
31 /// Pointer containing the rounded 64-KiB page of Target + Addend.
34 /// Fixup <- Target - Fixup + Addend : int32.
36 /// Fixup <- Target - Fixup + Addend : int64.
38 /// Fixup <- Fixup - Target + Addend : int32 (used by .eh_frame).
40
41 /// Fixup[15:0] <- Target + Addend : int16.
43 /// Fixup[15:0] <- (Target + Addend + 0x8000) >> 16.
45 /// Fixup[15:0] <- Target + Addend.
47 /// Fixup[15:0] <- (Target + Addend + 0x80008000) >> 32.
49 /// Fixup[15:0] <- (Target + Addend + 0x800080008000) >> 48.
51
52 /// J/JAL target. The target must be aligned and in the same 256-MiB region.
54 /// Fixup[15:0] <- (Target - Fixup + Addend) >> 2 : int16.
56 /// Fixup <- Target - Fixup + Addend : int32.
58 /// Release-6 compact branch immediate fields.
63 /// Paired PC-relative high and low halves.
66 /// _gp_disp high/low expressions. The O32 low half uses Fixup - 4 as P.
69
70 /// Fixup <- Target + Addend - _gp.
74 /// Fixup <- address of GOT entry - _gp.
78 /// Low offset complementary to a rounded 64-KiB GOT page entry.
80
81 /// Fixup <- Target + Addend - start-of-ORC-TLS-template.
86
87 /// Compound N32/N64 %neg(%gp_rel(Target + Addend)) fixups.
90
91 /// Create an exact-address GOT entry and rewrite to GOTOffset16.
93 /// Create a rounded 64-KiB page GOT entry and rewrite to GOTOffset16.
95 /// Create an exact-address GOT entry and rewrite to its high/low GP offset.
98 /// Create a two-word general/local-dynamic TLS descriptor.
101};
102
103LLVM_ABI const char *getEdgeKindName(Edge::Kind K);
104
105/// Returns true if G uses the MIPS release-6 ISA.
106LLVM_ABI bool isR6(const LinkGraph &G);
107
108/// Returns Pointer32 or Pointer64, according to G's pointer ABI.
109LLVM_ABI Edge::Kind getPointerEdgeKind(const LinkGraph &G);
110
111constexpr unsigned InstructionSize = sizeof(uint32_t);
112constexpr unsigned GOTPageBits = 16;
113constexpr uint64_t GOTPageSize = UINT64_C(1) << GOTPageBits;
116constexpr unsigned JumpRegionBits = 28;
118
119inline uint16_t getLo16(uint64_t Value) { return static_cast<uint16_t>(Value); }
120
122 return static_cast<uint16_t>((Value + GOTPageBias) >> 16);
123}
124
126 constexpr uint64_t Bias = GOTPageBias | (GOTPageBias << 16);
127 return static_cast<uint16_t>((Value + Bias) >> 32);
128}
129
131 constexpr uint64_t Bias =
132 GOTPageBias | (GOTPageBias << 16) | (GOTPageBias << 32);
133 return static_cast<uint16_t>((Value + Bias) >> 48);
134}
135
139
141 unsigned Bits;
142 unsigned Shift;
143 unsigned PCAlignment;
144};
145
146inline PCRelEncoding getPCRelEncoding(Edge::Kind Kind) {
147 switch (Kind) {
148 case PC16:
149 return {16, 2, 1};
150 case PC18S3:
151 return {18, 3, 8};
152 case PC19S2:
153 return {19, 2, 4};
154 case PC21S2:
155 return {21, 2, 1};
156 case PC26S2:
157 return {26, 2, 1};
158 default:
159 llvm_unreachable("not a MIPS immediate branch edge");
160 }
161}
162
163inline bool needsGP(Edge::Kind K) {
164 switch (K) {
165 case GPRel16:
166 case GPRel32:
167 case GPRel64:
168 case GOTOffset16:
169 case GOTOffsetHi16:
170 case GOTOffsetLo16:
171 case GPDispHi16:
172 case GPDispLo16:
173 case NegGPRelHi16:
174 case NegGPRelLo16:
175 return true;
176 default:
177 return false;
178 }
179}
180
181constexpr uint32_t InstructionImm16Mask = 0x0000ffffU;
182constexpr uint32_t InstructionImm26Mask = 0x03ffffffU;
183
185 endianness Endianness) {
187 support::endian::write32(Fixup, (Instruction & ~Mask) | (Value & Mask),
188 Endianness);
189}
190
192 endianness Endianness) {
194}
195
197 endianness Endianness) {
199}
200
201/// Apply fixup expression for edge to block content.
202/// GPSymbol and TLSBaseSymbol supply the bases for GP-relative and DTP-relative
203/// edges. They may be null when the edge does not require the respective base.
205 const Symbol *GPSymbol, const Symbol *TLSBaseSymbol) {
206 char *Fixup = B.getAlreadyMutableContent().data() + E.getOffset();
207 uint64_t P = B.getFixupAddress(E).getValue();
208 uint64_t S = E.getTarget().getAddress().getValue();
209 int64_t A = E.getAddend();
210 uint64_t TargetAddress = S + A;
211 const endianness Endianness = G.getEndianness();
212
213 auto TLSBaseAddr = [&]() -> Expected<uint64_t> {
214 if (TLSBaseSymbol)
215 return TLSBaseSymbol->getAddress().getValue();
217 "MIPS DTPREL relocation requires a TLS template");
218 };
219 auto CheckSigned = [&](int64_t V, unsigned Bits) -> Error {
220 if (!isIntN(Bits, V))
221 return makeTargetOutOfRangeError(G, B, E);
222 return Error::success();
223 };
224 auto CheckAligned = [&](int64_t V, unsigned Align) -> Error {
225 if (V & (Align - 1))
227 return Error::success();
228 };
229
230 int64_t V = static_cast<int64_t>(TargetAddress);
231 std::optional<uint64_t> GP;
232 if (needsGP(E.getKind())) {
233 assert(GPSymbol && "missing MIPS GP symbol");
234 GP = GPSymbol->getAddress().getValue();
235 }
236
237 switch (E.getKind()) {
238 case Pointer32:
239 if (TargetAddress > UINT32_MAX)
240 return makeTargetOutOfRangeError(G, B, E);
241 support::endian::write32(Fixup, static_cast<uint32_t>(TargetAddress),
242 Endianness);
243 break;
244 case Pointer64:
245 support::endian::write64(Fixup, TargetAddress, Endianness);
246 break;
247 case PagePointer32: {
248 uint64_t Page = getGOTPage(TargetAddress);
249 if (Page > UINT32_MAX)
250 return makeTargetOutOfRangeError(G, B, E);
251 support::endian::write32(Fixup, Page, Endianness);
252 break;
253 }
254 case PagePointer64:
255 support::endian::write64(Fixup, getGOTPage(TargetAddress), Endianness);
256 break;
257 case Delta32:
258 case PC32:
259 V = static_cast<int64_t>(TargetAddress - P);
260 if (auto Err = CheckSigned(V, 32))
261 return Err;
262 support::endian::write32(Fixup, V, Endianness);
263 break;
264 case Delta64:
265 support::endian::write64(Fixup, TargetAddress - P, Endianness);
266 break;
267 case NegDelta32:
268 V = static_cast<int64_t>(P - S + A);
269 if (auto Err = CheckSigned(V, 32))
270 return Err;
271 support::endian::write32(Fixup, V, Endianness);
272 break;
273 case Abs16:
274 if (auto Err = CheckSigned(V, 16))
275 return Err;
276 support::endian::write16(Fixup, V, Endianness);
277 break;
278 case Hi16:
279 writeImmediate16(Fixup, getHi16(TargetAddress), Endianness);
280 break;
281 case Lo16:
282 writeImmediate16(Fixup, getLo16(TargetAddress), Endianness);
283 break;
284 case Higher16:
285 writeImmediate16(Fixup, getHigher16(TargetAddress), Endianness);
286 break;
287 case Highest16:
288 writeImmediate16(Fixup, getHighest16(TargetAddress), Endianness);
289 break;
290 case Jump26: {
291 if (auto Err = CheckAligned(TargetAddress, InstructionSize))
292 return Err;
293 if (((P + InstructionSize) & JumpRegionMask) !=
294 (TargetAddress & JumpRegionMask))
295 return makeTargetOutOfRangeError(G, B, E);
296 writeImmediate26(Fixup, TargetAddress >> 2, Endianness);
297 break;
298 }
299 case PC16:
300 case PC18S3:
301 case PC19S2:
302 case PC21S2:
303 case PC26S2: {
304 PCRelEncoding Encoding = getPCRelEncoding(E.getKind());
305 uint64_t FixupPC = alignDown(P, Encoding.PCAlignment);
306 V = static_cast<int64_t>(TargetAddress - FixupPC);
307 if (auto Err = CheckAligned(V, 1U << Encoding.Shift))
308 return Err;
309 if (auto Err = CheckSigned(V, Encoding.Bits + Encoding.Shift))
310 return Err;
313 Fixup, Mask, static_cast<uint64_t>(V) >> Encoding.Shift, Endianness);
314 break;
315 }
316 case PCHi16:
317 V = static_cast<int64_t>(TargetAddress - P);
318 writeImmediate16(Fixup, getHi16(V), Endianness);
319 break;
320 case PCLo16:
321 writeImmediate16(Fixup, getLo16(TargetAddress - P), Endianness);
322 break;
323 case GPDispHi16:
324 V = static_cast<int64_t>(*GP + A - P);
325 writeImmediate16(Fixup, getHi16(V), Endianness);
326 break;
327 case GPDispLo16:
328 // Both halves use the address of the high instruction as P.
329 writeImmediate16(Fixup, getLo16(*GP + A - P + InstructionSize), Endianness);
330 break;
331 case GPRel16:
332 case GOTOffset16:
333 V = static_cast<int64_t>(S + A - *GP);
334 if (auto Err = CheckSigned(V, 16))
335 return Err;
336 writeImmediate16(Fixup, V, Endianness);
337 break;
338 case GPRel32:
339 V = static_cast<int64_t>(S + A - *GP);
340 if (auto Err = CheckSigned(V, 32))
341 return Err;
342 support::endian::write32(Fixup, V, Endianness);
343 break;
344 case GPRel64:
345 support::endian::write64(Fixup, TargetAddress - *GP, Endianness);
346 break;
347 case GOTOffsetHi16:
348 V = static_cast<int64_t>(S + A - *GP);
349 writeImmediate16(Fixup, getHi16(V), Endianness);
350 break;
351 case GOTOffsetLo16:
352 writeImmediate16(Fixup, getLo16(TargetAddress - *GP), Endianness);
353 break;
354 case GOTPageOffset16: {
355 uint64_t Page = getGOTPage(TargetAddress);
356 writeImmediate16(Fixup, getLo16(TargetAddress - Page), Endianness);
357 break;
358 }
359 case DTPRelHi16:
360 case DTPRelLo16:
361 case DTPRel32:
362 case DTPRel64: {
363 auto BaseOrErr = TLSBaseAddr();
364 if (!BaseOrErr)
365 return BaseOrErr.takeError();
366 V = static_cast<int64_t>(S + A - *BaseOrErr);
367 if (E.getKind() == DTPRelHi16)
368 writeImmediate16(Fixup, getHi16(V), Endianness);
369 else if (E.getKind() == DTPRelLo16)
370 writeImmediate16(Fixup, getLo16(V), Endianness);
371 else if (E.getKind() == DTPRel32) {
372 if (auto Err = CheckSigned(V, 32))
373 return Err;
374 support::endian::write32(Fixup, V, Endianness);
375 } else
376 support::endian::write64(Fixup, V, Endianness);
377 break;
378 }
379 case NegGPRelHi16:
380 case NegGPRelLo16:
381 V = static_cast<int64_t>(*GP - S - A);
382 if (E.getKind() == NegGPRelHi16)
383 writeImmediate16(Fixup, getHi16(V), Endianness);
384 else
385 writeImmediate16(Fixup, getLo16(V), Endianness);
386 break;
387 default:
389 "In graph " + G.getName() + ", section " + B.getSection().getName() +
390 ": unsupported MIPS edge kind " + G.getEdgeKindName(E.getKind()));
391 }
392 return Error::success();
393}
394
395/// Returns zero-filled pointer contents in the graph's pointer width.
397
398/// Creates an anonymous pointer, optionally initialized to InitialTarget.
400 Symbol *InitialTarget = nullptr,
401 Edge::AddendT InitialAddend = 0);
402
403/// Creates a stub that materializes PointerSymbol, loads its value into $t9,
404/// and jumps to $t9. Release-6 graphs use the release-6 indirect-jump encoding.
406 Section &StubSection,
407 Symbol &PointerSymbol);
408
409} // namespace mips
410} // namespace jitlink
411} // namespace llvm
412
413#endif // LLVM_EXECUTIONENGINE_JITLINK_MIPS_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_ABI
Definition Compiler.h:215
#define G(x, y, z)
Definition MD5.cpp:55
#define P(N)
PowerPC TLS Dynamic Call Fixup
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
LLVM Value Representation.
Definition Value.h:75
Represents an address in the executor process.
uint64_t getValue() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
uint32_t read32(const void *P, endianness E)
Definition Endian.h:392
void write32(void *P, uint32_t V, endianness E)
Definition Endian.h:435
void write16(void *P, uint16_t V, endianness E)
Definition Endian.h:432
void write64(void *P, uint64_t V, endianness E)
Definition Endian.h:438
This is an optimization pass for GlobalISel generic memory operations.
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
Definition MathExtras.h:541
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition MathExtras.h:249
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78
endianness
Definition bit.h:71
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39