X-Git-Url: http://nitlanguage.org diff --git a/src/compiling/compiling_global.nit b/src/compiling/compiling_global.nit index bbce5fa..d2217f8 100644 --- a/src/compiling/compiling_global.nit +++ b/src/compiling/compiling_global.nit @@ -23,24 +23,23 @@ private import syntax # Something that store color of table elements class ColorContext - attr _colors: HashMap[TableElt, Int] = null + var _colors: HashMap[TableElt, Int] = new HashMap[TableElt, Int] # The color of a table element. - meth color(e: TableElt): Int + fun color(e: TableElt): Int do return _colors[e] end # Is a table element already colored? - meth has_color(e: TableElt): Bool + fun has_color(e: TableElt): Bool do - return _colors != null and _colors.has_key(e) + return _colors.has_key(e) end # Assign a color to a table element. - meth color=(e: TableElt, c: Int) + fun color=(e: TableElt, c: Int) do - if _colors == null then _colors = new HashMap[TableElt, Int] _colors[e] = c var idx = c for i in [0..e.length[ do @@ -54,72 +53,77 @@ end class GlobalAnalysis special ColorContext # Associate global classes to compiled classes - readable attr _compiled_classes: HashMap[MMGlobalClass, CompiledClass] + readable var _compiled_classes: HashMap[MMGlobalClass, CompiledClass] = new HashMap[MMGlobalClass, CompiledClass] # The main module of the program globally analysed - readable attr _module: MMModule + readable var _module: MMModule # FIXME: do something better. - readable writable attr _max_class_table_length: Int + readable writable var _max_class_table_length: Int = 0 init(module: MMSrcModule) do - _compiled_classes = new HashMap[MMGlobalClass, CompiledClass] _module = module end end -redef class CompilerVisitor - # The global analysis result, if any - readable writable attr _global_analysis: GlobalAnalysis +class GlobalCompilerVisitor +special CompilerVisitor + # The global analysis result + readable var _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 + readable var _local_class: MMLocalClass # The identifier of the class - readable writable attr _id: Int + readable writable var _id: Int = 0 # The full class table of the class - readable writable attr _class_table: Array[TableElt] + readable var _class_table: Array[nullable TableElt] = new Array[nullable TableElt] # The full instance table of the class - readable writable attr _instance_table: Array[TableElt] + readable var _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 + readable writable var _class_layout: TableEltComposite = new TableEltComposite(self) # The proper instance table part (no superclasses but all refinements) - readable writable attr _instance_layout: TableEltComposite + readable writable var _instance_layout: TableEltComposite = new TableEltComposite(self) init(c: MMLocalClass) do _local_class = c end redef class MMSrcLocalClass # The table element of the subtype check - readable attr _class_color_pos: TableEltClassColor + fun class_color_pos: TableEltClassColor do return _class_color_pos.as(not null) + var _class_color_pos: nullable TableEltClassColor # The proper local class table part (nor superclasses nor refinments) - readable attr _class_layout: Array[LocalTableElt] + readable var _class_layout: Array[TableElt] = new Array[TableElt] # The proper local instance table part (nor superclasses nor refinments) - readable attr _instance_layout: Array[LocalTableElt] + readable var _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[LocalTableElt]) + fun build_layout_in(tc: ToolContext, module_table: Array[ModuleTableElt]) do - var clt = new Array[LocalTableElt] - _class_layout = clt - var ilt = new Array[LocalTableElt] - _instance_layout = ilt + var clt = _class_layout + var ilt = _instance_layout if global.intro == self then module_table.add(new TableEltClassId(self)) - _class_color_pos = new TableEltClassColor(self) - module_table.add(_class_color_pos) + 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 @@ -135,27 +139,35 @@ redef class MMSrcLocalClass clt.add(new TableEltSuper(p)) end end - module_table.append(ilt) - module_table.append(clt) + + 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[LocalTableElt] + var _local_table: Array[ModuleTableElt] = new Array[ModuleTableElt] # Builds the local tables and local classes layouts - meth local_analysis(tc: ToolContext) + fun local_analysis(tc: ToolContext) do - var lt = new Array[LocalTableElt] - _local_table = lt for c in src_local_classes do - c.build_layout_in(tc, lt) + c.build_layout_in(tc, _local_table) end end # Do the complete global analysis - meth global_analysis(cctx: ToolContext): GlobalAnalysis + fun global_analysis(cctx: ToolContext): GlobalAnalysis do #print "Do the complete global analysis" var ga = new GlobalAnalysis(self) @@ -166,7 +178,7 @@ redef class MMSrcModule ctab.add(new TableEltClassSelfId) itab.add(new TableEltVftPointer) - + var pclassid = -1 var classid = 3 @@ -212,7 +224,7 @@ redef class MMSrcModule # Compute core and crown classes for colorization var crown_classes = new HashSet[MMLocalClass] - var core_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 @@ -231,13 +243,14 @@ redef class MMSrcModule var cc = ga.compiled_classes[c.global] if core_classes.has(c) then # For core classes, just build the table - cc.class_table = build_tables(ga, c, ctab) + 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] - cc.class_table = scc.class_table.to_a + 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 @@ -252,15 +265,13 @@ redef class MMSrcModule # Fill class table and instance tables pools for c in classes do var cc = ga.compiled_classes[c.global] - var cte = new TableEltComposite(cc) - var ite = new TableEltComposite(cc) + 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 - cc.class_layout = cte - cc.instance_layout = ite end if core_classes.has(c) then @@ -278,18 +289,19 @@ redef class MMSrcModule colorize(ga, itab, crown_classes, 0) # Build class and instance tables now things are colored - ga.max_class_table_length = 0 + 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 - cc.class_table = build_tables(ga, c, ctab) - cc.instance_table = build_tables(ga, c, itab) + 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 = scc.class_table.to_a + 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 @@ -298,7 +310,8 @@ redef class MMSrcModule cc.class_table.add(null) end append_to_table(ga, cc.class_table, cc.class_layout) - cc.instance_table = scc.instance_table.to_a + 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 @@ -306,7 +319,7 @@ redef class MMSrcModule return ga end - private meth append_to_table(cc: ColorContext, table: Array[TableElt], cmp: TableEltComposite) + private fun append_to_table(cc: ColorContext, table: Array[nullable TableElt], cmp: TableEltComposite) do for j in [0..cmp.length[ do var e = cmp.item(j) @@ -315,7 +328,7 @@ redef class MMSrcModule end end - private meth build_tables(ga: GlobalAnalysis, c: MMLocalClass, elts: Array[TableElt]): Array[TableElt] + private fun build_tables_in(table: Array[nullable TableElt], ga: GlobalAnalysis, c: MMLocalClass, elts: Array[TableElt]) do var tab = new HashMap[Int, TableElt] var len = 0 @@ -329,25 +342,23 @@ redef class MMSrcModule end end end - var res = new Array[TableElt] var i = 0 while i < len do if tab.has_key(i) then var e = tab[i] for j in [0..e.length[ do - res[i] = e.item(j) + table[i] = e.item(j) i = i + 1 end else - res[i] = null + table[i] = null i = i + 1 end end - return res end # Perform coloring - meth colorize(ga: GlobalAnalysis, elts: Array[TableElt], classes: Collection[MMLocalClass], startcolor: Int) + fun 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] @@ -367,7 +378,7 @@ redef class MMSrcModule while trycolor != color do color = trycolor for c in rel_classes do - var idx = 0 + 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 @@ -390,7 +401,7 @@ redef class MMSrcModule end end - private meth free_color(es: Array[TableElt], c: MMLocalClass): Bool + private fun free_color(es: Array[TableElt], c: MMLocalClass): Bool do for e2 in es do if e2.is_related_to(c) then @@ -401,7 +412,7 @@ redef class MMSrcModule end # Compile module and class tables - meth compile_tables_to_c(v: CompilerVisitor) + fun compile_tables_to_c(v: GlobalCompilerVisitor) do for m in mhe.greaters_and_self do assert m isa MMSrcModule @@ -411,7 +422,7 @@ redef class MMSrcModule for c in local_classes do c.compile_tables_to_c(v) end - var s = "classtable_t TAG2VFT[4] = \{NULL" + 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 s.append(", (const classtable_t)VFT_{t}") @@ -420,11 +431,11 @@ redef class MMSrcModule end end s.append("};") - v.add_instr(s) + v.add_instr(s.to_s) end # Declare class table (for _sep.h) - meth declare_class_tables_to_c(v: CompilerVisitor) + fun declare_class_tables_to_c(v: GlobalCompilerVisitor) do for c in local_classes do if c.global.module == self then @@ -434,7 +445,7 @@ redef class MMSrcModule end # Compile main part (for _table.c) - meth compile_main_part(v: CompilerVisitor) + fun compile_main_part(v: GlobalCompilerVisitor) do v.add_instr("int main(int argc, char **argv) \{") v.indent @@ -445,12 +456,11 @@ redef class MMSrcModule print("No main") else var sys = class_by_name(sysname) - # var initm = sys.select_method(once "init".to_symbol) - var mainm = sys.select_method(once "main".to_symbol) - if mainm == null then + var name = once "main".to_symbol + if not sys.has_global_property_by_name(name) then print("No main") else - #v.add_instr("G_sys = NEW_{initm.cname}();") + var mainm = sys.select_method(name) v.add_instr("G_sys = NEW_Sys();") v.add_instr("{mainm.cname}(G_sys);") end @@ -459,9 +469,9 @@ redef class MMSrcModule v.unindent v.add_instr("}") end - - # Compile sep files - meth compile_mod_to_c(v: CompilerVisitor) + + # Compile sep files + fun compile_mod_to_c(v: GlobalCompilerVisitor) do v.add_decl("extern const char *LOCATE_{name};") if not v.tc.global then @@ -497,7 +507,7 @@ redef class MMSrcModule end # Compile module file for the current module - meth compile_local_table_to_c(v: CompilerVisitor) + fun compile_local_table_to_c(v: GlobalCompilerVisitor) do v.add_instr("const char *LOCATE_{name} = \"{filename}\";") @@ -515,24 +525,59 @@ redef class MMSrcModule end end +############################################################################### + +# An element of a class, an instance or a module table +abstract class AbsTableElt + # Compile the macro needed to use the element and other related elements + fun compile_macros(v: GlobalCompilerVisitor, 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 - meth is_related_to(c: MMLocalClass): Bool is abstract - meth length: Int do return 1 - meth item(i: Int): TableElt do return self - meth compile_macros(v: CompilerVisitor, value: String) is abstract - meth compile_to_c(v: CompilerVisitor, c: MMLocalClass): String is abstract +special AbsTableElt + # Is the element conflict to class `c' (used for coloring) + fun is_related_to(c: MMLocalClass): Bool is abstract + + # Number of sub-elements. 1 if none + fun length: Int do return 1 + + # Access the ith subelement. + fun item(i: Int): TableElt do return self + + # Return the value of the element for a given class + fun compile_to_c(v: GlobalCompilerVisitor, c: MMLocalClass): String is abstract end -abstract class LocalTableElt -special TableElt - meth value(ga: GlobalAnalysis): String is abstract +# An element of a module table +# Such an elements represent colors or identifiers +abstract class ModuleTableElt +special AbsTableElt + # Return the value of the element once the global analisys is performed + fun value(ga: GlobalAnalysis): String is abstract end -abstract class TableEltProp -special LocalTableElt - attr _property: MMLocalProperty +# An element of a module table that represents a group of TableElt defined in the same local class +class ModuleTableEltGroup +special ModuleTableElt + readable var _elements: Array[TableElt] = new Array[TableElt] - redef meth value(ga) do return "{ga.color(self)} /* Property {_property} */" + redef fun value(ga) do return "{ga.color(_elements.first)} /* Group of ? */" + redef fun compile_macros(v, value) + do + var i = 0 + 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 + var _property: MMLocalProperty init(p: MMLocalProperty) do @@ -540,31 +585,32 @@ special LocalTableElt end end +# An element that represents a function pointer to a global method class TableEltMeth special TableEltProp - redef meth compile_macros(v, value) + redef fun compile_macros(v, value) do 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] return p.cname end - init(p) do super 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 fun compile_macros(v, value) do 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 @@ -575,82 +621,82 @@ special TableEltProp if s == pc then found = true else if found and c.che < s then - var p = s[g] - if p != null then + if s.has_global_property(g) then #print "found {s.module}::{s}::{p}" - return p.cname + return s[g].cname end end end - assert false - return null + abort end - - init(p) do super end +# An element that represents the value stored for a global attribute class TableEltAttr special TableEltProp - redef meth compile_macros(v, value) + redef fun compile_macros(v, value) do 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} */" end - - init(p) do super end -class TableEltClass -special LocalTableElt - attr _local_class: MMLocalClass - redef meth is_related_to(c) - do - var bc = c.module[_local_class.global] - return c.cshe <= bc - end +# An element representing a class information +class AbsTableEltClass +special AbsTableElt + # The local class where the information comes from + var _local_class: MMLocalClass init(c: MMLocalClass) do _local_class = c end - meth symbol: String is abstract + # The C macro name refering the value + 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 fun 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 TableEltClass - redef meth symbol do return _local_class.global.id_id +special ModuleTableElt +special AbsTableEltClass + redef fun symbol do return _local_class.global.id_id - redef meth value(ga) + redef fun value(ga) do return "{ga.compiled_classes[_local_class.global].id} /* Id of {_local_class} */" end - - init(c) do super 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 fun symbol do return _local_class.global.init_table_pos_id - redef meth value(ga) - do - return "{ga.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] @@ -661,89 +707,92 @@ special TableEltClass end return "{i} /* {ga.color(self)}: {c} < {cc.local_class}: superclass init_table position */" end - - init(c) do super 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 - redef meth symbol do return _local_class.global.color_id +special ModuleTableElt + redef fun symbol do return _local_class.global.color_id - redef meth value(ga) + redef fun value(ga) do return "{ga.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 */" end - - init(c) do super end +# A Group of elements introduced in the same global-class that are colored together class TableEltComposite special TableElt - attr _table: Array[LocalTableElt] - 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 + var _table: Array[TableElt] + var _cc: CompiledClass + var _offsets: HashMap[MMLocalClass, Int] + redef fun length do return _table.length + redef fun is_related_to(c) do return c.cshe <= _cc.local_class - meth add(c: MMLocalClass, tab: Array[LocalTableElt]) + fun add(c: MMLocalClass, tab: Array[TableElt]) do _offsets[c] = _table.length _table.append(tab) end - redef meth item(i) do return _table[i] + redef fun item(i) do return _table[i] - redef meth compile_to_c(v, c) do abort + redef fun compile_to_c(v, c) do abort init(cc: CompiledClass) do _cc = cc - _table = new Array[LocalTableElt] + _table = new Array[TableElt] _offsets = new HashMap[MMLocalClass, Int] 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 fun is_related_to(c) do return true + 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 */" end - - init do 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 fun is_related_to(c) do return true + redef fun compile_to_c(v, c) do var ga = v.global_analysis return "/* {ga.color(self)}: Pointer to the classtable */" end - - init do 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) + redef fun 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 + fun compare(b: MMLocalClass): Int do var a = self if a == b then @@ -765,7 +814,7 @@ redef class MMLocalClass end # Declaration and macros related to the class table - meth declare_tables_to_c(v: CompilerVisitor) + fun declare_tables_to_c(v: GlobalCompilerVisitor) do v.add_decl("") var pi = primitive_info @@ -782,10 +831,10 @@ redef class MMLocalClass end # Compilation of table and new (or box) - meth compile_tables_to_c(v: CompilerVisitor) + fun compile_tables_to_c(v: GlobalCompilerVisitor) do var cc = v.global_analysis.compiled_classes[self.global] - var ctab = cc.class_table + 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 @@ -824,7 +873,7 @@ redef class MMLocalClass var ctx_old = v.ctx v.ctx = new CContext - var self_var = new ParamVariable(null, null) + 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] @@ -840,17 +889,10 @@ redef class MMLocalClass # FIXME: Not compatible with sep compilation assert p isa MMSrcAttribute var np = p.node - assert np isa AAttrPropdef var ne = np.n_expr if ne != null then var e = ne.compile_expr(v) v.add_instr("{p.global.attr_access}(obj) = {e};") - else - var pi = t.local_class.primitive_info - if pi != null and pi.tagged then - var default = t.default_cvalue - v.add_instr("{p.global.attr_access}(obj) = {default};") - end end end end @@ -861,6 +903,24 @@ redef class MMLocalClass 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 then + v.add_instr("if ({p.global.attr_access}(self) == NIT_NULL) \{ fprintf(stderr, \"Uninitialized attribute %s at %s.\\n\", \"{p.full_name}\", from); nit_exit(1); \}") + end + 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)}};" @@ -881,6 +941,7 @@ redef class MMLocalClass 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;") v.unindent v.add_instr("}")