Skip to content

Commit 7b4fa51

Browse files
authored
ccall: support different types for vararg arguments (#32800)
Not currently supported in the front-end syntax, this modifies the backend to represent it and be capable of handling it (and need fewer lines of code!).
1 parent 4537d78 commit 7b4fa51

File tree

10 files changed

+191
-162
lines changed

10 files changed

+191
-162
lines changed

base/compiler/ssair/passes.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ function getfield_elim_pass!(ir::IRCode, domtree::DomTree)
575575
is_getfield = true
576576
is_unchecked = true
577577
elseif isexpr(stmt, :foreigncall)
578-
nccallargs = stmt.args[5]
578+
nccallargs = length(stmt.args[3]::SimpleVector)
579579
new_preserves = Any[]
580580
old_preserves = stmt.args[(6+nccallargs):end]
581581
for (pidx, preserved_arg) in enumerate(old_preserves)
@@ -817,7 +817,7 @@ function getfield_elim_pass!(ir::IRCode, domtree::DomTree)
817817
# Insert the new preserves
818818
for (use, new_preserves) in preserve_uses
819819
useexpr = ir[SSAValue(use)]
820-
nccallargs = useexpr.args[5]
820+
nccallargs = length(useexpr.args[3]::SimpleVector)
821821
old_preserves = filter(ssa->!isa(ssa, SSAValue) || !(ssa.id in intermediaries), useexpr.args[(6+nccallargs):end])
822822
new_expr = Expr(:foreigncall, useexpr.args[1:(6+nccallargs-1)]...,
823823
old_preserves..., new_preserves...)

base/compiler/validation.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const VALID_EXPR_HEADS = IdDict{Any,Any}(
2323
:copyast => 1:1,
2424
:meta => 0:typemax(Int),
2525
:global => 1:1,
26-
:foreigncall => 3:typemax(Int),
26+
:foreigncall => 5:typemax(Int), # name, RT, AT, nreq, cconv, args..., roots...
2727
:cfunction => 5:5,
2828
:isdefined => 1:1,
2929
:loopinfo => 0:typemax(Int),

base/meta.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,9 +313,9 @@ function _partially_inline!(@nospecialize(x), slot_replacements::Vector{Any},
313313
elseif i == 3
314314
x.args[3] = Core.svec(Any[_instantiate_type_in_env(argt, type_signature, static_param_values) for argt in x.args[3]]...)
315315
elseif i == 4
316-
@assert isa((x.args[4]::QuoteNode).value, Symbol)
316+
@assert isa(x.args[4], Int)
317317
elseif i == 5
318-
@assert isa(x.args[5], Int)
318+
@assert isa((x.args[5]::QuoteNode).value, Symbol)
319319
else
320320
x.args[i] = _partially_inline!(x.args[i], slot_replacements,
321321
type_signature, static_param_values,

doc/src/devdocs/ast.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,39 @@ These symbols appear in the `head` field of [`Expr`](@ref)s in lowered form.
469469

470470
* `:inline` and `:noinline`: Inlining hints.
471471

472+
* `foreigncall`
473+
474+
Statically-computed container for `ccall` information. The fields are:
475+
476+
* `args[1]` : name
477+
478+
The expression that'll be parsed for the foreign function.
479+
480+
* `args[2]::Type` : RT
481+
482+
The (literal) return type, computed statically when the containing method was defined.
483+
484+
* `args[3]::SimpleVector` (of Types) : AT
485+
486+
The (literal) vector of argument types, computed statically when the containing method was defined.
487+
488+
* `args[4]::Int` : nreq
489+
490+
The number of required arguments for a varargs function definition.
491+
492+
* `args[5]::QuoteNode{Symbol}` : calling convention
493+
494+
The calling convention for the call.
495+
496+
* `args[6:length(args[3])]` : arguments
497+
498+
The values for all the arguments (with types of each given in args[3]).
499+
500+
* `args[(length(args[3]) + 1):end]` : gc-roots
501+
502+
The additional objects that may need to be gc-rooted for the duration of the call.
503+
See [Working with LLVM](@ref Working-with-LLVM) for where these are derived from and how they get handled.
504+
472505

473506
### Method
474507

doc/src/devdocs/llvm.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ need to make sure that the array does stay alive while we're doing the
277277
[`ccall`](@ref). To understand how this is done, first recall the lowering of the
278278
above code:
279279
```julia
280-
return $(Expr(:foreigncall, :(:foo), Cvoid, svec(Ptr{Float64}), :(:ccall), 1, :($(Expr(:foreigncall, :(:jl_array_ptr), Ptr{Float64}, svec(Any), :(:ccall), 1, :(A)))), :(A)))
280+
return $(Expr(:foreigncall, :(:foo), Cvoid, svec(Ptr{Float64}), 0, :(:ccall), Expr(:foreigncall, :(:jl_array_ptr), Ptr{Float64}, svec(Any), 0, :(:ccall), :(A)), :(A)))
281281
```
282282
The last `:(A)`, is an extra argument list inserted during lowering that informs
283283
the code generator which Julia level values need to be kept alive for the

0 commit comments

Comments
 (0)