Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FFI: Static types for references to Nit objects from C code #2348

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions src/compiler/compiler_ffi/compiler_ffi.nit
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ redef class MExplicitCall
assert mproperty isa MMethod

# In nitni files, declare internal function as extern
var full_friendly_csignature = mproperty.build_csignature(recv_mtype, v.compiler.mainmodule, null, long_signature, internal_call_context)
var full_friendly_csignature = mproperty.build_csignature(recv_mtype, v.compiler.mainmodule, null, long_signature, user_c_call_context)
ccu.header_decl.add("extern {full_friendly_csignature};\n")

if not compile_implementation_too then return
Expand Down Expand Up @@ -145,17 +145,16 @@ end
redef class MType
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
var call_context = user_c_call_context

# incr_ref
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 " #define {mangled_cname}_incr_ref(from) nitni_global_ref_incr(({call_context.name_mtype(self)})((void*)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 " #define {mangled_cname}_decr_ref(from) nitni_global_ref_decr(({call_context.name_mtype(self)})((void*)from))\n"
ccu.header_decl.add "#endif\n"
end
end
Expand All @@ -169,7 +168,7 @@ redef class MNullableType
var full_cname = "NIT_NULL___{base_cname}"

# In nitni files, declare internal function as extern
var full_friendly_csignature = "{cname_blind} {full_cname}()"
var full_friendly_csignature = "{friendly_cname} {full_cname}()"
ccu.header_decl.add("extern {full_friendly_csignature};\n")

# In nitni files, #define friendly as extern
Expand Down Expand Up @@ -204,7 +203,7 @@ redef class MExplicitSuper
var mclass_type = from.mclassdef.mclass.mclass_type

# 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)
var internal_csignature = mproperty.build_csignature(mclass_type, v.compiler.mainmodule, "___super", long_signature, user_c_call_context)
ccu.header_decl.add("extern {internal_csignature};\n")

# In nitni files, #define friendly as extern
Expand Down Expand Up @@ -262,7 +261,7 @@ redef class MExplicitCast
#

# In nitni files, declare internal function as extern
var full_friendly_csignature = "int {v.compiler.mainmodule.c_name }___{from.mangled_cname}_is_a_{to.mangled_cname}({from.cname_blind})"
var full_friendly_csignature = "int {v.compiler.mainmodule.c_name}___{from.mangled_cname}_is_a_{to.mangled_cname}({from.friendly_cname})"
ccu.header_decl.add("extern {full_friendly_csignature};\n")

# In nitni files, #define friendly as extern
Expand Down Expand Up @@ -301,7 +300,7 @@ redef class MExplicitCast
#

# In nitni files, declare internal function as extern
full_friendly_csignature = "{to.cname_blind} {v.compiler.mainmodule.c_name }___{from.mangled_cname}_as_{to.mangled_cname}({from.cname_blind})"
full_friendly_csignature = "{to.friendly_cname} {v.compiler.mainmodule.c_name }___{from.mangled_cname}_as_{to.mangled_cname}({from.friendly_cname})"
ccu.header_decl.add("extern {full_friendly_csignature};\n")

# In nitni files, #define friendly as extern
Expand Down
6 changes: 3 additions & 3 deletions src/compiler/compiler_ffi/light.nit
Original file line number Diff line number Diff line change
Expand Up @@ -274,9 +274,9 @@ redef class MType
assert not is_cprimitive

# define friendly type
ccu.header_c_types.add("#ifndef NIT_TYPE_{cname}\n")
ccu.header_c_types.add("#define NIT_TYPE_{cname} 1\n")
ccu.header_c_types.add("typedef struct nitni_instance *{cname};\n")
ccu.header_c_types.add("#ifndef NIT_TYPE_{friendly_cname}\n")
ccu.header_c_types.add("#define NIT_TYPE_{friendly_cname} 1\n")
ccu.header_c_types.add("typedef struct nit_struct{friendly_cname}_\{ struct nitni_instance *ref; \} *{friendly_cname};\n")
ccu.header_c_types.add("#endif\n")
end
end
4 changes: 2 additions & 2 deletions src/compiler/separate_compiler.nit
Original file line number Diff line number Diff line change
Expand Up @@ -1288,8 +1288,8 @@ class SeparateCompilerVisitor
self.add("{res} = BOX_{valtype.c_name}({value}); /* boxing {value.mtype} */")
self.require_declaration("type_{mtype.c_name}")
self.add("{res}->type = &type_{mtype.c_name};")
self.require_declaration("class_{mtype.c_name}")
self.add("{res}->class = &class_{mtype.c_name};")
self.require_declaration("class_{mtype.mclass.c_name}")
self.add("{res}->class = &class_{mtype.mclass.c_name};")
return res
else
return value
Expand Down
8 changes: 3 additions & 5 deletions src/ffi/cpp.nit
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class CPPLanguage
var mproperty = m.mpropdef.mproperty

# Signature of the indirection function implemented as `extern "C"` in C++
var indirection_sig = mproperty.build_csignature(mclass_type, mmodule, "___cpp_impl_mid", long_signature, internal_call_context)
var indirection_sig = mproperty.build_csignature(mclass_type, mmodule, "___cpp_impl_mid", long_signature, user_c_call_context)

## In C file (__ffi.c)

Expand All @@ -70,7 +70,7 @@ class CPPLanguage

# Call the indirection function from C (___impl)
var fc: CFunction = new ExternCFunction(m, mmodule)
fc.exprs.add(mproperty.build_ccall(mclass_type, mmodule, "___cpp_impl_mid", long_signature, cpp_call_context, null))
fc.exprs.add(mproperty.build_ccall(mclass_type, mmodule, "___cpp_impl_mid", long_signature, user_c_call_context, null))
fc.exprs.add("\n")
ecc.add_exported_function( fc )

Expand Down Expand Up @@ -114,8 +114,6 @@ class CPPLanguage
mmodule.cpp_file.add_local_function( fc )
end

redef fun compile_extern_class(block, m, ecc, mmodule) do end

redef fun get_ftype(block, m) do return new ForeignCppType(block.code)

redef fun compile_to_files(mmodule, compdir)
Expand Down Expand Up @@ -225,7 +223,7 @@ private class CppCallContext
end
end

return mtype.cname
return mtype.friendly_cname
end
end

Expand Down
6 changes: 2 additions & 4 deletions src/ffi/java.nit
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,6 @@ class JavaLanguage
mmodule.callbacks_used_from_java.join m.foreign_callbacks
end

redef fun compile_extern_class(block, m, ccu, mmodule) do end

redef fun get_ftype(block, m) do return new ForeignJavaType(block.code)

redef fun compile_to_files(mmodule, compdir)
Expand Down Expand Up @@ -381,15 +379,15 @@ private class ToJavaCallContext
super CallContext

redef fun cast_to(mtype, name) do return "({mtype.jni_type})({name})"
redef fun cast_from(mtype, name) do return "({mtype.cname})({name})"
redef fun cast_from(mtype, name) do return "({mtype.friendly_cname})({name})"
redef fun name_mtype(mtype) do return mtype.jni_type
end

# Context in C, when call are from JNI to normal C
private class FromJavaCallContext
super CallContext

redef fun cast_to(mtype, name) do return "({mtype.cname})({name})"
redef fun cast_to(mtype, name) do return "({mtype.friendly_cname})({name})"
redef fun cast_from(mtype, name) do return "({mtype.jni_type})({name})"
redef fun name_mtype(mtype) do return mtype.jni_type
end
Expand Down
37 changes: 7 additions & 30 deletions src/ffi/light_c.nit
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,11 @@ class CLanguage
redef fun compile_extern_method(block, m, ecc, mmodule)
do
var fc = new ExternCFunction(m, mmodule)
fc.decls.add( block.location.as_line_pragma )
fc.exprs.add( block.code )
fc.decls.add block.location.as_line_pragma
fc.exprs.add block.code
ecc.body_impl.add fc.to_writer
end

redef fun compile_extern_class(block, m, ecc, mmodule) do end

redef fun get_ftype(block, m) do return new ForeignCType(block.code)
end

Expand All @@ -71,9 +69,6 @@ redef class Location
end

redef class MModule
# FIXME make nullable the key of `cflags`, `ldflags` and `cppflags` when
# supported by the bootstrap

# Custom options for the C compiler (CFLAGS)
var cflags = new MultiHashMap[String, String]

Expand All @@ -92,31 +87,13 @@ class ForeignCType
end

# Context when calling user C code from generated code
fun to_c_call_context: ToCCallContext do return once new ToCCallContext

# Context when calling generated code from user C code
fun from_c_call_context: FromCCallContext do return once new FromCCallContext

# Context when calling user C code from generated code
class ToCCallContext
super CallContext
fun user_c_call_context: UserCCallContext do return once new UserCCallContext

# TODO: private init because singleton instance (see `to_c_call_context`)

redef fun name_mtype(mtype)
do
if mtype isa MClassType and mtype.mclass.kind == extern_kind then return "void *"
return mtype.cname
end
end

# Context when calling generated code from user C code
class FromCCallContext
# Context in C code written by the user
class UserCCallContext
super CallContext

# TODO: private init because singleton instance (see `from_c_call_context`)

redef fun name_mtype(mtype) do return mtype.cname
redef fun name_mtype(mtype) do return mtype.friendly_cname
end

class ExternCFunction
Expand All @@ -129,7 +106,7 @@ class ExternCFunction
self.method = method

var recv_mtype = method.mpropdef.mclassdef.bound_mtype
var csignature = method.mpropdef.mproperty.build_csignature(recv_mtype, mmodule, "___impl", long_signature, from_c_call_context)
var csignature = method.mpropdef.mproperty.build_csignature(recv_mtype, mmodule, "___impl", long_signature, user_c_call_context)

super( csignature )
end
Expand Down
4 changes: 1 addition & 3 deletions src/ffi/light_ffi.nit
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,12 @@ redef class AModule
ffi_ccu.body_decl.add("#endif\n")

for nclassdef in n_classdefs do
# Does it declares an extern type?
# Is it an extern class with an extern type?
if nclassdef isa AStdClassdef and nclassdef.n_extern_code_block != null then
mmodule.uses_ffi = true
var language = nclassdef.n_extern_code_block.language
assert language != null
mmodule.present_languages.add(language)
nclassdef.n_extern_code_block.language.compile_extern_class(
nclassdef.n_extern_code_block.as(not null), nclassdef, ffi_ccu, mmodule)
end
end
end
Expand Down
17 changes: 5 additions & 12 deletions src/ffi/light_ffi_base.nit
Original file line number Diff line number Diff line change
Expand Up @@ -103,19 +103,16 @@ redef class AExternCodeBlock
var language: nullable FFILanguage = null
end

# Visitor for a specific languages. Works kinda like a `Phase` and is executed
# by a `Phase`.
class FFILanguage
# Visitor for a foreign language
abstract class FFILanguage

# `FFILanguageAssignationPhase` assigning `self` to `AExternCodeBlock`s
var ffi_language_assignation_phase: FFILanguageAssignationPhase

init
do
ffi_language_assignation_phase.languages.add(self)
end
init do ffi_language_assignation_phase.languages.add(self)

# Is this `block` written in this language?
fun identify_language(block: AExternCodeBlock ): Bool is abstract
fun identify_language(block: AExternCodeBlock): Bool is abstract

# Generate wrapper code for this module/header code block
fun compile_module_block(block: AExternCodeBlock, ecc: CCompilationUnit, mmodule: MModule) is abstract
Expand All @@ -124,10 +121,6 @@ class FFILanguage
fun compile_extern_method(block: AExternCodeBlock, m: AMethPropdef,
ecc: CCompilationUnit, nmodule: MModule) is abstract

# Generate wrapper code for this extern class
fun compile_extern_class(block: AExternCodeBlock, m: AClassdef,
ecc: CCompilationUnit, mmodule: MModule) is abstract

# Get the foreign type of this extern class definition
fun get_ftype(block: AExternCodeBlock, m: AClassdef): ForeignType is abstract

Expand Down
4 changes: 1 addition & 3 deletions src/ffi/objc.nit
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,6 @@ class ObjCLanguage
mmodule.objc_file.add_exported_function fc
end

redef fun compile_extern_class(block, m, ecc, mmodule) do end

redef fun get_ftype(block, m) do return new ForeignObjCType(block.code)

redef fun compile_to_files(mmodule, compdir)
Expand Down Expand Up @@ -222,7 +220,7 @@ private class ObjCCallContext
end
end

return mtype.cname
return mtype.friendly_cname
end
end

Expand Down
4 changes: 2 additions & 2 deletions src/interpreter/dynamic_loading_ffi/on_demand_compiler.nit
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ typedef union nit_call_arg {
var used_types = collect_mtypes
for t in used_types do
if not t.is_cprimitive then
ecc.header_c_types.add "typedef void* {t.cname};\n"
ecc.header_c_types.add "typedef void* {t.friendly_cname};\n"
end
end

Expand Down Expand Up @@ -291,7 +291,7 @@ end

redef class MMethodDef
# Name of the entry point to the implementation function in the foreign lib
fun foreign_lib_entry_cname: String do return "entry__{cname}"
fun foreign_lib_entry_cname: String do return "entry__{friendly_cname}"

# Compile the standardized entry point as part of the foreign lib API
private fun compile_foreign_code_entry(ecc: CCompilationUnit)
Expand Down
6 changes: 3 additions & 3 deletions src/nitni/nitni_base.nit
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,14 @@ end
redef class MMethodDef
# Name of the function to callback this method from C,
# also used in other functions names used for this method.
fun cname: String do return "{mclassdef.mclass.name}_{mproperty.short_cname}"
fun friendly_cname: String do return "{mclassdef.mclass.name}_{mproperty.short_cname}"
end

redef class MType
# Representation of this type in pure C on the FFI extern side
# Object -> Object
# Pointer -> void*
fun cname: String do return cname_normal_class
fun friendly_cname: String do return cname_normal_class

# Representation of this type in C for the internal of the system
# Hides extern types.
Expand All @@ -89,7 +89,7 @@ redef class MType
end

redef class MClassType
redef fun cname
redef fun friendly_cname
do
var name = mclass.name
if name == "Bool" then return "int"
Expand Down
Loading