Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 14 | pmbaty | 1 | //===- OrcABISupport.h - ABI support code -----------------------*- C++ -*-===// |
| 2 | // |
||
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
||
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
||
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
||
| 6 | // |
||
| 7 | //===----------------------------------------------------------------------===// |
||
| 8 | // |
||
| 9 | // ABI specific code for Orc, e.g. callback assembly. |
||
| 10 | // |
||
| 11 | // ABI classes should be part of the JIT *target* process, not the host |
||
| 12 | // process (except where you're doing hosted JITing and the two are one and the |
||
| 13 | // same). |
||
| 14 | // |
||
| 15 | //===----------------------------------------------------------------------===// |
||
| 16 | |||
| 17 | #ifndef LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H |
||
| 18 | #define LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H |
||
| 19 | |||
| 20 | #include "llvm/ExecutionEngine/JITSymbol.h" |
||
| 21 | #include "llvm/Support/Error.h" |
||
| 22 | #include "llvm/Support/ErrorHandling.h" |
||
| 23 | #include "llvm/Support/MathExtras.h" |
||
| 24 | #include <cstdint> |
||
| 25 | |||
| 26 | namespace llvm { |
||
| 27 | namespace orc { |
||
| 28 | |||
| 29 | struct IndirectStubsAllocationSizes { |
||
| 30 | uint64_t StubBytes = 0; |
||
| 31 | uint64_t PointerBytes = 0; |
||
| 32 | unsigned NumStubs = 0; |
||
| 33 | }; |
||
| 34 | |||
| 35 | template <typename ORCABI> |
||
| 36 | IndirectStubsAllocationSizes |
||
| 37 | getIndirectStubsBlockSizes(unsigned MinStubs, unsigned RoundToMultipleOf = 0) { |
||
| 38 | assert( |
||
| 39 | (RoundToMultipleOf == 0 || (RoundToMultipleOf % ORCABI::StubSize == 0)) && |
||
| 40 | "RoundToMultipleOf is not a multiple of stub size"); |
||
| 41 | uint64_t StubBytes = MinStubs * ORCABI::StubSize; |
||
| 42 | if (RoundToMultipleOf) |
||
| 43 | StubBytes = alignTo(StubBytes, RoundToMultipleOf); |
||
| 44 | unsigned NumStubs = StubBytes / ORCABI::StubSize; |
||
| 45 | uint64_t PointerBytes = NumStubs * ORCABI::PointerSize; |
||
| 46 | return {StubBytes, PointerBytes, NumStubs}; |
||
| 47 | } |
||
| 48 | |||
| 49 | /// Generic ORC ABI support. |
||
| 50 | /// |
||
| 51 | /// This class can be substituted as the target architecture support class for |
||
| 52 | /// ORC templates that require one (e.g. IndirectStubsManagers). It does not |
||
| 53 | /// support lazy JITing however, and any attempt to use that functionality |
||
| 54 | /// will result in execution of an llvm_unreachable. |
||
| 55 | class OrcGenericABI { |
||
| 56 | public: |
||
| 57 | static constexpr unsigned PointerSize = sizeof(uintptr_t); |
||
| 58 | static constexpr unsigned TrampolineSize = 1; |
||
| 59 | static constexpr unsigned StubSize = 1; |
||
| 60 | static constexpr unsigned StubToPointerMaxDisplacement = 1; |
||
| 61 | static constexpr unsigned ResolverCodeSize = 1; |
||
| 62 | |||
| 63 | static void writeResolverCode(char *ResolveWorkingMem, |
||
| 64 | JITTargetAddress ResolverTargetAddr, |
||
| 65 | JITTargetAddress ReentryFnAddr, |
||
| 66 | JITTargetAddress ReentryCtxAddr) { |
||
| 67 | llvm_unreachable("writeResolverCode is not supported by the generic host " |
||
| 68 | "support class"); |
||
| 69 | } |
||
| 70 | |||
| 71 | static void writeTrampolines(char *TrampolineBlockWorkingMem, |
||
| 72 | JITTargetAddress TrampolineBlockTargetAddr, |
||
| 73 | JITTargetAddress ResolverAddr, |
||
| 74 | unsigned NumTrampolines) { |
||
| 75 | llvm_unreachable("writeTrampolines is not supported by the generic host " |
||
| 76 | "support class"); |
||
| 77 | } |
||
| 78 | |||
| 79 | static void writeIndirectStubsBlock( |
||
| 80 | char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress, |
||
| 81 | JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs) { |
||
| 82 | llvm_unreachable( |
||
| 83 | "writeIndirectStubsBlock is not supported by the generic host " |
||
| 84 | "support class"); |
||
| 85 | } |
||
| 86 | }; |
||
| 87 | |||
| 88 | class OrcAArch64 { |
||
| 89 | public: |
||
| 90 | static constexpr unsigned PointerSize = 8; |
||
| 91 | static constexpr unsigned TrampolineSize = 12; |
||
| 92 | static constexpr unsigned StubSize = 8; |
||
| 93 | static constexpr unsigned StubToPointerMaxDisplacement = 1U << 27; |
||
| 94 | static constexpr unsigned ResolverCodeSize = 0x120; |
||
| 95 | |||
| 96 | /// Write the resolver code into the given memory. The user is |
||
| 97 | /// responsible for allocating the memory and setting permissions. |
||
| 98 | /// |
||
| 99 | /// ReentryFnAddr should be the address of a function whose signature matches |
||
| 100 | /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr |
||
| 101 | /// argument of writeResolverCode will be passed as the second argument to |
||
| 102 | /// the function at ReentryFnAddr. |
||
| 103 | static void writeResolverCode(char *ResolverWorkingMem, |
||
| 104 | JITTargetAddress ResolverTargetAddress, |
||
| 105 | JITTargetAddress ReentryFnAddr, |
||
| 106 | JITTargetAddress RentryCtxAddr); |
||
| 107 | |||
| 108 | /// Write the requested number of trampolines into the given memory, |
||
| 109 | /// which must be big enough to hold 1 pointer, plus NumTrampolines |
||
| 110 | /// trampolines. |
||
| 111 | static void writeTrampolines(char *TrampolineBlockWorkingMem, |
||
| 112 | JITTargetAddress TrampolineBlockTargetAddress, |
||
| 113 | JITTargetAddress ResolverAddr, |
||
| 114 | unsigned NumTrampolines); |
||
| 115 | |||
| 116 | /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem. |
||
| 117 | /// Stubs will be written as if linked at StubsBlockTargetAddress, with the |
||
| 118 | /// Nth stub using the Nth pointer in memory starting at |
||
| 119 | /// PointersBlockTargetAddress. |
||
| 120 | static void writeIndirectStubsBlock( |
||
| 121 | char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress, |
||
| 122 | JITTargetAddress PointersBlockTargetAddress, unsigned MinStubs); |
||
| 123 | }; |
||
| 124 | |||
| 125 | /// X86_64 code that's common to all ABIs. |
||
| 126 | /// |
||
| 127 | /// X86_64 supports lazy JITing. |
||
| 128 | class OrcX86_64_Base { |
||
| 129 | public: |
||
| 130 | static constexpr unsigned PointerSize = 8; |
||
| 131 | static constexpr unsigned TrampolineSize = 8; |
||
| 132 | static constexpr unsigned StubSize = 8; |
||
| 133 | static constexpr unsigned StubToPointerMaxDisplacement = 1 << 31; |
||
| 134 | |||
| 135 | /// Write the requested number of trampolines into the given memory, |
||
| 136 | /// which must be big enough to hold 1 pointer, plus NumTrampolines |
||
| 137 | /// trampolines. |
||
| 138 | static void writeTrampolines(char *TrampolineBlockWorkingMem, |
||
| 139 | JITTargetAddress TrampolineBlockTargetAddress, |
||
| 140 | JITTargetAddress ResolverAddr, |
||
| 141 | unsigned NumTrampolines); |
||
| 142 | |||
| 143 | /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem. |
||
| 144 | /// Stubs will be written as if linked at StubsBlockTargetAddress, with the |
||
| 145 | /// Nth stub using the Nth pointer in memory starting at |
||
| 146 | /// PointersBlockTargetAddress. |
||
| 147 | static void writeIndirectStubsBlock( |
||
| 148 | char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress, |
||
| 149 | JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs); |
||
| 150 | }; |
||
| 151 | |||
| 152 | /// X86_64 support for SysV ABI (Linux, MacOSX). |
||
| 153 | /// |
||
| 154 | /// X86_64_SysV supports lazy JITing. |
||
| 155 | class OrcX86_64_SysV : public OrcX86_64_Base { |
||
| 156 | public: |
||
| 157 | static constexpr unsigned ResolverCodeSize = 0x6C; |
||
| 158 | |||
| 159 | /// Write the resolver code into the given memory. The user is |
||
| 160 | /// responsible for allocating the memory and setting permissions. |
||
| 161 | /// |
||
| 162 | /// ReentryFnAddr should be the address of a function whose signature matches |
||
| 163 | /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr |
||
| 164 | /// argument of writeResolverCode will be passed as the second argument to |
||
| 165 | /// the function at ReentryFnAddr. |
||
| 166 | static void writeResolverCode(char *ResolverWorkingMem, |
||
| 167 | JITTargetAddress ResolverTargetAddress, |
||
| 168 | JITTargetAddress ReentryFnAddr, |
||
| 169 | JITTargetAddress ReentryCtxAddr); |
||
| 170 | }; |
||
| 171 | |||
| 172 | /// X86_64 support for Win32. |
||
| 173 | /// |
||
| 174 | /// X86_64_Win32 supports lazy JITing. |
||
| 175 | class OrcX86_64_Win32 : public OrcX86_64_Base { |
||
| 176 | public: |
||
| 177 | static constexpr unsigned ResolverCodeSize = 0x74; |
||
| 178 | |||
| 179 | /// Write the resolver code into the given memory. The user is |
||
| 180 | /// responsible for allocating the memory and setting permissions. |
||
| 181 | /// |
||
| 182 | /// ReentryFnAddr should be the address of a function whose signature matches |
||
| 183 | /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr |
||
| 184 | /// argument of writeResolverCode will be passed as the second argument to |
||
| 185 | /// the function at ReentryFnAddr. |
||
| 186 | static void writeResolverCode(char *ResolverWorkingMem, |
||
| 187 | JITTargetAddress ResolverTargetAddress, |
||
| 188 | JITTargetAddress ReentryFnAddr, |
||
| 189 | JITTargetAddress ReentryCtxAddr); |
||
| 190 | }; |
||
| 191 | |||
| 192 | /// I386 support. |
||
| 193 | /// |
||
| 194 | /// I386 supports lazy JITing. |
||
| 195 | class OrcI386 { |
||
| 196 | public: |
||
| 197 | static constexpr unsigned PointerSize = 4; |
||
| 198 | static constexpr unsigned TrampolineSize = 8; |
||
| 199 | static constexpr unsigned StubSize = 8; |
||
| 200 | static constexpr unsigned StubToPointerMaxDisplacement = 1 << 31; |
||
| 201 | static constexpr unsigned ResolverCodeSize = 0x4a; |
||
| 202 | |||
| 203 | /// Write the resolver code into the given memory. The user is |
||
| 204 | /// responsible for allocating the memory and setting permissions. |
||
| 205 | /// |
||
| 206 | /// ReentryFnAddr should be the address of a function whose signature matches |
||
| 207 | /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr |
||
| 208 | /// argument of writeResolverCode will be passed as the second argument to |
||
| 209 | /// the function at ReentryFnAddr. |
||
| 210 | static void writeResolverCode(char *ResolverWorkingMem, |
||
| 211 | JITTargetAddress ResolverTargetAddress, |
||
| 212 | JITTargetAddress ReentryFnAddr, |
||
| 213 | JITTargetAddress ReentryCtxAddr); |
||
| 214 | |||
| 215 | /// Write the requested number of trampolines into the given memory, |
||
| 216 | /// which must be big enough to hold 1 pointer, plus NumTrampolines |
||
| 217 | /// trampolines. |
||
| 218 | static void writeTrampolines(char *TrampolineBlockWorkingMem, |
||
| 219 | JITTargetAddress TrampolineBlockTargetAddress, |
||
| 220 | JITTargetAddress ResolverAddr, |
||
| 221 | unsigned NumTrampolines); |
||
| 222 | |||
| 223 | /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem. |
||
| 224 | /// Stubs will be written as if linked at StubsBlockTargetAddress, with the |
||
| 225 | /// Nth stub using the Nth pointer in memory starting at |
||
| 226 | /// PointersBlockTargetAddress. |
||
| 227 | static void writeIndirectStubsBlock( |
||
| 228 | char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress, |
||
| 229 | JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs); |
||
| 230 | }; |
||
| 231 | |||
| 232 | // @brief Mips32 support. |
||
| 233 | // |
||
| 234 | // Mips32 supports lazy JITing. |
||
| 235 | class OrcMips32_Base { |
||
| 236 | public: |
||
| 237 | static constexpr unsigned PointerSize = 4; |
||
| 238 | static constexpr unsigned TrampolineSize = 20; |
||
| 239 | static constexpr unsigned StubSize = 8; |
||
| 240 | static constexpr unsigned StubToPointerMaxDisplacement = 1 << 31; |
||
| 241 | static constexpr unsigned ResolverCodeSize = 0xfc; |
||
| 242 | |||
| 243 | /// Write the requested number of trampolines into the given memory, |
||
| 244 | /// which must be big enough to hold 1 pointer, plus NumTrampolines |
||
| 245 | /// trampolines. |
||
| 246 | static void writeTrampolines(char *TrampolineBlockWorkingMem, |
||
| 247 | JITTargetAddress TrampolineBlockTargetAddress, |
||
| 248 | JITTargetAddress ResolverAddr, |
||
| 249 | unsigned NumTrampolines); |
||
| 250 | |||
| 251 | /// Write the resolver code into the given memory. The user is |
||
| 252 | /// responsible for allocating the memory and setting permissions. |
||
| 253 | /// |
||
| 254 | /// ReentryFnAddr should be the address of a function whose signature matches |
||
| 255 | /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr |
||
| 256 | /// argument of writeResolverCode will be passed as the second argument to |
||
| 257 | /// the function at ReentryFnAddr. |
||
| 258 | static void writeResolverCode(char *ResolverBlockWorkingMem, |
||
| 259 | JITTargetAddress ResolverBlockTargetAddress, |
||
| 260 | JITTargetAddress ReentryFnAddr, |
||
| 261 | JITTargetAddress ReentryCtxAddr, |
||
| 262 | bool isBigEndian); |
||
| 263 | /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem. |
||
| 264 | /// Stubs will be written as if linked at StubsBlockTargetAddress, with the |
||
| 265 | /// Nth stub using the Nth pointer in memory starting at |
||
| 266 | /// PointersBlockTargetAddress. |
||
| 267 | static void writeIndirectStubsBlock( |
||
| 268 | char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress, |
||
| 269 | JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs); |
||
| 270 | }; |
||
| 271 | |||
| 272 | class OrcMips32Le : public OrcMips32_Base { |
||
| 273 | public: |
||
| 274 | static void writeResolverCode(char *ResolverWorkingMem, |
||
| 275 | JITTargetAddress ResolverTargetAddress, |
||
| 276 | JITTargetAddress ReentryFnAddr, |
||
| 277 | JITTargetAddress ReentryCtxAddr) { |
||
| 278 | OrcMips32_Base::writeResolverCode(ResolverWorkingMem, ResolverTargetAddress, |
||
| 279 | ReentryFnAddr, ReentryCtxAddr, false); |
||
| 280 | } |
||
| 281 | }; |
||
| 282 | |||
| 283 | class OrcMips32Be : public OrcMips32_Base { |
||
| 284 | public: |
||
| 285 | static void writeResolverCode(char *ResolverWorkingMem, |
||
| 286 | JITTargetAddress ResolverTargetAddress, |
||
| 287 | JITTargetAddress ReentryFnAddr, |
||
| 288 | JITTargetAddress ReentryCtxAddr) { |
||
| 289 | OrcMips32_Base::writeResolverCode(ResolverWorkingMem, ResolverTargetAddress, |
||
| 290 | ReentryFnAddr, ReentryCtxAddr, true); |
||
| 291 | } |
||
| 292 | }; |
||
| 293 | |||
| 294 | // @brief Mips64 support. |
||
| 295 | // |
||
| 296 | // Mips64 supports lazy JITing. |
||
| 297 | class OrcMips64 { |
||
| 298 | public: |
||
| 299 | static constexpr unsigned PointerSize = 8; |
||
| 300 | static constexpr unsigned TrampolineSize = 40; |
||
| 301 | static constexpr unsigned StubSize = 32; |
||
| 302 | static constexpr unsigned StubToPointerMaxDisplacement = 1 << 31; |
||
| 303 | static constexpr unsigned ResolverCodeSize = 0x120; |
||
| 304 | |||
| 305 | /// Write the resolver code into the given memory. The user is |
||
| 306 | /// responsible for allocating the memory and setting permissions. |
||
| 307 | /// |
||
| 308 | /// ReentryFnAddr should be the address of a function whose signature matches |
||
| 309 | /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr |
||
| 310 | /// argument of writeResolverCode will be passed as the second argument to |
||
| 311 | /// the function at ReentryFnAddr. |
||
| 312 | static void writeResolverCode(char *ResolverWorkingMem, |
||
| 313 | JITTargetAddress ResolverTargetAddress, |
||
| 314 | JITTargetAddress ReentryFnAddr, |
||
| 315 | JITTargetAddress ReentryCtxAddr); |
||
| 316 | |||
| 317 | /// Write the requested number of trampolines into the given memory, |
||
| 318 | /// which must be big enough to hold 1 pointer, plus NumTrampolines |
||
| 319 | /// trampolines. |
||
| 320 | static void writeTrampolines(char *TrampolineBlockWorkingMem, |
||
| 321 | JITTargetAddress TrampolineBlockTargetAddress, |
||
| 322 | JITTargetAddress ResolverFnAddr, |
||
| 323 | unsigned NumTrampolines); |
||
| 324 | /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem. |
||
| 325 | /// Stubs will be written as if linked at StubsBlockTargetAddress, with the |
||
| 326 | /// Nth stub using the Nth pointer in memory starting at |
||
| 327 | /// PointersBlockTargetAddress. |
||
| 328 | static void writeIndirectStubsBlock( |
||
| 329 | char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress, |
||
| 330 | JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs); |
||
| 331 | }; |
||
| 332 | |||
| 333 | // @brief riscv64 support. |
||
| 334 | // |
||
| 335 | // RISC-V 64 supports lazy JITing. |
||
| 336 | class OrcRiscv64 { |
||
| 337 | public: |
||
| 338 | static constexpr unsigned PointerSize = 8; |
||
| 339 | static constexpr unsigned TrampolineSize = 16; |
||
| 340 | static constexpr unsigned StubSize = 16; |
||
| 341 | static constexpr unsigned StubToPointerMaxDisplacement = 1 << 31; |
||
| 342 | static constexpr unsigned ResolverCodeSize = 0x148; |
||
| 343 | |||
| 344 | /// Write the resolver code into the given memory. The user is |
||
| 345 | /// responsible for allocating the memory and setting permissions. |
||
| 346 | /// |
||
| 347 | /// ReentryFnAddr should be the address of a function whose signature matches |
||
| 348 | /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr |
||
| 349 | /// argument of writeResolverCode will be passed as the second argument to |
||
| 350 | /// the function at ReentryFnAddr. |
||
| 351 | static void writeResolverCode(char *ResolverWorkingMem, |
||
| 352 | JITTargetAddress ResolverTargetAddress, |
||
| 353 | JITTargetAddress ReentryFnAddr, |
||
| 354 | JITTargetAddress ReentryCtxAddr); |
||
| 355 | |||
| 356 | /// Write the requested number of trampolines into the given memory, |
||
| 357 | /// which must be big enough to hold 1 pointer, plus NumTrampolines |
||
| 358 | /// trampolines. |
||
| 359 | static void writeTrampolines(char *TrampolineBlockWorkingMem, |
||
| 360 | JITTargetAddress TrampolineBlockTargetAddress, |
||
| 361 | JITTargetAddress ResolverFnAddr, |
||
| 362 | unsigned NumTrampolines); |
||
| 363 | /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem. |
||
| 364 | /// Stubs will be written as if linked at StubsBlockTargetAddress, with the |
||
| 365 | /// Nth stub using the Nth pointer in memory starting at |
||
| 366 | /// PointersBlockTargetAddress. |
||
| 367 | static void writeIndirectStubsBlock( |
||
| 368 | char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress, |
||
| 369 | JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs); |
||
| 370 | }; |
||
| 371 | |||
| 372 | // @brief loongarch64 support. |
||
| 373 | // |
||
| 374 | // LoongArch 64 supports lazy JITing. |
||
| 375 | class OrcLoongArch64 { |
||
| 376 | public: |
||
| 377 | static constexpr unsigned PointerSize = 8; |
||
| 378 | static constexpr unsigned TrampolineSize = 16; |
||
| 379 | static constexpr unsigned StubSize = 16; |
||
| 380 | static constexpr unsigned StubToPointerMaxDisplacement = 1 << 31; |
||
| 381 | static constexpr unsigned ResolverCodeSize = 0xc8; |
||
| 382 | |||
| 383 | /// Write the resolver code into the given memory. The user is |
||
| 384 | /// responsible for allocating the memory and setting permissions. |
||
| 385 | /// |
||
| 386 | /// ReentryFnAddr should be the address of a function whose signature matches |
||
| 387 | /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr |
||
| 388 | /// argument of writeResolverCode will be passed as the second argument to |
||
| 389 | /// the function at ReentryFnAddr. |
||
| 390 | static void writeResolverCode(char *ResolverWorkingMem, |
||
| 391 | JITTargetAddress ResolverTargetAddress, |
||
| 392 | JITTargetAddress ReentryFnAddr, |
||
| 393 | JITTargetAddress ReentryCtxAddr); |
||
| 394 | |||
| 395 | /// Write the requested number of trampolines into the given memory, |
||
| 396 | /// which must be big enough to hold 1 pointer, plus NumTrampolines |
||
| 397 | /// trampolines. |
||
| 398 | static void writeTrampolines(char *TrampolineBlockWorkingMem, |
||
| 399 | JITTargetAddress TrampolineBlockTargetAddress, |
||
| 400 | JITTargetAddress ResolverFnAddr, |
||
| 401 | unsigned NumTrampolines); |
||
| 402 | |||
| 403 | /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem. |
||
| 404 | /// Stubs will be written as if linked at StubsBlockTargetAddress, with the |
||
| 405 | /// Nth stub using the Nth pointer in memory starting at |
||
| 406 | /// PointersBlockTargetAddress. |
||
| 407 | static void writeIndirectStubsBlock( |
||
| 408 | char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress, |
||
| 409 | JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs); |
||
| 410 | }; |
||
| 411 | |||
| 412 | } // end namespace orc |
||
| 413 | } // end namespace llvm |
||
| 414 | |||
| 415 | #endif // LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H |