JuliaLang / PackageCompiler.jl

Compile your Julia Package
https://julialang.github.io/PackageCompiler.jl/dev/
MIT License
1.42k stars 191 forks source link

Compiling Float16 code is broken #826

Open maleadt opened 1 year ago

maleadt commented 1 year ago

Given the following module:

module MyApp

function julia_main()::Cint
    try
        real_main()
    catch
        Base.invokelatest(Base.display_error, Base.catch_stack())
        return 1
    end
    return 0
end

function real_main()
    x = rand(Float32)
    f(x) = ccall("extern __gnu_f2h_ieee", llvmcall, Float16, (Float32,), x)
    @show f(x)
    return
end

if abspath(PROGRAM_FILE) == @__FILE__
    real_main()
end

end # module

Invoking directly works:

❯ jl --project=MyApp MyApp/src/MyApp.jl
f(x) = Float16(0.25)

Compiling doesn't:

julia> create_app("MyApp", "MyAppCompiled")
❯ ./MyAppCompiled/bin/MyApp
ERROR: could not load library "/home/tim/Julia/tmp/PackageCompiler.jl/examples/MyAppCompiled/lib/julia/sys.so"
/home/tim/Julia/tmp/PackageCompiler.jl/examples/MyAppCompiled/lib/julia/sys.so: undefined symbol: __gnu_f2h_ieee

I'm guessing this is because the __gnu_f2h_ieee -> julia__gnu_f2h_ieee mangling (either https://github.com/JuliaLang/julia/blob/0f269668c468ff6a2876221cdb21dfd78defb68c/src/jitlayers.cpp#L1408-L1414 or https://github.com/JuliaLang/julia/blob/0f269668c468ff6a2876221cdb21dfd78defb68c/src/aotcompile.cpp#L1017-L1030) isn't triggered by PackageCompiler.

cc @vchuravy

maleadt commented 1 year ago

Workaround: add the following definition to embedding_wrapper.c (when using create_app as I did above) or to julia_init.c (when using create_library):

extern uint16_t __gnu_f2h_ieee(float param);
JL_DLLEXPORT uint16_t __gnu_f2h_ieee(float param)
{
    return julia__gnu_f2h_ieee(param);
}

When invoking create_sysimage directly, I guess this should be written to a file based on julia_init.c and passed as julia_init_c_file?

It's also probably good to add the other aliases as well, so:

extern float julia__gnu_h2f_ieee(uint16_t param);
extern float __gnu_h2f_ieee(uint16_t param) {
    return julia__gnu_h2f_ieee(param);
}

extern uint16_t julia__gnu_f2h_ieee(float param);
extern uint16_t __gnu_f2h_ieee(float param) {
    return julia__gnu_f2h_ieee(param);
}

extern uint16_t julia__truncdfhf2(double param);
extern uint16_t __truncdfhf2(double param) {
    return julia__truncdfhf2(param);
}
andreasnoack commented 1 year ago

@maleadt Do you think these changes are just workarounds and the proper fix should happen elsewhere or do you think these changes should just be added here?

maleadt commented 1 year ago

There should probably be a proper fix so that Julia's mangling changes are applied to the code PackageCompiler saves. This is just a workaround to get your application working again. If a proper fix is impossible, I guess this could be put in a separate object file that's linked with every sysimage/library/app, but that would require maintaining a list of aliases in both places, and is not ideal.