-
Notifications
You must be signed in to change notification settings - Fork 9
Add K"static_eval" for cfunction/ccall/cglobal
#36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Linking JuliaLang/julia#57931 as a relevant discussion (though mostly about the shared library argument to |
|
Does this still support IIRC the ccall lowering is an awkward "local 'static' TypeVars + top-level evaluation" where the local static parameters have to be preserved as TypeVars in the resulting expression |
No, good catch! I think I've made it slightly too restrictive right now. Do the exact same rules apply to cglobal and cfunction? I can easily add |
e7c46ce to
2b83623
Compare
A few special forms have a kind of "deferred static evaluation" semantics for some of their children: * `@cfunction` - the function name and types * `ccall` / `foreigncall` / `@ccall` - the type arguments and sometimes the function name * `cglobal` - the function name * `@generated` - the expression defining the generated function stub For example, in `@ccall f()::Int`, the `Int` means "the symbol `Int` as looked up in global scope in the module, or as a static parameter of the method", and should fail if `Int` refers to a local variable. Currently all three of these cases are handled through different mechanisms with varying levels of hygiene inconsistency and ability to warn about access to local variables. To fix this problem, introduce the new `K"static_eval"` form which wraps an expression and preserves it as a piece of AST in the output (rather than producing IR), but still resolves scope and hygiene. Use this new form to remove all the special case child-index-dependent handling of these disparate forms from the IR. Also fixes bugs in `Base.@cfunction` hygiene where the function name might be resolved to a global symbol in the wrong module. Also move demo `@ccall` implementation into JuliaLowering, clean up and fix a few things which were broken and implement the gc_safe option from `Base.@ccall`. Makes use of static_eval kind for more precise diagnostics.
2b83623 to
617970e
Compare
|
@topolarity wow, the cases where static parameters are allowed are quite limited in the existing runtime's interpretation of julia> get_item(::Type{T}) where T = @ccall foo()::Ref{T}
get_item (generic function with 1 method)
julia> get_item(::Type{T}) where T = @ccall foo()::T
ERROR: TypeError: in ccall method definition, expected Type, got a value of type TypeVarI've updated things here to allow any use of static parameters because it doesn't seem like lowering can make the decision about which uses of static parameters are valid. |
K"deferred_toplevel_eval" for cfunction/ccall/cglobalK"static_eval" for cfunction/ccall/cglobal
I believe so! Here julia> plus(x::T) where T = @cfunction($((y)->x+y), Ref{T}, (Ref{T},))
julia> ccall(plus(1).ptr, Ref{Int}, (Ref{Int},), 2)
3
julia> ccall(plus(1 + 3im).ptr, Ref{Complex{Int}}, (Ref{Complex{Int}},), 2 - 2im)
3 + 1imand it looks like julia> find_sym(::Val{symbol}) where symbol = cglobal(symbol)
julia> find_sym(Val{:malloc}())
Ptr{Nothing} @0x00007bcdf5aad650
Yeah, that's true. That error message is arguably a defect of the type-checking in That error message should probably be more like this one: julia> struct Foo{T}; val::T; end
julia> foo(x::T) where T = @cfunction($((y)->[x] .+ y), Foo{T}, (Foo{T},))
ERROR: cfunction method definition: return type doesn't correspond to a C type |
Makes sense, that was also my guess after I got over the surprise :-)
From the user's high level point of view they may very well be trying to use ccall with a C type (eg, |
|
Ok, I think this will do. Thanks for the comments! |
A few special forms have a kind of "deferred top level evaluation" semantics for some of their children:
@cfunction- the function name and typesccall/foreigncall/@ccall- the type arguments and sometimes the function namecglobal- the function name@generated- the expression defining the generated function stubFor example, in
@ccall f()::Int, theIntmeans "the symbolIntas looked up in global scope in the module", and should fail ifIntrefers to a local variable. Currently all three of these cases are handled through different mechanisms with varying levels of hygiene inconsistency and ability to warn about access to local variables.To fix this problem, introduce the new
K"deferred_toplevel_eval"K"static_eval"form which wraps an expression and preserves it as a piece of AST in the output (rather than producing IR), but still resolves scope and hygiene.Use this new form to remove all the special case child-index-dependent handling of these disparate forms from the IR.
Also fixes bugs in
Base.@cfunctionhygiene where the function name might be resolved to a global symbol in the wrong module.Also move demo
@ccallimplementation into JuliaLowering, clean up and fix a few things which were broken and implement the gc_safe option fromBase.@ccall. Makes use of deferred_toplevel_eval kind for more precise diagnostics.Needed for #33 which makes the issues with
@cfunctionhygiene more obvious