HaxeFoundation / haxe

Haxe - The Cross-Platform Toolkit
https://haxe.org
6.09k stars 646 forks source link

[jvm] int parsing inconsistent with other targets #9808

Open skial opened 4 years ago

skial commented 4 years ago

The compiler parsing constant ints for the jvm target appears to be inconsistent with the python, js, interp and legacy java targets, I've not tested the rest. Tested against both Haxe 36263b3 and 4.0.5 with the same results.

package ;

class Main {

    public static function main() {
        var i32minc:Int = -2147483648;
        var i32maxc:Int = 2147483647;
        var i32min:Int = Std.int(-Math.pow(2, 31));
        var i32max:Int = Std.int(Math.pow(2, 31) - 1);
        var jvmmin:Int = -2147450880;
        var jvmerr:Int = -2147450881;
        // jvm      : 0, -1, -2147483648, 2147483647, -2147450880, 32767
        // java     : -2147483648, 2147483647, -2147483648, 2147483647, -2147450880, -2147450881
        // python   : -2147483648, 2147483647, -2147483648, 2147483647, -2147450880, -2147450881
        // js       : -2147483648, 2147483647, -2147483648, 2147483647, -2147450880, -2147450881
        // interp   : -2147483648,2147483647,0,-1,-2147450880,-2147450881
        trace( i32minc, i32maxc, i32min, i32max, jvmmin, jvmerr );
    }

}
Simn commented 4 years ago

I'll gladly fix this is somebody explains to me how Haxe's Int works.

Simn commented 4 years ago

Actually, this doesn't reproduce for me:

source/Main.hx:16: -2147483648, 2147483647, -2147483648, 2147483647, -2147450880, -2147450881

Decompiler says:

    public static void main() {
        int i32minc = -2147483648;
        int i32maxc = 2147483647;
        int i32min = Std.int(-Math.pow((double)2L, (double)31L));
        int i32max = Std.int(Math.pow((double)2L, (double)31L) - (double)1);
        int jvmmin = -2147450880;
        int jvmerr = -2147450881;
        Function var10000 = (Function)Log.trace;
        Array _hx_tmp_customParams = Array.ofNative(new java.lang.Object[]{i32maxc, i32min, i32max, jvmmin, jvmerr});
        var10000.invoke(i32minc, new Anon0("Main", _hx_tmp_customParams, "source/Main.hx", 16, "main"));
    }
Simn commented 4 years ago

I've made constant generation a bit less silly so that now we get this:

    public static void main() {
        int i32minc = -2147483648;
        int i32maxc = 2147483647;
        int i32min = Std.int(-Math.pow(2.0D, 31.0D));
        int i32max = Std.int(Math.pow(2.0D, 31.0D) - 1.0D);
        int jvmmin = -2147450880;
        int jvmerr = -2147450881;
        Function var10000 = (Function)Log.trace;
        Array _hx_tmp_customParams = Array.ofNative(new java.lang.Object[]{i32maxc, i32min, i32max, jvmmin, jvmerr});
        var10000.invoke(i32minc, new Anon0("Main", _hx_tmp_customParams, "source/Main.hx", 16, "main"));
    }
skial commented 4 years ago

I'm still getting my initial results and I'm not sure how to debug this further than by creating this repo with my source & generated files for you to take a look at.

I've also checked the generated output with JD Project/JD GUI and online decompiler's which report the same constant values being generated.

Simn commented 4 years ago

What is that, a maximal reproducible example...?

skial commented 4 years ago

😬😅 yeah i know I went overboard...

skial commented 3 years ago

I think I've discovered a bit more info on this issue.

It basically boils down to 32 bit vs 64 bit builds. I've only just remembered lix downloads 32 bit builds on Windows. I've checked with a 64 bit build and the jvm output prints the same values as the other tested targets.

But considering the jvm target appears to the the only target to generate incorrect constants with large values on 32 bit builds, I'm assuming it might be related to a call to OCamls Int32.to_int?

Convert the given 32-bit integer (type int32) to an integer (type int). On 32-bit platforms, the 32-bit integer is taken modulo 231, i.e. the high-order bit is lost during the conversion. On 64-bit platforms, the conversion is exact.