X-Git-Url: http://nitlanguage.org diff --git a/src/compiler/separate_erasure_compiler.nit b/src/compiler/separate_erasure_compiler.nit index 8e0a0b2..635e601 100644 --- a/src/compiler/separate_erasure_compiler.nit +++ b/src/compiler/separate_erasure_compiler.nit @@ -194,74 +194,12 @@ class SeparateErasureCompiler self.header.add_decl("typedef struct instance \{ const struct class *class; nitattribute_t attrs[1]; \} val; /* general C type representing a Nit instance. */") end - redef fun compile_class_to_c(mclass: MClass) + redef fun compile_class_if_universal(ccinfo, v) do - var mtype = mclass.intro.bound_mtype + var mclass = ccinfo.mclass + var mtype = ccinfo.mtype var c_name = mclass.c_name - - var class_table = self.class_tables[mclass] - var v = self.new_visitor - - var rta = runtime_type_analysis - var is_dead = false # mclass.kind == abstract_kind or mclass.kind == interface_kind - if not is_dead and rta != null and not rta.live_classes.has(mclass) and not mtype.is_c_primitive and mclass.name != "NativeArray" then - is_dead = true - end - - v.add_decl("/* runtime class {c_name} */") - - self.provide_declaration("class_{c_name}", "extern const struct class class_{c_name};") - v.add_decl("extern const struct type_table type_table_{c_name};") - - # Build class vft - v.add_decl("const struct class class_{c_name} = \{") - v.add_decl("{class_ids[mclass]},") - v.add_decl("\"{mclass.name}\", /* class_name_string */") - v.add_decl("{self.box_kind_of(mclass)}, /* box_kind */") - v.add_decl("{class_colors[mclass]},") - if not is_dead then - if build_class_vts_table(mclass) then - v.require_declaration("vts_table_{c_name}") - v.add_decl("&vts_table_{c_name},") - else - v.add_decl("NULL,") - end - v.add_decl("&type_table_{c_name},") - v.add_decl("\{") - var vft = self.method_tables.get_or_null(mclass) - if vft != null then for i in [0 .. vft.length[ do - var mpropdef = vft[i] - if mpropdef == null then - v.add_decl("NULL, /* empty */") - else - assert mpropdef isa MMethodDef - if rta != null and not rta.live_methoddefs.has(mpropdef) then - v.add_decl("NULL, /* DEAD {mclass.intro_mmodule}:{mclass}:{mpropdef} */") - continue - end - var rf = mpropdef.virtual_runtime_function - v.require_declaration(rf.c_name) - v.add_decl("(nitmethod_t){rf.c_name}, /* pointer to {mpropdef.full_name} */") - end - end - v.add_decl("\}") - end - v.add_decl("\};") - - # Build class type table - - v.add_decl("const struct type_table type_table_{c_name} = \{") - v.add_decl("{class_table.length},") - v.add_decl("\{") - for msuper in class_table do - if msuper == null then - v.add_decl("-1, /* empty */") - else - v.add_decl("{self.class_ids[msuper]}, /* {msuper} */") - end - end - v.add_decl("\}") - v.add_decl("\};") + var is_dead = ccinfo.is_dead if mtype.is_c_primitive or mtype.mclass.name == "Pointer" then #Build instance struct @@ -281,7 +219,7 @@ class SeparateErasureCompiler v.add("return (val*)res;") v.add("\}") - if mtype.mclass.name != "Pointer" then return + if mtype.mclass.name != "Pointer" then return true v = new_visitor self.provide_declaration("NEW_{c_name}", "{mtype.ctype} NEW_{c_name}();") @@ -299,7 +237,7 @@ class SeparateErasureCompiler v.add("return {res};") end v.add("\}") - return + return true else if mclass.name == "NativeArray" then #Build instance struct self.header.add_decl("struct instance_{c_name} \{") @@ -321,7 +259,7 @@ class SeparateErasureCompiler v.add("{res}->length = length;") v.add("return (val*){res};") v.add("\}") - return + return true else if mclass.name == "RoutineRef" then self.header.add_decl("struct instance_{c_name} \{") self.header.add_decl("const struct class *class;") @@ -341,7 +279,7 @@ class SeparateErasureCompiler v.add("{res}->method = method;") v.add("return (val*){res};") v.add("\}") - return + return true else if mtype.mclass.kind == extern_kind and mtype.mclass.name != "CString" then var pointer_type = mainmodule.pointer_type @@ -361,8 +299,84 @@ class SeparateErasureCompiler v.add("return {res};") end v.add("\}") - return + return true end + return false + end + + redef fun compile_class_vft(ccinfo, v) + do + var mclass = ccinfo.mclass + var mtype = ccinfo.mtype + var c_name = mclass.c_name + var is_dead = ccinfo.is_dead + var rta = runtime_type_analysis + + # Build class vft + self.provide_declaration("class_{c_name}", "extern const struct class class_{c_name};") + + v.add_decl("const struct class class_{c_name} = \{") + v.add_decl("{class_ids[mclass]},") + v.add_decl("\"{mclass.name}\", /* class_name_string */") + v.add_decl("{self.box_kind_of(mclass)}, /* box_kind */") + v.add_decl("{class_colors[mclass]},") + if not is_dead then + if build_class_vts_table(mclass) then + v.require_declaration("vts_table_{c_name}") + v.add_decl("&vts_table_{c_name},") + else + v.add_decl("NULL,") + end + v.add_decl("&type_table_{c_name},") + v.add_decl("\{") + var vft = self.method_tables.get_or_null(mclass) + if vft != null then for i in [0 .. vft.length[ do + var mpropdef = vft[i] + if mpropdef == null then + v.add_decl("NULL, /* empty */") + else + assert mpropdef isa MMethodDef + if rta != null and not rta.live_methoddefs.has(mpropdef) then + v.add_decl("NULL, /* DEAD {mclass.intro_mmodule}:{mclass}:{mpropdef} */") + continue + end + var rf = mpropdef.virtual_runtime_function + v.require_declaration(rf.c_name) + v.add_decl("(nitmethod_t){rf.c_name}, /* pointer to {mpropdef.full_name} */") + end + end + v.add_decl("\}") + end + v.add_decl("\};") + end + + protected fun compile_class_type_table(ccinfo: ClassCompilationInfo, v: SeparateCompilerVisitor) + do + var mclass = ccinfo.mclass + var c_name = mclass.c_name + var class_table = self.class_tables[mclass] + + # Build class type table + v.add_decl("const struct type_table type_table_{c_name} = \{") + v.add_decl("{class_table.length},") + v.add_decl("\{") + for msuper in class_table do + if msuper == null then + v.add_decl("-1, /* empty */") + else + v.add_decl("{self.class_ids[msuper]}, /* {msuper} */") + end + end + v.add_decl("\}") + v.add_decl("\};") + end + + redef fun compile_default_new(ccinfo, v) + do + var mclass = ccinfo.mclass + var mtype = ccinfo.mtype + var c_name = mclass.c_name + var is_dead = ccinfo.is_dead #Build NEW self.provide_declaration("NEW_{c_name}", "{mtype.ctype} NEW_{c_name}(void);") @@ -391,6 +405,33 @@ class SeparateErasureCompiler v.add("\}") end + redef fun build_class_compilation_info(mclass) + do + var ccinfo = super + var mtype = ccinfo.mtype + var rta = runtime_type_analysis + var is_dead = false # mclass.kind == abstract_kind or mclass.kind == interface_kind + if not is_dead and rta != null and not rta.live_classes.has(mclass) and not mtype.is_c_primitive and mclass.name != "NativeArray" then + is_dead = true + end + ccinfo.is_dead = is_dead + return ccinfo + end + + redef fun compile_class_to_c(mclass: MClass) + do + var ccinfo = build_class_compilation_info(mclass) + var v = new_visitor + v.add_decl("/* runtime class {mclass.c_name} */") + self.provide_declaration("class_{mclass.c_name}", "extern const struct class class_{mclass.c_name};") + v.add_decl("extern const struct type_table type_table_{mclass.c_name};") + self.compile_class_vft(ccinfo, v) + self.compile_class_type_table(ccinfo, v) + if not self.compile_class_if_universal(ccinfo, v) then + self.compile_default_new(ccinfo, v) + end + end + private fun build_class_vts_table(mclass: MClass): Bool do if self.vt_tables[mclass].is_empty then return false