Skip to content

Commit a44f86f

Browse files
maleadtKristofferC
authored andcommitted
Generate an error for closure cfunctions on unsupported platforms.
(cherry picked from commit f53e144)
1 parent 3050819 commit a44f86f

File tree

7 files changed

+36
-5
lines changed

7 files changed

+36
-5
lines changed

base/c.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Note that the argument type tuple must be a literal tuple, and not a tuple-value
4747
(although it can include a splat expression). And that these arguments will be evaluated in global scope
4848
during compile-time (not deferred until runtime).
4949
Adding a '\\\$' in front of the function argument changes this to instead create a runtime closure
50-
over the local variable `callable`.
50+
over the local variable `callable` (this is not supported on all architectures).
5151
5252
See [manual section on ccall and cfunction usage](@ref Calling-C-and-Fortran-Code).
5353

doc/src/manual/calling-c-and-fortran-code.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,10 @@ function qsort(a::Vector{T}, cmp) where T
945945
end
946946
```
947947

948+
!!! note
949+
Closure [`@cfunction`](@ref) rely on LLVM trampolines, which are not available on all
950+
platforms (for example ARM and PowerPC).
951+
948952

949953
## Closing a Library
950954

src/codegen.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5075,6 +5075,12 @@ static jl_cgval_t emit_cfunction(jl_codectx_t &ctx, jl_value_t *output_type, con
50755075
}
50765076

50775077
bool nest = (!fexpr_rt.constant || unionall_env);
5078+
#if defined(_CPU_AARCH64_) || defined(_CPU_ARM_) || defined(_CPU_PPC64_)
5079+
if (nest) {
5080+
emit_error(ctx, "cfunction: closures are not supported on this platform");
5081+
return jl_cgval_t();
5082+
}
5083+
#endif
50785084
Value *F = gen_cfun_wrapper(
50795085
jl_Module,
50805086
sig, fexpr_rt.constant,

src/support/platform.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
* CPU/Architecture:
2828
* _CPU_X86_
2929
* _CPU_X86_64_
30+
* _CPU_AARCH64_
3031
* _CPU_ARM_
3132
* _CPU_WASM_
3233
*/

test/ccall.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ using InteractiveUtils: code_llvm
66

77
import Libdl
88

9+
# for cfunction_closure
10+
include("testenv.jl")
11+
912
const libccalltest = "libccalltest"
1013

1114
const verbose = false
@@ -791,6 +794,8 @@ end
791794
## cfunction roundtrip
792795

793796
verbose && Libc.flush_cstdio()
797+
798+
if cfunction_closure
794799
verbose && println("Testing cfunction closures: ")
795800

796801
# helper Type for testing that constructors work
@@ -974,6 +979,12 @@ for (t, v) in ((Complex{Int32}, :ci32), (Complex{Int64}, :ci64),
974979
end
975980
end
976981

982+
else
983+
984+
@test_broken "cfunction: no support for closures on this platform"
985+
986+
end
987+
977988
# issue 13031
978989
foo13031(x) = Cint(1)
979990
foo13031p = @cfunction(foo13031, Cint, (Ref{Tuple{}},))

test/testenv.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,8 @@ if !@isdefined(testenv_defined)
3232
const curmod_name = fullname(curmod)
3333
const curmod_str = curmod === Main ? "Main" : join(curmod_name, ".")
3434
const curmod_prefix = "$(["$m." for m in curmod_name]...)"
35+
36+
# platforms that support cfunction with closures
37+
# (requires LLVM back-end support for trampoline intrinsics)
38+
const cfunction_closure = Sys.ARCH === :x86_64 || Sys.ARCH === :i686
3539
end

test/threads_exec.jl

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ using Test
44
using Base.Threads
55
using Base.Threads: SpinLock
66

7+
# for cfunction_closure
8+
include("testenv.jl")
9+
710
# threading constructs
811

912
let a = zeros(Int, 2 * nthreads())
@@ -460,10 +463,12 @@ function test_thread_cfunction()
460463
end
461464
@test sum(ok) == 10000
462465
end
463-
if nthreads() == 1
464-
test_thread_cfunction()
465-
else
466-
@test_broken "cfunction trampoline code not thread-safe"
466+
if cfunction_closure
467+
if nthreads() == 1
468+
test_thread_cfunction()
469+
else
470+
@test_broken "cfunction trampoline code not thread-safe"
471+
end
467472
end
468473

469474
# Compare the two ways of checking if threading is enabled.

0 commit comments

Comments
 (0)