@@ -143,14 +143,17 @@ function is_valid_ir_rvalue(ctx, lhs, rhs)
143143 return is_ssa (ctx, lhs) ||
144144 is_valid_ir_argument (ctx, rhs) ||
145145 (kind (lhs) == K " BindingId" &&
146- # FIXME : add: invoke cfunction gc_preserve_begin copyast
147- kind (rhs) in KSet " new splatnew isdefined call foreigncall gc_preserve_begin foreigncall new_opaque_closure" )
146+ # FIXME : add: invoke ?
147+ kind (rhs) in KSet " new splatnew cfunction isdefined call foreigncall gc_preserve_begin foreigncall new_opaque_closure" )
148148end
149149
150- function contains_nonglobal_binding (ctx, ex)
151- contains_unquoted (ex) do e
150+ function check_no_local_bindings (ctx, ex, msg )
151+ contains_nonglobal_binding = contains_unquoted (ex) do e
152152 kind (e) == K " BindingId" && lookup_binding (ctx, e). kind != = :global
153153 end
154+ if contains_nonglobal_binding
155+ throw (LoweringError (ex, msg))
156+ end
154157end
155158
156159# evaluate the arguments of a call, creating temporary locations as needed
@@ -582,18 +585,15 @@ function compile(ctx::LinearIRContext, ex, needs_value, in_tail_pos)
582585 @chk ! needs_value (ex," TOMBSTONE encountered in value position" )
583586 nothing
584587 elseif k == K " call" || k == K " new" || k == K " splatnew" || k == K " foreigncall" ||
585- k == K " new_opaque_closure"
586- # TODO k ∈ cfunction cglobal
588+ k == K " new_opaque_closure" || k == K " cfunction"
587589 if k == K " foreigncall"
588590 args = SyntaxList (ctx)
589591 # todo: is is_leaf correct here? flisp uses `atom?`
590592 func = ex[1 ]
591593 if kind (func) == K " call" && kind (func[1 ]) == K " core" && func[1 ]. name_val == " tuple"
592594 # Tuples like core.tuple(:funcname, mylib_name) are allowed,
593595 # but may only reference globals.
594- if contains_nonglobal_binding (ctx, func)
595- throw (LoweringError (func, " ccall function name and library expression cannot reference local variables" ))
596- end
596+ check_no_local_bindings (ctx, func, " ccall function name and library expression cannot reference local variables" )
597597 append! (args, compile_args (ctx, ex[1 : 1 ]))
598598 elseif is_leaf (func)
599599 append! (args, compile_args (ctx, ex[1 : 1 ]))
@@ -602,18 +602,27 @@ function compile(ctx::LinearIRContext, ex, needs_value, in_tail_pos)
602602 end
603603 # 2nd to 5th arguments of foreigncall are special. They must be
604604 # left in place but cannot reference locals.
605- if contains_nonglobal_binding (ctx, ex[2 ])
606- throw (LoweringError (ex[2 ], " ccall return type cannot reference local variables" ))
607- end
605+ check_no_local_bindings (ctx, ex[2 ], " ccall return type cannot reference local variables" )
608606 for argt in children (ex[3 ])
609- if contains_nonglobal_binding (ctx, argt)
610- throw (LoweringError (argt, " ccall argument types cannot reference local variables" ))
611- end
607+ check_no_local_bindings (ctx, argt,
608+ " ccall argument types cannot reference local variables" )
612609 end
613610 append! (args, ex[2 : 5 ])
614611 append! (args, compile_args (ctx, ex[6 : end ]))
615612 args
613+ elseif k == K " cfunction"
614+ # Arguments of cfunction must be left in place except for argument
615+ # 2 (fptr)
616+ args = copy (children (ex))
617+ args[2 ] = only (compile_args (ctx, args[2 : 2 ]))
618+ check_no_local_bindings (ctx, ex[3 ],
619+ " cfunction return type cannot reference local variables" )
620+ for arg in children (ex[4 ])
621+ check_no_local_bindings (ctx, arg,
622+ " cfunction argument cannot reference local variables" )
623+ end
616624 else
625+ # TODO : cglobal
617626 args = compile_args (ctx, children (ex))
618627 end
619628 callex = makenode (ctx, ex, k, args)
0 commit comments