X-Git-Url: http://nitlanguage.org diff --git a/src/compiler_ffi.nit b/src/compiler_ffi.nit index b885bc7..4c55f65 100644 --- a/src/compiler_ffi.nit +++ b/src/compiler_ffi.nit @@ -45,12 +45,25 @@ redef class MModule ensure_compile_nitni_base(v) nitni_ccu.header_c_types.add("#include \"{name}._ffi.h\"\n") + nitni_ccu.header_c_types.add """ +extern void nitni_global_ref_incr(void*); +extern void nitni_global_ref_decr(void*); +""" nitni_ccu.write_as_nitni(self, v.compiler.modelbuilder.compile_dir) for file in nitni_ccu.files do v.compiler.extern_bodies.add(new ExternCFile(file, c_compiler_options)) end + + # reset FFI things so the next compilation job, if any, starts with a clean context + # FIXME clean and rationalize this + nitni_ccu = null + compiled_ffi_methods.clear + ffi_ccu = null + ffi_files.clear + compiled_callbacks.clear + #Do not reset `foreign_callbacks` and `ffi_callbacks` because they are computed in previous phases end private fun ensure_compile_nitni_base(v: AbstractCompilerVisitor) @@ -154,6 +167,7 @@ redef class AMethPropdef end v.adapt_signature(mpropdef, arguments) + v.unbox_signature_extern(mpropdef, arguments) var arguments_for_c = new Array[String] for a in [0..arguments.length[ do @@ -169,7 +183,7 @@ redef class AMethPropdef arguments_for_c.add(arg.name) else v.add("struct nitni_instance* var_for_c_{a};") - v.add("var_for_c_{a} = malloc(sizeof(struct nitni_instance));") + v.add("var_for_c_{a} = nit_alloc(sizeof(struct nitni_instance));") v.add("var_for_c_{a}->value = {arg.name};") arguments_for_c.add("var_for_c_{a}") end @@ -186,6 +200,7 @@ redef class AMethPropdef v.add("ret_var = {externname}({arguments_for_c.join(", ")});") v.add("{recv_var} = ret_var->value;") end + recv_var = v.box_extern(recv_var, return_mtype) v.ret(recv_var) end @@ -212,6 +227,7 @@ redef class AMethPropdef var recv_var = v.new_var(return_mtype) v.adapt_signature(mpropdef, arguments) + v.unbox_signature_extern(mpropdef, arguments) arguments.shift @@ -226,7 +242,7 @@ redef class AMethPropdef arguments_for_c.add(arg.name) else v.add("struct nitni_instance* var_for_c_{a};") - v.add("var_for_c_{a} = malloc(sizeof(struct nitni_instance));") + v.add("var_for_c_{a} = nit_alloc(sizeof(struct nitni_instance));") v.add("var_for_c_{a}->value = {arg.name};") arguments_for_c.add("var_for_c_{a}") end @@ -239,6 +255,7 @@ redef class AMethPropdef v.add("ret_var = {externname}({arguments_for_c.join(", ")});") v.add("{recv_var} = ret_var->value;") end + recv_var = v.box_extern(recv_var, return_mtype) v.ret(recv_var) compile_ffi_support_to_c(v) @@ -285,7 +302,7 @@ redef class AbstractCompilerVisitor add("return {src};") else add("struct nitni_instance* ret_for_c;") - add("ret_for_c = malloc(sizeof(struct nitni_instance));") + add("ret_for_c = nit_alloc(sizeof(struct nitni_instance));") add("ret_for_c->value = {src};") add("return ret_for_c;") end @@ -307,14 +324,17 @@ redef class MType private fun compile_extern_helper_functions(v: AbstractCompilerVisitor, ccu: CCompilationUnit) do # actually, we do not need to do anything when using the bohem garbage collector + var call_context = from_c_call_context # incr_ref - var nitni_visitor = v.compiler.new_visitor - ccu.header_decl.add("#define {mangled_cname}_incr_ref(from) while(0)\{\}\n") - - # incr_ref - nitni_visitor = v.compiler.new_visitor - ccu.header_decl.add("#define {mangled_cname}_decr_ref(from) while(0)\{\}\n") + ccu.header_decl.add "#ifndef {mangled_cname}_incr_ref\n" + ccu.header_decl.add " #define {mangled_cname}_incr_ref(from) nitni_global_ref_incr(({call_context.name_mtype(self)})(from))\n" + ccu.header_decl.add "#endif\n" + + # decr_ref + ccu.header_decl.add "#ifndef {mangled_cname}_decr_ref\n" + ccu.header_decl.add " #define {mangled_cname}_decr_ref(from) nitni_global_ref_decr(({call_context.name_mtype(self)})(from))\n" + ccu.header_decl.add "#endif\n" end end @@ -345,7 +365,7 @@ redef class MNullableType var full_internal_csignature = "{cname_blind} {full_cname}()" nitni_visitor.add("{full_internal_csignature} \{") nitni_visitor.add("struct nitni_instance* ret_for_c;") - nitni_visitor.add("ret_for_c = malloc(sizeof(struct nitni_instance));") + nitni_visitor.add("ret_for_c = nit_alloc(sizeof(struct nitni_instance));") nitni_visitor.add("ret_for_c->value = NULL;") nitni_visitor.add("return ret_for_c;") nitni_visitor.add("\}") @@ -375,17 +395,14 @@ redef class MExplicitCall var mtype: MType = recv_mtype var recv_var = null if mproperty.is_init then - if recv_mtype.mclass.kind == extern_kind then - recv_var = nitni_visitor.new_var(mtype) - else - var recv_mtype = recv_mtype - recv_var = nitni_visitor.init_instance(recv_mtype) - nitni_visitor.add("{mtype.ctype} recv /* var self: {mtype} */;") - nitni_visitor.add("recv = {recv_var};") - end + var recv_mtype = recv_mtype + recv_var = nitni_visitor.init_instance(recv_mtype) + nitni_visitor.add("{mtype.ctype} recv /* var self: {mtype} */;") + nitni_visitor.add("recv = {recv_var};") else mtype = mtype.anchor_to(v.compiler.mainmodule, recv_mtype) recv_var = nitni_visitor.var_from_c("recv", mtype) + recv_var = nitni_visitor.box_extern(recv_var, mtype) end vars.add(recv_var) @@ -393,6 +410,7 @@ redef class MExplicitCall for p in msignature.mparameters do var arg_mtype = p.mtype.anchor_to(v.compiler.mainmodule, recv_mtype) var arg = nitni_visitor.var_from_c(p.name, arg_mtype) + arg = nitni_visitor.box_extern(arg, arg_mtype) vars.add(arg) end @@ -407,6 +425,7 @@ redef class MExplicitCall assert ret_var != null return_mtype = return_mtype.anchor_to(v.compiler.mainmodule, recv_mtype) ret_var = nitni_visitor.autobox(ret_var, return_mtype) + ret_var = nitni_visitor.unbox_extern(ret_var, return_mtype) nitni_visitor.ret_to_c(ret_var, return_mtype) end nitni_visitor.add("\}") @@ -443,11 +462,13 @@ redef class MExplicitSuper var vars = new Array[RuntimeVariable] var recv_var = nitni_visitor.var_from_c("recv", mclass_type) + recv_var = nitni_visitor.box_extern(recv_var, mclass_type) vars.add(recv_var) for p in msignature.mparameters do var arg_mtype = v.anchor(p.mtype) var arg = nitni_visitor.var_from_c(p.name, arg_mtype) + arg = nitni_visitor.box_extern(arg, arg_mtype) vars.add(arg) end @@ -457,6 +478,8 @@ redef class MExplicitSuper if return_mtype != null then assert ret_var != null return_mtype = v.anchor(return_mtype) + ret_var = nitni_visitor.autobox(ret_var, return_mtype) + ret_var = nitni_visitor.unbox_extern(ret_var, return_mtype) nitni_visitor.ret_to_c(ret_var, return_mtype) end nitni_visitor.add("\}") @@ -484,11 +507,14 @@ redef class MExplicitCast var nitni_visitor = v.compiler.new_visitor nitni_visitor.frame = v.frame - var full_internal_csignature = "int {v.compiler.mainmodule.name }___{from.mangled_cname}_is_a_{to.mangled_cname}({from.cname_blind} from)" + var full_internal_csignature = "int {v.compiler.mainmodule.name }___{from.mangled_cname}_is_a_{to.mangled_cname}({internal_call_context.name_mtype(from)} from)" + nitni_visitor.add_decl("/* nitni check for {from} to {to} */") nitni_visitor.add_decl("{full_internal_csignature} \{") - var from_var = new RuntimeVariable("from->value", from, from) + #var from_var = new RuntimeVariable("from->value", from, from) + var from_var = nitni_visitor.var_from_c("from", from) + from_var = nitni_visitor.box_extern(from_var, from) var recv_var = nitni_visitor.type_test(from_var, to, "FFI isa") nitni_visitor.add("return {recv_var};") @@ -515,11 +541,12 @@ redef class MExplicitCast nitni_visitor = v.compiler.new_visitor nitni_visitor.frame = v.frame - full_internal_csignature = "{to.cname_blind} {v.compiler.mainmodule.name }___{from.mangled_cname}_as_{to.mangled_cname}({from.cname_blind} from)" + full_internal_csignature = "{to.cname_blind} {v.compiler.mainmodule.name }___{from.mangled_cname}_as_{to.mangled_cname}({internal_call_context.name_mtype(from)} from)" nitni_visitor.add_decl("/* nitni cast for {from} to {to} */") nitni_visitor.add_decl("{full_internal_csignature} \{") from_var = nitni_visitor.var_from_c("from", from) + from_var = nitni_visitor.box_extern(from_var, from) ## test type var check = nitni_visitor.type_test(from_var, to, "FFI cast") @@ -529,6 +556,7 @@ redef class MExplicitCast ## internal cast recv_var = nitni_visitor.autobox(from_var, to) + recv_var = nitni_visitor.unbox_extern(recv_var, to) nitni_visitor.ret_to_c(recv_var, to)