Skip to content

Commit 4555002

Browse files
KristofferCmaleadt
andauthored
Fixes for Julia nightly (#725)
* change call to `codeinfo_for_const` to work on newer nightlies * Adapt to JuliaLang/julia#59436. * Fix tests. * Fix test runner. * Fix CI pipeline. --------- Co-authored-by: Tim Besard <[email protected]>
1 parent 6481ad9 commit 4555002

File tree

6 files changed

+164
-89
lines changed

6 files changed

+164
-89
lines changed

.github/workflows/Test.yml

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,34 +19,62 @@ jobs:
1919
fail-fast: false
2020
matrix:
2121
version: ['1.10', '1.11', '1.12-nightly', 'nightly']
22-
os: [ubuntu-latest, macOS-latest, windows-latest]
23-
arch: [x64]
22+
os: [ubuntu-24.04, ubuntu-24.04-arm, macOS-15, macOS-15-intel, windows-2025]
23+
arch: [x64, arm64]
2424
llvm_args: ['']
25+
exclude:
26+
# unsupported combinations
27+
- os: ubuntu-24.04
28+
arch: arm64
29+
- os: windows-2025
30+
arch: arm64
31+
- os: ubuntu-24.04-arm
32+
arch: x64
33+
- os: macOS-15
34+
arch: x64
35+
- os: macOS-15-intel
36+
arch: arm64
2537
include:
2638
# starting with Julia 1.10, we can enable opaque pointers
2739
# from Julia 1.12 on, this is the default.
2840
- version: '1.10'
29-
os: 'ubuntu-latest'
41+
os: 'ubuntu-24.04'
3042
arch: 'x64'
3143
llvm_args: '--opaque-pointers'
3244
- version: '1.10'
33-
os: 'macOS-latest'
45+
os: 'ubuntu-24.04-arm'
46+
arch: 'arm64'
47+
llvm_args: '--opaque-pointers'
48+
- version: '1.10'
49+
os: 'macOS-15'
50+
arch: 'arm64'
51+
llvm_args: '--opaque-pointers'
52+
- version: '1.10'
53+
os: 'macOS-15-intel'
3454
arch: 'x64'
3555
llvm_args: '--opaque-pointers'
3656
- version: '1.10'
37-
os: 'windows-latest'
57+
os: 'windows-2025'
3858
arch: 'x64'
3959
llvm_args: '--opaque-pointers'
4060
- version: '1.11'
41-
os: 'ubuntu-latest'
61+
os: 'ubuntu-24.04'
4262
arch: 'x64'
4363
llvm_args: '--opaque-pointers'
4464
- version: '1.11'
45-
os: 'macOS-latest'
65+
os: 'ubuntu-24.04-arm'
66+
arch: 'arm64'
67+
llvm_args: '--opaque-pointers'
68+
- version: '1.11'
69+
os: 'macOS-15'
70+
arch: 'arm64'
71+
llvm_args: '--opaque-pointers'
72+
- version: '1.11'
73+
os: 'macOS-15-intel'
4674
arch: 'x64'
4775
llvm_args: '--opaque-pointers'
4876
- version: '1.11'
49-
os: 'windows-latest'
77+
os: 'windows-2025'
5078
arch: 'x64'
5179
llvm_args: '--opaque-pointers'
5280
steps:
@@ -85,7 +113,7 @@ jobs:
85113
strategy:
86114
fail-fast: false
87115
matrix:
88-
os: [ubuntu-latest]
116+
os: [ubuntu-24.04]
89117
arch: [x64]
90118
llvm_args: ['', '--opaque-pointers']
91119
include:

src/jlgen.jl

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -321,10 +321,10 @@ CC.isoverlayed(::StackedMethodTable) = true
321321
# no need to fall back to the parent method view
322322
return result
323323
end
324-
324+
325325
parent_result = CC.findall(sig, table.parent; limit)::Union{Nothing, CC.MethodLookupResult}
326326
parent_result === nothing && return nothing #too many matches
327-
327+
328328
# merge the parent match results with the internal method table
329329
return CC.MethodLookupResult(
330330
CC.vcat(result.matches, parent_result.matches),
@@ -354,13 +354,13 @@ else
354354
# no need to fall back to the parent method view
355355
return CC.MethodMatchResult(result, true)
356356
end
357-
357+
358358
parent_result = CC.findall(sig, table.parent; limit)::Union{Nothing, CC.MethodMatchResult}
359359
parent_result === nothing && return nothing #too many matches
360-
360+
361361
overlayed = parent_result.overlayed | !CC.isempty(result)
362362
parent_result = parent_result.matches::CC.MethodLookupResult
363-
363+
364364
# merge the parent match results with the internal method table
365365
return CC.MethodMatchResult(
366366
CC.MethodLookupResult(
@@ -589,7 +589,11 @@ function ci_cache_populate(interp, cache, mi, min_world, max_world)
589589
# now make sure everything has source code, if desired
590590
mi = CC.get_ci_mi(callee)
591591
if CC.use_const_api(callee)
592-
src = CC.codeinfo_for_const(interp, mi, ci.rettype_const)
592+
if VERSION >= v"1.13.0-DEV.1121"
593+
src = CC.codeinfo_for_const(interp, mi, CC.WorldRange(callee.min_world, callee.max_world), callee.edges, callee.rettype_const)
594+
else
595+
src = CC.codeinfo_for_const(interp, mi, callee.rettype_const)
596+
end
593597
else
594598
# TODO: typeinf_code could return something with different edges/ages/owner/abi (needing an update to callee), which we don't handle here
595599
src = CC.typeinf_code(interp, mi, true)
@@ -801,11 +805,25 @@ function compile_method_instance(@nospecialize(job::CompilerJob))
801805
end
802806
end
803807

804-
if VERSION >= v"1.12.0-DEV.1703"
805-
# on sufficiently recent versions of Julia, we can query the MIs compiled.
806-
# this is required after the move to `invokce(::CodeInstance)`, because our
808+
if VERSION >= v"1.13.0-DEV.1120"
809+
# on sufficiently recent versions of Julia, we can query the CIs compiled.
810+
# this is required after the move to `invoke(::CodeInstance)`, because our
807811
# lookup function (used to populate method_instances) isn't always called then.
808812

813+
num_cis = Ref{Csize_t}(0)
814+
@ccall jl_get_llvm_cis(native_code::Ptr{Cvoid}, num_cis::Ptr{Csize_t},
815+
C_NULL::Ptr{Cvoid})::Nothing
816+
resize!(method_instances, num_cis[])
817+
@ccall jl_get_llvm_cis(native_code::Ptr{Cvoid}, num_cis::Ptr{Csize_t},
818+
method_instances::Ptr{Cvoid})::Nothing
819+
820+
for (i, ci) in enumerate(method_instances)
821+
method_instances[i] = ci.def::MethodInstance
822+
end
823+
824+
elseif VERSION >= v"1.12.0-DEV.1703"
825+
# slightly older versions of Julia used MIs directly
826+
809827
num_mis = Ref{Csize_t}(0)
810828
@ccall jl_get_llvm_mis(native_code::Ptr{Cvoid}, num_mis::Ptr{Csize_t},
811829
C_NULL::Ptr{Cvoid})::Nothing

test/native.jl

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,10 @@ end
340340
end
341341

342342
@testset "always_inline" begin
343-
# XXX: broken by JuliaLang/julia#51599, see JuliaGPU/GPUCompiler.jl#527
343+
# XXX: broken by JuliaLang/julia#51599, see JuliaGPU/GPUCompiler.jl#527.
344+
# yet somehow this works on 1.12?
345+
broken = VERSION >= v"1.13-"
346+
344347
mod = @eval module $(gensym())
345348
import ..sink
346349
expensive(x) = $(foldl((e, _) -> :($sink($e) + $sink(x)), 1:100; init=:x))
@@ -359,20 +362,20 @@ end
359362
Native.code_llvm(mod.g, Tuple{Int64}; dump_module=true, kernel=true)
360363
end
361364

362-
@test @filecheck begin
365+
@test @filecheck(begin
363366
check"CHECK-NOT: @{{(julia|j)_expensive_[0-9]+}}"
364367
Native.code_llvm(mod.g, Tuple{Int64}; dump_module=true, kernel=true, always_inline=true)
365-
end
368+
end) broken=broken
366369

367370
@test @filecheck begin
368371
check"CHECK: @{{(julia|j)_expensive_[0-9]+}}"
369372
Native.code_llvm(mod.h, Tuple{Int64}; dump_module=true, kernel=true)
370373
end
371374

372-
@test @filecheck begin
375+
@test @filecheck(begin
373376
check"CHECK-NOT: @{{(julia|j)_expensive_[0-9]+}}"
374377
Native.code_llvm(mod.h, Tuple{Int64}; dump_module=true, kernel=true, always_inline=true)
375-
end
378+
end) broken=broken
376379
end
377380

378381
@testset "function attributes" begin
@@ -659,7 +662,7 @@ end
659662
a[1] = a[1]^2
660663
return
661664
end
662-
665+
663666
function dkernel(a)
664667
ptr = Enzyme.deferred_codegen(typeof(kernel), Tuple{Vector{Float64}})
665668
ccall(ptr, Cvoid, (Vector{Float64},), a)

test/runtests.jl

Lines changed: 69 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -330,73 +330,85 @@ println("Testing finished in $elapsed")
330330

331331
# construct a testset to render the test results
332332
o_ts = Test.DefaultTestSet("Overall")
333-
Test.push_testset(o_ts)
334-
completed_tests = Set{String}()
335-
for (testname, (resp,)) in results
336-
push!(completed_tests, testname)
337-
if isa(resp, Test.DefaultTestSet)
338-
Test.push_testset(resp)
339-
Test.record(o_ts, resp)
340-
Test.pop_testset()
341-
elseif isa(resp, Tuple{Int,Int})
342-
fake = Test.DefaultTestSet(testname)
343-
for i in 1:resp[1]
344-
Test.record(fake, Test.Pass(:test, nothing, nothing, nothing, nothing))
345-
end
346-
for i in 1:resp[2]
347-
Test.record(fake, Test.Broken(:test, nothing))
348-
end
349-
Test.push_testset(fake)
350-
Test.record(o_ts, fake)
351-
Test.pop_testset()
352-
elseif isa(resp, RemoteException) && isa(resp.captured.ex, Test.TestSetException)
353-
println("Worker $(resp.pid) failed running test $(testname):")
354-
Base.showerror(stdout, resp.captured)
355-
println()
356-
fake = Test.DefaultTestSet(testname)
357-
for i in 1:resp.captured.ex.pass
358-
Test.record(fake, Test.Pass(:test, nothing, nothing, nothing, nothing))
359-
end
360-
for i in 1:resp.captured.ex.broken
361-
Test.record(fake, Test.Broken(:test, nothing))
362-
end
363-
for t in resp.captured.ex.errors_and_fails
364-
Test.record(fake, t)
365-
end
366-
Test.push_testset(fake)
367-
Test.record(o_ts, fake)
368-
Test.pop_testset()
333+
function with_testset(f, testset)
334+
@static if VERSION >= v"1.13.0-DEV.1044"
335+
Test.@with_testset testset f()
369336
else
370-
if !isa(resp, Exception)
371-
resp = ErrorException(string("Unknown result type : ", typeof(resp)))
337+
Test.push_testset(testset)
338+
try
339+
f()
340+
finally
341+
Test.pop_testset()
372342
end
373-
# If this test raised an exception that is not a remote testset exception,
374-
# i.e. not a RemoteException capturing a TestSetException that means
375-
# the test runner itself had some problem, so we may have hit a segfault,
376-
# deserialization errors or something similar. Record this testset as Errored.
377-
fake = Test.DefaultTestSet(testname)
378-
Test.record(fake, Test.Error(:nontest_error, testname, nothing, Any[(resp, [])], LineNumberNode(1)))
379-
Test.push_testset(fake)
380-
Test.record(o_ts, fake)
381-
Test.pop_testset()
382343
end
383344
end
384-
for test in tests
385-
(test in completed_tests) && continue
386-
fake = Test.DefaultTestSet(test)
387-
Test.record(fake, Test.Error(:test_interrupted, test, nothing,
388-
[("skipped", [])], LineNumberNode(1)))
389-
Test.push_testset(fake)
390-
Test.record(o_ts, fake)
391-
Test.pop_testset()
345+
with_testset(o_ts) do
346+
completed_tests = Set{String}()
347+
for (testname, (resp,)) in results
348+
push!(completed_tests, testname)
349+
if isa(resp, Test.DefaultTestSet)
350+
with_testset(resp) do
351+
Test.record(o_ts, resp)
352+
end
353+
elseif isa(resp, Tuple{Int,Int})
354+
fake = Test.DefaultTestSet(testname)
355+
for i in 1:resp[1]
356+
Test.record(fake, Test.Pass(:test, nothing, nothing, nothing, nothing))
357+
end
358+
for i in 1:resp[2]
359+
Test.record(fake, Test.Broken(:test, nothing))
360+
end
361+
with_testset(fake) do
362+
Test.record(o_ts, fake)
363+
end
364+
elseif isa(resp, RemoteException) && isa(resp.captured.ex, Test.TestSetException)
365+
println("Worker $(resp.pid) failed running test $(testname):")
366+
Base.showerror(stdout, resp.captured)
367+
println()
368+
fake = Test.DefaultTestSet(testname)
369+
for i in 1:resp.captured.ex.pass
370+
Test.record(fake, Test.Pass(:test, nothing, nothing, nothing, nothing))
371+
end
372+
for i in 1:resp.captured.ex.broken
373+
Test.record(fake, Test.Broken(:test, nothing))
374+
end
375+
for t in resp.captured.ex.errors_and_fails
376+
Test.record(fake, t)
377+
end
378+
with_testset(fake) do
379+
Test.record(o_ts, fake)
380+
end
381+
else
382+
if !isa(resp, Exception)
383+
resp = ErrorException(string("Unknown result type : ", typeof(resp)))
384+
end
385+
# If this test raised an exception that is not a remote testset exception,
386+
# i.e. not a RemoteException capturing a TestSetException that means
387+
# the test runner itself had some problem, so we may have hit a segfault,
388+
# deserialization errors or something similar. Record this testset as Errored.
389+
fake = Test.DefaultTestSet(testname)
390+
Test.record(fake, Test.Error(:nontest_error, testname, nothing, Base.ExceptionStack([(exception=resp,backtrace=[])]), LineNumberNode(1)))
391+
with_testset(fake) do
392+
Test.record(o_ts, fake)
393+
end
394+
end
395+
end
396+
for test in tests
397+
(test in completed_tests) && continue
398+
fake = Test.DefaultTestSet(test)
399+
Test.record(fake, Test.Error(:test_interrupted, test, nothing, Base.ExceptionStack([(exception="skipped",backtrace=[])]), LineNumberNode(1)))
400+
with_testset(fake) do
401+
Test.record(o_ts, fake)
402+
end
403+
end
392404
end
393405
println()
394406
Test.print_test_results(o_ts, 1)
395-
if !o_ts.anynonpass
407+
if (VERSION >= v"1.13.0-DEV.1037" && !Test.anynonpass(o_ts)) ||
408+
(VERSION < v"1.13.0-DEV.1037" && !o_ts.anynonpass)
396409
println(" \033[32;1mSUCCESS\033[0m")
397410
else
398411
println(" \033[31;1mFAILURE\033[0m\n")
399412
Test.print_test_errors(o_ts)
400413
throw(Test.FallbackTestSetException("Test run finished with errors"))
401414
end
402-

test/setup.jl

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@ for file in readdir(joinpath(@__DIR__, "helpers"))
1111
end
1212
using .FileCheck
1313

14+
if VERSION >= v"1.13.0-DEV.1044"
15+
using Base.ScopedValues
16+
end
17+
1418

1519
## entry point
1620

1721
function runtests(f, name)
18-
old_print_setting = Test.TESTSET_PRINT_ENABLE[]
19-
Test.TESTSET_PRINT_ENABLE[] = false
20-
21-
try
22+
function inner()
2223
# generate a temporary module to execute the tests in
2324
mod_name = Symbol("Test", rand(1:100), "Main_", replace(name, '/' => '_'))
2425
mod = @eval(Main, module $mod_name end)
@@ -61,8 +62,21 @@ function runtests(f, name)
6162

6263
GC.gc(true)
6364
res
64-
finally
65-
Test.TESTSET_PRINT_ENABLE[] = old_print_setting
65+
end
66+
67+
old_print_setting = Test.TESTSET_PRINT_ENABLE[]
68+
@static if VERSION >= v"1.13.0-DEV.1044"
69+
@with Test.TESTSET_PRINT_ENABLE=>false begin
70+
inner()
71+
end
72+
else
73+
old_print_setting = Test.TESTSET_PRINT_ENABLE[]
74+
Test.TESTSET_PRINT_ENABLE[] = false
75+
try
76+
inner()
77+
finally
78+
Test.TESTSET_PRINT_ENABLE[] = old_print_setting
79+
end
6680
end
6781
end
6882

0 commit comments

Comments
 (0)