JuliaInterop / ObjectiveC.jl

Objective-C embedded in Julia
Other
39 stars 10 forks source link

Implement fpret ABI #37

Closed tgymnich closed 2 months ago

tgymnich commented 2 months ago

We should look into implementing objc_msgSend_stret to support functions that return structs.

This might be the cause of issues like https://github.com/JuliaGPU/Metal.jl/issues/338.

maleadt commented 2 months ago

Apparently this isn't needed on arm64: https://github.com/llvm/llvm-project/blob/1563a8752b33a854c3ab5a4e8b3dce39ac9831b8/clang/lib/CodeGen/CGObjCMac.cpp#L2186-L2191

maleadt commented 2 months ago

stret depends on the platform, so it's not for all structs. Maybe we can re-use Julia's ABI support for this, or the reimplementation in GPUCompiler.

I noticed that there's an fpret too.

maleadt commented 2 months ago

MWE from Metal.jl:

using ObjectiveC, .Foundation

load_framework("Metal")
load_framework("CoreGraphics")

struct MTLSize
    width::NSUInteger
    height::NSUInteger
    depth::NSUInteger

    MTLSize(w=1, h=1, d=1) = new(w, h, d)
end

@objcwrapper MTLDevice <: NSObject

@objcproperties MTLDevice begin
    @autoproperty maxThreadsPerThreadgroup::MTLSize
end

MTLCreateSystemDefaultDevice() =
    MTLDevice(ccall(:MTLCreateSystemDefaultDevice, id{MTLDevice}, ()))

dev = MTLCreateSystemDefaultDevice()
@show dev.maxThreadsPerThreadgroup

For testing it would be better to have an API in Foundation or so that needs stret, but I haven't found one yet.

tgymnich commented 2 months ago

Would this work https://developer.apple.com/documentation/foundation/nsstring/1410144-rangeofstring?language=objc?

maleadt commented 2 months ago

I don't think NSRange is large enough for x64.

NSRect is even larger, and I confirmed this crashes under Rosetta:

using ObjectiveC, .Foundation

if sizeof(Ptr{Cvoid}) == 8
    const CGFloat = Float64
else
    const CGFloat = Float32
end

struct NSPoint
    x::CGFloat
    y::CGFloat
end

struct NSSize
    width::CGFloat
    height::CGFloat
end

struct NSRect
    origin::NSPoint
    size::NSSize
end

NSRect(x, y, width, height) =NSRect(NSPoint(x, y), NSSize(width, height))
NSRect() = NSRect(0, 0, 0, 0)

Foundation.NSValue(rect::NSRect) = NSValue(@objc [NSValue valueWithRect:rect::NSRect]::id{NSValue})
NSRect(val::NSValue) = @objc [val::id{NSValue} rectValue]::NSRect

rect = @show NSRect(1, 2, 3, 4)
val = NSValue(rect)
@show NSRect(val)
tgymnich commented 2 months ago

FPRet seems only relevant on 32 bit x86. On amd64 only long double uses FPRet. https://github.com/llvm/llvm-project/blob/803e03fbb7cd97461f349fb6e235592681fc1e6c/clang/lib/Basic/Targets/X86.h#L746

NSDecimal might trigger fpret on amd64 and arm64:

using ObjectiveC, .Foundation
pi = NSNumber(3.14)
@objc [pi::NSNumber decimalValue]::Ptr{NSNumber}

amd64:

[71948] signal (11.1): Segmentation fault: 11
in expression starting at REPL[7]:1
objc_msgSend at /usr/lib/libobjc.A.dylib (unknown line)
-[NSNumber(NSDecimalNumberExtensions) decimalValue] at /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (unknown line)
macro expansion at /Users/tim/Developer/ObjectiveC.jl/src/syntax.jl:163 [inlined]
top-level scope at ./REPL[7]:1
jl_toplevel_eval_flex at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/src/toplevel.c:925
jl_toplevel_eval_flex at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/src/toplevel.c:877
ijl_toplevel_eval at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/src/toplevel.c:943 [inlined]
ijl_toplevel_eval_in at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/src/toplevel.c:985
eval at ./boot.jl:385 [inlined]
eval_user_input at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/usr/share/julia/stdlib/v1.10/REPL/src/REPL.jl:150
repl_backend_loop at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/usr/share/julia/stdlib/v1.10/REPL/src/REPL.jl:246
#start_repl_backend#46 at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/usr/share/julia/stdlib/v1.10/REPL/src/REPL.jl:231
start_repl_backend at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/usr/share/julia/stdlib/v1.10/REPL/src/REPL.jl:228
_jl_invoke at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/src/gf.c:0 [inlined]
ijl_apply_generic at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/src/gf.c:3076
#run_repl#59 at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/usr/share/julia/stdlib/v1.10/REPL/src/REPL.jl:389
run_repl at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/usr/share/julia/stdlib/v1.10/REPL/src/REPL.jl:375
jfptr_run_repl_91898 at /Applications/Julia-1.10.app/Contents/Resources/julia/lib/julia/sys.dylib (unknown line)
_jl_invoke at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/src/gf.c:0 [inlined]
ijl_apply_generic at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/src/gf.c:3076
#1013 at ./client.jl:432
jfptr_YY.1013_82866 at /Applications/Julia-1.10.app/Contents/Resources/julia/lib/julia/sys.dylib (unknown line)
_jl_invoke at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/src/gf.c:0 [inlined]
ijl_apply_generic at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/src/gf.c:3076
jl_apply at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/src/./julia.h:1982 [inlined]
jl_f__call_latest at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/src/builtins.c:812
#invokelatest#2 at ./essentials.jl:892 [inlined]
invokelatest at ./essentials.jl:889 [inlined]
run_main_repl at ./client.jl:416
exec_options at ./client.jl:333
_start at ./client.jl:552
jfptr__start_82892 at /Applications/Julia-1.10.app/Contents/Resources/julia/lib/julia/sys.dylib (unknown line)
_jl_invoke at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/src/gf.c:0 [inlined]
ijl_apply_generic at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/src/gf.c:3076
jl_apply at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/src/./julia.h:1982 [inlined]
true_main at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/src/jlapi.c:582
jl_repl_entrypoint at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-10/src/jlapi.c:731
Allocations: 579395 (Pool: 578609; Big: 786); GC: 1
[1]    71948 segmentation fault  /Applications/Julia-1.10.app/Contents/Resources/julia/bin/julia

arm64:

ERROR: ReadOnlyMemoryError()
maleadt commented 2 months ago

Great, that's a simple reproduces. Let's start with stret, I've added an initial implementation in https://github.com/JuliaInterop/ObjectiveC.jl/pull/38.

maleadt commented 2 months ago

NSDecimal might trigger fpret on amd64 and arm64:

I guess you meant stret.

FPRet seems only relevant on 32 bit x86.

Looks like we don't need to support it then.