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 */")
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});")
v.add("return (val*)res;")
v.add("\}")
+ # A Pointer class also need its constructor
if mtype.mclass.name != "Pointer" then return
v = new_visitor
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")
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
self.require_declaration("BOX_{valtype.c_name}")
self.add("{res} = BOX_{valtype.c_name}({value}); /* autobox from {value.mtype} to {mtype} */")
return res
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}")
do
var mmethoddef = self.mmethoddef
+ var sig = "{c_ret} {c_name}{c_sig}"
+ compiler.provide_declaration(self.c_name, "{sig} __attribute__((weak));")
+
+ var rta = compiler.as(SeparateCompiler).runtime_type_analysis
+ if rta != null and not rta.live_mmodules.has(mmethoddef.mclassdef.mmodule) then
+ return
+ end
+
var recv = self.mmethoddef.mclassdef.bound_mtype
var v = compiler.new_visitor
var selfvar = new RuntimeVariable("self", called_recv, recv)
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
if ret != null then
comment.append(": {ret}")
end
- compiler.provide_declaration(self.c_name, "{sig};")
v.add_decl("/* method {self} for {comment} */")
v.add_decl("{sig} \{")