diff --git a/src/irgen.jl b/src/irgen.jl index 1456c008..072dfdf4 100644 --- a/src/irgen.jl +++ b/src/irgen.jl @@ -51,14 +51,26 @@ function irgen(@nospecialize(job::CompilerJob)) end end - # sanitize defined functions (Julia doesn't when using the external codegen policy) + # sanitize defined functions (Julia doesn't when using the external codegen policy). + # Sanitized names can collide, e.g. `julia_+_0` and `julia_-_0` from Julia 1.14, which + # numbers functions per compilation. Uniquify them ourselves, as LLVM would add a `.`. + renamed = Dict{String,String}() for val in collect(mod.functions) isdeclaration(val) && continue old_name = val.name new_name = safe_name(old_name) - if old_name != new_name - val.name = new_name + old_name == new_name && continue + unique_name, i = new_name, 0 + while haskey(mod.functions, unique_name) + i += 1 + unique_name = "$(new_name)_$i" end + val.name = unique_name + renamed[old_name] = unique_name + end + for (mi, entry) in compiled + compiled[mi] = (; entry..., func = get(renamed, entry.func, entry.func), + specfunc = get(renamed, entry.specfunc, entry.specfunc)) end # rename and process the entry point diff --git a/test/native.jl b/test/native.jl index e7959e0c..a387305f 100644 --- a/test/native.jl +++ b/test/native.jl @@ -430,6 +430,30 @@ end end end + @testset "sanitized function names" begin + # `+` and `*` both sanitize to `_`, so the callees' names collide wherever Julia + # numbers functions per compilation. + mod = @eval module $(gensym()) + @noinline var"f+"(x) = x + 1 + @noinline var"f*"(x) = x * 3 + kernel(x) = var"f+"(x) - var"f*"(x) + end + + job, _ = Native.create_job(mod.kernel, (Int,); validate=false) + JuliaContext() do ctx + ir, meta = GPUCompiler.compile(:llvm, job) + + specfuncs = Dict(mi.def.name => entry.specfunc for (mi, entry) in meta.compiled) + @test allunique(values(specfuncs)) + for name in values(specfuncs) + @test haskey(ir.functions, name) + @test name == GPUCompiler.safe_name(name) + end + @test occursin("mul", string(ir.functions[specfuncs[Symbol("f*")]])) + @test !occursin("mul", string(ir.functions[specfuncs[Symbol("f+")]])) + end + end + @testset "cached compilation" begin mod = @eval module $(gensym()) @noinline child(i) = i