[lua] Port _hx_bit_clamp to haxe code#12600
[lua] Port _hx_bit_clamp to haxe code#12600tobil4sk wants to merge 14 commits intoHaxeFoundation:developmentfrom
Conversation
We can now rely on normal dce so that the code for this function isn't generated unless required. It also provides more control over what code is generated. This also allows compile time abstractions that aren't supported on lua, like inline function calls, which reduce duplicate code.
This is a simpler operation which makes more sense here given the range of values this.length can have. Array fails to be dce'd in hello world, so removing this avoids clamp from being included.
In clampInt32, these are used before static init runs, which means they are set to nil
If lua 5.3+ is being targetted, we know that native bitwise operators are available, so we can use them. On lua 5.2, we know that bit32 is available so we don't need to generate a fallback for it being null.
|
I looked into why Code generation time (after DCE): DCE time: Fix: Remove
If nothing calls Also worth noting: |
Previously use._bitop was being set during the generator phase, at which point dce already occurred so @:ifFeature on lua.Boot.clampInt32 didn't work. This patch moves use._bitop detection to the dce phase, which means it will be set in time to make sure clampInt32 is included when needed.
-Min_Int32 is "optimised" into -2147483648 due to overflow
This analysis seems correct, but claude was a bit too confident about the solution. I did some digging and it seems like python already deals with the same problem: #11427. I lifted the solution from there, and the test seems to pass now. |
The clamp port caused a regression in underflow, but it wasn't caught due to this missing test case.
Haxe modulo generates as math.fmod, which rounds towards 0 instead of minus infinity. This breaks underflow. This requires adding lua.Syntax.modulo. Documentation is taken from: https://www.lua.org/manual/5.5/manual.html#3.4.1
Otherwise, the _hx_bit file will always be omitted when dce is off.
This allows the incomplete clamp implementations to be marked as extern inline, which prevents them from being generated outside of clampInt32. This is important especially for clampNativeOperator, which does not parse on lua < 5.3 so it cannot be generated outside testFunctionSupport. @:noPackageRestrict is needed here for the macro to work within the lua.Boot module.
|
Heya, I like your DCE fix and the haxe-side clampInt32. I can adapt to it on my work for #12599. I'm going to mark that one as draft, expecting this to get merged first, FWIW. |
|
I tried to avoid making conflicts with that PR, because I was hoping they can be merged together. It would be good if we also port _hx_bit to haxe, but having the native operators as they are now in #12599 would be a good start as it unblocks lua 5.5 support, and they shouldn't conflict. So maybe we can merge both of these for now and then handle further _hx_bit clean up in a new PR? As an aside, I've also been thinking in general about int behaviour. Int32 is the type that needs to comply with strict overflow rules, but for regular Int, haxe describes that as a type with platform specific behaviour so I wonder if we can avoid some of the overhead by making the behaviour closer to native lua. Ideally, we should be able to generate native operators directly in most cases, with these wrappers mainly for when strict int32 behaviour is needed. |
We can now rely on normal dce so that the code for this function isn't generated unless required. It also provides more control over what code is generated, which has allowed adding checks like lua_ver >= 5.3 to avoid redundant compatibility implementations.
This also allows compile time abstractions that aren't supported on lua, like inline function calls, which reduce duplicate code.
The generic implementation checks what is supported to decide which implementation to use, then patches the method to avoid having to rerun the feature detection every time. This can't go into static init because bitwise operations are needed in regex constructors, which are called in some static initialisers. I think this way is also fairly self contained which is nice.
Currently a test is failing because
__lua_Boot.clampInt32is nil, I think my check@:ifFeature("use._bitop")isn't sufficient.Below is the generated lua code, which could be improved, but I'm surprised at how close it is to the original!
Expand to view
Related to #8852.