LLVM 17.0.0git
OrcABISupport.cpp
Go to the documentation of this file.
1//===------------- OrcABISupport.cpp - ABI specific support code ----------===//
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
13
14#define DEBUG_TYPE "orc"
15
16using namespace llvm;
17using namespace llvm::orc;
18
19template <typename ORCABI>
20static bool stubAndPointerRangesOk(ExecutorAddr StubBlockAddr,
21 ExecutorAddr PointerBlockAddr,
22 unsigned NumStubs) {
23 constexpr unsigned MaxDisp = ORCABI::StubToPointerMaxDisplacement;
24 ExecutorAddr FirstStub = StubBlockAddr;
25 ExecutorAddr LastStub = FirstStub + ((NumStubs - 1) * ORCABI::StubSize);
26 ExecutorAddr FirstPointer = PointerBlockAddr;
27 ExecutorAddr LastPointer = FirstPointer + ((NumStubs - 1) * ORCABI::StubSize);
28
29 if (FirstStub < FirstPointer) {
30 if (LastStub >= FirstPointer)
31 return false; // Ranges overlap.
32 return (FirstPointer - FirstStub <= MaxDisp) &&
33 (LastPointer - LastStub <= MaxDisp); // out-of-range.
34 }
35
36 if (LastPointer >= FirstStub)
37 return false; // Ranges overlap.
38
39 return (FirstStub - FirstPointer <= MaxDisp) &&
40 (LastStub - LastPointer <= MaxDisp);
41}
42
43namespace llvm {
44namespace orc {
45
46void OrcAArch64::writeResolverCode(char *ResolverWorkingMem,
47 ExecutorAddr ResolverTargetAddress,
48 ExecutorAddr ReentryFnAddr,
49 ExecutorAddr ReentryCtxAddr) {
50
51 const uint32_t ResolverCode[] = {
52 // resolver_entry:
53 0xa9bf47fd, // 0x000: stp x29, x17, [sp, #-16]!
54 0x910003fd, // 0x004: mov x29, sp
55 0xa9bf73fb, // 0x008: stp x27, x28, [sp, #-16]!
56 0xa9bf6bf9, // 0x00c: stp x25, x26, [sp, #-16]!
57 0xa9bf63f7, // 0x010: stp x23, x24, [sp, #-16]!
58 0xa9bf5bf5, // 0x014: stp x21, x22, [sp, #-16]!
59 0xa9bf53f3, // 0x018: stp x19, x20, [sp, #-16]!
60 0xa9bf3fee, // 0x01c: stp x14, x15, [sp, #-16]!
61 0xa9bf37ec, // 0x020: stp x12, x13, [sp, #-16]!
62 0xa9bf2fea, // 0x024: stp x10, x11, [sp, #-16]!
63 0xa9bf27e8, // 0x028: stp x8, x9, [sp, #-16]!
64 0xa9bf1fe6, // 0x02c: stp x6, x7, [sp, #-16]!
65 0xa9bf17e4, // 0x030: stp x4, x5, [sp, #-16]!
66 0xa9bf0fe2, // 0x034: stp x2, x3, [sp, #-16]!
67 0xa9bf07e0, // 0x038: stp x0, x1, [sp, #-16]!
68 0xadbf7ffe, // 0x03c: stp q30, q31, [sp, #-32]!
69 0xadbf77fc, // 0x040: stp q28, q29, [sp, #-32]!
70 0xadbf6ffa, // 0x044: stp q26, q27, [sp, #-32]!
71 0xadbf67f8, // 0x048: stp q24, q25, [sp, #-32]!
72 0xadbf5ff6, // 0x04c: stp q22, q23, [sp, #-32]!
73 0xadbf57f4, // 0x050: stp q20, q21, [sp, #-32]!
74 0xadbf4ff2, // 0x054: stp q18, q19, [sp, #-32]!
75 0xadbf47f0, // 0x058: stp q16, q17, [sp, #-32]!
76 0xadbf3fee, // 0x05c: stp q14, q15, [sp, #-32]!
77 0xadbf37ec, // 0x060: stp q12, q13, [sp, #-32]!
78 0xadbf2fea, // 0x064: stp q10, q11, [sp, #-32]!
79 0xadbf27e8, // 0x068: stp q8, q9, [sp, #-32]!
80 0xadbf1fe6, // 0x06c: stp q6, q7, [sp, #-32]!
81 0xadbf17e4, // 0x070: stp q4, q5, [sp, #-32]!
82 0xadbf0fe2, // 0x074: stp q2, q3, [sp, #-32]!
83 0xadbf07e0, // 0x078: stp q0, q1, [sp, #-32]!
84 0x580004e0, // 0x07c: ldr x0, Lreentry_ctx_ptr
85 0xaa1e03e1, // 0x080: mov x1, x30
86 0xd1003021, // 0x084: sub x1, x1, #12
87 0x58000442, // 0x088: ldr x2, Lreentry_fn_ptr
88 0xd63f0040, // 0x08c: blr x2
89 0xaa0003f1, // 0x090: mov x17, x0
90 0xacc107e0, // 0x094: ldp q0, q1, [sp], #32
91 0xacc10fe2, // 0x098: ldp q2, q3, [sp], #32
92 0xacc117e4, // 0x09c: ldp q4, q5, [sp], #32
93 0xacc11fe6, // 0x0a0: ldp q6, q7, [sp], #32
94 0xacc127e8, // 0x0a4: ldp q8, q9, [sp], #32
95 0xacc12fea, // 0x0a8: ldp q10, q11, [sp], #32
96 0xacc137ec, // 0x0ac: ldp q12, q13, [sp], #32
97 0xacc13fee, // 0x0b0: ldp q14, q15, [sp], #32
98 0xacc147f0, // 0x0b4: ldp q16, q17, [sp], #32
99 0xacc14ff2, // 0x0b8: ldp q18, q19, [sp], #32
100 0xacc157f4, // 0x0bc: ldp q20, q21, [sp], #32
101 0xacc15ff6, // 0x0c0: ldp q22, q23, [sp], #32
102 0xacc167f8, // 0x0c4: ldp q24, q25, [sp], #32
103 0xacc16ffa, // 0x0c8: ldp q26, q27, [sp], #32
104 0xacc177fc, // 0x0cc: ldp q28, q29, [sp], #32
105 0xacc17ffe, // 0x0d0: ldp q30, q31, [sp], #32
106 0xa8c107e0, // 0x0d4: ldp x0, x1, [sp], #16
107 0xa8c10fe2, // 0x0d8: ldp x2, x3, [sp], #16
108 0xa8c117e4, // 0x0dc: ldp x4, x5, [sp], #16
109 0xa8c11fe6, // 0x0e0: ldp x6, x7, [sp], #16
110 0xa8c127e8, // 0x0e4: ldp x8, x9, [sp], #16
111 0xa8c12fea, // 0x0e8: ldp x10, x11, [sp], #16
112 0xa8c137ec, // 0x0ec: ldp x12, x13, [sp], #16
113 0xa8c13fee, // 0x0f0: ldp x14, x15, [sp], #16
114 0xa8c153f3, // 0x0f4: ldp x19, x20, [sp], #16
115 0xa8c15bf5, // 0x0f8: ldp x21, x22, [sp], #16
116 0xa8c163f7, // 0x0fc: ldp x23, x24, [sp], #16
117 0xa8c16bf9, // 0x100: ldp x25, x26, [sp], #16
118 0xa8c173fb, // 0x104: ldp x27, x28, [sp], #16
119 0xa8c17bfd, // 0x108: ldp x29, x30, [sp], #16
120 0xd65f0220, // 0x10c: ret x17
121 0x01234567, // 0x110: Lreentry_fn_ptr:
122 0xdeadbeef, // 0x114: .quad 0
123 0x98765432, // 0x118: Lreentry_ctx_ptr:
124 0xcafef00d // 0x11c: .quad 0
125 };
126
127 const unsigned ReentryFnAddrOffset = 0x110;
128 const unsigned ReentryCtxAddrOffset = 0x118;
129
130 memcpy(ResolverWorkingMem, ResolverCode, sizeof(ResolverCode));
131 memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnAddr,
132 sizeof(uint64_t));
133 memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxAddr,
134 sizeof(uint64_t));
135}
136
137void OrcAArch64::writeTrampolines(char *TrampolineBlockWorkingMem,
138 ExecutorAddr TrampolineBlockTargetAddress,
139 ExecutorAddr ResolverAddr,
140 unsigned NumTrampolines) {
141
142 unsigned OffsetToPtr = alignTo(NumTrampolines * TrampolineSize, 8);
143
144 memcpy(TrampolineBlockWorkingMem + OffsetToPtr, &ResolverAddr,
145 sizeof(uint64_t));
146
147 // OffsetToPtr is actually the offset from the PC for the 2nd instruction, so
148 // subtract 32-bits.
149 OffsetToPtr -= 4;
150
151 uint32_t *Trampolines =
152 reinterpret_cast<uint32_t *>(TrampolineBlockWorkingMem);
153
154 for (unsigned I = 0; I < NumTrampolines; ++I, OffsetToPtr -= TrampolineSize) {
155 Trampolines[3 * I + 0] = 0xaa1e03f1; // mov x17, x30
156 Trampolines[3 * I + 1] = 0x58000010 | (OffsetToPtr << 3); // adr x16, Lptr
157 Trampolines[3 * I + 2] = 0xd63f0200; // blr x16
158 }
159}
160
162 char *StubsBlockWorkingMem, ExecutorAddr StubsBlockTargetAddress,
163 ExecutorAddr PointersBlockTargetAddress, unsigned NumStubs) {
164 // Stub format is:
165 //
166 // .section __orc_stubs
167 // stub1:
168 // ldr x0, ptr1 ; PC-rel load of ptr1
169 // br x0 ; Jump to resolver
170 // stub2:
171 // ldr x0, ptr2 ; PC-rel load of ptr2
172 // br x0 ; Jump to resolver
173 //
174 // ...
175 //
176 // .section __orc_ptrs
177 // ptr1:
178 // .quad 0x0
179 // ptr2:
180 // .quad 0x0
181 //
182 // ...
183
184 static_assert(StubSize == PointerSize,
185 "Pointer and stub size must match for algorithm below");
186 assert(stubAndPointerRangesOk<OrcAArch64>(
187 StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) &&
188 "PointersBlock is out of range");
189 uint64_t PtrDisplacement =
190 PointersBlockTargetAddress - StubsBlockTargetAddress;
191 uint64_t *Stub = reinterpret_cast<uint64_t *>(StubsBlockWorkingMem);
192 uint64_t PtrOffsetField = PtrDisplacement << 3;
193
194 for (unsigned I = 0; I < NumStubs; ++I)
195 Stub[I] = 0xd61f020058000010 | PtrOffsetField;
196}
197
198void OrcX86_64_Base::writeTrampolines(char *TrampolineBlockWorkingMem,
199 ExecutorAddr TrampolineBlockTargetAddress,
200 ExecutorAddr ResolverAddr,
201 unsigned NumTrampolines) {
202
203 unsigned OffsetToPtr = NumTrampolines * TrampolineSize;
204
205 memcpy(TrampolineBlockWorkingMem + OffsetToPtr, &ResolverAddr,
206 sizeof(uint64_t));
207
208 uint64_t *Trampolines =
209 reinterpret_cast<uint64_t *>(TrampolineBlockWorkingMem);
210 uint64_t CallIndirPCRel = 0xf1c40000000015ff;
211
212 for (unsigned I = 0; I < NumTrampolines; ++I, OffsetToPtr -= TrampolineSize)
213 Trampolines[I] = CallIndirPCRel | ((OffsetToPtr - 6) << 16);
214}
215
217 char *StubsBlockWorkingMem, ExecutorAddr StubsBlockTargetAddress,
218 ExecutorAddr PointersBlockTargetAddress, unsigned NumStubs) {
219 // Stub format is:
220 //
221 // .section __orc_stubs
222 // stub1:
223 // jmpq *ptr1(%rip)
224 // .byte 0xC4 ; <- Invalid opcode padding.
225 // .byte 0xF1
226 // stub2:
227 // jmpq *ptr2(%rip)
228 //
229 // ...
230 //
231 // .section __orc_ptrs
232 // ptr1:
233 // .quad 0x0
234 // ptr2:
235 // .quad 0x0
236 //
237 // ...
238
239 // Populate the stubs page stubs and mark it executable.
240 static_assert(StubSize == PointerSize,
241 "Pointer and stub size must match for algorithm below");
242 assert(stubAndPointerRangesOk<OrcX86_64_Base>(
243 StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) &&
244 "PointersBlock is out of range");
245 uint64_t *Stub = reinterpret_cast<uint64_t *>(StubsBlockWorkingMem);
246 uint64_t PtrOffsetField =
247 (PointersBlockTargetAddress - StubsBlockTargetAddress - 6) << 16;
248 for (unsigned I = 0; I < NumStubs; ++I)
249 Stub[I] = 0xF1C40000000025ff | PtrOffsetField;
250}
251
252void OrcX86_64_SysV::writeResolverCode(char *ResolverWorkingMem,
253 ExecutorAddr ResolverTargetAddress,
254 ExecutorAddr ReentryFnAddr,
255 ExecutorAddr ReentryCtxAddr) {
256
257 LLVM_DEBUG({
258 dbgs() << "Writing resolver code to "
259 << formatv("{0:x16}", ResolverTargetAddress) << "\n";
260 });
261
262 const uint8_t ResolverCode[] = {
263 // resolver_entry:
264 0x55, // 0x00: pushq %rbp
265 0x48, 0x89, 0xe5, // 0x01: movq %rsp, %rbp
266 0x50, // 0x04: pushq %rax
267 0x53, // 0x05: pushq %rbx
268 0x51, // 0x06: pushq %rcx
269 0x52, // 0x07: pushq %rdx
270 0x56, // 0x08: pushq %rsi
271 0x57, // 0x09: pushq %rdi
272 0x41, 0x50, // 0x0a: pushq %r8
273 0x41, 0x51, // 0x0c: pushq %r9
274 0x41, 0x52, // 0x0e: pushq %r10
275 0x41, 0x53, // 0x10: pushq %r11
276 0x41, 0x54, // 0x12: pushq %r12
277 0x41, 0x55, // 0x14: pushq %r13
278 0x41, 0x56, // 0x16: pushq %r14
279 0x41, 0x57, // 0x18: pushq %r15
280 0x48, 0x81, 0xec, 0x08, 0x02, 0x00, 0x00, // 0x1a: subq 0x208, %rsp
281 0x48, 0x0f, 0xae, 0x04, 0x24, // 0x21: fxsave64 (%rsp)
282 0x48, 0xbf, // 0x26: movabsq <CBMgr>, %rdi
283
284 // 0x28: JIT re-entry ctx addr.
285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
286
287 0x48, 0x8b, 0x75, 0x08, // 0x30: movq 8(%rbp), %rsi
288 0x48, 0x83, 0xee, 0x06, // 0x34: subq $6, %rsi
289 0x48, 0xb8, // 0x38: movabsq <REntry>, %rax
290
291 // 0x3a: JIT re-entry fn addr:
292 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
293
294 0xff, 0xd0, // 0x42: callq *%rax
295 0x48, 0x89, 0x45, 0x08, // 0x44: movq %rax, 8(%rbp)
296 0x48, 0x0f, 0xae, 0x0c, 0x24, // 0x48: fxrstor64 (%rsp)
297 0x48, 0x81, 0xc4, 0x08, 0x02, 0x00, 0x00, // 0x4d: addq 0x208, %rsp
298 0x41, 0x5f, // 0x54: popq %r15
299 0x41, 0x5e, // 0x56: popq %r14
300 0x41, 0x5d, // 0x58: popq %r13
301 0x41, 0x5c, // 0x5a: popq %r12
302 0x41, 0x5b, // 0x5c: popq %r11
303 0x41, 0x5a, // 0x5e: popq %r10
304 0x41, 0x59, // 0x60: popq %r9
305 0x41, 0x58, // 0x62: popq %r8
306 0x5f, // 0x64: popq %rdi
307 0x5e, // 0x65: popq %rsi
308 0x5a, // 0x66: popq %rdx
309 0x59, // 0x67: popq %rcx
310 0x5b, // 0x68: popq %rbx
311 0x58, // 0x69: popq %rax
312 0x5d, // 0x6a: popq %rbp
313 0xc3, // 0x6b: retq
314 };
315
316 const unsigned ReentryFnAddrOffset = 0x3a;
317 const unsigned ReentryCtxAddrOffset = 0x28;
318
319 memcpy(ResolverWorkingMem, ResolverCode, sizeof(ResolverCode));
320 memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnAddr,
321 sizeof(uint64_t));
322 memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxAddr,
323 sizeof(uint64_t));
324}
325
326void OrcX86_64_Win32::writeResolverCode(char *ResolverWorkingMem,
327 ExecutorAddr ResolverTargetAddress,
328 ExecutorAddr ReentryFnAddr,
329 ExecutorAddr ReentryCtxAddr) {
330
331 // resolverCode is similar to OrcX86_64 with differences specific to windows
332 // x64 calling convention: arguments go into rcx, rdx and come in reverse
333 // order, shadow space allocation on stack
334 const uint8_t ResolverCode[] = {
335 // resolver_entry:
336 0x55, // 0x00: pushq %rbp
337 0x48, 0x89, 0xe5, // 0x01: movq %rsp, %rbp
338 0x50, // 0x04: pushq %rax
339 0x53, // 0x05: pushq %rbx
340 0x51, // 0x06: pushq %rcx
341 0x52, // 0x07: pushq %rdx
342 0x56, // 0x08: pushq %rsi
343 0x57, // 0x09: pushq %rdi
344 0x41, 0x50, // 0x0a: pushq %r8
345 0x41, 0x51, // 0x0c: pushq %r9
346 0x41, 0x52, // 0x0e: pushq %r10
347 0x41, 0x53, // 0x10: pushq %r11
348 0x41, 0x54, // 0x12: pushq %r12
349 0x41, 0x55, // 0x14: pushq %r13
350 0x41, 0x56, // 0x16: pushq %r14
351 0x41, 0x57, // 0x18: pushq %r15
352 0x48, 0x81, 0xec, 0x08, 0x02, 0x00, 0x00, // 0x1a: subq 0x208, %rsp
353 0x48, 0x0f, 0xae, 0x04, 0x24, // 0x21: fxsave64 (%rsp)
354
355 0x48, 0xb9, // 0x26: movabsq <CBMgr>, %rcx
356 // 0x28: JIT re-entry ctx addr.
357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
358
359 0x48, 0x8B, 0x55, 0x08, // 0x30: mov rdx, [rbp+0x8]
360 0x48, 0x83, 0xea, 0x06, // 0x34: sub rdx, 0x6
361
362 0x48, 0xb8, // 0x38: movabsq <REntry>, %rax
363 // 0x3a: JIT re-entry fn addr:
364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365
366 // 0x42: sub rsp, 0x20 (Allocate shadow space)
367 0x48, 0x83, 0xEC, 0x20,
368 0xff, 0xd0, // 0x46: callq *%rax
369
370 // 0x48: add rsp, 0x20 (Free shadow space)
371 0x48, 0x83, 0xC4, 0x20,
372
373 0x48, 0x89, 0x45, 0x08, // 0x4C: movq %rax, 8(%rbp)
374 0x48, 0x0f, 0xae, 0x0c, 0x24, // 0x50: fxrstor64 (%rsp)
375 0x48, 0x81, 0xc4, 0x08, 0x02, 0x00, 0x00, // 0x55: addq 0x208, %rsp
376 0x41, 0x5f, // 0x5C: popq %r15
377 0x41, 0x5e, // 0x5E: popq %r14
378 0x41, 0x5d, // 0x60: popq %r13
379 0x41, 0x5c, // 0x62: popq %r12
380 0x41, 0x5b, // 0x64: popq %r11
381 0x41, 0x5a, // 0x66: popq %r10
382 0x41, 0x59, // 0x68: popq %r9
383 0x41, 0x58, // 0x6a: popq %r8
384 0x5f, // 0x6c: popq %rdi
385 0x5e, // 0x6d: popq %rsi
386 0x5a, // 0x6e: popq %rdx
387 0x59, // 0x6f: popq %rcx
388 0x5b, // 0x70: popq %rbx
389 0x58, // 0x71: popq %rax
390 0x5d, // 0x72: popq %rbp
391 0xc3, // 0x73: retq
392 };
393
394 const unsigned ReentryFnAddrOffset = 0x3a;
395 const unsigned ReentryCtxAddrOffset = 0x28;
396
397 memcpy(ResolverWorkingMem, ResolverCode, sizeof(ResolverCode));
398 memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnAddr,
399 sizeof(uint64_t));
400 memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxAddr,
401 sizeof(uint64_t));
402}
403
404void OrcI386::writeResolverCode(char *ResolverWorkingMem,
405 ExecutorAddr ResolverTargetAddress,
406 ExecutorAddr ReentryFnAddr,
407 ExecutorAddr ReentryCtxAddr) {
408
409 assert((ReentryFnAddr.getValue() >> 32) == 0 && "ReentryFnAddr out of range");
410 assert((ReentryCtxAddr.getValue() >> 32) == 0 &&
411 "ReentryCtxAddr out of range");
412
413 const uint8_t ResolverCode[] = {
414 // resolver_entry:
415 0x55, // 0x00: pushl %ebp
416 0x89, 0xe5, // 0x01: movl %esp, %ebp
417 0x54, // 0x03: pushl %esp
418 0x83, 0xe4, 0xf0, // 0x04: andl $-0x10, %esp
419 0x50, // 0x07: pushl %eax
420 0x53, // 0x08: pushl %ebx
421 0x51, // 0x09: pushl %ecx
422 0x52, // 0x0a: pushl %edx
423 0x56, // 0x0b: pushl %esi
424 0x57, // 0x0c: pushl %edi
425 0x81, 0xec, 0x18, 0x02, 0x00, 0x00, // 0x0d: subl $0x218, %esp
426 0x0f, 0xae, 0x44, 0x24, 0x10, // 0x13: fxsave 0x10(%esp)
427 0x8b, 0x75, 0x04, // 0x18: movl 0x4(%ebp), %esi
428 0x83, 0xee, 0x05, // 0x1b: subl $0x5, %esi
429 0x89, 0x74, 0x24, 0x04, // 0x1e: movl %esi, 0x4(%esp)
430 0xc7, 0x04, 0x24, 0x00, 0x00, 0x00,
431 0x00, // 0x22: movl <cbmgr>, (%esp)
432 0xb8, 0x00, 0x00, 0x00, 0x00, // 0x29: movl <reentry>, %eax
433 0xff, 0xd0, // 0x2e: calll *%eax
434 0x89, 0x45, 0x04, // 0x30: movl %eax, 0x4(%ebp)
435 0x0f, 0xae, 0x4c, 0x24, 0x10, // 0x33: fxrstor 0x10(%esp)
436 0x81, 0xc4, 0x18, 0x02, 0x00, 0x00, // 0x38: addl $0x218, %esp
437 0x5f, // 0x3e: popl %edi
438 0x5e, // 0x3f: popl %esi
439 0x5a, // 0x40: popl %edx
440 0x59, // 0x41: popl %ecx
441 0x5b, // 0x42: popl %ebx
442 0x58, // 0x43: popl %eax
443 0x8b, 0x65, 0xfc, // 0x44: movl -0x4(%ebp), %esp
444 0x5d, // 0x48: popl %ebp
445 0xc3 // 0x49: retl
446 };
447
448 const unsigned ReentryFnAddrOffset = 0x2a;
449 const unsigned ReentryCtxAddrOffset = 0x25;
450
451 memcpy(ResolverWorkingMem, ResolverCode, sizeof(ResolverCode));
452 memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnAddr,
453 sizeof(uint32_t));
454 memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxAddr,
455 sizeof(uint32_t));
456}
457
458void OrcI386::writeTrampolines(char *TrampolineWorkingMem,
459 ExecutorAddr TrampolineBlockTargetAddress,
460 ExecutorAddr ResolverAddr,
461 unsigned NumTrampolines) {
462 assert((ResolverAddr.getValue() >> 32) == 0 && "ResolverAddr out of range");
463
464 uint64_t CallRelImm = 0xF1C4C400000000e8;
465 uint64_t ResolverRel = ResolverAddr - TrampolineBlockTargetAddress - 5;
466
467 uint64_t *Trampolines = reinterpret_cast<uint64_t *>(TrampolineWorkingMem);
468 for (unsigned I = 0; I < NumTrampolines; ++I, ResolverRel -= TrampolineSize)
469 Trampolines[I] = CallRelImm | (ResolverRel << 8);
470}
471
472void OrcI386::writeIndirectStubsBlock(char *StubsBlockWorkingMem,
473 ExecutorAddr StubsBlockTargetAddress,
474 ExecutorAddr PointersBlockTargetAddress,
475 unsigned NumStubs) {
476 assert((StubsBlockTargetAddress.getValue() >> 32) == 0 &&
477 "StubsBlockTargetAddress is out of range");
478 assert((PointersBlockTargetAddress.getValue() >> 32) == 0 &&
479 "PointersBlockTargetAddress is out of range");
480
481 // Stub format is:
482 //
483 // .section __orc_stubs
484 // stub1:
485 // jmpq *ptr1
486 // .byte 0xC4 ; <- Invalid opcode padding.
487 // .byte 0xF1
488 // stub2:
489 // jmpq *ptr2
490 //
491 // ...
492 //
493 // .section __orc_ptrs
494 // ptr1:
495 // .quad 0x0
496 // ptr2:
497 // .quad 0x0
498 //
499 // ...
500
501 assert(stubAndPointerRangesOk<OrcI386>(
502 StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) &&
503 "PointersBlock is out of range");
504
505 uint64_t *Stub = reinterpret_cast<uint64_t *>(StubsBlockWorkingMem);
506 uint64_t PtrAddr = PointersBlockTargetAddress.getValue();
507 for (unsigned I = 0; I < NumStubs; ++I, PtrAddr += 4)
508 Stub[I] = 0xF1C40000000025ff | (PtrAddr << 16);
509}
510
511void OrcMips32_Base::writeResolverCode(char *ResolverWorkingMem,
512 ExecutorAddr ResolverTargetAddress,
513 ExecutorAddr ReentryFnAddr,
514 ExecutorAddr ReentryCtxAddr,
515 bool isBigEndian) {
516
517 const uint32_t ResolverCode[] = {
518 // resolver_entry:
519 0x27bdff98, // 0x00: addiu $sp,$sp,-104
520 0xafa20000, // 0x04: sw $v0,0($sp)
521 0xafa30004, // 0x08: sw $v1,4($sp)
522 0xafa40008, // 0x0c: sw $a0,8($sp)
523 0xafa5000c, // 0x10: sw $a1,12($sp)
524 0xafa60010, // 0x14: sw $a2,16($sp)
525 0xafa70014, // 0x18: sw $a3,20($sp)
526 0xafb00018, // 0x1c: sw $s0,24($sp)
527 0xafb1001c, // 0x20: sw $s1,28($sp)
528 0xafb20020, // 0x24: sw $s2,32($sp)
529 0xafb30024, // 0x28: sw $s3,36($sp)
530 0xafb40028, // 0x2c: sw $s4,40($sp)
531 0xafb5002c, // 0x30: sw $s5,44($sp)
532 0xafb60030, // 0x34: sw $s6,48($sp)
533 0xafb70034, // 0x38: sw $s7,52($sp)
534 0xafa80038, // 0x3c: sw $t0,56($sp)
535 0xafa9003c, // 0x40: sw $t1,60($sp)
536 0xafaa0040, // 0x44: sw $t2,64($sp)
537 0xafab0044, // 0x48: sw $t3,68($sp)
538 0xafac0048, // 0x4c: sw $t4,72($sp)
539 0xafad004c, // 0x50: sw $t5,76($sp)
540 0xafae0050, // 0x54: sw $t6,80($sp)
541 0xafaf0054, // 0x58: sw $t7,84($sp)
542 0xafb80058, // 0x5c: sw $t8,88($sp)
543 0xafb9005c, // 0x60: sw $t9,92($sp)
544 0xafbe0060, // 0x64: sw $fp,96($sp)
545 0xafbf0064, // 0x68: sw $ra,100($sp)
546
547 // JIT re-entry ctx addr.
548 0x00000000, // 0x6c: lui $a0,ctx
549 0x00000000, // 0x70: addiu $a0,$a0,ctx
550
551 0x03e02825, // 0x74: move $a1, $ra
552 0x24a5ffec, // 0x78: addiu $a1,$a1,-20
553
554 // JIT re-entry fn addr:
555 0x00000000, // 0x7c: lui $t9,reentry
556 0x00000000, // 0x80: addiu $t9,$t9,reentry
557
558 0x0320f809, // 0x84: jalr $t9
559 0x00000000, // 0x88: nop
560 0x8fbf0064, // 0x8c: lw $ra,100($sp)
561 0x8fbe0060, // 0x90: lw $fp,96($sp)
562 0x8fb9005c, // 0x94: lw $t9,92($sp)
563 0x8fb80058, // 0x98: lw $t8,88($sp)
564 0x8faf0054, // 0x9c: lw $t7,84($sp)
565 0x8fae0050, // 0xa0: lw $t6,80($sp)
566 0x8fad004c, // 0xa4: lw $t5,76($sp)
567 0x8fac0048, // 0xa8: lw $t4,72($sp)
568 0x8fab0044, // 0xac: lw $t3,68($sp)
569 0x8faa0040, // 0xb0: lw $t2,64($sp)
570 0x8fa9003c, // 0xb4: lw $t1,60($sp)
571 0x8fa80038, // 0xb8: lw $t0,56($sp)
572 0x8fb70034, // 0xbc: lw $s7,52($sp)
573 0x8fb60030, // 0xc0: lw $s6,48($sp)
574 0x8fb5002c, // 0xc4: lw $s5,44($sp)
575 0x8fb40028, // 0xc8: lw $s4,40($sp)
576 0x8fb30024, // 0xcc: lw $s3,36($sp)
577 0x8fb20020, // 0xd0: lw $s2,32($sp)
578 0x8fb1001c, // 0xd4: lw $s1,28($sp)
579 0x8fb00018, // 0xd8: lw $s0,24($sp)
580 0x8fa70014, // 0xdc: lw $a3,20($sp)
581 0x8fa60010, // 0xe0: lw $a2,16($sp)
582 0x8fa5000c, // 0xe4: lw $a1,12($sp)
583 0x8fa40008, // 0xe8: lw $a0,8($sp)
584 0x27bd0068, // 0xec: addiu $sp,$sp,104
585 0x0300f825, // 0xf0: move $ra, $t8
586 0x03200008, // 0xf4: jr $t9
587 0x00000000, // 0xf8: move $t9, $v0/v1
588 };
589
590 const unsigned ReentryFnAddrOffset = 0x7c; // JIT re-entry fn addr lui
591 const unsigned ReentryCtxAddrOffset = 0x6c; // JIT re-entry context addr lui
592 const unsigned Offsett = 0xf8;
593
594 memcpy(ResolverWorkingMem, ResolverCode, sizeof(ResolverCode));
595
596 // Depending on endian return value will be in v0 or v1.
597 uint32_t MoveVxT9 = isBigEndian ? 0x0060c825 : 0x0040c825;
598 memcpy(ResolverWorkingMem + Offsett, &MoveVxT9, sizeof(MoveVxT9));
599
600 uint32_t ReentryCtxLUi =
601 0x3c040000 | (((ReentryCtxAddr.getValue() + 0x8000) >> 16) & 0xFFFF);
602 uint32_t ReentryCtxADDiu = 0x24840000 | (ReentryCtxAddr.getValue() & 0xFFFF);
603 memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxLUi,
604 sizeof(ReentryCtxLUi));
605 memcpy(ResolverWorkingMem + ReentryCtxAddrOffset + 4, &ReentryCtxADDiu,
606 sizeof(ReentryCtxADDiu));
607
608 uint32_t ReentryFnLUi =
609 0x3c190000 | (((ReentryFnAddr.getValue() + 0x8000) >> 16) & 0xFFFF);
610 uint32_t ReentryFnADDiu = 0x27390000 | (ReentryFnAddr.getValue() & 0xFFFF);
611 memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnLUi,
612 sizeof(ReentryFnLUi));
613 memcpy(ResolverWorkingMem + ReentryFnAddrOffset + 4, &ReentryFnADDiu,
614 sizeof(ReentryFnADDiu));
615}
616
617void OrcMips32_Base::writeTrampolines(char *TrampolineBlockWorkingMem,
618 ExecutorAddr TrampolineBlockTargetAddress,
619 ExecutorAddr ResolverAddr,
620 unsigned NumTrampolines) {
621
622 assert((ResolverAddr.getValue() >> 32) == 0 && "ResolverAddr out of range");
623
624 uint32_t *Trampolines =
625 reinterpret_cast<uint32_t *>(TrampolineBlockWorkingMem);
626 uint32_t RHiAddr = ((ResolverAddr.getValue() + 0x8000) >> 16);
627
628 for (unsigned I = 0; I < NumTrampolines; ++I) {
629 // move $t8,$ra
630 // lui $t9,ResolverAddr
631 // addiu $t9,$t9,ResolverAddr
632 // jalr $t9
633 // nop
634 Trampolines[5 * I + 0] = 0x03e0c025;
635 Trampolines[5 * I + 1] = 0x3c190000 | (RHiAddr & 0xFFFF);
636 Trampolines[5 * I + 2] = 0x27390000 | (ResolverAddr.getValue() & 0xFFFF);
637 Trampolines[5 * I + 3] = 0x0320f809;
638 Trampolines[5 * I + 4] = 0x00000000;
639 }
640}
641
643 char *StubsBlockWorkingMem, ExecutorAddr StubsBlockTargetAddress,
644 ExecutorAddr PointersBlockTargetAddress, unsigned NumStubs) {
645 assert((StubsBlockTargetAddress.getValue() >> 32) == 0 &&
646 "InitialPtrVal is out of range");
647
648 // Stub format is:
649 //
650 // .section __orc_stubs
651 // stub1:
652 // lui $t9, ptr1
653 // lw $t9, %lo(ptr1)($t9)
654 // jr $t9
655 // stub2:
656 // lui $t9, ptr2
657 // lw $t9,%lo(ptr1)($t9)
658 // jr $t9
659 //
660 // ...
661 //
662 // .section __orc_ptrs
663 // ptr1:
664 // .word 0x0
665 // ptr2:
666 // .word 0x0
667 //
668 // i..
669
670 assert(stubAndPointerRangesOk<OrcMips32_Base>(
671 StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) &&
672 "PointersBlock is out of range");
673
674 // Populate the stubs page stubs and mark it executable.
675 uint32_t *Stub = reinterpret_cast<uint32_t *>(StubsBlockWorkingMem);
676 uint64_t PtrAddr = PointersBlockTargetAddress.getValue();
677
678 for (unsigned I = 0; I < NumStubs; ++I) {
679 uint32_t HiAddr = ((PtrAddr + 0x8000) >> 16);
680 Stub[4 * I + 0] = 0x3c190000 | (HiAddr & 0xFFFF); // lui $t9,ptr1
681 Stub[4 * I + 1] = 0x8f390000 | (PtrAddr & 0xFFFF); // lw $t9,%lo(ptr1)($t9)
682 Stub[4 * I + 2] = 0x03200008; // jr $t9
683 Stub[4 * I + 3] = 0x00000000; // nop
684 PtrAddr += 4;
685 }
686}
687
688void OrcMips64::writeResolverCode(char *ResolverWorkingMem,
689 ExecutorAddr ResolverTargetAddress,
690 ExecutorAddr ReentryFnAddr,
691 ExecutorAddr ReentryCtxAddr) {
692
693 const uint32_t ResolverCode[] = {
694 //resolver_entry:
695 0x67bdff30, // 0x00: daddiu $sp,$sp,-208
696 0xffa20000, // 0x04: sd v0,0(sp)
697 0xffa30008, // 0x08: sd v1,8(sp)
698 0xffa40010, // 0x0c: sd a0,16(sp)
699 0xffa50018, // 0x10: sd a1,24(sp)
700 0xffa60020, // 0x14: sd a2,32(sp)
701 0xffa70028, // 0x18: sd a3,40(sp)
702 0xffa80030, // 0x1c: sd a4,48(sp)
703 0xffa90038, // 0x20: sd a5,56(sp)
704 0xffaa0040, // 0x24: sd a6,64(sp)
705 0xffab0048, // 0x28: sd a7,72(sp)
706 0xffac0050, // 0x2c: sd t0,80(sp)
707 0xffad0058, // 0x30: sd t1,88(sp)
708 0xffae0060, // 0x34: sd t2,96(sp)
709 0xffaf0068, // 0x38: sd t3,104(sp)
710 0xffb00070, // 0x3c: sd s0,112(sp)
711 0xffb10078, // 0x40: sd s1,120(sp)
712 0xffb20080, // 0x44: sd s2,128(sp)
713 0xffb30088, // 0x48: sd s3,136(sp)
714 0xffb40090, // 0x4c: sd s4,144(sp)
715 0xffb50098, // 0x50: sd s5,152(sp)
716 0xffb600a0, // 0x54: sd s6,160(sp)
717 0xffb700a8, // 0x58: sd s7,168(sp)
718 0xffb800b0, // 0x5c: sd t8,176(sp)
719 0xffb900b8, // 0x60: sd t9,184(sp)
720 0xffbe00c0, // 0x64: sd fp,192(sp)
721 0xffbf00c8, // 0x68: sd ra,200(sp)
722
723 // JIT re-entry ctx addr.
724 0x00000000, // 0x6c: lui $a0,heighest(ctx)
725 0x00000000, // 0x70: daddiu $a0,$a0,heigher(ctx)
726 0x00000000, // 0x74: dsll $a0,$a0,16
727 0x00000000, // 0x78: daddiu $a0,$a0,hi(ctx)
728 0x00000000, // 0x7c: dsll $a0,$a0,16
729 0x00000000, // 0x80: daddiu $a0,$a0,lo(ctx)
730
731 0x03e02825, // 0x84: move $a1, $ra
732 0x64a5ffdc, // 0x88: daddiu $a1,$a1,-36
733
734 // JIT re-entry fn addr:
735 0x00000000, // 0x8c: lui $t9,reentry
736 0x00000000, // 0x90: daddiu $t9,$t9,reentry
737 0x00000000, // 0x94: dsll $t9,$t9,
738 0x00000000, // 0x98: daddiu $t9,$t9,
739 0x00000000, // 0x9c: dsll $t9,$t9,
740 0x00000000, // 0xa0: daddiu $t9,$t9,
741 0x0320f809, // 0xa4: jalr $t9
742 0x00000000, // 0xa8: nop
743 0xdfbf00c8, // 0xac: ld ra, 200(sp)
744 0xdfbe00c0, // 0xb0: ld fp, 192(sp)
745 0xdfb900b8, // 0xb4: ld t9, 184(sp)
746 0xdfb800b0, // 0xb8: ld t8, 176(sp)
747 0xdfb700a8, // 0xbc: ld s7, 168(sp)
748 0xdfb600a0, // 0xc0: ld s6, 160(sp)
749 0xdfb50098, // 0xc4: ld s5, 152(sp)
750 0xdfb40090, // 0xc8: ld s4, 144(sp)
751 0xdfb30088, // 0xcc: ld s3, 136(sp)
752 0xdfb20080, // 0xd0: ld s2, 128(sp)
753 0xdfb10078, // 0xd4: ld s1, 120(sp)
754 0xdfb00070, // 0xd8: ld s0, 112(sp)
755 0xdfaf0068, // 0xdc: ld t3, 104(sp)
756 0xdfae0060, // 0xe0: ld t2, 96(sp)
757 0xdfad0058, // 0xe4: ld t1, 88(sp)
758 0xdfac0050, // 0xe8: ld t0, 80(sp)
759 0xdfab0048, // 0xec: ld a7, 72(sp)
760 0xdfaa0040, // 0xf0: ld a6, 64(sp)
761 0xdfa90038, // 0xf4: ld a5, 56(sp)
762 0xdfa80030, // 0xf8: ld a4, 48(sp)
763 0xdfa70028, // 0xfc: ld a3, 40(sp)
764 0xdfa60020, // 0x100: ld a2, 32(sp)
765 0xdfa50018, // 0x104: ld a1, 24(sp)
766 0xdfa40010, // 0x108: ld a0, 16(sp)
767 0xdfa30008, // 0x10c: ld v1, 8(sp)
768 0x67bd00d0, // 0x110: daddiu $sp,$sp,208
769 0x0300f825, // 0x114: move $ra, $t8
770 0x03200008, // 0x118: jr $t9
771 0x0040c825, // 0x11c: move $t9, $v0
772 };
773
774 const unsigned ReentryFnAddrOffset = 0x8c; // JIT re-entry fn addr lui
775 const unsigned ReentryCtxAddrOffset = 0x6c; // JIT re-entry ctx addr lui
776
777 memcpy(ResolverWorkingMem, ResolverCode, sizeof(ResolverCode));
778
779 uint32_t ReentryCtxLUi =
780 0x3c040000 |
781 (((ReentryCtxAddr.getValue() + 0x800080008000) >> 48) & 0xFFFF);
782 uint32_t ReentryCtxDADDiu =
783 0x64840000 | (((ReentryCtxAddr.getValue() + 0x80008000) >> 32) & 0xFFFF);
784 uint32_t ReentryCtxDSLL = 0x00042438;
785 uint32_t ReentryCtxDADDiu2 =
786 0x64840000 | ((((ReentryCtxAddr.getValue() + 0x8000) >> 16) & 0xFFFF));
787 uint32_t ReentryCtxDSLL2 = 0x00042438;
788 uint32_t ReentryCtxDADDiu3 =
789 0x64840000 | (ReentryCtxAddr.getValue() & 0xFFFF);
790
791 memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxLUi,
792 sizeof(ReentryCtxLUi));
793 memcpy(ResolverWorkingMem + (ReentryCtxAddrOffset + 4), &ReentryCtxDADDiu,
794 sizeof(ReentryCtxDADDiu));
795 memcpy(ResolverWorkingMem + (ReentryCtxAddrOffset + 8), &ReentryCtxDSLL,
796 sizeof(ReentryCtxDSLL));
797 memcpy(ResolverWorkingMem + (ReentryCtxAddrOffset + 12), &ReentryCtxDADDiu2,
798 sizeof(ReentryCtxDADDiu2));
799 memcpy(ResolverWorkingMem + (ReentryCtxAddrOffset + 16), &ReentryCtxDSLL2,
800 sizeof(ReentryCtxDSLL2));
801 memcpy(ResolverWorkingMem + (ReentryCtxAddrOffset + 20), &ReentryCtxDADDiu3,
802 sizeof(ReentryCtxDADDiu3));
803
804 uint32_t ReentryFnLUi =
805 0x3c190000 |
806 (((ReentryFnAddr.getValue() + 0x800080008000) >> 48) & 0xFFFF);
807
808 uint32_t ReentryFnDADDiu =
809 0x67390000 | (((ReentryFnAddr.getValue() + 0x80008000) >> 32) & 0xFFFF);
810
811 uint32_t ReentryFnDSLL = 0x0019cc38;
812
813 uint32_t ReentryFnDADDiu2 =
814 0x67390000 | (((ReentryFnAddr.getValue() + 0x8000) >> 16) & 0xFFFF);
815
816 uint32_t ReentryFnDSLL2 = 0x0019cc38;
817
818 uint32_t ReentryFnDADDiu3 = 0x67390000 | (ReentryFnAddr.getValue() & 0xFFFF);
819
820 memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnLUi,
821 sizeof(ReentryFnLUi));
822 memcpy(ResolverWorkingMem + (ReentryFnAddrOffset + 4), &ReentryFnDADDiu,
823 sizeof(ReentryFnDADDiu));
824 memcpy(ResolverWorkingMem + (ReentryFnAddrOffset + 8), &ReentryFnDSLL,
825 sizeof(ReentryFnDSLL));
826 memcpy(ResolverWorkingMem + (ReentryFnAddrOffset + 12), &ReentryFnDADDiu2,
827 sizeof(ReentryFnDADDiu2));
828 memcpy(ResolverWorkingMem + (ReentryFnAddrOffset + 16), &ReentryFnDSLL2,
829 sizeof(ReentryFnDSLL2));
830 memcpy(ResolverWorkingMem + (ReentryFnAddrOffset + 20), &ReentryFnDADDiu3,
831 sizeof(ReentryFnDADDiu3));
832}
833
834void OrcMips64::writeTrampolines(char *TrampolineBlockWorkingMem,
835 ExecutorAddr TrampolineBlockTargetAddress,
836 ExecutorAddr ResolverAddr,
837 unsigned NumTrampolines) {
838
839 uint32_t *Trampolines =
840 reinterpret_cast<uint32_t *>(TrampolineBlockWorkingMem);
841
842 uint64_t HeighestAddr = ((ResolverAddr.getValue() + 0x800080008000) >> 48);
843 uint64_t HeigherAddr = ((ResolverAddr.getValue() + 0x80008000) >> 32);
844 uint64_t HiAddr = ((ResolverAddr.getValue() + 0x8000) >> 16);
845
846 for (unsigned I = 0; I < NumTrampolines; ++I) {
847 Trampolines[10 * I + 0] = 0x03e0c025; // move $t8,$ra
848 Trampolines[10 * I + 1] = 0x3c190000 | (HeighestAddr & 0xFFFF); // lui $t9,resolveAddr
849 Trampolines[10 * I + 2] = 0x67390000 | (HeigherAddr & 0xFFFF); // daddiu $t9,$t9,%higher(resolveAddr)
850 Trampolines[10 * I + 3] = 0x0019cc38; // dsll $t9,$t9,16
851 Trampolines[10 * I + 4] = 0x67390000 | (HiAddr & 0xFFFF); // daddiu $t9,$t9,%hi(ptr)
852 Trampolines[10 * I + 5] = 0x0019cc38; // dsll $t9,$t9,16
853 Trampolines[10 * I + 6] = 0x67390000 | (ResolverAddr.getValue() &
854 0xFFFF); // daddiu $t9,$t9,%lo(ptr)
855 Trampolines[10 * I + 7] = 0x0320f809; // jalr $t9
856 Trampolines[10 * I + 8] = 0x00000000; // nop
857 Trampolines[10 * I + 9] = 0x00000000; // nop
858 }
859}
860
861void OrcMips64::writeIndirectStubsBlock(char *StubsBlockWorkingMem,
862 ExecutorAddr StubsBlockTargetAddress,
863 ExecutorAddr PointersBlockTargetAddress,
864 unsigned NumStubs) {
865 // Stub format is:
866 //
867 // .section __orc_stubs
868 // stub1:
869 // lui $t9,ptr1
870 // dsll $t9,$t9,16
871 // daddiu $t9,$t9,%hi(ptr)
872 // dsll $t9,$t9,16
873 // ld $t9,%lo(ptr)
874 // jr $t9
875 // stub2:
876 // lui $t9,ptr1
877 // dsll $t9,$t9,16
878 // daddiu $t9,$t9,%hi(ptr)
879 // dsll $t9,$t9,16
880 // ld $t9,%lo(ptr)
881 // jr $t9
882 //
883 // ...
884 //
885 // .section __orc_ptrs
886 // ptr1:
887 // .dword 0x0
888 // ptr2:
889 // .dword 0x0
890 //
891 // ...
892
893 assert(stubAndPointerRangesOk<OrcMips64>(
894 StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) &&
895 "PointersBlock is out of range");
896
897 // Populate the stubs page stubs and mark it executable.
898 uint32_t *Stub = reinterpret_cast<uint32_t *>(StubsBlockWorkingMem);
899 uint64_t PtrAddr = PointersBlockTargetAddress.getValue();
900
901 for (unsigned I = 0; I < NumStubs; ++I, PtrAddr += 8) {
902 uint64_t HeighestAddr = ((PtrAddr + 0x800080008000) >> 48);
903 uint64_t HeigherAddr = ((PtrAddr + 0x80008000) >> 32);
904 uint64_t HiAddr = ((PtrAddr + 0x8000) >> 16);
905 Stub[8 * I + 0] = 0x3c190000 | (HeighestAddr & 0xFFFF); // lui $t9,ptr1
906 Stub[8 * I + 1] = 0x67390000 | (HeigherAddr & 0xFFFF); // daddiu $t9,$t9,%higher(ptr)
907 Stub[8 * I + 2] = 0x0019cc38; // dsll $t9,$t9,16
908 Stub[8 * I + 3] = 0x67390000 | (HiAddr & 0xFFFF); // daddiu $t9,$t9,%hi(ptr)
909 Stub[8 * I + 4] = 0x0019cc38; // dsll $t9,$t9,16
910 Stub[8 * I + 5] = 0xdf390000 | (PtrAddr & 0xFFFF); // ld $t9,%lo(ptr)
911 Stub[8 * I + 6] = 0x03200008; // jr $t9
912 Stub[8 * I + 7] = 0x00000000; // nop
913 }
914}
915
916void OrcRiscv64::writeResolverCode(char *ResolverWorkingMem,
917 ExecutorAddr ResolverTargetAddress,
918 ExecutorAddr ReentryFnAddr,
919 ExecutorAddr ReentryCtxAddr) {
920
921 const uint32_t ResolverCode[] = {
922 0xef810113, // 0x00: addi sp,sp,-264
923 0x00813023, // 0x04: sd s0,0(sp)
924 0x00913423, // 0x08: sd s1,8(sp)
925 0x01213823, // 0x0c: sd s2,16(sp)
926 0x01313c23, // 0x10: sd s3,24(sp)
927 0x03413023, // 0x14: sd s4,32(sp)
928 0x03513423, // 0x18: sd s5,40(sp)
929 0x03613823, // 0x1c: sd s6,48(sp)
930 0x03713c23, // 0x20: sd s7,56(sp)
931 0x05813023, // 0x24: sd s8,64(sp)
932 0x05913423, // 0x28: sd s9,72(sp)
933 0x05a13823, // 0x2c: sd s10,80(sp)
934 0x05b13c23, // 0x30: sd s11,88(sp)
935 0x06113023, // 0x34: sd ra,96(sp)
936 0x06a13423, // 0x38: sd a0,104(sp)
937 0x06b13823, // 0x3c: sd a1,112(sp)
938 0x06c13c23, // 0x40: sd a2,120(sp)
939 0x08d13023, // 0x44: sd a3,128(sp)
940 0x08e13423, // 0x48: sd a4,136(sp)
941 0x08f13823, // 0x4c: sd a5,144(sp)
942 0x09013c23, // 0x50: sd a6,152(sp)
943 0x0b113023, // 0x54: sd a7,160(sp)
944 0x0a813427, // 0x58: fsd fs0,168(sp)
945 0x0a913827, // 0x5c: fsd fs1,176(sp)
946 0x0b213c27, // 0x60: fsd fs2,184(sp)
947 0x0d313027, // 0x64: fsd fs3,192(sp)
948 0x0d413427, // 0x68: fsd fs4,200(sp)
949 0x0d513827, // 0x6c: fsd fs5,208(sp)
950 0x0d613c27, // 0x70: fsd fs6,216(sp)
951 0x0f713027, // 0x74: fsd fs7,224(sp)
952 0x0f813427, // 0x78: fsd fs8,232(sp)
953 0x0f913827, // 0x7c: fsd fs9,240(sp)
954 0x0fa13c27, // 0x80: fsd fs10,248(sp)
955 0x11b13027, // 0x84: fsd fs11,256(sp)
956 0x00000517, // 0x88: auipc a0,0x0
957 0x0b053503, // 0x8c: ld a0,176(a0) # 0x138
958 0x00030593, // 0x90: mv a1,t1
959 0xff458593, // 0x94: addi a1,a1,-12
960 0x00000617, // 0x98: auipc a2,0x0
961 0x0a863603, // 0x9c: ld a2,168(a2) # 0x140
962 0x000600e7, // 0xa0: jalr a2
963 0x00050293, // 0xa4: mv t0,a0
964 0x00013403, // 0xa8: ld s0,0(sp)
965 0x00813483, // 0xac: ld s1,8(sp)
966 0x01013903, // 0xb0: ld s2,16(sp)
967 0x01813983, // 0xb4: ld s3,24(sp)
968 0x02013a03, // 0xb8: ld s4,32(sp)
969 0x02813a83, // 0xbc: ld s5,40(sp)
970 0x03013b03, // 0xc0: ld s6,48(sp)
971 0x03813b83, // 0xc4: ld s7,56(sp)
972 0x04013c03, // 0xc8: ld s8,64(sp)
973 0x04813c83, // 0xcc: ld s9,72(sp)
974 0x05013d03, // 0xd0: ld s10,80(sp)
975 0x05813d83, // 0xd4: ld s11,88(sp)
976 0x06013083, // 0xd8: ld ra,96(sp)
977 0x06813503, // 0xdc: ld a0,104(sp)
978 0x07013583, // 0xe0: ld a1,112(sp)
979 0x07813603, // 0xe4: ld a2,120(sp)
980 0x08013683, // 0xe8: ld a3,128(sp)
981 0x08813703, // 0xec: ld a4,136(sp)
982 0x09013783, // 0xf0: ld a5,144(sp)
983 0x09813803, // 0xf4: ld a6,152(sp)
984 0x0a013883, // 0xf8: ld a7,160(sp)
985 0x0a813407, // 0xfc: fld fs0,168(sp)
986 0x0b013487, // 0x100: fld fs1,176(sp)
987 0x0b813907, // 0x104: fld fs2,184(sp)
988 0x0c013987, // 0x108: fld fs3,192(sp)
989 0x0c813a07, // 0x10c: fld fs4,200(sp)
990 0x0d013a87, // 0x110: fld fs5,208(sp)
991 0x0d813b07, // 0x114: fld fs6,216(sp)
992 0x0e013b87, // 0x118: fld fs7,224(sp)
993 0x0e813c07, // 0x11c: fld fs8,232(sp)
994 0x0f013c87, // 0x120: fld fs9,240(sp)
995 0x0f813d07, // 0x124: fld fs10,248(sp)
996 0x10013d87, // 0x128: fld fs11,256(sp)
997 0x10810113, // 0x12c: addi sp,sp,264
998 0x00028067, // 0x130: jr t0
999 0x12345678, // 0x134: padding to align at 8 byte
1000 0x12345678, // 0x138: Lreentry_ctx_ptr:
1001 0xdeadbeef, // 0x13c: .quad 0
1002 0x98765432, // 0x140: Lreentry_fn_ptr:
1003 0xcafef00d // 0x144: .quad 0
1004 };
1005
1006 const unsigned ReentryCtxAddrOffset = 0x138;
1007 const unsigned ReentryFnAddrOffset = 0x140;
1008
1009 memcpy(ResolverWorkingMem, ResolverCode, sizeof(ResolverCode));
1010 memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnAddr,
1011 sizeof(uint64_t));
1012 memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxAddr,
1013 sizeof(uint64_t));
1014}
1015
1016void OrcRiscv64::writeTrampolines(char *TrampolineBlockWorkingMem,
1017 ExecutorAddr TrampolineBlockTargetAddress,
1018 ExecutorAddr ResolverAddr,
1019 unsigned NumTrampolines) {
1020
1021 unsigned OffsetToPtr = alignTo(NumTrampolines * TrampolineSize, 8);
1022
1023 memcpy(TrampolineBlockWorkingMem + OffsetToPtr, &ResolverAddr,
1024 sizeof(uint64_t));
1025
1026 uint32_t *Trampolines =
1027 reinterpret_cast<uint32_t *>(TrampolineBlockWorkingMem);
1028 for (unsigned I = 0; I < NumTrampolines; ++I, OffsetToPtr -= TrampolineSize) {
1029 uint32_t Hi20 = (OffsetToPtr + 0x800) & 0xFFFFF000;
1030 uint32_t Lo12 = OffsetToPtr - Hi20;
1031 Trampolines[4 * I + 0] = 0x00000297 | Hi20; // auipc t0, %hi(Lptr)
1032 Trampolines[4 * I + 1] =
1033 0x0002b283 | ((Lo12 & 0xFFF) << 20); // ld t0, %lo(Lptr)
1034 Trampolines[4 * I + 2] = 0x00028367; // jalr t1, t0
1035 Trampolines[4 * I + 3] = 0xdeadface; // padding
1036 }
1037}
1038
1040 char *StubsBlockWorkingMem, ExecutorAddr StubsBlockTargetAddress,
1041 ExecutorAddr PointersBlockTargetAddress, unsigned NumStubs) {
1042 // Stub format is:
1043 //
1044 // .section __orc_stubs
1045 // stub1:
1046 // auipc t0, %hi(ptr1) ; PC-rel load of ptr1
1047 // ld t0, %lo(t0)
1048 // jr t0 ; Jump to resolver
1049 // .quad 0 ; Pad to 16 bytes
1050 // stub2:
1051 // auipc t0, %hi(ptr1) ; PC-rel load of ptr1
1052 // ld t0, %lo(t0)
1053 // jr t0 ; Jump to resolver
1054 // .quad 0
1055 //
1056 // ...
1057 //
1058 // .section __orc_ptrs
1059 // ptr1:
1060 // .quad 0x0
1061 // ptr2:
1062 // .quad 0x0
1063 //
1064 // ...
1065
1066 assert(stubAndPointerRangesOk<OrcRiscv64>(
1067 StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) &&
1068 "PointersBlock is out of range");
1069
1070 uint32_t *Stub = reinterpret_cast<uint32_t *>(StubsBlockWorkingMem);
1071
1072 for (unsigned I = 0; I < NumStubs; ++I) {
1073 uint64_t PtrDisplacement =
1074 PointersBlockTargetAddress - StubsBlockTargetAddress;
1075 uint32_t Hi20 = (PtrDisplacement + 0x800) & 0xFFFFF000;
1076 uint32_t Lo12 = PtrDisplacement - Hi20;
1077 Stub[4 * I + 0] = 0x00000297 | Hi20; // auipc t0, %hi(Lptr)
1078 Stub[4 * I + 1] = 0x0002b283 | ((Lo12 & 0xFFF) << 20); // ld t0, %lo(Lptr)
1079 Stub[4 * I + 2] = 0x00028067; // jr t0
1080 Stub[4 * I + 3] = 0xfeedbeef; // padding
1081 PointersBlockTargetAddress += PointerSize;
1082 StubsBlockTargetAddress += StubSize;
1083 }
1084}
1085
1086void OrcLoongArch64::writeResolverCode(char *ResolverWorkingMem,
1087 ExecutorAddr ResolverTargetAddress,
1088 ExecutorAddr ReentryFnAddr,
1089 ExecutorAddr ReentryCtxAddr) {
1090
1091 LLVM_DEBUG({
1092 dbgs() << "Writing resolver code to "
1093 << formatv("{0:x16}", ResolverTargetAddress) << "\n";
1094 });
1095
1096 const uint32_t ResolverCode[] = {
1097 0x02fde063, // 0x0: addi.d $sp, $sp, -136(0xf78)
1098 0x29c00061, // 0x4: st.d $ra, $sp, 0
1099 0x29c02064, // 0x8: st.d $a0, $sp, 8(0x8)
1100 0x29c04065, // 0xc: st.d $a1, $sp, 16(0x10)
1101 0x29c06066, // 0x10: st.d $a2, $sp, 24(0x18)
1102 0x29c08067, // 0x14: st.d $a3, $sp, 32(0x20)
1103 0x29c0a068, // 0x18: st.d $a4, $sp, 40(0x28)
1104 0x29c0c069, // 0x1c: st.d $a5, $sp, 48(0x30)
1105 0x29c0e06a, // 0x20: st.d $a6, $sp, 56(0x38)
1106 0x29c1006b, // 0x24: st.d $a7, $sp, 64(0x40)
1107 0x2bc12060, // 0x28: fst.d $fa0, $sp, 72(0x48)
1108 0x2bc14061, // 0x2c: fst.d $fa1, $sp, 80(0x50)
1109 0x2bc16062, // 0x30: fst.d $fa2, $sp, 88(0x58)
1110 0x2bc18063, // 0x34: fst.d $fa3, $sp, 96(0x60)
1111 0x2bc1a064, // 0x38: fst.d $fa4, $sp, 104(0x68)
1112 0x2bc1c065, // 0x3c: fst.d $fa5, $sp, 112(0x70)
1113 0x2bc1e066, // 0x40: fst.d $fa6, $sp, 120(0x78)
1114 0x2bc20067, // 0x44: fst.d $fa7, $sp, 128(0x80)
1115 0x1c000004, // 0x48: pcaddu12i $a0, 0
1116 0x28c1c084, // 0x4c: ld.d $a0, $a0, 112(0x70)
1117 0x001501a5, // 0x50: move $a1, $t1
1118 0x02ffd0a5, // 0x54: addi.d $a1, $a1, -12(0xff4)
1119 0x1c000006, // 0x58: pcaddu12i $a2, 0
1120 0x28c1a0c6, // 0x5c: ld.d $a2, $a2, 104(0x68)
1121 0x4c0000c1, // 0x60: jirl $ra, $a2, 0
1122 0x0015008c, // 0x64: move $t0, $a0
1123 0x2b820067, // 0x68: fld.d $fa7, $sp, 128(0x80)
1124 0x2b81e066, // 0x6c: fld.d $fa6, $sp, 120(0x78)
1125 0x2b81c065, // 0x70: fld.d $fa5, $sp, 112(0x70)
1126 0x2b81a064, // 0x74: fld.d $fa4, $sp, 104(0x68)
1127 0x2b818063, // 0x78: fld.d $fa3, $sp, 96(0x60)
1128 0x2b816062, // 0x7c: fld.d $fa2, $sp, 88(0x58)
1129 0x2b814061, // 0x80: fld.d $fa1, $sp, 80(0x50)
1130 0x2b812060, // 0x84: fld.d $fa0, $sp, 72(0x48)
1131 0x28c1006b, // 0x88: ld.d $a7, $sp, 64(0x40)
1132 0x28c0e06a, // 0x8c: ld.d $a6, $sp, 56(0x38)
1133 0x28c0c069, // 0x90: ld.d $a5, $sp, 48(0x30)
1134 0x28c0a068, // 0x94: ld.d $a4, $sp, 40(0x28)
1135 0x28c08067, // 0x98: ld.d $a3, $sp, 32(0x20)
1136 0x28c06066, // 0x9c: ld.d $a2, $sp, 24(0x18)
1137 0x28c04065, // 0xa0: ld.d $a1, $sp, 16(0x10)
1138 0x28c02064, // 0xa4: ld.d $a0, $sp, 8(0x8)
1139 0x28c00061, // 0xa8: ld.d $ra, $sp, 0
1140 0x02c22063, // 0xac: addi.d $sp, $sp, 136(0x88)
1141 0x4c000180, // 0xb0: jr $t0
1142 0x00000000, // 0xb4: padding to align at 8 bytes
1143 0x01234567, // 0xb8: Lreentry_ctx_ptr:
1144 0xdeedbeef, // 0xbc: .dword 0
1145 0x98765432, // 0xc0: Lreentry_fn_ptr:
1146 0xcafef00d, // 0xc4: .dword 0
1147 };
1148
1149 const unsigned ReentryCtxAddrOffset = 0xb8;
1150 const unsigned ReentryFnAddrOffset = 0xc0;
1151
1152 memcpy(ResolverWorkingMem, ResolverCode, sizeof(ResolverCode));
1153 memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnAddr,
1154 sizeof(uint64_t));
1155 memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxAddr,
1156 sizeof(uint64_t));
1157}
1158
1159void OrcLoongArch64::writeTrampolines(char *TrampolineBlockWorkingMem,
1160 ExecutorAddr TrampolineBlockTargetAddress,
1161 ExecutorAddr ResolverAddr,
1162 unsigned NumTrampolines) {
1163
1164 LLVM_DEBUG({
1165 dbgs() << "Writing trampoline code to "
1166 << formatv("{0:x16}", TrampolineBlockTargetAddress) << "\n";
1167 });
1168
1169 unsigned OffsetToPtr = alignTo(NumTrampolines * TrampolineSize, 8);
1170
1171 memcpy(TrampolineBlockWorkingMem + OffsetToPtr, &ResolverAddr,
1172 sizeof(uint64_t));
1173
1174 uint32_t *Trampolines =
1175 reinterpret_cast<uint32_t *>(TrampolineBlockWorkingMem);
1176 for (unsigned I = 0; I < NumTrampolines; ++I, OffsetToPtr -= TrampolineSize) {
1177 uint32_t Hi20 = (OffsetToPtr + 0x800) & 0xfffff000;
1178 uint32_t Lo12 = OffsetToPtr - Hi20;
1179 Trampolines[4 * I + 0] =
1180 0x1c00000c |
1181 (((Hi20 >> 12) & 0xfffff) << 5); // pcaddu12i $t0, %pc_hi20(Lptr)
1182 Trampolines[4 * I + 1] =
1183 0x28c0018c | ((Lo12 & 0xfff) << 10); // ld.d $t0, $t0, %pc_lo12(Lptr)
1184 Trampolines[4 * I + 2] = 0x4c00018d; // jirl $t1, $t0, 0
1185 Trampolines[4 * I + 3] = 0x0; // padding
1186 }
1187}
1188
1190 char *StubsBlockWorkingMem, ExecutorAddr StubsBlockTargetAddress,
1191 ExecutorAddr PointersBlockTargetAddress, unsigned NumStubs) {
1192 // Stub format is:
1193 //
1194 // .section __orc_stubs
1195 // stub1:
1196 // pcaddu12i $t0, %pc_hi20(ptr1) ; PC-rel load of ptr1
1197 // ld.d $t0, $t0, %pc_lo12(ptr1)
1198 // jr $t0 ; Jump to resolver
1199 // .dword 0 ; Pad to 16 bytes
1200 // stub2:
1201 // pcaddu12i $t0, %pc_hi20(ptr2) ; PC-rel load of ptr2
1202 // ld.d $t0, $t0, %pc_lo12(ptr2)
1203 // jr $t0 ; Jump to resolver
1204 // .dword 0 ; Pad to 16 bytes
1205 // ...
1206 //
1207 // .section __orc_ptrs
1208 // ptr1:
1209 // .dword 0x0
1210 // ptr2:
1211 // .dword 0x0
1212 // ...
1213 LLVM_DEBUG({
1214 dbgs() << "Writing stubs code to "
1215 << formatv("{0:x16}", StubsBlockTargetAddress) << "\n";
1216 });
1217 assert(stubAndPointerRangesOk<OrcLoongArch64>(
1218 StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) &&
1219 "PointersBlock is out of range");
1220
1221 uint32_t *Stub = reinterpret_cast<uint32_t *>(StubsBlockWorkingMem);
1222
1223 for (unsigned I = 0; I < NumStubs; ++I) {
1224 uint64_t PtrDisplacement =
1225 PointersBlockTargetAddress - StubsBlockTargetAddress;
1226 uint32_t Hi20 = (PtrDisplacement + 0x800) & 0xfffff000;
1227 uint32_t Lo12 = PtrDisplacement - Hi20;
1228 Stub[4 * I + 0] = 0x1c00000c | (((Hi20 >> 12) & 0xfffff)
1229 << 5); // pcaddu12i $t0, %pc_hi20(Lptr)
1230 Stub[4 * I + 1] =
1231 0x28c0018c | ((Lo12 & 0xfff) << 10); // ld.d $t0, $t0, %pc_lo12(Lptr)
1232 Stub[4 * I + 2] = 0x4c000180; // jr $t0
1233 Stub[4 * I + 3] = 0x0; // padding
1234 PointersBlockTargetAddress += PointerSize;
1235 StubsBlockTargetAddress += StubSize;
1236 }
1237}
1238
1239} // End namespace orc.
1240} // End namespace llvm.
static std::optional< bool > isBigEndian(const SmallDenseMap< int64_t, int64_t, 8 > &MemOffset2Idx, int64_t LowestIdx)
Given a map from byte offsets in memory to indices in a load/store, determine if that map corresponds...
#define LLVM_DEBUG(X)
Definition: Debug.h:101
#define I(x, y, z)
Definition: MD5.cpp:58
static bool stubAndPointerRangesOk(ExecutorAddr StubBlockAddr, ExecutorAddr PointerBlockAddr, unsigned NumStubs)
Provides a library for accessing information about this process and other processes on the operating ...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Represents an address in the executor process.
uint64_t getValue() const
static constexpr unsigned PointerSize
Definition: OrcABISupport.h:91
static void writeResolverCode(char *ResolverWorkingMem, ExecutorAddr ResolverTargetAddress, ExecutorAddr ReentryFnAddr, ExecutorAddr RentryCtxAddr)
Write the resolver code into the given memory.
static void writeTrampolines(char *TrampolineBlockWorkingMem, ExecutorAddr TrampolineBlockTargetAddress, ExecutorAddr ResolverAddr, unsigned NumTrampolines)
Write the requested number of trampolines into the given memory, which must be big enough to hold 1 p...
static constexpr unsigned TrampolineSize
Definition: OrcABISupport.h:92
static constexpr unsigned StubSize
Definition: OrcABISupport.h:93
static void writeIndirectStubsBlock(char *StubsBlockWorkingMem, ExecutorAddr StubsBlockTargetAddress, ExecutorAddr PointersBlockTargetAddress, unsigned MinStubs)
Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem.
static void writeResolverCode(char *ResolverWorkingMem, ExecutorAddr ResolverTargetAddress, ExecutorAddr ReentryFnAddr, ExecutorAddr ReentryCtxAddr)
Write the resolver code into the given memory.
static void writeTrampolines(char *TrampolineBlockWorkingMem, ExecutorAddr TrampolineBlockTargetAddress, ExecutorAddr ResolverAddr, unsigned NumTrampolines)
Write the requested number of trampolines into the given memory, which must be big enough to hold 1 p...
static void writeIndirectStubsBlock(char *StubsBlockWorkingMem, ExecutorAddr StubsBlockTargetAddress, ExecutorAddr PointersBlockTargetAddress, unsigned NumStubs)
Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem.
static constexpr unsigned TrampolineSize
static constexpr unsigned StubSize
static constexpr unsigned PointerSize
static constexpr unsigned TrampolineSize
static void writeResolverCode(char *ResolverWorkingMem, ExecutorAddr ResolverTargetAddress, ExecutorAddr ReentryFnAddr, ExecutorAddr ReentryCtxAddr)
Write the resolver code into the given memory.
static void writeIndirectStubsBlock(char *StubsBlockWorkingMem, ExecutorAddr StubsBlockTargetAddress, ExecutorAddr PointersBlockTargetAddress, unsigned NumStubs)
Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem.
static void writeTrampolines(char *TrampolineBlockWorkingMem, ExecutorAddr TrampolineBlockTargetAddress, ExecutorAddr ResolverFnAddr, unsigned NumTrampolines)
Write the requested number of trampolines into the given memory, which must be big enough to hold 1 p...
static void writeResolverCode(char *ResolverBlockWorkingMem, ExecutorAddr ResolverBlockTargetAddress, ExecutorAddr ReentryFnAddr, ExecutorAddr ReentryCtxAddr, bool isBigEndian)
Write the resolver code into the given memory.
static void writeIndirectStubsBlock(char *StubsBlockWorkingMem, ExecutorAddr StubsBlockTargetAddress, ExecutorAddr PointersBlockTargetAddress, unsigned NumStubs)
Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem.
static void writeTrampolines(char *TrampolineBlockWorkingMem, ExecutorAddr TrampolineBlockTargetAddress, ExecutorAddr ResolverAddr, unsigned NumTrampolines)
Write the requested number of trampolines into the given memory, which must be big enough to hold 1 p...
static void writeIndirectStubsBlock(char *StubsBlockWorkingMem, ExecutorAddr StubsBlockTargetAddress, ExecutorAddr PointersBlockTargetAddress, unsigned NumStubs)
Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem.
static void writeTrampolines(char *TrampolineBlockWorkingMem, ExecutorAddr TrampolineBlockTargetAddress, ExecutorAddr ResolverFnAddr, unsigned NumTrampolines)
Write the requested number of trampolines into the given memory, which must be big enough to hold 1 p...
static void writeResolverCode(char *ResolverWorkingMem, ExecutorAddr ResolverTargetAddress, ExecutorAddr ReentryFnAddr, ExecutorAddr ReentryCtxAddr)
Write the resolver code into the given memory.
static constexpr unsigned StubSize
static constexpr unsigned TrampolineSize
static void writeIndirectStubsBlock(char *StubsBlockWorkingMem, ExecutorAddr StubsBlockTargetAddress, ExecutorAddr PointersBlockTargetAddress, unsigned NumStubs)
Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem.
static void writeTrampolines(char *TrampolineBlockWorkingMem, ExecutorAddr TrampolineBlockTargetAddress, ExecutorAddr ResolverFnAddr, unsigned NumTrampolines)
Write the requested number of trampolines into the given memory, which must be big enough to hold 1 p...
static constexpr unsigned PointerSize
static void writeResolverCode(char *ResolverWorkingMem, ExecutorAddr ResolverTargetAddress, ExecutorAddr ReentryFnAddr, ExecutorAddr ReentryCtxAddr)
Write the resolver code into the given memory.
static constexpr unsigned PointerSize
static constexpr unsigned StubSize
static void writeIndirectStubsBlock(char *StubsBlockWorkingMem, ExecutorAddr StubsBlockTargetAddress, ExecutorAddr PointersBlockTargetAddress, unsigned NumStubs)
Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem.
static void writeTrampolines(char *TrampolineBlockWorkingMem, ExecutorAddr TrampolineBlockTargetAddress, ExecutorAddr ResolverAddr, unsigned NumTrampolines)
Write the requested number of trampolines into the given memory, which must be big enough to hold 1 p...
static constexpr unsigned TrampolineSize
static void writeResolverCode(char *ResolverWorkingMem, ExecutorAddr ResolverTargetAddress, ExecutorAddr ReentryFnAddr, ExecutorAddr ReentryCtxAddr)
Write the resolver code into the given memory.
static void writeResolverCode(char *ResolverWorkingMem, ExecutorAddr ResolverTargetAddress, ExecutorAddr ReentryFnAddr, ExecutorAddr ReentryCtxAddr)
Write the resolver code into the given memory.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155