compile: store instance size in class table
[nit.git] / src / compiling / compiling_global.nit
index d2a4616..2a686f2 100644 (file)
 # Compute and generate tables for classes and modules.
 package compiling_global
 
-#import compiling_base
-private import compiling_methods
-private import syntax
+private import compiling_icode
 
 # Something that store color of table elements
 class ColorContext
-       attr _colors: HashMap[TableElt, Int] = new HashMap[TableElt, Int]
+       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.has_key(e)
        end
 
        # Assign a color to a table element.
-       meth color=(e: TableElt, c: Int)
+       fun color=(e: TableElt, c: Int)
        do
                _colors[e] = c
                var idx = c
@@ -53,15 +51,15 @@ end
 class GlobalAnalysis
 special ColorContext
        # Associate global classes to compiled classes
-       readable attr _compiled_classes: HashMap[MMGlobalClass, CompiledClass] = new 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 = 0
+       readable writable var _max_class_table_length: Int = 0
 
-       init(module: MMSrcModule)
+       init(module: MMModule)
        do
                _module = module
        end
@@ -70,8 +68,8 @@ end
 class GlobalCompilerVisitor
 special CompilerVisitor
        # The global analysis result
-       readable attr _global_analysis: GlobalAnalysis
-       init(m: MMSrcModule, tc: ToolContext, ga: GlobalAnalysis)
+       readable var _global_analysis: GlobalAnalysis
+       init(m: MMModule, tc: ToolContext, ga: GlobalAnalysis)
        do
                super(m, tc)
                _global_analysis = ga
@@ -82,39 +80,39 @@ end
 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 = 0
+       readable writable var _id: Int = 0
 
        # The full class table of the class
-       readable attr _class_table: Array[nullable TableElt] = new Array[nullable TableElt]
+       readable var _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]
+       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 = new TableEltComposite(self)
+       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 = new TableEltComposite(self)
+       readable writable var _instance_layout: TableEltComposite = new TableEltComposite(self)
 
        init(c: MMLocalClass) do _local_class = c
 end
 
-redef class MMSrcLocalClass
+redef class MMConcreteClass
        # 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
+       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[TableElt] = new Array[TableElt]
+       readable var _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]
+       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[ModuleTableElt])
+       fun build_layout_in(tc: ToolContext, module_table: Array[ModuleTableElt])
        do
                var clt = _class_layout
                var ilt = _instance_layout
@@ -126,16 +124,16 @@ redef class MMSrcLocalClass
                        module_table.add(cpp)
                        clt.add(new TableEltClassInitTable(self))
                end
-               for p in src_local_properties do
+               for p in local_local_properties do
                        var pg = p.global
                        if pg.intro == p then
-                               if p isa MMSrcAttribute then
+                               if p isa MMAttribute then
                                        ilt.add(new TableEltAttr(p))
-                               else if p isa MMSrcMethod then
+                               else if p isa MMMethod then
                                        clt.add(new TableEltMeth(p))
                                end
                        end
-                       if p isa MMSrcMethod and p.need_super then
+                       if p isa MMMethod and p.need_super then
                                clt.add(new TableEltSuper(p))
                        end
                end
@@ -154,20 +152,22 @@ redef class MMSrcLocalClass
        end
 end
 
-redef class MMSrcModule
+redef class MMModule
        # The local table of the module (refers things introduced in the module)
-       attr _local_table: Array[ModuleTableElt] = new Array[ModuleTableElt]
+       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
-               for c in src_local_classes do
-                       c.build_layout_in(tc, _local_table)
+               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
-       meth global_analysis(cctx: ToolContext): GlobalAnalysis
+       fun global_analysis(cctx: ToolContext): GlobalAnalysis
        do
                #print "Do the complete global analysis"
                var ga = new GlobalAnalysis(self)
@@ -177,7 +177,9 @@ redef class MMSrcModule
                var itab = new Array[TableElt]
 
                ctab.add(new TableEltClassSelfId)
+               ctab.add(new TableEltClassObjectSize)
                itab.add(new TableEltVftPointer)
+               itab.add(new TableEltObjectId)
 
                var pclassid = -1
                var classid = 3
@@ -218,7 +220,7 @@ redef class MMSrcModule
 
                        # Store the colortableelt in the class table pool
                        var bc = c.global.intro
-                       assert bc isa MMSrcLocalClass
+                       assert bc isa MMConcreteClass
                        ctab.add(bc.class_color_pos)
                end
 
@@ -252,7 +254,7 @@ redef class MMSrcModule
                                assert cc.class_table.is_empty
                                cc.class_table.add_all(scc.class_table)
                                var bc = c.global.intro
-                               assert bc isa MMSrcLocalClass
+                               assert bc isa MMConcreteClass
                                var colpos = bc.class_color_pos
                                var colposcolor = cc.class_table.length
                                ga.color(colpos) = colposcolor
@@ -268,7 +270,7 @@ redef class MMSrcModule
                        var cte = cc.class_layout
                        var ite = cc.instance_layout
                        for sc in c.crhe.greaters_and_self do
-                               if sc isa MMSrcLocalClass then
+                               if sc isa MMConcreteClass then
                                        cte.add(sc, sc.class_layout)
                                        ite.add(sc, sc.instance_layout)
                                end
@@ -303,7 +305,7 @@ redef class MMSrcModule
                                cc.class_table.clear
                                cc.class_table.add_all(scc.class_table)
                                var bc = c.global.intro
-                               assert bc isa MMSrcLocalClass
+                               assert bc isa MMConcreteClass
                                var colpos = bc.class_color_pos
                                cc.class_table[ga.color(colpos)] = colpos
                                while cc.class_table.length <= maxcolor do
@@ -319,7 +321,7 @@ redef class MMSrcModule
                return ga
        end
 
-       private meth append_to_table(cc: ColorContext, table: Array[nullable 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)
@@ -328,7 +330,7 @@ redef class MMSrcModule
                end
        end
 
-       private meth build_tables_in(table: Array[nullable TableElt], ga: GlobalAnalysis, c: MMLocalClass, elts: 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
@@ -358,7 +360,7 @@ redef class MMSrcModule
        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]
@@ -401,7 +403,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
@@ -412,10 +414,9 @@ redef class MMSrcModule
        end
 
        # Compile module and class tables
-       meth compile_tables_to_c(v: GlobalCompilerVisitor)
+       fun compile_tables_to_c(v: GlobalCompilerVisitor)
        do
                for m in mhe.greaters_and_self do
-                       assert m isa MMSrcModule
                        m.compile_local_table_to_c(v)
                end
 
@@ -435,7 +436,7 @@ redef class MMSrcModule
        end
 
        # Declare class table (for _sep.h)
-       meth declare_class_tables_to_c(v: GlobalCompilerVisitor)
+       fun declare_class_tables_to_c(v: GlobalCompilerVisitor)
        do
                for c in local_classes do
                        if c.global.module == self then
@@ -445,7 +446,7 @@ redef class MMSrcModule
        end
 
        # Compile main part (for _table.c)
-       meth compile_main_part(v: GlobalCompilerVisitor)
+       fun compile_main_part(v: GlobalCompilerVisitor)
        do
                v.add_instr("int main(int argc, char **argv) \{")
                v.indent
@@ -471,7 +472,7 @@ redef class MMSrcModule
        end
 
        # Compile sep files
-       meth compile_mod_to_c(v: GlobalCompilerVisitor)
+       fun compile_mod_to_c(v: GlobalCompilerVisitor)
        do
                v.add_decl("extern const char *LOCATE_{name};")
                if not v.tc.global then
@@ -488,17 +489,18 @@ redef class MMSrcModule
                        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,9 +509,9 @@ 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: GlobalCompilerVisitor)
        do
-               v.add_instr("const char *LOCATE_{name} = \"{filename}\";")
+               v.add_instr("const char *LOCATE_{name} = \"{location.file}\";")
 
                if v.tc.global or _local_table.is_empty then
                        return
@@ -530,7 +532,7 @@ 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
-       meth compile_macros(v: GlobalCompilerVisitor, value: String) is abstract
+       fun compile_macros(v: GlobalCompilerVisitor, value: String) is abstract
 end
 
 # An element of a class or an instance table
@@ -538,16 +540,16 @@ end
 abstract class TableElt
 special AbsTableElt
        # Is the element conflict to class `c' (used for coloring)
-       meth is_related_to(c: MMLocalClass): Bool is abstract
+       fun is_related_to(c: MMLocalClass): Bool is abstract
 
        # Number of sub-elements. 1 if none
-       meth length: Int do return 1
+       fun length: Int do return 1
 
        # Access the ith subelement.
-       meth item(i: Int): TableElt do return self
+       fun item(i: Int): TableElt do return self
 
        # 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: GlobalCompilerVisitor, c: MMLocalClass): String is abstract
 end
 
 # An element of a module table
@@ -555,16 +557,16 @@ end
 abstract class ModuleTableElt
 special AbsTableElt
        # Return the value of the element once the global analisys is performed
-       meth value(ga: GlobalAnalysis): String is abstract
+       fun value(ga: GlobalAnalysis): 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]
+       readable var _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 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
@@ -577,7 +579,7 @@ end
 # An element that represents a class property
 abstract class TableEltProp
 special TableElt
-       attr _property: MMLocalProperty
+       var _property: MMLocalProperty
 
        init(p: MMLocalProperty)
        do
@@ -588,13 +590,13 @@ 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
@@ -604,13 +606,13 @@ 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
@@ -634,13 +636,13 @@ 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]
@@ -652,7 +654,7 @@ end
 class AbsTableEltClass
 special AbsTableElt
        # The local class where the information comes from
-       attr _local_class: MMLocalClass
+       var _local_class: MMLocalClass
 
        init(c: MMLocalClass)
        do
@@ -660,9 +662,9 @@ special AbsTableElt
        end
 
        # 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
@@ -672,7 +674,7 @@ end
 class TableEltClass
 special TableElt
 special AbsTableEltClass
-       redef meth is_related_to(c)
+       redef fun is_related_to(c)
        do
                var bc = c.module[_local_class.global]
                return c.cshe <= bc
@@ -683,9 +685,9 @@ end
 class TableEltClassId
 special ModuleTableElt
 special AbsTableEltClass
-       redef meth symbol do return _local_class.global.id_id
+       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
@@ -694,9 +696,9 @@ 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 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]
@@ -716,14 +718,14 @@ end
 class TableEltClassColor
 special TableEltClass
 special ModuleTableElt
-       redef meth symbol do return _local_class.global.color_id
+       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]
@@ -734,21 +736,21 @@ 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
+       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[TableElt])
+       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
@@ -761,19 +763,52 @@ 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
 end
 
+
+# The element that represent the Object Size
+class TableEltClassObjectSize
+special TableElt
+       redef fun is_related_to(c) do return true
+       redef fun compile_to_c(v, c)
+       do
+        var nb = 0
+        var ga = v.global_analysis
+               if c.name == "NativeArray".to_symbol then
+                       nb = -1
+               else
+                       var cc = ga.compiled_classes[c.global]
+                       var itab = cc.instance_table
+                       for e in itab do
+                               nb += 1
+                       end
+               end
+               return "{nb} /* {ga.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 fun compile_to_c(v, c)
+       do
+               var ga = v.global_analysis
+               return "/* {ga.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 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 */"
@@ -786,13 +821,13 @@ end
 # 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
@@ -814,24 +849,26 @@ redef class MMLocalClass
        end
 
        # Declaration and macros related to the class table
-       meth declare_tables_to_c(v: GlobalCompilerVisitor)
+       fun declare_tables_to_c(v: GlobalCompilerVisitor)
        do
                v.add_decl("")
                var pi = primitive_info
                v.add_decl("extern const classtable_elt_t VFT_{name}[];")
-               if pi == null then
+               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
                        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: GlobalCompilerVisitor)
        do
                var cc = v.global_analysis.compiled_classes[self.global]
                var ctab = cc.class_table
@@ -864,62 +901,80 @@ 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};")
+                       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("}")
+               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;")
+                               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.unindent
+                               v.add_instr("}")
                        end
-                       v.add_instr("return OBJ2VAL(obj);")
-                       v.cfc.generate_var_decls
-                       ctx_old.append(v.ctx)
-                       v.ctx = ctx_old
-                       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); \}")
+                       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
+                               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 +983,32 @@ 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 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
                                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 = iroutine.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.unindent
                                v.add_instr("}")
                        end
@@ -954,6 +1020,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 +1029,44 @@ 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 ctx_old = v.ctx
+               v.ctx = new CContext
+
+               v.out_contexts.clear
+
+               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
+
+               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)
+       end
+end
+