Skip to main content

luaur_code_gen/functions/
is_supported.rs

1use luaur_vm::macros::lua_extra_size::LUA_EXTRA_SIZE;
2use luaur_vm::macros::lua_use_longjmp::LUA_USE_LONGJMP;
3use luaur_vm::records::lua_node::LuaNode;
4use luaur_vm::records::lua_t_value::TValue;
5
6use crate::functions::is_unwind_supported::is_unwind_supported;
7use crate::macros::codegen_target_a_64::CODEGEN_TARGET_A64;
8use crate::macros::codegen_target_x_64::CODEGEN_TARGET_X64;
9
10// NOTE: This function is native-only in the original codegen. It depends on
11// platform ABI assumptions (TValue/LuaNode layout) and CPU feature detection.
12pub fn is_supported() -> bool {
13    if LUA_EXTRA_SIZE != 1 {
14        return false;
15    }
16
17    // The JIT emits machine code with hardcoded structure sizes/offsets, so the
18    // runtime ABI layout must match what the code generator assumes. C++
19    // (CodeGen/src/CodeGen.cpp) bails out of native codegen if these don't hold:
20    //   if (sizeof(TValue) != 16) return false;
21    //   if (sizeof(LuaNode) != 32) return false;
22    if core::mem::size_of::<TValue>() != 16 {
23        return false;
24    }
25
26    if core::mem::size_of::<LuaNode>() != 32 {
27        return false;
28    }
29
30    #[cfg(not(windows))]
31    {
32        if LUA_USE_LONGJMP == 0 && !is_unwind_supported() {
33            return false;
34        }
35    }
36    #[cfg(windows)]
37    {
38        if !is_unwind_supported() {
39            return false;
40        }
41    }
42
43    #[cfg(CODEGEN_TARGET_X64)]
44    {
45        // CPU feature check for AVX1/VEX encoded XMM ops and ROUNDSD via SSE4.1.
46        // Use the same CPUID leaf as the C++ code: EAX=1.
47        //
48        // We use is_x86_feature_detected! which is supported on wasm32 for
49        // non-native targets behind cfg; this function is native-only so it is
50        // fine to rely on x86 intrinsics when compiling for x86.
51        #[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
52        {
53            use core::arch::x86::__cpuid;
54
55            let cpuinfo = unsafe { __cpuid(1) };
56            // https://en.wikipedia.org/wiki/CPUID#EAX=1:_Processor_Info_and_Feature_Bits
57            // cpuinfo.ecx holds feature bits. Bit 28 == AVX1.
58            if (cpuinfo.ecx & (1 << 28)) == 0 {
59                return false;
60            }
61        }
62
63        #[cfg(not(any(target_arch = "x86_64", target_arch = "x86")))]
64        {
65            return false;
66        }
67
68        return true;
69    }
70
71    #[cfg(CODEGEN_TARGET_A64)]
72    {
73        return true;
74    }
75
76    false
77}