From 8652e0d7438aef4be322b6c14699ad2832ea30e6 Mon Sep 17 00:00:00 2001 From: Em Chu Date: Fri, 21 Nov 2025 10:46:15 -0800 Subject: [PATCH] [JuliaLowering] Remove use of `@SyntaxTree` in ccall I'm assuming this macro (which is defined as "go find the file or REPL history entry this Expr came from and re-parse the text to SyntaxTree") is mostly for convenience in interactive environments. It's also breakable at precompile time with changes in the way we expand `quote`, and it takes a noticable amount of time in inference. This change just uses the less-convenient `@ast` form like the rest of the project. --- JuliaLowering/src/syntax_macros.jl | 27 ++++++---- JuliaLowering/test/misc_ir.jl | 80 ++++++++++++------------------ 2 files changed, 50 insertions(+), 57 deletions(-) diff --git a/JuliaLowering/src/syntax_macros.jl b/JuliaLowering/src/syntax_macros.jl index 0621c528191ef..cd6599a3fbbb8 100644 --- a/JuliaLowering/src/syntax_macros.jl +++ b/JuliaLowering/src/syntax_macros.jl @@ -189,13 +189,20 @@ function ccall_macro_lower(ctx, ex, convention, func, rettype, types, args, gc_s ] ] elseif kf == K"$" - check = @SyntaxTree quote - func = $(func[1]) - if !isa(func, Ptr{Cvoid}) - name = :($(func[1])) - throw(ArgumentError("interpolated function `$name` was not a `Ptr{Cvoid}`, but $(typeof(func))")) - end - end + fid = @ast ctx func[1] "func"::K"Identifier" + check = @ast ctx func [K"block" + [K"=" fid func[1]] + [K"if" + [K"call" (!isa)::K"Value" fid [K"curly" Ptr::K"Value" Cvoid::K"Value"]] + [K"block" + [K"=" "name"::K"Identifier" [K"quote" func[1]]] + [K"call" throw::K"Value" + [K"call" ArgumentError::K"Value" + [K"string" + "interpolated function `"::K"String" + "name"::K"Identifier" + "` was not a `Ptr{Cvoid}`, but "::K"String" + [K"call" typeof::K"Value" fid]]]]]]] push!(statements, check) lowered_func = check[1][1] else @@ -208,9 +215,11 @@ function ccall_macro_lower(ctx, ex, convention, func, rettype, types, args, gc_s for (i, (type, arg)) in enumerate(zip(types, args)) argi = @ast ctx arg "arg$i"::K"Identifier" # TODO: Does it help to emit ssavar() here for the `argi`? - push!(statements, @SyntaxTree :(local $argi = Base.cconvert($type, $arg))) + push!(statements, + @ast ctx arg [K"local" + [K"=" argi [K"call" Base.cconvert::K"Value" type arg]]]) push!(roots, argi) - push!(cargs, @SyntaxTree :(Base.unsafe_convert($type, $argi))) + push!(cargs, @ast ctx ex [K"call" Base.unsafe_convert::K"Value" type argi]) end effect_flags = UInt16(0) push!(statements, @ast ctx ex [K"foreigncall" diff --git a/JuliaLowering/test/misc_ir.jl b/JuliaLowering/test/misc_ir.jl index 912e10ed27d50..0b9ab2ee7e78c 100644 --- a/JuliaLowering/test/misc_ir.jl +++ b/JuliaLowering/test/misc_ir.jl @@ -402,59 +402,43 @@ end # Basic @ccall lowering @ccall foo(x::X, y::Y)::R #--------------------- -1 JuliaLowering.Base -2 (call top.getproperty %₁ :cconvert) -3 TestMod.X -4 TestMod.x -5 (= slot₁/arg1 (call %₂ %₃ %₄)) -6 JuliaLowering.Base -7 (call top.getproperty %₆ :cconvert) -8 TestMod.Y -9 TestMod.y -10 (= slot₂/arg2 (call %₇ %₈ %₉)) -11 JuliaLowering.Base -12 (call top.getproperty %₁₁ :unsafe_convert) -13 TestMod.X -14 slot₁/arg1 -15 (call %₁₂ %₁₃ %₁₄) -16 JuliaLowering.Base -17 (call top.getproperty %₁₆ :unsafe_convert) -18 TestMod.Y -19 slot₂/arg2 -20 (call %₁₇ %₁₈ %₁₉) -21 slot₁/arg1 -22 slot₂/arg2 -23 (foreigncall :foo (static_eval TestMod.R) (static_eval (call core.svec TestMod.X TestMod.Y)) 0 :($(QuoteNode((:ccall, 0x0000, false)))) %₁₅ %₂₀ %₂₁ %₂₂) -24 (return %₂₃) +1 TestMod.X +2 TestMod.x +3 (= slot₁/arg1 (call Base.cconvert %₁ %₂)) +4 TestMod.Y +5 TestMod.y +6 (= slot₂/arg2 (call Base.cconvert %₄ %₅)) +7 TestMod.X +8 slot₁/arg1 +9 (call Base.unsafe_convert %₇ %₈) +10 TestMod.Y +11 slot₂/arg2 +12 (call Base.unsafe_convert %₁₀ %₁₁) +13 slot₁/arg1 +14 slot₂/arg2 +15 (foreigncall :foo (static_eval TestMod.R) (static_eval (call core.svec TestMod.X TestMod.Y)) 0 :($(QuoteNode((:ccall, 0x0000, false)))) %₉ %₁₂ %₁₃ %₁₄) +16 (return %₁₅) ######################################## # @ccall lowering with gc_safe @ccall foo(x::X; y::Y)::R gc_safe=true #--------------------- -1 JuliaLowering.Base -2 (call top.getproperty %₁ :cconvert) -3 TestMod.X -4 TestMod.x -5 (= slot₁/arg1 (call %₂ %₃ %₄)) -6 JuliaLowering.Base -7 (call top.getproperty %₆ :cconvert) -8 TestMod.Y -9 TestMod.y -10 (= slot₂/arg2 (call %₇ %₈ %₉)) -11 JuliaLowering.Base -12 (call top.getproperty %₁₁ :unsafe_convert) -13 TestMod.X -14 slot₁/arg1 -15 (call %₁₂ %₁₃ %₁₄) -16 JuliaLowering.Base -17 (call top.getproperty %₁₆ :unsafe_convert) -18 TestMod.Y -19 slot₂/arg2 -20 (call %₁₇ %₁₈ %₁₉) -21 slot₁/arg1 -22 slot₂/arg2 -23 (foreigncall :foo (static_eval TestMod.R) (static_eval (call core.svec TestMod.X TestMod.Y)) 1 :($(QuoteNode((:ccall, 0x0000, true)))) %₁₅ %₂₀ %₂₁ %₂₂) -24 (return %₂₃) +1 TestMod.X +2 TestMod.x +3 (= slot₁/arg1 (call Base.cconvert %₁ %₂)) +4 TestMod.Y +5 TestMod.y +6 (= slot₂/arg2 (call Base.cconvert %₄ %₅)) +7 TestMod.X +8 slot₁/arg1 +9 (call Base.unsafe_convert %₇ %₈) +10 TestMod.Y +11 slot₂/arg2 +12 (call Base.unsafe_convert %₁₀ %₁₁) +13 slot₁/arg1 +14 slot₂/arg2 +15 (foreigncall :foo (static_eval TestMod.R) (static_eval (call core.svec TestMod.X TestMod.Y)) 1 :($(QuoteNode((:ccall, 0x0000, true)))) %₉ %₁₂ %₁₃ %₁₄) +16 (return %₁₅) ######################################## # non-macro ccall with vararg in signature, but none provided