separate_compiler: `shortcut_equate` works on `is_same_instance`
[nit.git] / src / compiler / separate_compiler.nit
index 4dfbeb0..33e8d8a 100644 (file)
@@ -22,19 +22,19 @@ import rapid_type_analysis
 # Add separate compiler specific options
 redef class ToolContext
        # --separate
-       var opt_separate: OptionBool = new OptionBool("Use separate compilation", "--separate")
+       var opt_separate = new OptionBool("Use separate compilation", "--separate")
        # --no-inline-intern
-       var opt_no_inline_intern: OptionBool = new OptionBool("Do not inline call to intern methods", "--no-inline-intern")
+       var opt_no_inline_intern = new OptionBool("Do not inline call to intern methods", "--no-inline-intern")
        # --no-union-attribute
-       var opt_no_union_attribute: OptionBool = new OptionBool("Put primitive attibutes in a box instead of an union", "--no-union-attribute")
+       var opt_no_union_attribute = new OptionBool("Put primitive attibutes in a box instead of an union", "--no-union-attribute")
        # --no-shortcut-equate
-       var opt_no_shortcut_equate: OptionBool = new OptionBool("Always call == in a polymorphic way", "--no-shortcut-equal")
+       var opt_no_shortcut_equate = new OptionBool("Always call == in a polymorphic way", "--no-shortcut-equal")
        # --inline-coloring-numbers
-       var opt_inline_coloring_numbers: OptionBool = new OptionBool("Inline colors and ids (semi-global)", "--inline-coloring-numbers")
+       var opt_inline_coloring_numbers = new OptionBool("Inline colors and ids (semi-global)", "--inline-coloring-numbers")
        # --inline-some-methods
-       var opt_inline_some_methods: OptionBool = new OptionBool("Allow the separate compiler to inline some methods (semi-global)", "--inline-some-methods")
+       var opt_inline_some_methods = new OptionBool("Allow the separate compiler to inline some methods (semi-global)", "--inline-some-methods")
        # --direct-call-monomorph
-       var opt_direct_call_monomorph: OptionBool = new OptionBool("Allow the separate compiler to direct call monomorph sites (semi-global)", "--direct-call-monomorph")
+       var opt_direct_call_monomorph = new OptionBool("Allow the separate compiler to direct call monomorph sites (semi-global)", "--direct-call-monomorph")
        # --skip-dead-methods
        var opt_skip_dead_methods = new OptionBool("Do not compile dead methods (semi-global)", "--skip-dead-methods")
        # --semi-global
@@ -42,7 +42,7 @@ redef class ToolContext
        # --no-colo-dead-methods
        var opt_colo_dead_methods = new OptionBool("Force colorization of dead methods", "--colo-dead-methods")
        # --tables-metrics
-       var opt_tables_metrics: OptionBool = new OptionBool("Enable static size measuring of tables used for vft, typing and resolution", "--tables-metrics")
+       var opt_tables_metrics = new OptionBool("Enable static size measuring of tables used for vft, typing and resolution", "--tables-metrics")
 
        redef init
        do
@@ -92,33 +92,35 @@ redef class ModelBuilder
                var compiler = new SeparateCompiler(mainmodule, self, runtime_type_analysis)
                compiler.compile_header
 
+               var c_name = mainmodule.c_name
+
                # compile class structures
                self.toolcontext.info("Property coloring", 2)
-               compiler.new_file("{mainmodule.name}.classes")
+               compiler.new_file("{c_name}.classes")
                compiler.do_property_coloring
                for m in mainmodule.in_importation.greaters do
                        for mclass in m.intro_mclasses do
-                               if mclass.kind == abstract_kind or mclass.kind == interface_kind then continue
+                               #if mclass.kind == abstract_kind or mclass.kind == interface_kind then continue
                                compiler.compile_class_to_c(mclass)
                        end
                end
 
                # The main function of the C
-               compiler.new_file("{mainmodule.name}.main")
+               compiler.new_file("{c_name}.main")
                compiler.compile_nitni_global_ref_functions
                compiler.compile_main_function
                compiler.compile_finalizer_function
 
                # compile methods
                for m in mainmodule.in_importation.greaters do
-                       self.toolcontext.info("Generate C for module {m}", 2)
-                       compiler.new_file("{m.name}.sep")
+                       self.toolcontext.info("Generate C for module {m.full_name}", 2)
+                       compiler.new_file("{m.c_name}.sep")
                        compiler.compile_module_to_c(m)
                end
 
                # compile live & cast type structures
                self.toolcontext.info("Type coloring", 2)
-               compiler.new_file("{mainmodule.name}.types")
+               compiler.new_file("{c_name}.types")
                var mtypes = compiler.do_type_coloring
                for t in mtypes do
                        compiler.compile_type_to_c(t)
@@ -156,17 +158,15 @@ class SeparateCompiler
        private var undead_types: Set[MType] = new HashSet[MType]
        private var live_unresolved_types: Map[MClassDef, Set[MType]] = new HashMap[MClassDef, HashSet[MType]]
 
-       private var type_ids: Map[MType, Int]
-       private var type_colors: Map[MType, Int]
-       private var opentype_colors: Map[MType, Int]
-       protected var method_colors: Map[PropertyLayoutElement, Int]
-       protected var attr_colors: Map[MAttribute, Int]
+       private var type_ids: Map[MType, Int] is noinit
+       private var type_colors: Map[MType, Int] is noinit
+       private var opentype_colors: Map[MType, Int] is noinit
+       protected var method_colors: Map[PropertyLayoutElement, Int] is noinit
+       protected var attr_colors: Map[MAttribute, Int] is noinit
 
-       init(mainmodule: MModule, mmbuilder: ModelBuilder, runtime_type_analysis: nullable RapidTypeAnalysis) do
-               super(mainmodule, mmbuilder)
+       init do
                var file = new_file("nit.common")
                self.header = new CodeWriter(file)
-               self.runtime_type_analysis = runtime_type_analysis
                self.compile_box_kinds
        end
 
@@ -191,7 +191,11 @@ class SeparateCompiler
                        self.header.add_decl("void* val;")
                        for c, v in self.box_kinds do
                                var t = c.mclass_type
-                               self.header.add_decl("{t.ctype} {t.ctypename};")
+
+                               # `Pointer` reuse the `val` field
+                               if t.mclass.name == "Pointer" then continue
+
+                               self.header.add_decl("{t.ctype_extern} {t.ctypename};")
                        end
                        self.header.add_decl("\} nitattribute_t; /* general C type representing a Nit attribute. */")
                end
@@ -213,9 +217,11 @@ class SeparateCompiler
 
        fun box_kind_of(mclass: MClass): Int
        do
-               if mclass.mclass_type.ctype == "val*" then
+               #var pointer_type = self.mainmodule.pointer_type
+               #if mclass.mclass_type.ctype == "val*" or mclass.mclass_type.is_subtype(self.mainmodule, mclass.mclass_type pointer_type) then
+               if mclass.mclass_type.ctype_extern == "val*" then
                        return 0
-               else if mclass.kind == extern_kind then
+               else if mclass.kind == extern_kind and mclass.name != "NativeString" then
                        return self.box_kinds[self.mainmodule.get_primitive_class("Pointer")]
                else
                        return self.box_kinds[mclass]
@@ -412,13 +418,12 @@ class SeparateCompiler
                var live_cast_types = runtime_type_analysis.live_cast_types
                var mtypes = new HashSet[MType]
                mtypes.add_all(live_types)
-               mtypes.add_all(live_cast_types)
                for c in self.box_kinds.keys do
                        mtypes.add(c.mclass_type)
                end
 
                # Compute colors
-               var poset = poset_from_mtypes(mtypes)
+               var poset = poset_from_mtypes(mtypes, live_cast_types)
                var colorer = new POSetColorer[MType]
                colorer.colorize(poset)
                type_ids = colorer.ids
@@ -431,12 +436,13 @@ class SeparateCompiler
                return poset
        end
 
-       private fun poset_from_mtypes(mtypes: Set[MType]): POSet[MType] do
+       private fun poset_from_mtypes(mtypes, cast_types: Set[MType]): POSet[MType] do
                var poset = new POSet[MType]
                for e in mtypes do
                        poset.add_node(e)
-                       for o in mtypes do
+                       for o in cast_types do
                                if e == o then continue
+                               poset.add_node(o)
                                if e.is_subtype(mainmodule, null, o) then
                                        poset.add_edge(e, o)
                                end
@@ -662,14 +668,13 @@ class SeparateCompiler
        do
                var mtype = mclass.intro.bound_mtype
                var c_name = mclass.c_name
-               var c_instance_name = mclass.c_instance_name
 
                var vft = self.method_tables[mclass]
                var attrs = self.attr_tables[mclass]
                var v = new_visitor
 
                var rta = runtime_type_analysis
-               var is_dead = rta != null and not rta.live_classes.has(mclass) and mtype.ctype == "val*" and mclass.name != "NativeArray"
+               var is_dead = rta != null and not rta.live_classes.has(mclass) and mtype.ctype == "val*" and mclass.name != "NativeArray" and mclass.name != "Pointer"
 
                v.add_decl("/* runtime class {c_name} */")
 
@@ -698,23 +703,24 @@ class SeparateCompiler
                        v.add_decl("\};")
                end
 
-               if mtype.ctype != "val*" then
-                       if mtype.mclass.name == "Pointer" or mtype.mclass.kind != extern_kind then
-                               #Build instance struct
-                               self.header.add_decl("struct instance_{c_instance_name} \{")
-                               self.header.add_decl("const struct type *type;")
-                               self.header.add_decl("const struct class *class;")
-                               self.header.add_decl("{mtype.ctype} value;")
-                               self.header.add_decl("\};")
-                       end
+               if mtype.ctype != "val*" or mtype.mclass.name == "Pointer" then
+                       # Is a primitive type or the Pointer class, not any other extern class
+
+                       #Build instance struct
+                       self.header.add_decl("struct instance_{c_name} \{")
+                       self.header.add_decl("const struct type *type;")
+                       self.header.add_decl("const struct class *class;")
+                       self.header.add_decl("{mtype.ctype_extern} value;")
+                       self.header.add_decl("\};")
 
-                       if not rta.live_types.has(mtype) then return
+                       if not rta.live_types.has(mtype) and mtype.mclass.name != "Pointer" then return
 
                        #Build BOX
-                       self.provide_declaration("BOX_{c_name}", "val* BOX_{c_name}({mtype.ctype});")
+                       self.provide_declaration("BOX_{c_name}", "val* BOX_{c_name}({mtype.ctype_extern});")
                        v.add_decl("/* allocate {mtype} */")
-                       v.add_decl("val* BOX_{mtype.c_name}({mtype.ctype} value) \{")
-                       v.add("struct instance_{c_instance_name}*res = nit_alloc(sizeof(struct instance_{c_instance_name}));")
+                       v.add_decl("val* BOX_{mtype.c_name}({mtype.ctype_extern} value) \{")
+                       v.add("struct instance_{c_name}*res = nit_alloc(sizeof(struct instance_{c_name}));")
+                       v.compiler.undead_types.add(mtype)
                        v.require_declaration("type_{c_name}")
                        v.add("res->type = &type_{c_name};")
                        v.require_declaration("class_{c_name}")
@@ -722,10 +728,31 @@ class SeparateCompiler
                        v.add("res->value = value;")
                        v.add("return (val*)res;")
                        v.add("\}")
+
+                       if mtype.mclass.name != "Pointer" then return
+
+                       v = new_visitor
+                       self.provide_declaration("NEW_{c_name}", "{mtype.ctype} NEW_{c_name}(const struct type* type);")
+                       v.add_decl("/* allocate {mtype} */")
+                       v.add_decl("{mtype.ctype} NEW_{c_name}(const struct type* type) \{")
+                       if is_dead then
+                               v.add_abort("{mclass} is DEAD")
+                       else
+                               var res = v.new_named_var(mtype, "self")
+                               res.is_exact = true
+                               v.add("{res} = nit_alloc(sizeof(struct instance_{mtype.c_name}));")
+                               v.add("{res}->type = type;")
+                               hardening_live_type(v, "type")
+                               v.require_declaration("class_{c_name}")
+                               v.add("{res}->class = &class_{c_name};")
+                               v.add("((struct instance_{mtype.c_name}*){res})->value = NULL;")
+                               v.add("return {res};")
+                       end
+                       v.add("\}")
                        return
                else if mclass.name == "NativeArray" then
                        #Build instance struct
-                       self.header.add_decl("struct instance_{c_instance_name} \{")
+                       self.header.add_decl("struct instance_{c_name} \{")
                        self.header.add_decl("const struct type *type;")
                        self.header.add_decl("const struct class *class;")
                        # NativeArrays are just a instance header followed by a length and an array of values
@@ -738,9 +765,9 @@ class SeparateCompiler
                        v.add_decl("/* allocate {mtype} */")
                        v.add_decl("{mtype.ctype} NEW_{c_name}(int length, const struct type* type) \{")
                        var res = v.get_name("self")
-                       v.add_decl("struct instance_{c_instance_name} *{res};")
+                       v.add_decl("struct instance_{c_name} *{res};")
                        var mtype_elt = mtype.arguments.first
-                       v.add("{res} = nit_alloc(sizeof(struct instance_{c_instance_name}) + length*sizeof({mtype_elt.ctype}));")
+                       v.add("{res} = nit_alloc(sizeof(struct instance_{c_name}) + length*sizeof({mtype_elt.ctype}));")
                        v.add("{res}->type = type;")
                        hardening_live_type(v, "type")
                        v.require_declaration("class_{c_name}")
@@ -749,6 +776,30 @@ class SeparateCompiler
                        v.add("return (val*){res};")
                        v.add("\}")
                        return
+               else if mtype.mclass.kind == extern_kind and mtype.mclass.name != "NativeString" then
+                       # Is an extern class (other than Pointer and NativeString)
+                       # Pointer is caught in a previous `if`, and NativeString is internal
+
+                       var pointer_type = mainmodule.pointer_type
+
+                       self.provide_declaration("NEW_{c_name}", "{mtype.ctype} NEW_{c_name}(const struct type* type);")
+                       v.add_decl("/* allocate {mtype} */")
+                       v.add_decl("{mtype.ctype} NEW_{c_name}(const struct type* type) \{")
+                       if is_dead then
+                               v.add_abort("{mclass} is DEAD")
+                       else
+                               var res = v.new_named_var(mtype, "self")
+                               res.is_exact = true
+                               v.add("{res} = nit_alloc(sizeof(struct instance_{pointer_type.c_name}));")
+                               v.add("{res}->type = type;")
+                               hardening_live_type(v, "type")
+                               v.require_declaration("class_{c_name}")
+                               v.add("{res}->class = &class_{c_name};")
+                               v.add("((struct instance_{pointer_type.c_name}*){res})->value = NULL;")
+                               v.add("return {res};")
+                       end
+                       v.add("\}")
+                       return
                end
 
                #Build NEW
@@ -909,6 +960,21 @@ class SeparateCompilerVisitor
                end
        end
 
+       redef fun unbox_signature_extern(m, args)
+       do
+               var msignature = m.msignature.resolve_for(m.mclassdef.bound_mtype, m.mclassdef.bound_mtype, m.mclassdef.mmodule, true)
+               if not m.mproperty.is_init and m.is_extern then
+                       args.first = self.unbox_extern(args.first, m.mclassdef.mclass.mclass_type)
+               end
+               for i in [0..msignature.arity[ do
+                       var t = msignature.mparameters[i].mtype
+                       if i == msignature.vararg_rank then
+                               t = args[i+1].mtype
+                       end
+                       if m.is_extern then args[i+1] = self.unbox_extern(args[i+1], t)
+               end
+       end
+
        redef fun autobox(value, mtype)
        do
                if value.mtype == mtype then
@@ -916,9 +982,12 @@ class SeparateCompilerVisitor
                else if value.mtype.ctype == "val*" and mtype.ctype == "val*" then
                        return value
                else if value.mtype.ctype == "val*" then
-                       return self.new_expr("((struct instance_{mtype.c_instance_name}*){value})->value; /* autounbox from {value.mtype} to {mtype} */", mtype)
+                       return self.new_expr("((struct instance_{mtype.c_name}*){value})->value; /* autounbox from {value.mtype} to {mtype} */", mtype)
                else if mtype.ctype == "val*" then
                        var valtype = value.mtype.as(MClassType)
+                       if mtype isa MClassType and mtype.mclass.kind == extern_kind and mtype.mclass.name != "NativeString" then
+                               valtype = compiler.mainmodule.pointer_type
+                       end
                        var res = self.new_var(mtype)
                        if compiler.runtime_type_analysis != null and not compiler.runtime_type_analysis.live_types.has(valtype) then
                                self.add("/*no autobox from {value.mtype} to {mtype}: {value.mtype} is not live! */")
@@ -941,6 +1010,42 @@ class SeparateCompilerVisitor
                end
        end
 
+       redef fun unbox_extern(value, mtype)
+       do
+               if mtype isa MClassType and mtype.mclass.kind == extern_kind and
+                  mtype.mclass.name != "NativeString" then
+                       var pointer_type = compiler.mainmodule.pointer_type
+                       var res = self.new_var_extern(mtype)
+                       self.add "{res} = ((struct instance_{pointer_type.c_name}*){value})->value; /* unboxing {value.mtype} */"
+                       return res
+               else
+                       return value
+               end
+       end
+
+       redef fun box_extern(value, mtype)
+       do
+               if mtype isa MClassType and mtype.mclass.kind == extern_kind and
+                  mtype.mclass.name != "NativeString" then
+                       var valtype = compiler.mainmodule.pointer_type
+                       var res = self.new_var(mtype)
+                       if compiler.runtime_type_analysis != null and not compiler.runtime_type_analysis.live_types.has(value.mtype.as(MClassType)) then
+                               self.add("/*no boxing of {value.mtype}: {value.mtype} is not live! */")
+                               self.add("PRINT_ERROR(\"Dead code executed!\\n\"); show_backtrace(1);")
+                               return res
+                       end
+                       self.require_declaration("BOX_{valtype.c_name}")
+                       self.add("{res} = BOX_{valtype.c_name}({value}); /* boxing {value.mtype} */")
+                       self.require_declaration("type_{mtype.c_name}")
+                       self.add("{res}->type = &type_{mtype.c_name};")
+                       self.require_declaration("class_{mtype.c_name}")
+                       self.add("{res}->class = &class_{mtype.c_name};")
+                       return res
+               else
+                       return value
+               end
+       end
+
        # Return a C expression returning the runtime type structure of the value
        # The point of the method is to works also with primitives types.
        fun type_info(value: RuntimeVariable): String
@@ -957,14 +1062,12 @@ class SeparateCompilerVisitor
        redef fun compile_callsite(callsite, args)
        do
                var rta = compiler.runtime_type_analysis
-               var recv = args.first.mtype
                var mmethod = callsite.mproperty
                # TODO: Inlining of new-style constructors
                if compiler.modelbuilder.toolcontext.opt_direct_call_monomorph.value and rta != null and not mmethod.is_root_init then
                        var tgs = rta.live_targets(callsite)
                        if tgs.length == 1 then
                                # DIRECT CALL
-                               self.varargize(mmethod.intro, mmethod.intro.msignature.as(not null), args)
                                var res0 = before_send(mmethod, args)
                                var res = call(tgs.first, tgs.first.mclassdef.bound_mtype, args)
                                if res0 != null then
@@ -980,8 +1083,6 @@ class SeparateCompilerVisitor
        end
        redef fun send(mmethod, arguments)
        do
-               self.varargize(mmethod.intro, mmethod.intro.msignature.as(not null), arguments)
-
                if arguments.first.mcasttype.ctype != "val*" then
                        # In order to shortcut the primitive, we need to find the most specific method
                        # Howverr, because of performance (no flattening), we always work on the realmainmodule
@@ -995,13 +1096,13 @@ class SeparateCompilerVisitor
                return table_send(mmethod, arguments, mmethod.const_color)
        end
 
-       # Handel common special cases before doing the effective method invocation
+       # Handle common special cases before doing the effective method invocation
        # This methods handle the `==` and `!=` methods and the case of the null receiver.
        # Note: a { is open in the generated C, that enclose and protect the effective method invocation.
        # Client must not forget to close the } after them.
        #
        # The value returned is the result of the common special cases.
-       # If not null, client must compine it with the result of their own effective method invocation.
+       # If not null, client must compile it with the result of their own effective method invocation.
        #
        # If `before_send` can shortcut the whole message sending, a dummy `if(0){`
        # is generated to cancel the effective method invocation that will follow
@@ -1011,10 +1112,10 @@ class SeparateCompilerVisitor
                var res: nullable RuntimeVariable = null
                var recv = arguments.first
                var consider_null = not self.compiler.modelbuilder.toolcontext.opt_no_check_null.value or mmethod.name == "==" or mmethod.name == "!="
-               var maybenull = recv.mcasttype isa MNullableType and consider_null
+               var maybenull = (recv.mcasttype isa MNullableType or recv.mcasttype isa MNullType) and consider_null
                if maybenull then
                        self.add("if ({recv} == NULL) \{")
-                       if mmethod.name == "==" then
+                       if mmethod.name == "==" or mmethod.name == "is_same_instance" then
                                res = self.new_var(bool_type)
                                var arg = arguments[1]
                                if arg.mcasttype isa MNullableType then
@@ -1041,15 +1142,15 @@ class SeparateCompilerVisitor
                else
                        self.add("\{")
                end
-               if not self.compiler.modelbuilder.toolcontext.opt_no_shortcut_equate.value and (mmethod.name == "==" or mmethod.name == "!=") then
-                       if res == null then res = self.new_var(bool_type)
-                       # Recv is not null, thus is arg is, it is easy to conclude (and respect the invariants)
+               if not self.compiler.modelbuilder.toolcontext.opt_no_shortcut_equate.value and (mmethod.name == "==" or mmethod.name == "!=" or mmethod.name == "is_same_instance") then
+                       # Recv is not null, thus if arg is, it is easy to conclude (and respect the invariants)
                        var arg = arguments[1]
                        if arg.mcasttype isa MNullType then
-                               if mmethod.name == "==" then
-                                       self.add("{res} = 0; /* arg is null but recv is not */")
-                               else
+                               if res == null then res = self.new_var(bool_type)
+                               if mmethod.name == "!=" then
                                        self.add("{res} = 1; /* arg is null and recv is not */")
+                               else # `==` and `is_same_instance`
+                                       self.add("{res} = 0; /* arg is null but recv is not */")
                                end
                                self.add("\}") # closes the null case
                                self.add("if (0) \{") # what follow is useless, CC will drop it
@@ -1071,10 +1172,7 @@ class SeparateCompilerVisitor
                var res: nullable RuntimeVariable
                var msignature = mmethod.intro.msignature.resolve_for(mmethod.intro.mclassdef.bound_mtype, mmethod.intro.mclassdef.bound_mtype, mmethod.intro.mclassdef.mmodule, true)
                var ret = msignature.return_mtype
-               if mmethod.is_new then
-                       ret = arguments.first.mtype
-                       res = self.new_var(ret)
-               else if ret == null then
+               if ret == null then
                        res = null
                else
                        res = self.new_var(ret)
@@ -1125,10 +1223,7 @@ class SeparateCompilerVisitor
 
                var res: nullable RuntimeVariable
                var ret = mmethoddef.msignature.return_mtype
-               if mmethoddef.mproperty.is_new then
-                       ret = arguments.first.mtype
-                       res = self.new_var(ret)
-               else if ret == null then
+               if ret == null then
                        res = null
                else
                        ret = ret.resolve_for(mmethoddef.mclassdef.bound_mtype, mmethoddef.mclassdef.bound_mtype, mmethoddef.mclassdef.mmodule, true)
@@ -1307,7 +1402,7 @@ class SeparateCompilerVisitor
                                # The attribute is primitive, thus we store it in a box
                                # The trick is to create the box the first time then resuse the box
                                self.add("if ({attr} != NULL) \{")
-                               self.add("((struct instance_{mtype.c_instance_name}*){attr})->value = {value}; /* {a} on {recv.inspect} */")
+                               self.add("((struct instance_{mtype.c_name}*){attr})->value = {value}; /* {a} on {recv.inspect} */")
                                self.add("\} else \{")
                                value = self.autobox(value, self.object_type.as_nullable)
                                self.add("{attr} = {value}; /* {a} on {recv.inspect} */")
@@ -1481,7 +1576,8 @@ class SeparateCompilerVisitor
                self.add_decl("const char* {res};")
                if value.mtype.ctype == "val*" then
                        self.add "{res} = {value} == NULL ? \"null\" : {value}->type->name;"
-               else if value.mtype isa MClassType and value.mtype.as(MClassType).mclass.kind == extern_kind then
+               else if value.mtype isa MClassType and value.mtype.as(MClassType).mclass.kind == extern_kind and
+                       value.mtype.as(MClassType).name != "NativeString" then
                        self.add "{res} = \"{value.mtype.as(MClassType).mclass}\";"
                else
                        self.require_declaration("type_{value.mtype.c_name}")
@@ -1564,12 +1660,12 @@ class SeparateCompilerVisitor
                        end
                end
                if primitive != null then
-                       test.add("((struct instance_{primitive.c_instance_name}*){value1})->value == ((struct instance_{primitive.c_instance_name}*){value2})->value")
+                       test.add("((struct instance_{primitive.c_name}*){value1})->value == ((struct instance_{primitive.c_name}*){value2})->value")
                else if can_be_primitive(value1) and can_be_primitive(value2) then
                        test.add("{value1}->class == {value2}->class")
                        var s = new Array[String]
                        for t, v in self.compiler.box_kinds do
-                               s.add "({value1}->class->box_kind == {v} && ((struct instance_{t.c_instance_name}*){value1})->value == ((struct instance_{t.c_instance_name}*){value2})->value)"
+                               s.add "({value1}->class->box_kind == {v} && ((struct instance_{t.c_name}*){value1})->value == ((struct instance_{t.c_name}*){value2})->value)"
                        end
                        test.add("({s.join(" || ")})")
                else
@@ -1635,7 +1731,7 @@ class SeparateCompilerVisitor
        do
                var elttype = arguments.first.mtype
                var nclass = self.get_class("NativeArray")
-               var recv = "((struct instance_{nclass.c_instance_name}*){arguments[0]})->values"
+               var recv = "((struct instance_{nclass.c_name}*){arguments[0]})->values"
                if pname == "[]" then
                        self.ret(self.new_expr("{recv}[{arguments[1]}]", ret_type.as(not null)))
                        return
@@ -1643,10 +1739,10 @@ class SeparateCompilerVisitor
                        self.add("{recv}[{arguments[1]}]={arguments[2]};")
                        return
                else if pname == "length" then
-                       self.ret(self.new_expr("((struct instance_{nclass.c_instance_name}*){arguments[0]})->length", ret_type.as(not null)))
+                       self.ret(self.new_expr("((struct instance_{nclass.c_name}*){arguments[0]})->length", ret_type.as(not null)))
                        return
                else if pname == "copy_to" then
-                       var recv1 = "((struct instance_{nclass.c_instance_name}*){arguments[1]})->values"
+                       var recv1 = "((struct instance_{nclass.c_name}*){arguments[1]})->values"
                        self.add("memmove({recv1}, {recv}, {arguments[2]}*sizeof({elttype.ctype}));")
                        return
                end
@@ -1655,7 +1751,7 @@ class SeparateCompilerVisitor
        redef fun calloc_array(ret_type, arguments)
        do
                var mclass = self.get_class("ArrayCapable")
-               var ft = mclass.mclass_type.arguments.first.as(MParameterType)
+               var ft = mclass.mparameters.first
                var res = self.native_array_instance(ft, arguments[1])
                self.ret(res)
        end
@@ -1720,9 +1816,6 @@ class SeparateRuntimeFunction
                var ret = msignature.return_mtype
                if ret != null then
                        sig.append("{ret.ctype} ")
-               else if mmethoddef.mproperty.is_new then
-                       ret = recv
-                       sig.append("{ret.ctype} ")
                else
                        sig.append("void ")
                end
@@ -1797,9 +1890,6 @@ class VirtualRuntimeFunction
                var ret = msignature.return_mtype
                if ret != null then
                        sig.append("{ret.ctype} ")
-               else if mmethoddef.mproperty.is_new then
-                       ret = recv
-                       sig.append("{ret.ctype} ")
                else
                        sig.append("void ")
                end
@@ -1851,23 +1941,6 @@ end
 
 redef class MType
        fun const_color: String do return "COLOR_{c_name}"
-
-       # C name of the instance type to use
-       fun c_instance_name: String do return c_name
-end
-
-redef class MClassType
-       redef fun c_instance_name do return mclass.c_instance_name
-end
-
-redef class MClass
-       # Extern classes use the C instance of kernel::Pointer
-       fun c_instance_name: String
-       do
-               if kind == extern_kind then
-                       return "kernel__Pointer"
-               else return c_name
-       end
 end
 
 interface PropertyLayoutElement end
@@ -1881,3 +1954,13 @@ redef class MPropDef
        super PropertyLayoutElement
        fun const_color: String do return "COLOR_{c_name}"
 end
+
+redef class AMethPropdef
+       # The semi-global compilation does not support inlining calls to extern news
+       redef fun can_inline
+       do
+               var m = mpropdef
+               if m != null and m.mproperty.is_init and m.is_extern then return false
+               return super
+       end
+end