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