X-Git-Url: http://nitlanguage.org diff --git a/src/compiler/separate_compiler.nit b/src/compiler/separate_compiler.nit index 8c400f9..2d98fb6 100644 --- a/src/compiler/separate_compiler.nit +++ b/src/compiler/separate_compiler.nit @@ -22,19 +22,22 @@ 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") + # --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: 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 +45,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 @@ -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,45 +93,7 @@ redef class ModelBuilder self.toolcontext.info("*** GENERATING C ***", 1) var compiler = new SeparateCompiler(mainmodule, self, runtime_type_analysis) - compiler.compile_header - - # compile class structures - self.toolcontext.info("Property coloring", 2) - compiler.new_file("{mainmodule.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 - compiler.compile_class_to_c(mclass) - end - end - - # The main function of the C - compiler.new_file("{mainmodule.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") - compiler.compile_module_to_c(m) - end - - # compile live & cast type structures - self.toolcontext.info("Type coloring", 2) - compiler.new_file("{mainmodule.name}.types") - var mtypes = compiler.do_type_coloring - for t in mtypes do - compiler.compile_type_to_c(t) - end - # compile remaining types structures (useless but needed for the symbol resolution at link-time) - for t in compiler.undead_types do - if mtypes.has(t) then continue - compiler.compile_type_to_c(t) - end - + compiler.do_compilation compiler.display_stats var time1 = get_time @@ -156,20 +121,72 @@ 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 + redef fun do_compilation + do + var compiler = self + compiler.compile_header + + var c_name = mainmodule.c_name + + # compile class structures + modelbuilder.toolcontext.info("Property coloring", 2) + 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 + compiler.compile_class_to_c(mclass) + end + end + + # The main function of the C + 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 + 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 + 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) + end + # compile remaining types structures (useless but needed for the symbol resolution at link-time) + for t in compiler.undead_types do + if mtypes.has(t) then continue + compiler.compile_type_to_c(t) + end + + end + redef fun compile_header_structs do self.header.add_decl("typedef void(*nitmethod_t)(void); /* general C type representing a Nit method. */") self.compile_header_attribute_structs @@ -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 @@ -418,13 +429,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 @@ -437,12 +447,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 @@ -963,7 +974,6 @@ class SeparateCompilerVisitor 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) - var recv = args.first if not m.mproperty.is_init and m.is_extern then args.first = self.unbox_extern(args.first, m.mclassdef.mclass.mclass_type) end @@ -1063,14 +1073,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 + # 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 - 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 @@ -1086,8 +1094,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 @@ -1117,10 +1123,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 @@ -1147,15 +1153,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 @@ -1177,10 +1183,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) @@ -1231,10 +1234,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) @@ -1827,9 +1827,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 @@ -1904,9 +1901,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 @@ -1956,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