X-Git-Url: http://nitlanguage.org diff --git a/src/separate_compiler.nit b/src/separate_compiler.nit index 90f6ae4..8967946 100644 --- a/src/separate_compiler.nit +++ b/src/separate_compiler.nit @@ -65,6 +65,8 @@ redef class ModelBuilder compiler.compile_header # compile class structures + compiler.new_file("{mainmodule.name}.classes") + compiler.do_property_coloring for m in mainmodule.in_importation.greaters do for mclass in m.intro_mclasses do compiler.compile_class_to_c(mclass) @@ -72,17 +74,17 @@ redef class ModelBuilder end # The main function of the C - compiler.new_file + compiler.new_file("{mainmodule.name}.main") compiler.compile_main_function # compile methods for m in mainmodule.in_importation.greaters do - compiler.new_file + compiler.new_file("{m.name}.sep") compiler.compile_module_to_c(m) end # compile live & cast type structures - compiler.new_file + compiler.new_file("{mainmodule.name}.types") var mtypes = compiler.do_type_coloring for t in mtypes do compiler.compile_type_to_c(t) @@ -107,29 +109,30 @@ class SeparateCompiler private var type_layout: nullable Layout[MType] private var resolution_layout: nullable Layout[MType] - protected var method_layout: nullable PropertyLayout[MMethod] - protected var attr_layout: nullable PropertyLayout[MAttribute] + protected var method_layout: nullable Layout[MMethod] + protected var attr_layout: nullable Layout[MAttribute] init(mainmodule: MModule, mmbuilder: ModelBuilder, runtime_type_analysis: RapidTypeAnalysis) do super(mainmodule, mmbuilder) - self.header = new_visitor + var file = new_file("nit.common") + self.header = new CodeWriter(file) self.runtime_type_analysis = runtime_type_analysis - self.do_property_coloring self.compile_box_kinds end redef fun compile_header_structs do self.header.add_decl("typedef void(*nitmethod_t)(void); /* general C type representing a Nit method. */") self.compile_header_attribute_structs - self.header.add_decl("struct class \{ int box_kind; nitmethod_t vft[1]; \}; /* general C type representing a Nit class. */") + self.header.add_decl("struct class \{ int box_kind; nitmethod_t vft[]; \}; /* general C type representing a Nit class. */") # With resolution_table_table, all live type resolution are stored in a big table: resolution_table - self.header.add_decl("struct type \{ int id; const char *name; int color; short int is_nullable; struct types *resolution_table; int table_size; int type_table[1]; \}; /* general C type representing a Nit type. */") + self.header.add_decl("struct type \{ int id; const char *name; int color; short int is_nullable; const struct types *resolution_table; int table_size; int type_table[]; \}; /* general C type representing a Nit type. */") + self.header.add_decl("struct instance \{ const struct type *type; const struct class *class; nitattribute_t attrs[]; \}; /* general C type representing a Nit instance. */") if modelbuilder.toolcontext.opt_phmod_typing.value or modelbuilder.toolcontext.opt_phand_typing.value then - self.header.add_decl("struct types \{ int mask; struct type *types[1]; \}; /* a list types (used for vts, fts and unresolved lists). */") + self.header.add_decl("struct types \{ int mask; const struct type *types[]; \}; /* a list types (used for vts, fts and unresolved lists). */") else - self.header.add_decl("struct types \{ struct type *types[1]; \}; /* a list types (used for vts, fts and unresolved lists). */") + self.header.add_decl("struct types \{ int dummy; const struct type *types[]; \}; /* a list types (used for vts, fts and unresolved lists). */") end if modelbuilder.toolcontext.opt_phmod_typing.value then @@ -138,7 +141,7 @@ class SeparateCompiler self.header.add_decl("#define HASH(mask, id) ((mask)&(id))") end - self.header.add_decl("typedef struct \{ struct type *type; struct class *class; nitattribute_t attrs[1]; \} val; /* general C type representing a Nit instance. */") + self.header.add_decl("typedef struct instance val; /* general C type representing a Nit instance. */") end fun compile_header_attribute_structs @@ -183,21 +186,22 @@ class SeparateCompiler end fun compile_color_consts(colors: Map[Object, Int]) do + var v = new_visitor for m, c in colors do if color_consts_done.has(m) then continue if m isa MProperty then if modelbuilder.toolcontext.opt_inline_coloring_numbers.value then - self.header.add_decl("#define {m.const_color} {c}") + self.provide_declaration(m.const_color, "#define {m.const_color} {c}") else - self.header.add_decl("extern const int {m.const_color};") - self.header.add("const int {m.const_color} = {c};") + self.provide_declaration(m.const_color, "extern const int {m.const_color};") + v.add("const int {m.const_color} = {c};") end else if m isa MType then if modelbuilder.toolcontext.opt_inline_coloring_numbers.value then - self.header.add_decl("#define {m.const_color} {c}") + self.provide_declaration(m.const_color, "#define {m.const_color} {c}") else - self.header.add_decl("extern const int {m.const_color};") - self.header.add("const int {m.const_color} = {c};") + self.provide_declaration(m.const_color, "extern const int {m.const_color};") + v.add("const int {m.const_color} = {c};") end end color_consts_done.add(m) @@ -210,22 +214,38 @@ class SeparateCompiler fun do_property_coloring do var mclasses = new HashSet[MClass].from(modelbuilder.model.mclasses) + # Layouts + var method_layout_builder: PropertyLayoutBuilder[MMethod] + var attribute_layout_builder: PropertyLayoutBuilder[MAttribute] + #FIXME PH and BM layouts too slow for large programs + #if modelbuilder.toolcontext.opt_bm_typing.value then + # method_layout_builder = new MMethodBMizer(self.mainmodule) + # attribute_layout_builder = new MAttributeBMizer(self.mainmodule) + #else if modelbuilder.toolcontext.opt_phmod_typing.value then + # method_layout_builder = new MMethodHasher(new PHModOperator, self.mainmodule) + # attribute_layout_builder = new MAttributeHasher(new PHModOperator, self.mainmodule) + #else if modelbuilder.toolcontext.opt_phand_typing.value then + # method_layout_builder = new MMethodHasher(new PHAndOperator, self.mainmodule) + # attribute_layout_builder = new MAttributeHasher(new PHAndOperator, self.mainmodule) + #else + method_layout_builder = new MMethodColorer(self.mainmodule) + attribute_layout_builder = new MAttributeColorer(self.mainmodule) + #end + # methods coloration - var method_coloring = new CLPropertyLayoutBuilder[MMethod](new MMethodColorer(mainmodule)) - var method_layout = method_coloring.build_layout(mclasses) + var method_layout = method_layout_builder.build_layout(mclasses) self.method_tables = build_method_tables(mclasses, method_layout) self.compile_color_consts(method_layout.pos) self.method_layout = method_layout # attributes coloration - var attribute_coloring = new CLPropertyLayoutBuilder[MAttribute](new MAttributeColorer(mainmodule)) - var attr_layout = attribute_coloring.build_layout(mclasses) + var attr_layout = attribute_layout_builder.build_layout(mclasses) self.attr_tables = build_attr_tables(mclasses, attr_layout) self.compile_color_consts(attr_layout.pos) self.attr_layout = attr_layout end - fun build_method_tables(mclasses: Set[MClass], layout: PropertyLayout[MProperty]): Map[MClass, Array[nullable MPropDef]] do + fun build_method_tables(mclasses: Set[MClass], layout: Layout[MProperty]): Map[MClass, Array[nullable MPropDef]] do var tables = new HashMap[MClass, Array[nullable MPropDef]] for mclass in mclasses do var table = new Array[nullable MPropDef] @@ -269,7 +289,7 @@ class SeparateCompiler return tables end - fun build_attr_tables(mclasses: Set[MClass], layout: PropertyLayout[MProperty]): Map[MClass, Array[nullable MPropDef]] do + fun build_attr_tables(mclasses: Set[MClass], layout: Layout[MProperty]): Map[MClass, Array[nullable MPropDef]] do var tables = new HashMap[MClass, Array[nullable MPropDef]] for mclass in mclasses do var table = new Array[nullable MPropDef] @@ -324,20 +344,20 @@ class SeparateCompiler end for mtype in mtypes do - retieve_live_partial_types(mtype) + retrieve_partial_types(mtype) end mtypes.add_all(self.partial_types) # Typing Layout var layout_builder: TypingLayoutBuilder[MType] if modelbuilder.toolcontext.opt_bm_typing.value then - layout_builder = new BMTypeLayoutBuilder(self.mainmodule) + layout_builder = new MTypeBMizer(self.mainmodule) else if modelbuilder.toolcontext.opt_phmod_typing.value then - layout_builder = new PHTypeLayoutBuilder(self.mainmodule, new PHModOperator) + layout_builder = new MTypeHasher(new PHModOperator, self.mainmodule) else if modelbuilder.toolcontext.opt_phand_typing.value then - layout_builder = new PHTypeLayoutBuilder(self.mainmodule, new PHAndOperator) + layout_builder = new MTypeHasher(new PHAndOperator, self.mainmodule) else - layout_builder = new CLTypingLayoutBuilder[MType](new MTypeColorer(self.mainmodule)) + layout_builder = new MTypeColorer(self.mainmodule) end # colorize types @@ -400,13 +420,13 @@ class SeparateCompiler # Compute the table layout with the prefered method var resolution_builder: ResolutionLayoutBuilder if modelbuilder.toolcontext.opt_bm_typing.value then - resolution_builder = new BMResolutionLayoutBuilder + resolution_builder = new ResolutionBMizer else if modelbuilder.toolcontext.opt_phmod_typing.value then - resolution_builder = new PHResolutionLayoutBuilder(new PHModOperator) + resolution_builder = new ResolutionHasher(new PHModOperator) else if modelbuilder.toolcontext.opt_phand_typing.value then - resolution_builder = new PHResolutionLayoutBuilder(new PHAndOperator) + resolution_builder = new ResolutionHasher(new PHAndOperator) else - resolution_builder = new CLResolutionLayoutBuilder + resolution_builder = new ResolutionColorer end self.resolution_layout = resolution_builder.build_layout(mtype2unresolved) self.resolution_tables = self.build_resolution_tables(mtype2unresolved) @@ -458,7 +478,7 @@ class SeparateCompiler return tables end - fun retieve_live_partial_types(mtype: MType) do + fun retrieve_partial_types(mtype: MType) do # add formal types arguments to mtypes if mtype isa MGenericType then for ft in mtype.arguments do @@ -467,7 +487,7 @@ class SeparateCompiler abort end self.partial_types.add(ft) - retieve_live_partial_types(ft) + retrieve_partial_types(ft) end end var mclass_type: MClassType @@ -495,12 +515,10 @@ class SeparateCompiler for pd in cd.mpropdefs do if not pd isa MMethodDef then continue #print "compile {pd} @ {cd} @ {mmodule}" - var r = new SeparateRuntimeFunction(pd) + var r = pd.separate_runtime_function r.compile_to_c(self) - if true or cd.bound_mtype.ctype != "val*" then - var r2 = new VirtualRuntimeFunction(pd) - r2.compile_to_c(self) - end + var r2 = pd.virtual_runtime_function + r2.compile_to_c(self) end end self.mainmodule = old_module @@ -514,19 +532,10 @@ class SeparateCompiler v.add_decl("/* runtime type {mtype} */") # extern const struct type_X - self.header.add_decl("extern const struct type_{c_name} type_{c_name};") - self.header.add_decl("struct type_{c_name} \{") - self.header.add_decl("int id;") - self.header.add_decl("const char *name;") - self.header.add_decl("int color;") - self.header.add_decl("short int is_nullable;") - self.header.add_decl("const struct types *resolution_table;") - self.header.add_decl("int table_size;") - self.header.add_decl("int type_table[{self.type_tables[mtype].length}];") - self.header.add_decl("\};") + self.provide_declaration("type_{c_name}", "extern const struct type type_{c_name};") # const struct type_X - v.add_decl("const struct type_{c_name} type_{c_name} = \{") + v.add_decl("const struct type type_{c_name} = \{") v.add_decl("{self.type_layout.ids[mtype]},") v.add_decl("\"{mtype}\", /* class_name_string */") var layout = self.type_layout @@ -541,7 +550,8 @@ class SeparateCompiler v.add_decl("0,") end if compile_type_resolution_table(mtype) then - v.add_decl("(struct types*) &resolution_table_{c_name},") + v.require_declaration("resolution_table_{c_name}") + v.add_decl("&resolution_table_{c_name},") else v.add_decl("NULL,") end @@ -571,19 +581,15 @@ class SeparateCompiler var layout = self.resolution_layout # extern const struct resolution_table_X resolution_table_X - self.header.add_decl("extern const struct resolution_table_{mtype.c_name} resolution_table_{mtype.c_name};") - self.header.add_decl("struct resolution_table_{mtype.c_name} \{") - if layout isa PHLayout[MClassType, MType] then - self.header.add_decl("int mask;") - end - self.header.add_decl("struct type *types[{self.resolution_tables[mclass_type].length}];") - self.header.add_decl("\};") + self.provide_declaration("resolution_table_{mtype.c_name}", "extern const struct types resolution_table_{mtype.c_name};") # const struct fts_table_X fts_table_X var v = new_visitor - v.add_decl("const struct resolution_table_{mtype.c_name} resolution_table_{mtype.c_name} = \{") + v.add_decl("const struct types resolution_table_{mtype.c_name} = \{") if layout isa PHLayout[MClassType, MType] then v.add_decl("{layout.masks[mclass_type]},") + else + v.add_decl("0, /* dummy */") end v.add_decl("\{") for t in self.resolution_tables[mclass_type] do @@ -596,13 +602,14 @@ class SeparateCompiler var tv = t.resolve_for(mclass_type, mclass_type, self.mainmodule, true) # FIXME: What typeids means here? How can a tv not be live? if self.type_layout.ids.has_key(tv) then - v.add_decl("(struct type*)&type_{tv.c_name}, /* {t}: {tv} */") + v.require_declaration("type_{tv.c_name}") + v.add_decl("&type_{tv.c_name}, /* {t}: {tv} */") else v.add_decl("NULL, /* empty ({t}: {tv} not a live type) */") end end end - v.add_decl("\},") + v.add_decl("\}") v.add_decl("\};") return true end @@ -621,14 +628,9 @@ class SeparateCompiler v.add_decl("/* runtime class {c_name} */") - self.header.add_decl("struct class_{c_name} \{") - self.header.add_decl("int box_kind;") - self.header.add_decl("nitmethod_t vft[{vft.length}];") - self.header.add_decl("\};") - # Build class vft - self.header.add_decl("extern const struct class_{c_name} class_{c_name};") - v.add_decl("const struct class_{c_name} class_{c_name} = \{") + 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("{self.box_kind_of(mclass)}, /* box_kind */") v.add_decl("\{") for i in [0 .. vft.length[ do @@ -636,11 +638,10 @@ class SeparateCompiler if mpropdef == null then v.add_decl("NULL, /* empty */") else - if true or mpropdef.mclassdef.bound_mtype.ctype != "val*" then - v.add_decl("(nitmethod_t)VIRTUAL_{mpropdef.c_name}, /* pointer to {mclass.intro_mmodule}:{mclass}:{mpropdef} */") - else - v.add_decl("(nitmethod_t){mpropdef.c_name}, /* pointer to {mclass.intro_mmodule}:{mclass}:{mpropdef} */") - end + assert mpropdef isa MMethodDef + var rf = mpropdef.virtual_runtime_function + v.require_declaration(rf.c_name) + v.add_decl("(nitmethod_t){rf.c_name}, /* pointer to {mclass.intro_mmodule}:{mclass}:{mpropdef} */") end end v.add_decl("\}") @@ -656,63 +657,56 @@ class SeparateCompiler if not self.runtime_type_analysis.live_types.has(mtype) then return + #Build BOX self.header.add_decl("val* BOX_{c_name}({mtype.ctype});") v.add_decl("/* allocate {mtype} */") v.add_decl("val* BOX_{mtype.c_name}({mtype.ctype} value) \{") - v.add("struct instance_{c_name}*res = GC_MALLOC(sizeof(struct instance_{c_name}));") - v.add("res->type = (struct type*) &type_{c_name};") - v.add("res->class = (struct class*) &class_{c_name};") + v.add("struct instance_{c_name}*res = nit_alloc(sizeof(struct instance_{c_name}));") + v.require_declaration("type_{c_name}") + v.add("res->type = &type_{c_name};") + v.require_declaration("class_{c_name}") + v.add("res->class = &class_{c_name};") v.add("res->value = value;") v.add("return (val*)res;") v.add("\}") return - end - - var is_native_array = mclass.name == "NativeArray" - - var sig - if is_native_array then - sig = "int length, struct type* type" - else - sig = "struct type* type" - end - - #Build instance struct - #extern const struct instance_array__NativeArray instance_array__NativeArray; - self.header.add_decl("struct instance_{c_name} \{") - self.header.add_decl("const struct type *type;") - self.header.add_decl("const struct class *class;") - self.header.add_decl("nitattribute_t attrs[{attrs.length}];") - if is_native_array then + else if mclass.name == "NativeArray" then + #Build instance struct + self.header.add_decl("struct instance_{c_name} \{") + self.header.add_decl("const struct type *type;") + self.header.add_decl("const struct class *class;") # NativeArrays are just a instance header followed by an array of values self.header.add_decl("val* values[0];") - end - self.header.add_decl("\};") + self.header.add_decl("\};") + #Build NEW + self.provide_declaration("NEW_{c_name}", "{mtype.ctype} NEW_{c_name}(int length, const struct type* type);") + v.add_decl("/* allocate {mtype} */") + v.add_decl("{mtype.ctype} NEW_{c_name}(int length, const struct type* type) \{") + var res = v.new_named_var(mtype, "self") + res.is_exact = true + var mtype_elt = mtype.arguments.first + v.add("{res} = nit_alloc(sizeof(struct instance_{c_name}) + length*sizeof({mtype_elt.ctype}));") + v.add("{res}->type = type;") + hardening_live_type(v, "type") + v.require_declaration("class_{c_name}") + v.add("{res}->class = &class_{c_name};") + v.add("return {res};") + v.add("\}") + return + end - self.header.add_decl("{mtype.ctype} NEW_{c_name}({sig});") + #Build NEW + self.provide_declaration("NEW_{c_name}", "{mtype.ctype} NEW_{c_name}(const struct type* type);") v.add_decl("/* allocate {mtype} */") - v.add_decl("{mtype.ctype} NEW_{c_name}({sig}) \{") + v.add_decl("{mtype.ctype} NEW_{c_name}(const struct type* type) \{") var res = v.new_named_var(mtype, "self") res.is_exact = true - if is_native_array then - var mtype_elt = mtype.arguments.first - v.add("{res} = GC_MALLOC(sizeof(struct instance_{c_name}) + length*sizeof({mtype_elt.ctype}));") - else - v.add("{res} = GC_MALLOC(sizeof(struct instance_{c_name}));") - end + v.add("{res} = nit_alloc(sizeof(struct instance) + {attrs.length}*sizeof(nitattribute_t));") v.add("{res}->type = type;") - if v.compiler.modelbuilder.toolcontext.opt_hardening.value then - v.add("if(type == NULL) \{") - v.add_abort("type null") - v.add("\}") - v.add("if(type->resolution_table == NULL) \{") - v.add("fprintf(stderr, \"Insantiation of a dead type: %s\\n\", type->name);") - v.add_abort("type dead") - v.add("\}") - end - v.add("{res}->class = (struct class*) &class_{c_name};") - + hardening_live_type(v, "type") + v.require_declaration("class_{c_name}") + v.add("{res}->class = &class_{c_name};") self.generate_init_attr(v, res, mtype) v.add("return {res};") v.add("\}") @@ -720,6 +714,19 @@ class SeparateCompiler generate_check_init_instance(mtype) end + # Add a dynamic test to ensure that the type referenced by `t` is a live type + fun hardening_live_type(v: VISITOR, t: String) + do + if not v.compiler.modelbuilder.toolcontext.opt_hardening.value then return + v.add("if({t} == NULL) \{") + v.add_abort("type null") + v.add("\}") + v.add("if({t}->resolution_table == NULL) \{") + v.add("fprintf(stderr, \"Insantiation of a dead type: %s\\n\", {t}->name);") + v.add_abort("type dead") + v.add("\}") + end + redef fun generate_check_init_instance(mtype) do if self.modelbuilder.toolcontext.opt_no_check_initialization.value then return @@ -727,7 +734,7 @@ class SeparateCompiler var v = self.new_visitor var c_name = mtype.mclass.c_name var res = new RuntimeVariable("self", mtype, mtype) - self.header.add_decl("void CHECK_NEW_{c_name}({mtype.ctype});") + self.provide_declaration("CHECK_NEW_{c_name}", "void CHECK_NEW_{c_name}({mtype.ctype});") v.add_decl("/* allocate {mtype} */") v.add_decl("void CHECK_NEW_{c_name}({mtype.ctype} {res}) \{") self.generate_check_attr(v, res, mtype) @@ -851,6 +858,7 @@ class SeparateCompilerVisitor if value.mtype.ctype == "val*" then return "{value}->type" else + self.require_declaration("type_{value.mtype.c_name}") return "(&type_{value.mtype.c_name})" end end @@ -939,6 +947,7 @@ class SeparateCompilerVisitor var r if ret == null then r = "void" else r = ret.ctype + self.require_declaration(mmethod.const_color) var call = "(({r} (*)({s}))({arguments.first}->class->vft[{mmethod.const_color}]))({ss}) /* {mmethod} on {arguments.first.inspect}*/" if res != null then @@ -987,6 +996,7 @@ class SeparateCompilerVisitor # Autobox arguments self.adapt_signature(mmethoddef, arguments) + self.require_declaration(mmethoddef.c_name) if res == null then self.add("{mmethoddef.c_name}({arguments.join(", ")});") return null @@ -997,6 +1007,13 @@ class SeparateCompilerVisitor return res end + redef fun supercall(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): nullable RuntimeVariable + do + # FIXME implements a polymorphic access in tables + m = m.lookup_next_definition(m.mclassdef.mmodule, m.mclassdef.bound_mtype) + return self.call(m, recvtype, args) + end + redef fun vararg_instance(mpropdef, recv, varargs, elttype) do # A vararg must be stored into an new array @@ -1031,6 +1048,7 @@ class SeparateCompilerVisitor return res end + self.require_declaration(a.const_color) if self.compiler.modelbuilder.toolcontext.opt_no_union_attribute.value then self.add("{res} = {recv}->attrs[{a.const_color}] != NULL; /* {a} on {recv.inspect}*/") else @@ -1053,6 +1071,7 @@ class SeparateCompilerVisitor var intromclassdef = a.intro.mclassdef ret = ret.resolve_for(intromclassdef.bound_mtype, intromclassdef.bound_mtype, intromclassdef.mmodule, true) + self.require_declaration(a.const_color) if self.compiler.modelbuilder.toolcontext.opt_no_union_attribute.value then # Get the attribute or a box (ie. always a val*) var cret = self.object_type.as_nullable @@ -1098,6 +1117,7 @@ class SeparateCompilerVisitor # Adapt the value to the declared type value = self.autobox(value, mtype) + self.require_declaration(a.const_color) if self.compiler.modelbuilder.toolcontext.opt_no_union_attribute.value then var attr = "{recv}->attrs[{a.const_color}]" if mtype.ctype != "val*" then @@ -1121,24 +1141,28 @@ class SeparateCompilerVisitor redef fun init_instance(mtype) do + self.require_declaration("NEW_{mtype.mclass.c_name}") var compiler = self.compiler if mtype isa MGenericType and mtype.need_anchor then link_unresolved_type(self.frame.mpropdef.mclassdef, mtype) var recv = self.frame.arguments.first var recv_type_info = self.type_info(recv) + self.require_declaration(mtype.const_color) if compiler.modelbuilder.toolcontext.opt_phmod_typing.value or compiler.modelbuilder.toolcontext.opt_phand_typing.value then - return self.new_expr("NEW_{mtype.mclass.c_name}((struct type *) {recv_type_info}->resolution_table->types[HASH({recv_type_info}->resolution_table->mask, {mtype.const_color})])", mtype) + return self.new_expr("NEW_{mtype.mclass.c_name}({recv_type_info}->resolution_table->types[HASH({recv_type_info}->resolution_table->mask, {mtype.const_color})])", mtype) else - return self.new_expr("NEW_{mtype.mclass.c_name}((struct type *) {recv_type_info}->resolution_table->types[{mtype.const_color}])", mtype) + return self.new_expr("NEW_{mtype.mclass.c_name}({recv_type_info}->resolution_table->types[{mtype.const_color}])", mtype) end end compiler.undead_types.add(mtype) - return self.new_expr("NEW_{mtype.mclass.c_name}((struct type *) &type_{mtype.c_name})", mtype) + self.require_declaration("type_{mtype.c_name}") + return self.new_expr("NEW_{mtype.mclass.c_name}(&type_{mtype.c_name})", mtype) end redef fun check_init_instance(value, mtype) do if self.compiler.modelbuilder.toolcontext.opt_no_check_initialization.value then return + self.require_declaration("CHECK_NEW_{mtype.mclass.c_name}") self.add("CHECK_NEW_{mtype.mclass.c_name}({value});") end @@ -1176,10 +1200,11 @@ class SeparateCompilerVisitor if ntype.need_anchor then var type_struct = self.get_name("type_struct") - self.add_decl("struct type* {type_struct};") + self.add_decl("const struct type* {type_struct};") # Either with resolution_table with a direct resolution link_unresolved_type(self.frame.mpropdef.mclassdef, ntype) + self.require_declaration(ntype.const_color) if compiler.modelbuilder.toolcontext.opt_phmod_typing.value or compiler.modelbuilder.toolcontext.opt_phand_typing.value then self.add("{type_struct} = {recv_type_info}->resolution_table->types[HASH({recv_type_info}->resolution_table->mask, {ntype.const_color})];") else @@ -1199,6 +1224,7 @@ class SeparateCompilerVisitor end else if ntype isa MClassType then compiler.undead_types.add(mtype) + self.require_declaration("type_{mtype.c_name}") self.add("{cltype} = type_{mtype.c_name}.color;") self.add("{idtype} = type_{mtype.c_name}.id;") if compiler.modelbuilder.toolcontext.opt_typing_test_metrics.value then @@ -1247,7 +1273,8 @@ class SeparateCompilerVisitor self.add("{res} = 0; /* is_same_type_test: incompatible types {value1.mtype} vs. {value2.mtype}*/") else var mtype1 = value1.mtype.as(MClassType) - self.add("{res} = ({value2} != NULL) && ({value2}->class == (struct class*) &class_{mtype1.c_name}); /* is_same_type_test */") + self.require_declaration("class_{mtype1.c_name}") + self.add("{res} = ({value2} != NULL) && ({value2}->class == &class_{mtype1.c_name}); /* is_same_type_test */") end else self.add("{res} = ({value1} == {value2}) || ({value1} != NULL && {value2} != NULL && {value1}->class == {value2}->class); /* is_same_type_test */") @@ -1262,6 +1289,7 @@ class SeparateCompilerVisitor if value.mtype.ctype == "val*" then self.add "{res} = {value} == NULL ? \"null\" : {value}->type->name;" else + self.require_declaration("type_{value.mtype.c_name}") self.add "{res} = type_{value.mtype.c_name}.name;" end return res @@ -1282,7 +1310,8 @@ class SeparateCompilerVisitor self.add("{res} = 0; /* incompatible types {value1.mtype} vs. {value2.mtype}*/") else var mtype1 = value1.mtype.as(MClassType) - self.add("{res} = ({value2} != NULL) && ({value2}->class == (struct class*) &class_{mtype1.c_name});") + self.require_declaration("class_{mtype1.c_name}") + self.add("{res} = ({value2} != NULL) && ({value2}->class == &class_{mtype1.c_name});") self.add("if ({res}) \{") self.add("{res} = ({self.autobox(value2, value1.mtype)} == {value1});") self.add("\}") @@ -1393,20 +1422,23 @@ class SeparateCompilerVisitor fun native_array_instance(elttype: MType, length: RuntimeVariable): RuntimeVariable do var mtype = self.get_class("NativeArray").get_mtype([elttype]) + self.require_declaration("NEW_{mtype.mclass.c_name}") assert mtype isa MGenericType var compiler = self.compiler if mtype.need_anchor then link_unresolved_type(self.frame.mpropdef.mclassdef, mtype) var recv = self.frame.arguments.first var recv_type_info = self.type_info(recv) + self.require_declaration(mtype.const_color) if compiler.modelbuilder.toolcontext.opt_phmod_typing.value or compiler.modelbuilder.toolcontext.opt_phand_typing.value then - return self.new_expr("NEW_{mtype.mclass.c_name}({length}, (struct type *) {recv_type_info}->resolution_table->types[HASH({recv_type_info}->resolution_table->mask, {mtype.const_color})])", mtype) + return self.new_expr("NEW_{mtype.mclass.c_name}({length}, {recv_type_info}->resolution_table->types[HASH({recv_type_info}->resolution_table->mask, {mtype.const_color})])", mtype) else - return self.new_expr("NEW_{mtype.mclass.c_name}({length}, (struct type *) {recv_type_info}->resolution_table->types[{mtype.const_color}])", mtype) + return self.new_expr("NEW_{mtype.mclass.c_name}({length}, {recv_type_info}->resolution_table->types[{mtype.const_color}])", mtype) end end compiler.undead_types.add(mtype) - return self.new_expr("NEW_{mtype.mclass.c_name}({length}, (struct type *) &type_{mtype.c_name})", mtype) + self.require_declaration("type_{mtype.c_name}") + return self.new_expr("NEW_{mtype.mclass.c_name}({length}, &type_{mtype.c_name})", mtype) end redef fun native_array_def(pname, ret_type, arguments) @@ -1445,6 +1477,30 @@ class SeparateCompilerVisitor end end +redef class MMethodDef + fun separate_runtime_function: AbstractRuntimeFunction + do + var res = self.separate_runtime_function_cache + if res == null then + res = new SeparateRuntimeFunction(self) + self.separate_runtime_function_cache = res + end + return res + end + private var separate_runtime_function_cache: nullable SeparateRuntimeFunction + + fun virtual_runtime_function: AbstractRuntimeFunction + do + var res = self.virtual_runtime_function_cache + if res == null then + res = new VirtualRuntimeFunction(self) + self.virtual_runtime_function_cache = res + end + return res + end + private var virtual_runtime_function_cache: nullable VirtualRuntimeFunction +end + # The C function associated to a methoddef separately compiled class SeparateRuntimeFunction super AbstractRuntimeFunction @@ -1479,7 +1535,7 @@ class SeparateRuntimeFunction end sig.append(self.c_name) sig.append("({selfvar.mtype.ctype} {selfvar}") - comment.append("(self: {selfvar}") + comment.append("({selfvar}: {selfvar.mtype}") arguments.add(selfvar) for i in [0..msignature.arity[ do var mtype = msignature.mparameters[i].mtype @@ -1496,7 +1552,7 @@ class SeparateRuntimeFunction if ret != null then comment.append(": {ret}") end - compiler.header.add_decl("{sig};") + compiler.provide_declaration(self.c_name, "{sig};") v.add_decl("/* method {self} for {comment} */") v.add_decl("{sig} \{") @@ -1555,7 +1611,7 @@ class VirtualRuntimeFunction end sig.append(self.c_name) sig.append("({selfvar.mtype.ctype} {selfvar}") - comment.append("(self: {selfvar}") + comment.append("({selfvar}: {selfvar.mtype}") arguments.add(selfvar) for i in [0..msignature.arity[ do var mtype = msignature.mparameters[i].mtype @@ -1572,7 +1628,7 @@ class VirtualRuntimeFunction if ret != null then comment.append(": {ret}") end - compiler.header.add_decl("{sig};") + compiler.provide_declaration(self.c_name, "{sig};") v.add_decl("/* method {self} for {comment} */") v.add_decl("{sig} \{") @@ -1581,10 +1637,11 @@ class VirtualRuntimeFunction end frame.returnlabel = v.get_name("RET_LABEL") - if recv != arguments.first.mtype then - #print "{self} {recv} {arguments.first}" + var subret = v.call(mmethoddef, recv, arguments) + if ret != null then + assert subret != null + v.assign(frame.returnvar.as(not null), subret) end - mmethoddef.compile_inside_to_c(v, arguments) v.add("{frame.returnlabel.as(not null)}:;") if ret != null then