X-Git-Url: http://nitlanguage.org diff --git a/src/compiler/separate_compiler.nit b/src/compiler/separate_compiler.nit index 085a36d..ff5f3ba 100644 --- a/src/compiler/separate_compiler.nit +++ b/src/compiler/separate_compiler.nit @@ -252,7 +252,8 @@ class SeparateCompiler do # Collect all bas box class # FIXME: this is not completely fine with a separate compilation scheme - for classname in ["Int", "Bool", "Char", "Float", "NativeString", "Pointer"] do + for classname in ["Int", "Bool", "Byte", "Char", "Float", "NativeString", + "Pointer", "Int8", "Int16", "UInt16", "Int32", "UInt32"] do var classes = self.mainmodule.model.get_mclasses_by_name(classname) if classes == null then continue assert classes.length == 1 else print classes.join(", ") @@ -625,6 +626,7 @@ class SeparateCompiler for cd in mmodule.mclassdefs do for pd in cd.mpropdefs do if not pd isa MMethodDef then continue + if pd.msignature == null then continue # Skip broken method var rta = runtime_type_analysis if modelbuilder.toolcontext.opt_skip_dead_methods.value and rta != null and not rta.live_methoddefs.has(pd) then continue #print "compile {pd} @ {cd} @ {mmodule}" @@ -768,7 +770,8 @@ class SeparateCompiler end v.add_decl("\},") else - v.add_decl("0, \{\}, /*DEAD TYPE*/") + # Use -1 to indicate dead type, the info is used by --hardening + v.add_decl("-1, \{\}, /*DEAD TYPE*/") end v.add_decl("\};") end @@ -817,12 +820,15 @@ class SeparateCompiler var v = new_visitor var rta = runtime_type_analysis - var is_dead = rta != null and not rta.live_classes.has(mclass) and not mtype.is_c_primitive and mclass.name != "NativeArray" and mclass.name != "Pointer" + var is_dead = rta != null and not rta.live_classes.has(mclass) + # While the class may be dead, some part of separately compiled code may use symbols associated to the class, so + # in order to compile and link correctly the C code, these symbols should be declared and defined. + var need_corpse = is_dead and mtype.is_c_primitive or mclass.kind == extern_kind or mclass.kind == enum_kind - v.add_decl("/* runtime class {c_name} */") + v.add_decl("/* runtime class {c_name}: {mclass.full_name} (dead={is_dead}; need_corpse={need_corpse})*/") # Build class vft - if not is_dead then + if not is_dead or need_corpse then self.provide_declaration("class_{c_name}", "extern const struct class class_{c_name};") v.add_decl("const struct class class_{c_name} = \{") v.add_decl("{self.box_kind_of(mclass)}, /* box_kind */") @@ -859,7 +865,8 @@ class SeparateCompiler self.header.add_decl("{mtype.ctype_extern} value;") self.header.add_decl("\};") - if not rta.live_types.has(mtype) and mtype.mclass.name != "Pointer" then return + # Pointer is needed by extern types, live or not + if is_dead and mtype.mclass.name != "Pointer" then return #Build BOX self.provide_declaration("BOX_{c_name}", "val* BOX_{c_name}({mtype.ctype_extern});") @@ -875,6 +882,7 @@ class SeparateCompiler v.add("return (val*)res;") v.add("\}") + # A Pointer class also need its constructor if mtype.mclass.name != "Pointer" then return v = new_visitor @@ -929,7 +937,7 @@ class SeparateCompiler var pointer_type = mainmodule.pointer_type self.provide_declaration("NEW_{c_name}", "{mtype.ctype} NEW_{c_name}(const struct type* type);") - v.add_decl("/* allocate {mtype} */") + v.add_decl("/* allocate extern {mtype} */") v.add_decl("{mtype.ctype} NEW_{c_name}(const struct type* type) \{") if is_dead then v.add_abort("{mclass} is DEAD") @@ -1036,7 +1044,7 @@ class SeparateCompiler v.add("if({t} == NULL) \{") v.add_abort("type null") v.add("\}") - v.add("if({t}->table_size == 0) \{") + v.add("if({t}->table_size < 0) \{") v.add("PRINT_ERROR(\"Insantiation of a dead type: %s\\n\", {t}->name);") v.add_abort("type dead") v.add("\}") @@ -1192,7 +1200,7 @@ class SeparateCompilerVisitor if mtype.name == "Int" then return self.new_expr("(long)({value})>>2", mtype) else if mtype.name == "Char" then - return self.new_expr("(char)((long)({value})>>2)", mtype) + return self.new_expr("(uint32_t)((long)({value})>>2)", mtype) else if mtype.name == "Bool" then return self.new_expr("(short int)((long)({value})>>2)", mtype) else @@ -1201,27 +1209,29 @@ class SeparateCompilerVisitor end return self.new_expr("((struct instance_{mtype.c_name}*){value})->value; /* autounbox from {value.mtype} to {mtype} */", mtype) else if not mtype.is_c_primitive then + assert value.mtype == value.mcasttype if value.mtype.is_tagged then + var res if value.mtype.name == "Int" then - return self.new_expr("(val*)({value}<<2|1)", mtype) + res = self.new_expr("(val*)({value}<<2|1)", mtype) else if value.mtype.name == "Char" then - return self.new_expr("(val*)((long)({value})<<2|2)", mtype) + res = self.new_expr("(val*)((long)({value})<<2|2)", mtype) else if value.mtype.name == "Bool" then - return self.new_expr("(val*)((long)({value})<<2|3)", mtype) + res = self.new_expr("(val*)((long)({value})<<2|3)", mtype) else abort end + # Do not loose type info + res.mcasttype = value.mcasttype + return res end var valtype = value.mtype.as(MClassType) if mtype isa MClassType and mtype.mclass.kind == extern_kind and mtype.mclass.name != "NativeString" then valtype = compiler.mainmodule.pointer_type end var res = self.new_var(mtype) - 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("PRINT_ERROR(\"Dead code executed!\\n\"); fatal_exit(1);") - return res - end + # Do not loose type info + res.mcasttype = value.mcasttype self.require_declaration("BOX_{valtype.c_name}") self.add("{res} = BOX_{valtype.c_name}({value}); /* autobox from {value.mtype} to {mtype} */") return res @@ -1257,11 +1267,7 @@ class SeparateCompilerVisitor 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\"); fatal_exit(1);") - return res - end + compiler.undead_types.add(mtype) self.require_declaration("BOX_{valtype.c_name}") self.add("{res} = BOX_{valtype.c_name}({value}); /* boxing {value.mtype} */") self.require_declaration("type_{mtype.c_name}") @@ -2207,13 +2213,15 @@ class SeparateRuntimeFunction # The C type for the function pointer. var c_funptrtype: String is lazy do return "{c_ret}(*){c_sig}" - # The arguments, as generated by `compile_to_c` - private var arguments: Array[RuntimeVariable] is noinit - redef fun compile_to_c(compiler) do var mmethoddef = self.mmethoddef + var sig = "{c_ret} {c_name}{c_sig}" + compiler.provide_declaration(self.c_name, "{sig};") + + var rta = compiler.as(SeparateCompiler).runtime_type_analysis + var recv = self.mmethoddef.mclassdef.bound_mtype var v = compiler.new_visitor var selfvar = new RuntimeVariable("self", called_recv, recv) @@ -2224,12 +2232,7 @@ class SeparateRuntimeFunction var msignature = called_signature var ret = called_signature.return_mtype - var sig = new FlatBuffer var comment = new FlatBuffer - sig.append(c_ret) - sig.append(" ") - sig.append(self.c_name) - sig.append(c_sig) comment.append("({selfvar}: {selfvar.mtype}") arguments.add(selfvar) for i in [0..msignature.arity[ do @@ -2245,8 +2248,6 @@ class SeparateRuntimeFunction if ret != null then comment.append(": {ret}") end - compiler.provide_declaration(self.c_name, "{sig};") - self.arguments = arguments.to_a v.add_decl("/* method {self} for {comment} */") v.add_decl("{sig} \{") @@ -2261,6 +2262,8 @@ class SeparateRuntimeFunction assert subret != null v.assign(frame.returnvar.as(not null), subret) end + else if rta != null and not rta.live_mmodules.has(mmethoddef.mclassdef.mmodule) then + v.add_abort("FATAL: Dead method executed.") else mmethoddef.compile_inside_to_c(v, arguments) end @@ -2279,8 +2282,10 @@ class SeparateRuntimeFunction fun compile_trampolines(compiler: SeparateCompiler) do var recv = self.mmethoddef.mclassdef.bound_mtype - var selfvar = arguments.first + var selfvar = new RuntimeVariable("self", called_recv, recv) var ret = called_signature.return_mtype + var arguments = ["self"] + for i in [0..called_signature.arity[ do arguments.add "p{i}" if mmethoddef.is_intro and not recv.is_c_primitive then var m = mmethoddef.mproperty