X-Git-Url: http://nitlanguage.org diff --git a/src/separate_erasure_compiler.nit b/src/separate_erasure_compiler.nit index 126cde0..af3a43c 100644 --- a/src/separate_erasure_compiler.nit +++ b/src/separate_erasure_compiler.nit @@ -32,6 +32,15 @@ redef class ToolContext self.option_context.add_option(self.opt_erasure, self.opt_no_check_erasure_cast, opt_rta) end + redef fun process_options(args) + do + super + + if opt_no_check_all.value then + opt_no_check_erasure_cast.value = true + end + end + var erasure_compiler_phase = new ErasureCompilerPhase(self, null) end @@ -71,6 +80,7 @@ redef class ModelBuilder # The main function of the C compiler.new_file("{mainmodule.name}.main") + compiler.compile_nitni_global_ref_functions compiler.compile_main_function # compile methods @@ -209,7 +219,6 @@ class SeparateErasureCompiler 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] @@ -280,25 +289,42 @@ class SeparateErasureCompiler v.add_decl("\}") v.add_decl("\};") - 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 class *class;") - self.header.add_decl("{mtype.ctype} value;") - self.header.add_decl("\};") - end + if mtype.ctype != "val*" or mtype.mclass.name == "Pointer" then + #Build instance struct + self.header.add_decl("struct instance_{c_name} \{") + self.header.add_decl("const struct class *class;") + self.header.add_decl("{mtype.ctype} value;") + self.header.add_decl("\};") #Build BOX self.provide_declaration("BOX_{c_name}", "val* BOX_{c_name}({mtype.ctype});") 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("struct instance_{c_name}*res = nit_alloc(sizeof(struct instance_{c_name}));") v.require_declaration("class_{c_name}") v.add("res->class = &class_{c_name};") 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}();") + v.add_decl("/* allocate {mtype} */") + v.add_decl("{mtype.ctype} NEW_{c_name}() \{") + 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.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 @@ -322,6 +348,26 @@ class SeparateErasureCompiler v.add("return (val*){res};") v.add("\}") return + else if mtype.mclass.kind == extern_kind and mtype.mclass.name != "NativeString" then + var pointer_type = mainmodule.pointer_type + + self.provide_declaration("NEW_{c_name}", "{mtype.ctype} NEW_{c_name}();") + v.add_decl("/* allocate {mtype} */") + v.add_decl("{mtype.ctype} NEW_{c_name}() \{") + 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;") + 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 @@ -338,6 +384,7 @@ class SeparateErasureCompiler v.require_declaration("class_{c_name}") v.add("{res}->class = &class_{c_name};") self.generate_init_attr(v, res, mtype) + v.set_finalizer res v.add("return {res};") end v.add("\}") @@ -568,6 +615,40 @@ class SeparateErasureCompilerVisitor return res 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("class_{mtype.c_name}") + self.add("{res}->class = &class_{mtype.c_name};") + return res + else + return value + end + end + redef fun class_name_string(value) do var res = self.get_name("var_class_name")