X-Git-Url: http://nitlanguage.org diff --git a/src/global_compiler.nit b/src/global_compiler.nit index 9e79281..2196071 100644 --- a/src/global_compiler.nit +++ b/src/global_compiler.nit @@ -61,6 +61,9 @@ redef class ModelBuilder var compiler = new GlobalCompiler(mainmodule, self, runtime_type_analysis) compiler.compile_header + if mainmodule.model.get_mclasses_by_name("Pointer") != null then + runtime_type_analysis.live_types.add(mainmodule.pointer_type) + end for t in runtime_type_analysis.live_types do compiler.declare_runtimeclass(t) end @@ -71,12 +74,16 @@ redef class ModelBuilder for t in runtime_type_analysis.live_types do if t.ctype == "val*" then compiler.generate_init_instance(t) + if t.mclass.kind == extern_kind then + compiler.generate_box_instance(t) + end else compiler.generate_box_instance(t) end end # The main function of the C + compiler.compile_nitni_global_ref_functions compiler.compile_main_function # Compile until all runtime_functions are visited @@ -115,7 +122,7 @@ class GlobalCompiler self.runtime_type_analysis = runtime_type_analysis self.live_primitive_types = new Array[MClassType] for t in runtime_type_analysis.live_types do - if t.ctype != "val*" then + if t.ctype != "val*" or t.mclass.name == "Pointer" then self.live_primitive_types.add(t) end end @@ -192,11 +199,11 @@ class GlobalCompiler v.add_decl("{mtype.arguments.first.ctype} values[1];") end - if mtype.ctype != "val*" then + if mtype.ctype_extern != "val*" then # Is the Nit type is native then the struct is a box with two fields: # * the `classid` to be polymorph # * the `value` that contains the native value. - v.add_decl("{mtype.ctype} value;") + v.add_decl("{mtype.ctype_extern} value;") end # Collect all attributes and associate them a field in the structure. @@ -243,6 +250,7 @@ class GlobalCompiler v.add("{res}->classid = {self.classid(mtype)};") self.generate_init_attr(v, res, mtype) + v.set_finalizer res v.add("return {res};") v.add("\}") end @@ -250,7 +258,6 @@ class GlobalCompiler fun generate_box_instance(mtype: MClassType) do assert self.runtime_type_analysis.live_types.has(mtype) - assert mtype.ctype != "val*" var v = self.new_visitor self.header.add_decl("val* BOX_{mtype.c_name}({mtype.ctype});") @@ -269,7 +276,14 @@ class GlobalCompiler redef fun compile_nitni_structs do - self.header.add_decl("struct nitni_instance \{ val *value; \};") + self.header.add_decl """ +struct nitni_instance \{ + struct nitni_instance *next, + *prev; /* adjacent global references in global list */ + int count; /* number of time this global reference has been marked */ + val *value; +\};""" + super end end @@ -309,6 +323,34 @@ class GlobalCompilerVisitor 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 res = self.new_var_extern(mtype) + self.add "{res} = ((struct {mtype.c_name}*){value})->value; /* unboxing {value.mtype} */" + return res + else + return value + end + end + + redef fun box_extern(value, mtype) + do + if not mtype isa MClassType or mtype.mclass.kind != extern_kind or + mtype.mclass.name == "NativeString" then return value + + var valtype = value.mtype.as(MClassType) + 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.add("{res} = BOX_{valtype.c_name}({value}); /* boxing {value.mtype} */") + return res + end + # The runtime types that are acceptable for a given receiver. fun collect_types(recv: RuntimeVariable): Array[MClassType] do @@ -348,7 +390,7 @@ class GlobalCompilerVisitor return else if pname == "copy_to" then var recv1 = "((struct {arguments[1].mcasttype.c_name}*){arguments[1]})->values" - self.add("memcpy({recv1},{recv},{arguments[2]}*sizeof({elttype.ctype}));") + self.add("memmove({recv1},{recv},{arguments[2]}*sizeof({elttype.ctype}));") return end end @@ -392,7 +434,7 @@ class GlobalCompilerVisitor if res != null then self.assign(res, res2.as(not null)) return res end - var consider_null = not self.compiler.modelbuilder.toolcontext.opt_no_check_other.value or m.name == "==" or m.name == "!=" + var consider_null = not self.compiler.modelbuilder.toolcontext.opt_no_check_null.value or m.name == "==" or m.name == "!=" if args.first.mcasttype isa MNullableType or args.first.mcasttype isa MNullType and consider_null then # The reciever is potentially null, so we have to 3 cases: ==, != or NullPointerException self.add("if ({args.first} == NULL) \{ /* Special null case */") @@ -471,7 +513,8 @@ class GlobalCompilerVisitor do check_valid_reciever(recvtype) #debug("call {m} on {recvtype} on {args.first}:{args.first.mtype}") - if m.mclassdef.mclass.name == "Object" and recvtype.ctype == "val*" then + if m.mproperty.is_toplevel then + # Do not customize top-level methods recvtype = m.mclassdef.bound_mtype end return recvtype @@ -497,6 +540,7 @@ class GlobalCompilerVisitor do var recv_type = get_recvtype(m, recvtype, args) var recv = get_recv(recv_type, args) + if m.is_extern then recv = unbox_extern(recv, recv_type) var new_args = args.to_a self.varargize(m, m.msignature.as(not null), new_args) new_args.first = recv @@ -509,6 +553,7 @@ class GlobalCompilerVisitor do var recv_type = get_recvtype(m, recvtype, args) var recv = get_recv(recv_type, args) + if m.is_extern then recv = unbox_extern(recv, recv_type) var new_args = args.to_a new_args.first = recv return finalize_call(m, recv_type, new_args) @@ -582,6 +627,19 @@ class GlobalCompilerVisitor end end + redef fun unbox_signature_extern(m, args) + do + var recv = args.first + for i in [0..m.msignature.arity[ do + var t = m.msignature.mparameters[i].mtype + if i == m.msignature.vararg_rank then + t = args[i+1].mtype + end + t = self.resolve_for(t, recv) + if m.is_extern then args[i+1] = self.unbox_extern(args[i+1], t) + end + end + # FIXME: this is currently buggy since recv is not exact redef fun vararg_instance(mpropdef, recv, varargs, elttype) do @@ -667,7 +725,7 @@ class GlobalCompilerVisitor var ta = a.intro.static_mtype.as(not null) ta = self.resolve_for(ta, recv2) var res2 = self.new_expr("((struct {t.c_name}*){recv})->{a.intro.c_name}", ta) - if not ta isa MNullableType and not self.compiler.modelbuilder.toolcontext.opt_no_check_other.value then + if not ta isa MNullableType and not self.compiler.modelbuilder.toolcontext.opt_no_check_attr_isset.value then if ta.ctype == "val*" then self.add("if ({res2} == NULL) \{") self.add_abort("Uninitialized attribute {a.name}") @@ -836,6 +894,15 @@ class GlobalCompilerVisitor if not t.is_subtype(self.compiler.mainmodule, null, value2.mcasttype) then continue s.add "({value1}->classid == {self.compiler.classid(t)} && ((struct {t.c_name}*){value1})->value == ((struct {t.c_name}*){value2})->value)" end + + if self.compiler.mainmodule.model.get_mclasses_by_name("Pointer") != null then + var pointer_type = self.compiler.mainmodule.pointer_type + if value1.mcasttype.is_subtype(self.compiler.mainmodule, null, pointer_type) or + value2.mcasttype.is_subtype(self.compiler.mainmodule, null, pointer_type) then + s.add "(((struct {pointer_type.c_name}*){value1})->value == ((struct {pointer_type.c_name}*){value2})->value)" + end + end + if s.is_empty then self.add("{res} = {value1} == {value2};") else