//============================================================================= // Indirect Call Dispatch // // REX_LOOKUP_FUNC indexes into the per-module dispatch table at // IMAGE_BASE + IMAGE_SIZE. REX_CALL_INDIRECT_FUNC bounds-checks the target // against the caller's [REX_CODE_BASE, REX_CODE_BASE + REX_CODE_SIZE + // REX_THUNK_RESERVE_SIZE) range; out-of-bounds targets and in-bounds // unregistered slots fall back to rex::runtime::ResolveIndirectFunction, // which queries the global FunctionDispatcher across every loaded module. //============================================================================= #ifdef REXGLUE_ENABLE_PROFILING #include #define REX_PROFILE_INDIRECT_DISPATCH() PROFILE_FUNCTION_DISPATCHED() #else #define REX_PROFILE_INDIRECT_DISPATCH() #endif #define REX_LOOKUP_FUNC(x, y) \ (*(PPCFunc**)(x + REX_IMAGE_BASE + REX_IMAGE_SIZE + (u64(u32(y) - REX_CODE_BASE) * 2))) #define REX_CALL_INDIRECT_FUNC(x) \ do { \ REX_PROFILE_INDIRECT_DISPATCH(); \ uint32_t rex_indirect_target_ = (uint32_t)(x); \ PPCFunc* rex_indirect_func_; \ if ((uint32_t)(rex_indirect_target_ - REX_CODE_BASE) < \ REX_CODE_SIZE + REX_THUNK_RESERVE_SIZE) [[likely]] { \ rex_indirect_func_ = REX_LOOKUP_FUNC(base, rex_indirect_target_); \ } else { \ rex_indirect_func_ = nullptr; \ } \ if (!rex_indirect_func_) [[unlikely]] { \ ctx.last_indirect_target = rex_indirect_target_; \ rex_indirect_func_ = rex::runtime::ResolveIndirectFunction(rex_indirect_target_); \ } \ rex_indirect_func_(ctx, base); \ } while (0)