X-Git-Url: http://nitlanguage.org diff --git a/src/compiling/compiling_global.nit b/src/compiling/compiling_global.nit index 23f5791..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 table_computation private import compiling_icode -# Something that store color of table elements -class ColorContext - var _colors: HashMap[TableElt, Int] = new HashMap[TableElt, Int] - - # The color of a table element. - fun color(e: TableElt): Int - do - return _colors[e] - end - - # Is a table element already colored? - fun has_color(e: TableElt): Bool - do - return _colors.has_key(e) - end - - # Assign a color to a table element. - fun 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 var _compiled_classes: HashMap[MMGlobalClass, CompiledClass] = new HashMap[MMGlobalClass, CompiledClass] - - # The main module of the program globally analysed - readable var _module: MMModule - - # FIXME: do something better. - readable writable var _max_class_table_length: Int = 0 - - init(module: MMModule) - do - _module = module - end -end - -class GlobalCompilerVisitor -special CompilerVisitor - # The global analysis result - readable var _global_analysis: GlobalAnalysis - init(m: MMModule, 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 var _local_class: MMLocalClass - - # The identifier of the class - readable writable var _id: Int = 0 - - # The full class table of the class - readable var _class_table: Array[nullable TableElt] = new Array[nullable TableElt] - - # The full instance table of the class - readable var _instance_table: Array[nullable TableElt] = new Array[nullable TableElt] - - # The proper class table part (no superclasses but all refinements) - readable writable var _class_layout: TableEltComposite = new TableEltComposite(self) - - # The proper instance table part (no superclasses but all refinements) - readable writable var _instance_layout: TableEltComposite = new TableEltComposite(self) - - init(c: MMLocalClass) do _local_class = c -end - -redef class MMConcreteClass - # The table element of the subtype check - 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 var _class_layout: Array[TableElt] = new Array[TableElt] - - # The proper local instance table part (nor superclasses nor refinments) - readable var _instance_layout: Array[TableElt] = new Array[TableElt] - - # Build the local layout of the class and feed the module table - fun 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 local_local_properties do - var pg = p.global - if pg.intro == p then - if p isa MMAttribute then - ilt.add(new TableEltAttr(p)) - else if p isa MMMethod then - clt.add(new TableEltMeth(p)) - end - end - if p isa MMMethod 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 MMModule - # The local table of the module (refers things introduced in the module) - var _local_table: Array[ModuleTableElt] = new Array[ModuleTableElt] - - # Builds the local tables and local classes layouts - fun local_analysis(tc: ToolContext) - do - for c in local_classes do - if c isa MMConcreteClass then - c.build_layout_in(tc, _local_table) - end - end - end - - # Do the complete global analysis - fun 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) - itab.add(new TableEltObjectId) - - 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 MMConcreteClass - 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 MMConcreteClass - 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 MMConcreteClass 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 MMConcreteClass - 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 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) - cc.color(e) = table.length - table.add(e) - end - end - - 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 - 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 - 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] - 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 fun 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 - +redef class Program # Compile module and class tables - fun compile_tables_to_c(v: GlobalCompilerVisitor) + fun compile_tables_to_c(v: CompilerVisitor) do - for m in mhe.greaters_and_self do + 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,54 +45,49 @@ redef class MMModule v.add_instr(s.to_s) end - # Declare class table (for _sep.h) - fun 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) - fun 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 - fun 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 @@ -508,18 +114,18 @@ redef class MMModule end # Compile module file for the current module - fun compile_local_table_to_c(v: GlobalCompilerVisitor) + fun compile_local_table_to_c(v: CompilerVisitor) do - v.add_instr("const char *LOCATE_{name} = \"{location.file}\";") + 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("\};") @@ -528,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 - fun 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) - 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 - +redef class TableElt # Return the value of the element for a given class - fun 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 - fun 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 var _elements: Array[TableElt] = new Array[TableElt] - - redef fun value(ga) do return "{ga.color(_elements.first)} /* Group of ? */" +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 - var _property: MMLocalProperty - - init(p: MMLocalProperty) - do - _property = p - end -end - -# An element that represents a function pointer to a global method -class TableEltMeth -special TableEltProp +redef class TableEltMeth redef fun 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 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 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 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 @@ -632,34 +203,22 @@ special TableEltProp end end -# An element that represents the value stored for a global attribute -class TableEltAttr -special TableEltProp +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 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 - var _local_class: MMLocalClass - - init(c: MMLocalClass) - do - _local_class = c - end - +redef class AbsTableEltClass # The C macro name refering the value fun symbol: String is abstract @@ -669,173 +228,111 @@ special AbsTableElt 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 ModuleTableElt -special AbsTableEltClass - redef fun symbol do return _local_class.global.id_id +redef class TableEltClassId + redef fun symbol do return local_class.global.id_id - redef fun 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 fun 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 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 fun symbol do return _local_class.global.color_id +redef class TableEltClassColor + redef fun symbol do return local_class.global.color_id - redef fun 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 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 - 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 +redef class TableEltComposite + redef fun compile_to_c(v, c) do abort +end - fun 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 fun item(i) do return _table[i] - - redef fun compile_to_c(v, c) do abort - - init(cc: CompiledClass) +redef class TableEltClassSelfName + redef fun compile_to_c(v, c) do - _cc = cc - _table = new Array[TableElt] - _offsets = new HashMap[MMLocalClass, Int] + var prog = v.program + return "\"{c.global.name}\" /* {prog.table_information.color(self)}: Class Name */" end end -# The element that represent the class id -class TableEltClassSelfId -special TableElt - redef fun is_related_to(c) do return true +redef class TableEltClassObjectSize 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 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 object id -class TableEltObjectId -special TableElt - redef fun is_related_to(c) do return true +redef class TableEltObjectId redef fun compile_to_c(v, c) do - var ga = v.global_analysis - return "/* {ga.color(self)}: Object_id */" + var p = v.program + return "/* {p.table_information.color(self)}: Object_id */" end end -# The element that -class TableEltVftPointer -special TableElt - redef fun is_related_to(c) do return true +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 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 - fun 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 - fun 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 name == "NativeArray".to_symbol then - v.add_decl("val_t NEW_NativeArray(size_t length, size_t size);") - else 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; bigint object_id; {t} val;};") @@ -845,13 +342,13 @@ redef class MMLocalClass end # Compilation of table and new (or box) - fun 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}] = \{") @@ -892,63 +389,39 @@ redef class MMLocalClass v.add_instr("}") else if pi == null then do - var iself = new IRegister(get_type) - var iselfa = [iself] - var iroutine = new IRoutine(new Array[IRegister], iself) - var icb = new ICodeBuilder(module, iroutine) - var obj = new INative("OBJ2VAL(obj)", null) - obj.result = iself - icb.stmt(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 - var ir = p.iroutine - if ir == null then continue - # FIXME: Not compatible with sep compilation - var e = icb.inline_routine(ir, iselfa, null).as(not null) - icb.stmt(new IAttrWrite(p, iself, e)) - end - end - - var cname = "NEW_{name}" - var args = iroutine.compile_signature_to_c(v, cname, "new {name}", null, null) - var ctx_old = v.ctx - v.ctx = new CContext - v.add_decl("obj_t obj;") + # 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;") - var r = iroutine.compile_to_c(v, cname, args).as(not null) - v.add_instr("return {r};") - ctx_old.append(v.ctx) - v.ctx = ctx_old + v.add_instr("return OBJ2VAL(obj);") v.unindent v.add_instr("}") end - do # Compile CHECKNAME - var iself = new IRegister(get_type) - var iselfa = [iself] - var iroutine = new IRoutine(iselfa, null) - var icb = new ICodeBuilder(module, iroutine) - 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 - icb.add_attr_check(p, iself) - end - end var cname = "CHECKNEW_{name}" - var args = iroutine.compile_signature_to_c(v, cname, "check new {name}", null, null) - var ctx_old = v.ctx - v.ctx = new CContext - iroutine.compile_to_c(v, cname, args) - ctx_old.append(v.ctx) - v.ctx = ctx_old + 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 @@ -962,30 +435,14 @@ redef class MMLocalClass if not p.global.is_init_for(self) then continue assert p isa MMMethod - var iself = new IRegister(get_type) - var iparams = new Array[IRegister] - for i in [0..p.signature.arity[ do iparams.add(new IRegister(p.signature[i])) - var iroutine = new IRoutine(iparams, iself) - iroutine.location = p.iroutine.location - var icb = new ICodeBuilder(module, iroutine) - - var inew = new INative("NEW_{name}()", null) - inew.result = iself - icb.stmt(inew) - var iargs = [iself] - iargs.add_all(iparams) - icb.stmt(new INative("{p.cname}(@@@{", @@@"*iparams.length}, init_table)", iargs)) - icb.stmt(new INative("CHECKNEW_{name}(@@@)", [iself])) - var cname = "NEW_{self}_{p.global.intro.cname}" - var new_args = iroutine.compile_signature_to_c(v, cname, "new {self} {p.full_name}", null, null) - var ctx_old = v.ctx - v.ctx = new CContext + 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) - var e = iroutine.compile_to_c(v, cname, new_args).as(not null) + var e = new_instance_iroutine[p].compile_to_c(v, cname, new_args).as(not null) v.add_instr("return {e};") - ctx_old.append(v.ctx) - v.ctx = ctx_old + v.decl_writer = decl_writer_old v.unindent v.add_instr("}") end @@ -1015,10 +472,10 @@ redef class MMMethod 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 ctx_old = v.ctx - v.ctx = new CContext - - v.out_contexts.clear + 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 @@ -1035,15 +492,13 @@ redef class MMMethod if s == null then v.add_instr("return;") else - v.add_instr("return ", s, ";") + v.add_instr("return {s};") end - - ctx_old.append(v.ctx) - v.ctx = ctx_old v.unindent v.add_instr("}") - for ctx in v.out_contexts do v.ctx.merge(ctx) + v.writer = writer_old + v.decl_writer = decl_writer_old end end