X-Git-Url: http://nitlanguage.org diff --git a/src/compiling/compiling_global.nit b/src/compiling/compiling_global.nit index 96837be..1a8a817 100644 --- a/src/compiling/compiling_global.nit +++ b/src/compiling/compiling_global.nit @@ -17,414 +17,25 @@ # Compute and generate tables for classes and modules. package compiling_global -#import compiling_base -private import compiling_methods -private import syntax - -# Something that store color of table elements -class ColorContext - attr _colors: HashMap[TableElt, Int] = new HashMap[TableElt, Int] - - # The color of a table element. - meth color(e: TableElt): Int - do - return _colors[e] - end - - # Is a table element already colored? - meth has_color(e: TableElt): Bool - do - return _colors.has_key(e) - end - - # Assign a color to a table element. - meth color=(e: TableElt, c: Int) - do - _colors[e] = c - var idx = c - for i in [0..e.length[ do - _colors[e.item(i)] = idx - idx = idx + 1 - end - end -end - -# All information and results of the global analysis. -class GlobalAnalysis -special ColorContext - # Associate global classes to compiled classes - readable attr _compiled_classes: HashMap[MMGlobalClass, CompiledClass] = new HashMap[MMGlobalClass, CompiledClass] - - # The main module of the program globally analysed - readable attr _module: MMModule - - # FIXME: do something better. - readable writable attr _max_class_table_length: Int = 0 - - init(module: MMSrcModule) - do - _module = module - end -end - -class GlobalCompilerVisitor -special CompilerVisitor - # The global analysis result - readable attr _global_analysis: GlobalAnalysis - init(m: MMSrcModule, tc: ToolContext, ga: GlobalAnalysis) - do - super(m, tc) - _global_analysis = ga - end -end - -# A compiled class is a class in a program -class CompiledClass -special ColorContext - # The corresponding local class in the main module of the prgram - readable attr _local_class: MMLocalClass - - # The identifier of the class - readable writable attr _id: Int = 0 - - # The full class table of the class - readable attr _class_table: Array[nullable TableElt] = new Array[nullable TableElt] - - # The full instance table of the class - readable attr _instance_table: Array[nullable TableElt] = new Array[nullable TableElt] - - # The proper class table part (no superclasses but all refinements) - readable writable attr _class_layout: TableEltComposite = new TableEltComposite(self) - - # The proper instance table part (no superclasses but all refinements) - readable writable attr _instance_layout: TableEltComposite = new TableEltComposite(self) - - init(c: MMLocalClass) do _local_class = c -end - -redef class MMSrcLocalClass - # The table element of the subtype check - meth class_color_pos: TableEltClassColor do return _class_color_pos.as(not null) - attr _class_color_pos: nullable TableEltClassColor - - # The proper local class table part (nor superclasses nor refinments) - readable attr _class_layout: Array[TableElt] = new Array[TableElt] - - # The proper local instance table part (nor superclasses nor refinments) - readable attr _instance_layout: Array[TableElt] = new Array[TableElt] - - # Build the local layout of the class and feed the module table - meth build_layout_in(tc: ToolContext, module_table: Array[ModuleTableElt]) - do - var clt = _class_layout - var ilt = _instance_layout - - if global.intro == self then - module_table.add(new TableEltClassId(self)) - var cpp = new TableEltClassColor(self) - _class_color_pos = cpp - module_table.add(cpp) - clt.add(new TableEltClassInitTable(self)) - end - for p in src_local_properties do - var pg = p.global - if pg.intro == p then - if p isa MMSrcAttribute then - ilt.add(new TableEltAttr(p)) - else if p isa MMSrcMethod then - clt.add(new TableEltMeth(p)) - end - end - if p isa MMSrcMethod and p.need_super then - clt.add(new TableEltSuper(p)) - end - end - - if not ilt.is_empty then - var teg = new ModuleTableEltGroup - teg.elements.append(ilt) - module_table.add(teg) - end - - if not clt.is_empty then - var teg = new ModuleTableEltGroup - teg.elements.append(clt) - module_table.add(teg) - end - end -end - -redef class MMSrcModule - # The local table of the module (refers things introduced in the module) - attr _local_table: Array[ModuleTableElt] = new Array[ModuleTableElt] - - # Builds the local tables and local classes layouts - meth local_analysis(tc: ToolContext) - do - for c in src_local_classes do - c.build_layout_in(tc, _local_table) - end - end - - # Do the complete global analysis - meth global_analysis(cctx: ToolContext): GlobalAnalysis - do - #print "Do the complete global analysis" - var ga = new GlobalAnalysis(self) - var smallest_classes = new Array[MMLocalClass] - var global_properties = new HashSet[MMGlobalProperty] - var ctab = new Array[TableElt] - var itab = new Array[TableElt] - - ctab.add(new TableEltClassSelfId) - itab.add(new TableEltVftPointer) - - var pclassid = -1 - var classid = 3 - - # We have to work on ALL the classes of the module - var classes = new Array[MMLocalClass] - for c in local_classes do - c.compute_super_classes - classes.add(c) - end - (new ClassSorter).sort(classes) - - for c in classes do - # Finish processing the class (if invisible) - c.compute_ancestors - c.inherit_global_properties - - # Associate a CompiledClass to the class - var cc = new CompiledClass(c) - ga.compiled_classes[c.global] = cc - - # Assign a unique class identifier - # (negative are for primitive classes) - var gc = c.global - var bm = gc.module - if c.primitive_info != null then - cc.id = pclassid - pclassid = pclassid - 4 - else - cc.id = classid - classid = classid + 4 - end - - # Register is the class is a leaf - if c.cshe.direct_smallers.is_empty then - smallest_classes.add(c) - end - - # Store the colortableelt in the class table pool - var bc = c.global.intro - assert bc isa MMSrcLocalClass - ctab.add(bc.class_color_pos) - end - - # Compute core and crown classes for colorization - var crown_classes = new HashSet[MMLocalClass] - var core_classes = new HashSet[MMLocalClass] - for c in smallest_classes do - while c.cshe.direct_greaters.length == 1 do - c = c.cshe.direct_greaters.first - end - crown_classes.add(c) - core_classes.add_all(c.cshe.greaters_and_self) - end - #print("nbclasses: {classes.length} leaves: {smallest_classes.length} crown: {crown_classes.length} core: {core_classes.length}") - - # Colorize core color for typechecks - colorize(ga, ctab, crown_classes, 0) - - # Compute tables for typechecks - var maxcolor = 0 - for c in classes do - var cc = ga.compiled_classes[c.global] - if core_classes.has(c) then - # For core classes, just build the table - build_tables_in(cc.class_table, ga, c, ctab) - if maxcolor < cc.class_table.length then maxcolor = cc.class_table.length - else - # For other classes, it's easier: just append to the parent tables - var sc = c.cshe.direct_greaters.first - var scc = ga.compiled_classes[sc.global] - assert cc.class_table.is_empty - cc.class_table.add_all(scc.class_table) - var bc = c.global.intro - assert bc isa MMSrcLocalClass - var colpos = bc.class_color_pos - var colposcolor = cc.class_table.length - ga.color(colpos) = colposcolor - cc.class_table.add(colpos) - if maxcolor < colposcolor then maxcolor = colposcolor - end - end - ga.max_class_table_length = maxcolor + 1 - - # Fill class table and instance tables pools - for c in classes do - var cc = ga.compiled_classes[c.global] - var cte = cc.class_layout - var ite = cc.instance_layout - for sc in c.crhe.greaters_and_self do - if sc isa MMSrcLocalClass then - cte.add(sc, sc.class_layout) - ite.add(sc, sc.instance_layout) - end - end - - if core_classes.has(c) then - if cte.length > 0 then - ctab.add(cte) - end - if ite.length > 0 then - itab.add(ite) - end - end - end - - # Colorize all elements in pools tables - colorize(ga, ctab, crown_classes, maxcolor+1) - colorize(ga, itab, crown_classes, 0) - - # Build class and instance tables now things are colored - ga.max_class_table_length = 0 - for c in classes do - var cc = ga.compiled_classes[c.global] - if core_classes.has(c) then - # For core classes, just build the table - build_tables_in(cc.class_table, ga, c, ctab) - build_tables_in(cc.instance_table, ga, c, itab) - else - # For other classes, it's easier: just append to the parent tables - var sc = c.cshe.direct_greaters.first - var scc = ga.compiled_classes[sc.global] - cc.class_table.clear - cc.class_table.add_all(scc.class_table) - var bc = c.global.intro - assert bc isa MMSrcLocalClass - var colpos = bc.class_color_pos - cc.class_table[ga.color(colpos)] = colpos - while cc.class_table.length <= maxcolor do - cc.class_table.add(null) - end - append_to_table(ga, cc.class_table, cc.class_layout) - assert cc.instance_table.is_empty - cc.instance_table.add_all(scc.instance_table) - append_to_table(ga, cc.instance_table, cc.instance_layout) - end - end - - return ga - end - - private meth append_to_table(cc: ColorContext, table: Array[nullable TableElt], cmp: TableEltComposite) - do - for j in [0..cmp.length[ do - var e = cmp.item(j) - cc.color(e) = table.length - table.add(e) - end - end - - private meth build_tables_in(table: Array[nullable TableElt], ga: GlobalAnalysis, c: MMLocalClass, elts: Array[TableElt]) - do - var tab = new HashMap[Int, TableElt] - var len = 0 - for e in elts do - if e.is_related_to(c) then - var col = ga.color(e) - var l = col + e.length - tab[col] = e - if len < l then - len = l - end - end - end - var i = 0 - while i < len do - if tab.has_key(i) then - var e = tab[i] - for j in [0..e.length[ do - table[i] = e.item(j) - i = i + 1 - end - else - table[i] = null - i = i + 1 - end - end - end - - # Perform coloring - meth colorize(ga: GlobalAnalysis, elts: Array[TableElt], classes: Collection[MMLocalClass], startcolor: Int) - do - var colors = new HashMap[Int, Array[TableElt]] - var rel_classes = new Array[MMLocalClass] - for e in elts do - var color = -1 - var len = e.length - if ga.has_color(e) then - color = ga.color(e) - else - rel_classes.clear - for c in classes do - if e.is_related_to(c) then - rel_classes.add(c) - end - end - var trycolor = startcolor - while trycolor != color do - color = trycolor - for c in rel_classes do - var idx = 0 - while idx < len do - if colors.has_key(trycolor + idx) and not free_color(colors[trycolor + idx], c) then - trycolor = trycolor + idx + 1 - idx = 0 - else - idx = idx + 1 - end - end - end - end - ga.color(e) = color - end - for idx in [0..len[ do - if colors.has_key(color + idx) then - colors[color + idx].add(e) - else - colors[color + idx] = [e] - end - end - end - end - - private meth free_color(es: Array[TableElt], c: MMLocalClass): Bool - do - for e2 in es do - if e2.is_related_to(c) then - return false - end - end - return true - end +import table_computation +private import compiling_icode +redef class Program # Compile module and class tables - meth compile_tables_to_c(v: GlobalCompilerVisitor) + fun compile_tables_to_c(v: CompilerVisitor) do - for m in mhe.greaters_and_self do - assert m isa MMSrcModule + for m in main_module.mhe.greaters_and_self do m.compile_local_table_to_c(v) end - for c in local_classes do + with_each_live_local_classes !action(c) do + if c.global.is_abstract or c.global.is_interface then continue c.compile_tables_to_c(v) end + var s = new Buffer.from("classtable_t TAG2VFT[4] = \{NULL") for t in ["Int","Char","Bool"] do - if has_global_class_named(t.to_symbol) then + if main_module.has_global_class_named(t.to_symbol) then s.append(", (const classtable_t)VFT_{t}") else s.append(", NULL") @@ -434,71 +45,67 @@ redef class MMSrcModule v.add_instr(s.to_s) end - # Declare class table (for _sep.h) - meth declare_class_tables_to_c(v: GlobalCompilerVisitor) - do - for c in local_classes do - if c.global.module == self then - c.declare_tables_to_c(v) - end - end - end - # Compile main part (for _table.c) - meth compile_main_part(v: GlobalCompilerVisitor) + fun compile_main_part(v: CompilerVisitor) do v.add_instr("int main(int argc, char **argv) \{") v.indent v.add_instr("prepare_signals();") v.add_instr("glob_argc = argc; glob_argv = argv;") - var sysname = once "Sys".to_symbol - if not has_global_class_named(sysname) then + if v.program.main_method == null then print("No main") else - var sys = class_by_name(sysname) - var name = once "main".to_symbol - if not sys.has_global_property_by_name(name) then - print("No main") - else - var mainm = sys.select_method(name) - v.add_instr("G_sys = NEW_Sys();") - v.add_instr("{mainm.cname}(G_sys);") - end + v.add_instr("G_sys = NEW_Sys();") + v.add_instr("register_static_object(&G_sys);") + v.add_instr("{v.program.main_method.cname}(G_sys);") end v.add_instr("return 0;") v.unindent v.add_instr("}") end +end + +redef class MMModule + # Declare class table (for _sep.h or _glob.h) + fun declare_class_tables_to_c(v: CompilerVisitor) + do + for c in local_classes do + if c.global.mmmodule == self then + c.declare_tables_to_c(v) + end + end + end # Compile sep files - meth compile_mod_to_c(v: GlobalCompilerVisitor) + fun compile_mod_to_c(v: CompilerVisitor) do v.add_decl("extern const char *LOCATE_{name};") - if not v.tc.global then + if not v.program.tc.use_SFT_optimization then v.add_decl("extern const int SFT_{name}[];") end var i = 0 - for e in _local_table do + for e in local_table do var value: String - if v.tc.global then - value = "{e.value(v.global_analysis)}" + if v.program.tc.use_SFT_optimization then + value = "{e.value(v.program)}" else value = "SFT_{name}[{i}]" i = i + 1 end e.compile_macros(v, value) end - for c in src_local_classes do + for c in local_classes do + if not c isa MMConcreteClass then continue for pg in c.global_properties do var p = c[pg] - if p.local_class == c then + if p.local_class == c and p isa MMMethod then p.compile_property_to_c(v) end if pg.is_init_for(c) then # Declare constructors var params = new Array[String] - for i in [0..p.signature.arity[ do - params.add("val_t p{i}") + for j in [0..p.signature.arity[ do + params.add("val_t p{j}") end v.add_decl("val_t NEW_{c}_{p.global.intro.cname}({params.join(", ")});") end @@ -507,18 +114,18 @@ redef class MMSrcModule end # Compile module file for the current module - meth compile_local_table_to_c(v: GlobalCompilerVisitor) + fun compile_local_table_to_c(v: CompilerVisitor) do - v.add_instr("const char *LOCATE_{name} = \"{filename}\";") + v.add_instr("const char *LOCATE_{name} = \"{location.file.filename}\";") - if v.tc.global or _local_table.is_empty then + if v.program.tc.use_SFT_optimization or local_table.is_empty then return end - v.add_instr("const int SFT_{name}[{_local_table.length}] = \{") + v.add_instr("const int SFT_{name}[{local_table.length}] = \{") v.indent - for e in _local_table do - v.add_instr(e.value(v.global_analysis) + ",") + for e in local_table do + v.add_instr(e.value(v.program) + ",") end v.unindent v.add_instr("\};") @@ -527,93 +134,58 @@ end ############################################################################### -# An element of a class, an instance or a module table -abstract class AbsTableElt +redef class AbsTableElt # Compile the macro needed to use the element and other related elements - meth compile_macros(v: GlobalCompilerVisitor, value: String) is abstract + fun compile_macros(v: CompilerVisitor, value: String) is abstract end -# An element of a class or an instance table -# Such an elements represent method function pointers, attribute values, etc. -abstract class TableElt -special AbsTableElt - # Is the element conflict to class `c' (used for coloring) - meth is_related_to(c: MMLocalClass): Bool is abstract - - # Number of sub-elements. 1 if none - meth length: Int do return 1 - - # Access the ith subelement. - meth item(i: Int): TableElt do return self - +redef class TableElt # Return the value of the element for a given class - meth compile_to_c(v: GlobalCompilerVisitor, c: MMLocalClass): String is abstract + fun compile_to_c(v: CompilerVisitor, c: MMLocalClass): String is abstract end -# An element of a module table -# Such an elements represent colors or identifiers -abstract class ModuleTableElt -special AbsTableElt +redef class ModuleTableElt # Return the value of the element once the global analisys is performed - meth value(ga: GlobalAnalysis): String is abstract + fun value(prog: Program): String is abstract end -# An element of a module table that represents a group of TableElt defined in the same local class -class ModuleTableEltGroup -special ModuleTableElt - readable attr _elements: Array[TableElt] = new Array[TableElt] - - redef meth value(ga) do return "{ga.color(_elements.first)} /* Group of ? */" - redef meth compile_macros(v, value) +redef class ModuleTableEltGroup + redef fun value(prog) do return "{prog.table_information.color(elements.first)} /* Group of ? */" + redef fun compile_macros(v, value) do var i = 0 - for e in _elements do + for e in elements do e.compile_macros(v, "{value} + {i}") i += 1 end end end -# An element that represents a class property -abstract class TableEltProp -special TableElt - attr _property: MMLocalProperty - - init(p: MMLocalProperty) +redef class TableEltMeth + redef fun compile_macros(v, value) do - _property = p - end -end - -# An element that represents a function pointer to a global method -class TableEltMeth -special TableEltProp - redef meth compile_macros(v, value) - do - var pg = _property.global + var pg = property.global v.add_decl("#define {pg.meth_call}(recv) (({pg.intro.cname}_t)CALL((recv), ({value})))") end - redef meth compile_to_c(v, c) + redef fun compile_to_c(v, c) do - var p = c[_property.global] + var p = c[property.global] return p.cname end end -# An element that represents a function pointer to the super method of a local method -class TableEltSuper -special TableEltProp - redef meth compile_macros(v, value) +redef class TableEltSuper + redef fun compile_macros(v, value) do - var p = _property + var p = property v.add_decl("#define {p.super_meth_call}(recv) (({p.cname}_t)CALL((recv), ({value})))") end - redef meth compile_to_c(v, c) + redef fun compile_to_c(v, c) do - var pc = _property.local_class - var g = _property.global + var pc = property.local_class + var g = property.global var lin = c.che.linear_extension var found = false for s in lin do @@ -631,213 +203,152 @@ special TableEltProp end end -# An element that represents the value stored for a global attribute -class TableEltAttr -special TableEltProp - redef meth compile_macros(v, value) +redef class TableEltAttr + redef fun compile_macros(v, value) do - var pg = _property.global + var pg = property.global v.add_decl("#define {pg.attr_access}(recv) ATTR(recv, ({value}))") end - redef meth compile_to_c(v, c) + redef fun compile_to_c(v, c) do - var ga = v.global_analysis - var p = c[_property.global] - return "/* {ga.color(self)}: Attribute {c}::{p} */" + var prog = v.program + var p = c[property.global] + return "/* {prog.table_information.color(self)}: Attribute {c}::{p} */" end end -# An element representing a class information -class AbsTableEltClass -special AbsTableElt - # The local class where the information comes from - attr _local_class: MMLocalClass - - init(c: MMLocalClass) - do - _local_class = c - end - +redef class AbsTableEltClass # The C macro name refering the value - meth symbol: String is abstract + fun symbol: String is abstract - redef meth compile_macros(v, value) + redef fun compile_macros(v, value) do v.add_decl("#define {symbol} ({value})") end end -# An element of a class table representing a class information -class TableEltClass -special TableElt -special AbsTableEltClass - redef meth is_related_to(c) - do - var bc = c.module[_local_class.global] - return c.cshe <= bc - end -end - -# An element representing the id of a class in a module table -class TableEltClassId -special ModuleTableElt -special AbsTableEltClass - redef meth symbol do return _local_class.global.id_id +redef class TableEltClassId + redef fun symbol do return local_class.global.id_id - redef meth value(ga) + redef fun value(prog) do - return "{ga.compiled_classes[_local_class.global].id} /* Id of {_local_class} */" + return "{prog.compiled_classes[local_class.global].id} /* Id of {local_class} */" end end -# An element representing the constructor marker position in a class table -class TableEltClassInitTable -special TableEltClass - redef meth symbol do return _local_class.global.init_table_pos_id +redef class TableEltClassInitTable + redef fun symbol do return local_class.global.init_table_pos_id - redef meth compile_to_c(v, c) + redef fun compile_to_c(v, c) do - var ga = v.global_analysis - var cc = ga.compiled_classes[_local_class.global] + var prog = v.program + var cc = prog.compiled_classes[local_class.global] var linext = c.cshe.reverse_linear_extension var i = 0 - while linext[i].global != _local_class.global do + while linext[i].global != local_class.global do i += 1 end - return "{i} /* {ga.color(self)}: {c} < {cc.local_class}: superclass init_table position */" + return "{i} /* {prog.table_information.color(self)}: {c} < {cc.local_class}: superclass init_table position */" end end -# An element used for a cast -# Note: this element is both a TableElt and a ModuleTableElt. -# At the TableElt offset, there is the id of the super-class -# At the ModuleTableElt offset, there is the TableElt offset (ie. the color of the super-class). -class TableEltClassColor -special TableEltClass -special ModuleTableElt - redef meth symbol do return _local_class.global.color_id +redef class TableEltClassColor + redef fun symbol do return local_class.global.color_id - redef meth value(ga) + redef fun value(prog) do - return "{ga.color(self)} /* Color of {_local_class} */" + return "{prog.table_information.color(self)} /* Color of {local_class} */" end - redef meth compile_to_c(v, c) + redef fun compile_to_c(v, c) do - var ga = v.global_analysis - var cc = ga.compiled_classes[_local_class.global] - return "{cc.id} /* {ga.color(self)}: {c} < {cc.local_class}: superclass typecheck marker */" + var prog = v.program + var cc = prog.compiled_classes[local_class.global] + return "{cc.id} /* {prog.table_information.color(self)}: {c} < {cc.local_class}: superclass typecheck marker */" end end -# A Group of elements introduced in the same global-class that are colored together -class TableEltComposite -special TableElt - attr _table: Array[TableElt] - attr _cc: CompiledClass - attr _offsets: HashMap[MMLocalClass, Int] - redef meth length do return _table.length - redef meth is_related_to(c) do return c.cshe <= _cc.local_class +redef class TableEltComposite + redef fun compile_to_c(v, c) do abort +end - meth add(c: MMLocalClass, tab: Array[TableElt]) +redef class TableEltClassSelfId + redef fun compile_to_c(v, c) do - _offsets[c] = _table.length - _table.append(tab) + var prog = v.program + return "{prog.compiled_classes[c.global].id} /* {prog.table_information.color(self)}: Identity */" end +end - redef meth item(i) do return _table[i] - - redef meth compile_to_c(v, c) do abort +redef class TableEltClassSelfName + redef fun compile_to_c(v, c) + do + var prog = v.program + return "\"{c.global.name}\" /* {prog.table_information.color(self)}: Class Name */" + end +end - init(cc: CompiledClass) +redef class TableEltClassObjectSize + redef fun compile_to_c(v, c) do - _cc = cc - _table = new Array[TableElt] - _offsets = new HashMap[MMLocalClass, Int] + var nb = 0 + var p = v.program + if c.name == "NativeArray".to_symbol then + nb = -1 + else + var cc = p.compiled_classes[c.global] + var itab = cc.instance_table + for e in itab do + nb += 1 + end + end + return "{nb} /* {p.table_information.color(self)}: Object size (-1 if a NativeArray)*/" end end -# The element that represent the class id -class TableEltClassSelfId -special TableElt - redef meth is_related_to(c) do return true - redef meth compile_to_c(v, c) +redef class TableEltObjectId + redef fun compile_to_c(v, c) do - var ga = v.global_analysis - return "{v.global_analysis.compiled_classes[c.global].id} /* {ga.color(self)}: Identity */" + var p = v.program + return "/* {p.table_information.color(self)}: Object_id */" end end -# The element that -class TableEltVftPointer -special TableElt - redef meth is_related_to(c) do return true - redef meth compile_to_c(v, c) +redef class TableEltVftPointer + redef fun compile_to_c(v, c) do - var ga = v.global_analysis - return "/* {ga.color(self)}: Pointer to the classtable */" + var prog = v.program + return "/* {prog.table_information.color(self)}: Pointer to the classtable */" end end ############################################################################### -# Used to sort local class in a deterministic total order -# The total order superset the class refinement and the class specialisation relations -class ClassSorter -special AbstractSorter[MMLocalClass] - redef meth compare(a, b) do return a.compare(b) - init do end -end - redef class MMLocalClass - # Comparaison in a total order that superset the class refinement and the class specialisation relations - meth compare(b: MMLocalClass): Int - do - var a = self - if a == b then - return 0 - else if a.module.mhe < b.module then - return 1 - else if b.module.mhe < a.module then - return -1 - end - var ar = a.cshe.rank - var br = b.cshe.rank - if ar > br then - return 1 - else if br > ar then - return -1 - else - return b.name.to_s <=> a.name.to_s - end - end - # Declaration and macros related to the class table - meth declare_tables_to_c(v: GlobalCompilerVisitor) + fun declare_tables_to_c(v: CompilerVisitor) do v.add_decl("") var pi = primitive_info v.add_decl("extern const classtable_elt_t VFT_{name}[];") - if pi == null then - # v.add_decl("val_t NEW_{name}(void);") - else if not pi.tagged then + if pi != null and not pi.tagged then var t = pi.cname var tbox = "struct TBOX_{name}" - v.add_decl("{tbox} \{ const classtable_elt_t * vft; {t} val;};") + v.add_decl("{tbox} \{ const classtable_elt_t * vft; bigint object_id; {t} val;};") v.add_decl("val_t BOX_{name}({t} val);") v.add_decl("#define UNBOX_{name}(x) ((({tbox} *)(VAL2OBJ(x)))->val)") end end # Compilation of table and new (or box) - meth compile_tables_to_c(v: GlobalCompilerVisitor) + fun compile_tables_to_c(v: CompilerVisitor) do - var cc = v.global_analysis.compiled_classes[self.global] + var cc = v.program.compiled_classes[self.global] var ctab = cc.class_table var clen = ctab.length - if v.global_analysis.max_class_table_length > ctab.length then - clen = v.global_analysis.max_class_table_length + if v.program.table_information.max_class_table_length > ctab.length then + clen = v.program.table_information.max_class_table_length end v.add_instr("const classtable_elt_t VFT_{name}[{clen}] = \{") @@ -864,62 +375,56 @@ redef class MMLocalClass end var pi = primitive_info - if pi == null then - v.cfc = new CFunctionContext(v) - v.nmc = new NitMethodContext(null) - var s = "val_t NEW_{name}(void)" - v.add_instr(s + " \{") + if name == "NativeArray".to_symbol then + v.add_instr("val_t NEW_NativeArray(size_t length, size_t size) \{") v.indent - var ctx_old = v.ctx - v.ctx = new CContext - - var self_var = new ParamVariable(once ("self".to_symbol), null) - var self_var_cname = v.cfc.register_variable(self_var) - v.nmc.method_params = [self_var] - - v.add_instr("obj_t obj;") - v.add_instr("obj = alloc(sizeof(val_t) * {itab.length});") - v.add_instr("obj->vft = (classtable_elt_t*)VFT_{name};") - v.add_assignment(self_var_cname, "OBJ2VAL(obj)") - - for g in global_properties do - var p = self[g] - var t = p.signature.return_type - if p isa MMAttribute and t != null then - # FIXME: Not compatible with sep compilation - assert p isa MMSrcAttribute - var np = p.node - var ne = np.n_expr - if ne != null then - var e = ne.compile_expr(v) - v.add_instr("{p.global.attr_access}(obj) = {e};") - end - end - end - v.add_instr("return OBJ2VAL(obj);") - v.cfc.generate_var_decls - ctx_old.append(v.ctx) - v.ctx = ctx_old + v.add_instr("Nit_NativeArray array;") + v.add_instr("array = (Nit_NativeArray)alloc(sizeof(struct Nit_NativeArray) + ((length - 1) * size));") + v.add_instr("array->vft = (classtable_elt_t*)VFT_{name};") + v.add_instr("array->object_id = object_id_counter;") + v.add_instr("object_id_counter = object_id_counter + 1;") + v.add_instr("array->size = length;") + v.add_instr("return OBJ2VAL(array);") v.unindent v.add_instr("}") - - # Compile CHECKNAME - var s = "void CHECKNEW_{name}(val_t self, char *from)" - v.add_instr(s + " \{") - v.indent - var ctx_old = v.ctx - v.ctx = new CContext - for g in global_properties do - var p = self[g] - var t = p.signature.return_type - if p isa MMAttribute and t != null and not t.is_nullable and v.tc.opt_warn.value > 0 then - v.add_instr("if ({p.global.attr_access}(self) == NIT_NULL) fprintf(stderr, \"Uninitialized attribute %s at %s.\\n\", \"{p.full_name}\", from);") - end + else if pi == null then + do + # Generate INIT_ATTRIBUTES routine + var cname = "INIT_ATTRIBUTES__{name}" + var args = init_var_iroutine.compile_signature_to_c(v, cname, "init var of {name}", null, null) + var decl_writer_old = v.decl_writer + v.decl_writer = v.writer.sub + init_var_iroutine.compile_to_c(v, cname, args) + v.decl_writer = decl_writer_old + v.unindent + v.add_instr("}") + end + do + # Generate NEW routine + v.add_decl("val_t NEW_{name}(void);") + v.add_instr("val_t NEW_{name}(void)") + v.add_instr("\{") + v.indent + v.add_instr("obj_t obj;") + v.add_instr("obj = alloc(sizeof(val_t) * {itab.length});") + v.add_instr("obj->vft = (classtable_elt_t*)VFT_{name};") + v.add_instr("obj[1].object_id = object_id_counter;") + v.add_instr("object_id_counter = object_id_counter + 1;") + v.add_instr("return OBJ2VAL(obj);") + v.unindent + v.add_instr("}") + end + do + # Compile CHECKNAME + var cname = "CHECKNEW_{name}" + var args = checknew_iroutine.compile_signature_to_c(v, cname, "check new {name}", null, null) + var decl_writer_old = v.decl_writer + v.decl_writer = v.writer.sub + checknew_iroutine.compile_to_c(v, cname, args) + v.decl_writer = decl_writer_old + v.unindent + v.add_instr("}") end - ctx_old.append(v.ctx) - v.ctx = ctx_old - v.unindent - v.add_instr("}") var init_table_size = cshe.greaters.length + 1 var init_table_decl = "int init_table[{init_table_size}] = \{0{", 0" * (init_table_size-1)}};" @@ -928,21 +433,16 @@ redef class MMLocalClass var p = self[g] # FIXME skip invisible constructors if not p.global.is_init_for(self) then continue - var params = new Array[String] - var args = ["self"] - for i in [0..p.signature.arity[ do - params.add("val_t p{i}") - args.add("p{i}") - end - args.add("init_table") - var s = "val_t NEW_{self}_{p.global.intro.cname}({params.join(", ")}) \{" - v.add_instr(s) - v.indent + assert p isa MMMethod + + var cname = "NEW_{self}_{p.global.intro.cname}" + var new_args = new_instance_iroutine[p].compile_signature_to_c(v, cname, "new {self} {p.full_name}", null, null) + var decl_writer_old = v.decl_writer + v.decl_writer = v.writer.sub v.add_instr(init_table_decl) - v.add_instr("val_t self = NEW_{name}();") - v.add_instr("{p.cname}({args.join(", ")});") - v.add_instr("CHECKNEW_{name}(self, \"{p.full_name} for {self}\");") - v.add_instr("return self;") + var e = new_instance_iroutine[p].compile_to_c(v, cname, new_args).as(not null) + v.add_instr("return {e};") + v.decl_writer = decl_writer_old v.unindent v.add_instr("}") end @@ -954,6 +454,8 @@ redef class MMLocalClass v.add_instr("{tbox} *box = ({tbox}*)alloc(sizeof({tbox}));") v.add_instr("box->vft = VFT_{name};") v.add_instr("box->val = val;") + v.add_instr("box->object_id = object_id_counter;") + v.add_instr("object_id_counter = object_id_counter + 1;") v.add_instr("return OBJ2VAL(box);") v.unindent v.add_instr("}") @@ -961,3 +463,42 @@ redef class MMLocalClass end end +redef class MMMethod + fun compile_property_to_c(v: CompilerVisitor) + do + var ir = iroutine + assert ir != null + + var more_params: nullable String = null + if global.is_init then more_params = "int* init_table" + var args = ir.compile_signature_to_c(v, cname, full_name, null, more_params) + var writer_old = v.writer + v.writer = v.writer.sub + var decl_writer_old = v.decl_writer + v.decl_writer = v.writer.sub + + var itpos: nullable String = null + if global.is_init then + itpos = "itpos{v.new_number}" + v.add_decl("int {itpos} = VAL2OBJ({args.first})->vft[{local_class.global.init_table_pos_id}].i;") + v.add_instr("if (init_table[{itpos}]) return;") + end + + var s = ir.compile_to_c(v, cname, args) + + if itpos != null then + v.add_instr("init_table[{itpos}] = 1;") + end + if s == null then + v.add_instr("return;") + else + v.add_instr("return {s};") + end + v.unindent + v.add_instr("}") + + v.writer = writer_old + v.decl_writer = decl_writer_old + end +end +