compiler: add `Platform::supports_linker_script`
[nit.git] / src / compiler / separate_compiler.nit
index 33e8d8a..2d98fb6 100644 (file)
@@ -29,6 +29,9 @@ redef class ToolContext
        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 = new OptionBool("Always call == in a polymorphic way", "--no-shortcut-equal")
+       # --colors-are-symbols
+       var opt_colors_are_symbols = new OptionBool("Store colors as symbols (faster)", "--colors-are-symbols")
+
        # --inline-coloring-numbers
        var opt_inline_coloring_numbers = new OptionBool("Inline colors and ids (semi-global)", "--inline-coloring-numbers")
        # --inline-some-methods
@@ -50,7 +53,7 @@ redef class ToolContext
                self.option_context.add_option(self.opt_separate)
                self.option_context.add_option(self.opt_no_inline_intern)
                self.option_context.add_option(self.opt_no_union_attribute)
-               self.option_context.add_option(self.opt_no_shortcut_equate)
+               self.option_context.add_option(self.opt_no_shortcut_equate, opt_colors_are_symbols)
                self.option_context.add_option(self.opt_inline_coloring_numbers, opt_inline_some_methods, opt_direct_call_monomorph, opt_skip_dead_methods, opt_semi_global)
                self.option_context.add_option(self.opt_colo_dead_methods)
                self.option_context.add_option(self.opt_tables_metrics)
@@ -90,12 +93,55 @@ redef class ModelBuilder
                self.toolcontext.info("*** GENERATING C ***", 1)
 
                var compiler = new SeparateCompiler(mainmodule, self, runtime_type_analysis)
+               compiler.do_compilation
+               compiler.display_stats
+
+               var time1 = get_time
+               self.toolcontext.info("*** END GENERATING C: {time1-time0} ***", 2)
+               write_and_make(compiler)
+       end
+
+       # Count number of invocations by VFT
+       private var nb_invok_by_tables = 0
+       # Count number of invocations by direct call
+       private var nb_invok_by_direct = 0
+       # Count number of invocations by inlining
+       private var nb_invok_by_inline = 0
+end
+
+# Singleton that store the knowledge about the separate compilation process
+class SeparateCompiler
+       super AbstractCompiler
+
+       redef type VISITOR: SeparateCompilerVisitor
+
+       # The result of the RTA (used to know live types and methods)
+       var runtime_type_analysis: nullable RapidTypeAnalysis
+
+       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] 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 do
+               var file = new_file("nit.common")
+               self.header = new CodeWriter(file)
+               self.compile_box_kinds
+       end
+
+       redef fun do_compilation
+       do
+               var compiler = self
                compiler.compile_header
 
                var c_name = mainmodule.c_name
 
                # compile class structures
-               self.toolcontext.info("Property coloring", 2)
+               modelbuilder.toolcontext.info("Property coloring", 2)
                compiler.new_file("{c_name}.classes")
                compiler.do_property_coloring
                for m in mainmodule.in_importation.greaters do
@@ -113,14 +159,22 @@ redef class ModelBuilder
 
                # compile methods
                for m in mainmodule.in_importation.greaters do
-                       self.toolcontext.info("Generate C for module {m.full_name}", 2)
+                       modelbuilder.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)
+               modelbuilder.toolcontext.info("Type coloring", 2)
                compiler.new_file("{c_name}.types")
+               compiler.compile_types
+       end
+
+       # Color and compile type structures and cast information
+       fun compile_types
+       do
+               var compiler = self
+
                var mtypes = compiler.do_type_coloring
                for t in mtypes do
                        compiler.compile_type_to_c(t)
@@ -131,43 +185,6 @@ redef class ModelBuilder
                        compiler.compile_type_to_c(t)
                end
 
-               compiler.display_stats
-
-               var time1 = get_time
-               self.toolcontext.info("*** END GENERATING C: {time1-time0} ***", 2)
-               write_and_make(compiler)
-       end
-
-       # Count number of invocations by VFT
-       private var nb_invok_by_tables = 0
-       # Count number of invocations by direct call
-       private var nb_invok_by_direct = 0
-       # Count number of invocations by inlining
-       private var nb_invok_by_inline = 0
-end
-
-# Singleton that store the knowledge about the separate compilation process
-class SeparateCompiler
-       super AbstractCompiler
-
-       redef type VISITOR: SeparateCompilerVisitor
-
-       # The result of the RTA (used to know live types and methods)
-       var runtime_type_analysis: nullable RapidTypeAnalysis
-
-       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] 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 do
-               var file = new_file("nit.common")
-               self.header = new CodeWriter(file)
-               self.compile_box_kinds
        end
 
        redef fun compile_header_structs do
@@ -238,27 +255,21 @@ class SeparateCompiler
 
        fun compile_color_const(v: SeparateCompilerVisitor, m: Object, color: Int) do
                if color_consts_done.has(m) then return
-               if m isa MProperty then
+               if m isa MEntity then
                        if modelbuilder.toolcontext.opt_inline_coloring_numbers.value then
                                self.provide_declaration(m.const_color, "#define {m.const_color} {color}")
-                       else
+                       else if not modelbuilder.toolcontext.opt_colors_are_symbols.value or not v.compiler.target_platform.supports_linker_script then
                                self.provide_declaration(m.const_color, "extern const int {m.const_color};")
                                v.add("const int {m.const_color} = {color};")
-                       end
-               else if m isa MPropDef then
-                       if modelbuilder.toolcontext.opt_inline_coloring_numbers.value then
-                               self.provide_declaration(m.const_color, "#define {m.const_color} {color}")
                        else
-                               self.provide_declaration(m.const_color, "extern const int {m.const_color};")
-                               v.add("const int {m.const_color} = {color};")
-                       end
-               else if m isa MType then
-                       if modelbuilder.toolcontext.opt_inline_coloring_numbers.value then
-                               self.provide_declaration(m.const_color, "#define {m.const_color} {color}")
-                       else
-                               self.provide_declaration(m.const_color, "extern const int {m.const_color};")
-                               v.add("const int {m.const_color} = {color};")
+                               # The color 'C' is the ``address'' of a false static variable 'XC'
+                               self.provide_declaration(m.const_color, "#define {m.const_color} ((long)&X{m.const_color})\nextern const void X{m.const_color};")
+                               if color == -1 then color = 0 # Symbols cannot be negative, so just use 0 for dead things
+                               # Teach the linker that the address of 'XC' is `color`.
+                               linker_script.add("X{m.const_color} = {color};")
                        end
+               else
+                       abort
                end
                color_consts_done.add(m)
        end
@@ -1063,8 +1074,8 @@ class SeparateCompilerVisitor
        do
                var rta = compiler.runtime_type_analysis
                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
+               # TODO: Inlining of new-style constructors with initializers
+               if compiler.modelbuilder.toolcontext.opt_direct_call_monomorph.value and rta != null and callsite.mpropdef.initializers.is_empty then
                        var tgs = rta.live_targets(callsite)
                        if tgs.length == 1 then
                                # DIRECT CALL
@@ -1939,20 +1950,18 @@ class VirtualRuntimeFunction
        redef fun call(v, arguments) do abort
 end
 
-redef class MType
-       fun const_color: String do return "COLOR_{c_name}"
+redef class MEntity
+       var const_color: String is lazy do return "COLOR_{c_name}"
 end
 
 interface PropertyLayoutElement end
 
 redef class MProperty
        super PropertyLayoutElement
-       fun const_color: String do return "COLOR_{c_name}"
 end
 
 redef class MPropDef
        super PropertyLayoutElement
-       fun const_color: String do return "COLOR_{c_name}"
 end
 
 redef class AMethPropdef