X-Git-Url: http://nitlanguage.org diff --git a/src/separate_compiler.nit b/src/separate_compiler.nit index ea4e00f..981c0d8 100644 --- a/src/separate_compiler.nit +++ b/src/separate_compiler.nit @@ -18,6 +18,8 @@ module separate_compiler import abstract_compiler import layout_builders import rapid_type_analysis +import collect_super_sends +import compiler_ffi # Add separate compiler specific options redef class ToolContext @@ -56,7 +58,7 @@ redef class ToolContext end redef class ModelBuilder - fun run_separate_compiler(mainmodule: MModule, runtime_type_analysis: RapidTypeAnalysis) + fun run_separate_compiler(mainmodule: MModule, runtime_type_analysis: nullable RapidTypeAnalysis) do var time0 = get_time self.toolcontext.info("*** GENERATING C ***", 1) @@ -109,7 +111,7 @@ class SeparateCompiler redef type VISITOR: SeparateCompilerVisitor # The result of the RTA (used to know live types and methods) - var runtime_type_analysis: RapidTypeAnalysis + var runtime_type_analysis: nullable RapidTypeAnalysis private var undead_types: Set[MType] = new HashSet[MType] private var partial_types: Set[MType] = new HashSet[MType] @@ -120,7 +122,7 @@ class SeparateCompiler protected var method_layout: nullable Layout[PropertyLayoutElement] protected var attr_layout: nullable Layout[MAttribute] - init(mainmodule: MModule, mmbuilder: ModelBuilder, runtime_type_analysis: RapidTypeAnalysis) do + init(mainmodule: MModule, mmbuilder: ModelBuilder, runtime_type_analysis: nullable RapidTypeAnalysis) do super(mainmodule, mmbuilder) var file = new_file("nit.common") self.header = new CodeWriter(file) @@ -270,7 +272,12 @@ class SeparateCompiler end # lookup super calls and add it to the list of mmethods to build layout with - var super_calls = runtime_type_analysis.live_super_sends + var super_calls + if runtime_type_analysis != null then + super_calls = runtime_type_analysis.live_super_sends + else + super_calls = modelbuilder.collect_super_sends + end for mmethoddef in super_calls do var mclass = mmethoddef.mclassdef.mclass mmethods[mclass].add(mmethoddef) @@ -722,7 +729,7 @@ class SeparateCompiler var attrs = self.attr_tables[mclass] var v = new_visitor - var is_dead = not runtime_type_analysis.live_classes.has(mclass) and mtype.ctype == "val*" and mclass.name != "NativeArray" + var is_dead = runtime_type_analysis != null and not runtime_type_analysis.live_classes.has(mclass) and mtype.ctype == "val*" and mclass.name != "NativeArray" v.add_decl("/* runtime class {c_name} */") @@ -814,8 +821,6 @@ class SeparateCompiler v.add("return {res};") end v.add("\}") - - generate_check_init_instance(mtype) end # Add a dynamic test to ensure that the type referenced by `t` is a live type @@ -831,24 +836,6 @@ class SeparateCompiler v.add("\}") end - redef fun generate_check_init_instance(mtype) - do - if self.modelbuilder.toolcontext.opt_no_check_initialization.value then return - - var v = self.new_visitor - var c_name = mtype.mclass.c_name - var res = new RuntimeVariable("self", mtype, mtype) - self.provide_declaration("CHECK_NEW_{c_name}", "void CHECK_NEW_{c_name}({mtype.ctype});") - v.add_decl("/* allocate {mtype} */") - v.add_decl("void CHECK_NEW_{c_name}({mtype.ctype} {res}) \{") - if runtime_type_analysis.live_classes.has(mtype.mclass) then - self.generate_check_attr(v, res, mtype) - else - v.add_abort("{mtype.mclass} is DEAD") - end - v.add("\}") - end - redef fun new_visitor do return new SeparateCompilerVisitor(self) # Stats @@ -908,6 +895,17 @@ class SeparateCompiler end print "\t{total}\t{holes}" end + + redef fun compile_nitni_structs + do + self.header.add_decl("struct nitni_instance \{struct instance *value;\};") + end + + redef fun finalize_ffi_for_module(nmodule) + do + self.mainmodule = nmodule.mmodule.as(not null) + super + end end # A visitor on the AST of property definition that generate the C code of a separate compilation process. @@ -943,13 +941,15 @@ class SeparateCompilerVisitor else if mtype.ctype == "val*" then var valtype = value.mtype.as(MClassType) var res = self.new_var(mtype) - if not compiler.runtime_type_analysis.live_types.has(valtype) then + 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! */") self.add("printf(\"Dead code executed!\\n\"); show_backtrace(1);") return res end self.add("{res} = BOX_{valtype.c_name}({value}); /* autobox from {value.mtype} to {mtype} */") return res + else if value.mtype.cname_blind == "void*" and mtype.cname_blind == "void*" then + return value else # Bad things will appen! var res = self.new_var(mtype) @@ -974,11 +974,7 @@ class SeparateCompilerVisitor redef fun send(mmethod, arguments) do self.varargize(mmethod.intro, mmethod.intro.msignature.as(not null), arguments) - return table_send(mmethod, arguments, mmethod.const_color) - end - private fun table_send(mmethod: MMethod, arguments: Array[RuntimeVariable], const_color: String): nullable RuntimeVariable - do 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 @@ -989,6 +985,11 @@ class SeparateCompilerVisitor return res end + return table_send(mmethod, arguments, mmethod.const_color) + end + + private fun table_send(mmethod: MMethod, arguments: Array[RuntimeVariable], const_color: String): nullable RuntimeVariable + do 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 @@ -1128,6 +1129,15 @@ class SeparateCompilerVisitor redef fun supercall(m: MMethodDef, recvtype: MClassType, arguments: Array[RuntimeVariable]): nullable RuntimeVariable do + if arguments.first.mcasttype.ctype != "val*" then + # In order to shortcut the primitive, we need to find the most specific method + # However, because of performance (no flattening), we always work on the realmainmodule + var main = self.compiler.mainmodule + self.compiler.mainmodule = self.compiler.realmainmodule + var res = self.monomorphic_super_send(m, recvtype, arguments) + self.compiler.mainmodule = main + return res + end return table_send(m.mproperty, arguments, m.const_color) end @@ -1276,13 +1286,6 @@ class SeparateCompilerVisitor return self.new_expr("NEW_{mtype.mclass.c_name}(&type_{mtype.c_name})", mtype) end - redef fun check_init_instance(value, mtype) - do - if self.compiler.modelbuilder.toolcontext.opt_no_check_initialization.value then return - self.require_declaration("CHECK_NEW_{mtype.mclass.c_name}") - self.add("CHECK_NEW_{mtype.mclass.c_name}({value});") - end - redef fun type_test(value, mtype, tag) do self.add("/* {value.inspect} isa {mtype} */") @@ -1405,6 +1408,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 + self.add "{res} = \"{value.mtype.as(MClassType).mclass}\";" else self.require_declaration("type_{value.mtype.c_name}") self.add "{res} = type_{value.mtype.c_name}.name;" @@ -1531,7 +1536,6 @@ class SeparateCompilerVisitor self.add("((struct instance_{nclass.c_name}*){nat})->values[{i}] = (val*) {r};") end self.send(self.get_property("with_native", arrayclass.intro.bound_mtype), [res, nat, length]) - self.check_init_instance(res, arraytype) self.add("\}") return res end