X-Git-Url: http://nitlanguage.org diff --git a/src/compiler/compiler_ffi.nit b/src/compiler/compiler_ffi.nit index 331955e..42423f9 100644 --- a/src/compiler/compiler_ffi.nit +++ b/src/compiler/compiler_ffi.nit @@ -18,7 +18,7 @@ module compiler_ffi intrude import abstract_compiler -intrude import common_ffi +intrude import ffi import nitni redef class MModule @@ -27,8 +27,7 @@ redef class MModule private fun nmodule(v: AbstractCompilerVisitor): nullable AModule do - var m2n = v.compiler.modelbuilder.mmodule2nmodule - return m2n.get_or_null(self) + return v.compiler.modelbuilder.mmodule2node(self) end redef fun finalize_ffi(compiler: AbstractCompiler) @@ -44,16 +43,19 @@ 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("#include \"{c_name}._ffi.h\"\n") nitni_ccu.header_c_types.add """ extern void nitni_global_ref_incr(void*); extern void nitni_global_ref_decr(void*); """ + var cflags = self.cflags[""].join(" ") 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)) + var f = new ExternCFile(file, cflags) + f.pkgconfigs.add_all pkgconfigs + v.compiler.extern_bodies.add(f) end # reset FFI things so the next compilation job, if any, starts with a clean context @@ -75,14 +77,11 @@ extern void nitni_global_ref_decr(void*); redef fun collect_linker_libs do - var s = c_linker_options - if s.is_empty then return null - var res = new ArraySet[String] - res.add s - return res + if not self.ldflags.keys.has("") then return null + return self.ldflags[""] end - private var compiled_callbacks: Array[NitniCallback] = new Array[NitniCallback] + private var compiled_callbacks = new Array[NitniCallback] # Returns true if callbacks has yet to be generated and register it as being generated private fun check_callback_compilation(cb: NitniCallback): Bool @@ -98,8 +97,7 @@ redef class AMethPropdef do var mmodule = mpropdef.mclassdef.mmodule var mainmodule = v.compiler.mainmodule - var amainmodule = v.compiler.modelbuilder.mmodule2nmodule[mainmodule] - var amodule = v.compiler.modelbuilder.mmodule2nmodule[mmodule] + var amodule = v.compiler.modelbuilder.mmodule2node(mmodule) var mclass_type = mpropdef.mclassdef.bound_mtype # Declare as extern @@ -119,21 +117,21 @@ redef class AMethPropdef mtype.compile_extern_type(v, ccu) # has callbacks already been compiled? (this may very well happen with global compilation) - if mmodule.check_callback_compilation(mtype) then mtype.compile_extern_helper_functions(v, ccu) + mtype.compile_extern_helper_functions(v, ccu, mmodule.check_callback_compilation(mtype)) end end # compile callbacks - for cb in foreign_callbacks.callbacks do if mainmodule.check_callback_compilation(cb) then - cb.compile_extern_callback(v, ccu) + for cb in foreign_callbacks.callbacks do + cb.compile_extern_callback(v, ccu, mainmodule.check_callback_compilation(cb)) end - for cb in foreign_callbacks.supers do if mainmodule.check_callback_compilation(cb) then - cb.compile_extern_callback(v, ccu) + for cb in foreign_callbacks.supers do + cb.compile_extern_callback(v, ccu, mainmodule.check_callback_compilation(cb)) end - for cb in foreign_callbacks.casts do if mainmodule.check_callback_compilation(cb) then - cb.compile_extern_callbacks(v, ccu) + for cb in foreign_callbacks.casts do + cb.compile_extern_callbacks(v, ccu, mainmodule.check_callback_compilation(cb)) end # manage nitni callback set @@ -255,11 +253,11 @@ end redef class CCompilationUnit fun write_as_nitni(mmodule: MModule, compdir: String) do - var base_name = "{mmodule.name}._nitni" + var base_name = "{mmodule.c_name}._nitni" var h_file = "{base_name}.h" write_header_to_file( mmodule, "{compdir}/{h_file}", new Array[String], - "{mmodule.cname.to_s.to_upper}_NITG_NITNI_H") + "{mmodule.c_name.to_s.to_upper}_NITG_NITNI_H") var c_file = "{base_name}.c" write_body_to_file( mmodule, "{compdir}/{c_file}", ["\"{h_file}\""] ) @@ -311,7 +309,7 @@ redef class MType ccu.header_c_types.add("#endif\n") end - private fun compile_extern_helper_functions(v: AbstractCompilerVisitor, ccu: CCompilationUnit) + private fun compile_extern_helper_functions(v: AbstractCompilerVisitor, ccu: CCompilationUnit, compile_implementation_too: Bool) do # actually, we do not need to do anything when using the bohem garbage collector var call_context = from_c_call_context @@ -329,7 +327,7 @@ redef class MType end redef class MNullableType - redef fun compile_extern_helper_functions(v, ccu) + redef fun compile_extern_helper_functions(v, ccu, compile_implementation_too) do super @@ -343,6 +341,8 @@ redef class MNullableType # In nitni files, #define friendly as extern ccu.header_decl.add("#define {base_cname} {full_cname}\n") + if not compile_implementation_too then return + # FIXME: This is ugly an broke the separate compilation principle # The real function MUST be compiled only once, #define pragma only protect the compiler, not the loader # However, I am not sure of the right approach here (eg. week refs are ugly) @@ -363,7 +363,7 @@ redef class MNullableType end redef class MExplicitCall - private fun compile_extern_callback(v: AbstractCompilerVisitor, ccu: CCompilationUnit) + private fun compile_extern_callback(v: AbstractCompilerVisitor, ccu: CCompilationUnit, compile_implementation_too: Bool) do var mproperty = mproperty assert mproperty isa MMethod @@ -372,6 +372,8 @@ redef class MExplicitCall var full_friendly_csignature = mproperty.build_csignature(recv_mtype, v.compiler.mainmodule, null, long_signature, internal_call_context) ccu.header_decl.add("extern {full_friendly_csignature};\n") + if not compile_implementation_too then return + # Internally, implement internal function var nitni_visitor = v.compiler.new_visitor nitni_visitor.frame = v.frame @@ -386,7 +388,7 @@ redef class MExplicitCall var recv_var = null if mproperty.is_init then var recv_mtype = recv_mtype - recv_var = nitni_visitor.init_instance(recv_mtype) + recv_var = nitni_visitor.init_instance_or_extern(recv_mtype) nitni_visitor.add("{mtype.ctype} recv /* var self: {mtype} */;") nitni_visitor.add("recv = {recv_var};") else @@ -423,12 +425,11 @@ redef class MExplicitCall end redef class MExplicitSuper - private fun compile_extern_callback(v: AbstractCompilerVisitor, ccu: CCompilationUnit) + private fun compile_extern_callback(v: AbstractCompilerVisitor, ccu: CCompilationUnit, compile_implementation_too: Bool) do var mproperty = from.mproperty assert mproperty isa MMethod var mclass_type = from.mclassdef.mclass.mclass_type - var mmodule = from.mclassdef.mmodule # In nitni files, declare internal function as extern var internal_csignature = mproperty.build_csignature(mclass_type, v.compiler.mainmodule, "___super", long_signature, internal_call_context) @@ -439,6 +440,8 @@ redef class MExplicitSuper var internal_cname = mproperty.build_cname(mclass_type, v.compiler.mainmodule, "___super", long_signature) ccu.header_decl.add("#define {friendly_cname} {internal_cname}\n") + if not compile_implementation_too then return + # Internally, implement internal function var nitni_visitor = v.compiler.new_visitor nitni_visitor.frame = v.frame @@ -477,7 +480,7 @@ redef class MExplicitSuper end redef class MExplicitCast - private fun compile_extern_callbacks(v: AbstractCompilerVisitor, ccu: CCompilationUnit) + private fun compile_extern_callbacks(v: AbstractCompilerVisitor, ccu: CCompilationUnit, compile_implementation_too: Bool) do var from = from var to = to @@ -493,22 +496,23 @@ redef class MExplicitCast # In nitni files, #define friendly as extern ccu.header_decl.add("#define {check_cname} {v.compiler.mainmodule.name}___{check_cname}\n") - # Internally, implement internal function - var nitni_visitor = v.compiler.new_visitor - nitni_visitor.frame = v.frame + if compile_implementation_too then + # Internally, implement internal function + 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}({internal_call_context.name_mtype(from)} 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} \{") + 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 = 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};") + 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};") - nitni_visitor.add("\}") + nitni_visitor.add("\}") + end # special checks if from == to.as_nullable then @@ -527,30 +531,32 @@ redef class MExplicitCast # In nitni files, #define friendly as extern ccu.header_decl.add("#define {cast_cname} {v.compiler.mainmodule.name}___{cast_cname}\n") - # Internally, implement internal function - nitni_visitor = v.compiler.new_visitor - nitni_visitor.frame = v.frame + if compile_implementation_too then + # Internally, implement internal function + var 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}({internal_call_context.name_mtype(from)} from)" - nitni_visitor.add_decl("/* nitni cast for {from} to {to} */") - nitni_visitor.add_decl("{full_internal_csignature} \{") + var 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) + var 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") - nitni_visitor.add("if (!{check}) \{") - nitni_visitor.add_abort("FFI cast failed") - nitni_visitor.add("\}") + ## test type + var check = nitni_visitor.type_test(from_var, to, "FFI cast") + nitni_visitor.add("if (!{check}) \{") + nitni_visitor.add_abort("FFI cast failed") + nitni_visitor.add("\}") - ## internal cast - recv_var = nitni_visitor.autobox(from_var, to) - recv_var = nitni_visitor.unbox_extern(recv_var, to) + ## internal cast + var 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) + nitni_visitor.ret_to_c(recv_var, to) - nitni_visitor.add("\}") + nitni_visitor.add("\}") + end # special casts if from.as_nullable == to then