end
redef class ModelBuilder
- redef fun run_global_compiler(mainmodule: MModule, runtime_type_analysis: RapidTypeAnalysis)
- do
- if self.toolcontext.opt_erasure.value then
- run_separate_erasure_compiler(mainmodule, runtime_type_analysis)
- else
- super
- end
- end
-
fun run_separate_erasure_compiler(mainmodule: MModule, runtime_type_analysis: RapidTypeAnalysis)
do
var time0 = get_time
v.add_decl("#include <gc/gc.h>")
v.add_decl("typedef void(*nitmethod_t)(void); /* general C type representing a Nit method. */")
v.add_decl("typedef void* nitattribute_t; /* general C type representing a Nit attribute. */")
- v.add_decl("struct class \{ int id; int color; struct type_table *type_table; nitmethod_t vft[1]; \}; /* general C type representing a Nit class. */")
+ v.add_decl("struct class \{ int id; int box_kind; int color; struct type_table *type_table; nitmethod_t vft[1]; \}; /* general C type representing a Nit class. */")
v.add_decl("struct type_table \{ int size; int table[1]; \}; /* colorized type table. */")
v.add_decl("typedef struct \{ struct class *class; nitattribute_t attrs[1]; \} val; /* general C type representing a Nit instance. */")
v.add_decl("extern const char const * class_names[];")
# for the class_name and output_class_name methods
self.compile_class_names
+ self.compile_box_kinds
end
redef fun compile_class_names do
self.header.add_decl("extern const struct class_{c_name} class_{c_name};")
self.header.add_decl("struct class_{c_name} \{")
self.header.add_decl("int id;")
+ self.header.add_decl("int box_kind;")
self.header.add_decl("int color;")
self.header.add_decl("struct type_table *type_table;")
self.header.add_decl("nitmethod_t vft[{vft.length}];")
-
- if mtype.ctype != "val*" then
- # Is the Nit type is native then the struct is a box with two fields:
- # * the `vft` to be polymorph
- # * the `value` that contains the native value.
- self.header.add_decl("{mtype.ctype} value;")
- end
-
- # Collect all attributes and associate them a field in the structure.
- # Note: we do not try to optimize the order and helps CC to optimize the client code.
- for cd in mtype.collect_mclassdefs(self.mainmodule) do
- for p in cd.intro_mproperties do
- if not p isa MAttribute then continue
- var t = p.intro.static_mtype.as(not null)
- t = t.anchor_to(self.mainmodule, mtype)
- self.header.add_decl("{t.ctype} {p.intro.c_name}; /* {p}: {t} */")
- end
- end
self.header.add_decl("\};")
# Build class vft
v.add_decl("const struct class_{c_name} class_{c_name} = \{")
v.add_decl("{self.class_ids[mclass]},")
+ v.add_decl("{self.box_kind_of(mclass)}, /* box_kind */")
v.add_decl("{self.class_colors[mclass]},")
v.add_decl("(struct type_table*) &type_table_{c_name},")
v.add_decl("\{")
v.add_decl("\{")
for msuper in class_table do
if msuper == null then
- v.add_decl("0, /* empty */")
+ v.add_decl("-1, /* empty */")
else
v.add_decl("{self.class_ids[msuper]}, /* {msuper} */")
end
end
v.add("{res}->class = (struct class*) &class_{c_name};")
- for cd in mtype.collect_mclassdefs(self.mainmodule)
- do
- var n = self.modelbuilder.mclassdef2nclassdef[cd]
- for npropdef in n.n_propdefs do
- if npropdef isa AAttrPropdef then
- npropdef.init_expr(v, res)
- end
- end
- end
+ self.generate_init_attr(v, res, mtype)
v.add("return {res};")
v.add("\}")
+
+ generate_check_init_instance(mtype)
end
redef fun new_visitor do return new SeparateErasureCompilerVisitor(self)
class SeparateErasureCompilerVisitor
super SeparateCompilerVisitor
- # Box or unbox a value to another type iff a C type conversion is needed
- # ENSURE: result.mtype.ctype == mtype.ctype
- redef fun autobox(value: RuntimeVariable, mtype: MType): RuntimeVariable
- do
- if value.mtype.ctype == mtype.ctype then
- return value
- else if value.mtype.ctype == "val*" then
- return self.new_expr("((struct instance_{mtype.c_name}*){value})->value; /* autounbox from {value.mtype} to {mtype} */", mtype)
- 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
- self.add("/*no autobox from {value.mtype} to {mtype}: {value.mtype} is not live! */")
- self.add("printf(\"Dead code executed!\\n\"); exit(1);")
- return res
- end
- var totype = value.mtype
- if totype isa MNullableType then totype = totype.mtype
- self.add("{res} = BOX_{valtype.c_name}({value}); /* autobox from {value.mtype} to {mtype} */")
- return res
- else
- # Bad things will appen!
- var res = self.new_var(mtype)
- self.add("/* {res} left unintialized (cannot convert {value.mtype} to {mtype}) */")
- self.add("printf(\"Cast error: Cannot cast %s to %s.\\n\", \"{value.mtype}\", \"{mtype}\"); exit(1);")
- return res
- end
- end
-
redef fun init_instance(mtype)
do
return self.new_expr("NEW_{mtype.mclass.c_name}()", mtype)
redef fun type_test(value, mtype)
do
var res = self.new_var(bool_type)
- var boxed = self.autobox(value, self.object_type)
var cltype = self.get_name("cltype")
self.add_decl("int {cltype};")
maybe_null = true
end
end
+
+ if value.mcasttype.is_subtype(self.frame.mpropdef.mclassdef.mmodule, self.frame.mpropdef.mclassdef.bound_mtype, mtype) then
+ self.add("{res} = 1; /* easy {value.inspect} isa {mtype}*/")
+ return res
+ end
+
+ var type_table
+ if value.mtype.ctype == "val*" then
+ type_table = "{value}->class->type_table"
+ else
+ var mclass = value.mtype.as(MClassType).mclass
+ type_table = "type_table_{mclass.c_name}"
+ end
+
if mtype isa MClassType then
self.add("{cltype} = class_{mtype.mclass.c_name}.color;")
self.add("{idtype} = class_{mtype.mclass.c_name}.id;")
var s: String
if maybe_null then
- s = "{boxed} == NULL ||"
+ s = "{value} == NULL ||"
else
- s = "{boxed} != NULL &&"
+ s = "{value} != NULL &&"
end
# check color is in table
- self.add("if({boxed} != NULL && {cltype} >= {boxed}->class->type_table->size) \{")
+ self.add("if({value} != NULL && {cltype} >= {type_table}->size) \{")
self.add("{res} = 0;")
self.add("\} else \{")
- self.add("{res} = {s} {boxed}->class->type_table->table[{cltype}] == {idtype};")
+ self.add("{res} = {s} {type_table}->table[{cltype}] == {idtype};")
self.add("\}")
return res
end
- redef fun class_name_string(value1)
+ redef fun class_name_string(value)
do
var res = self.get_name("var_class_name")
- self.add_decl("const char* {res} = class_names[self->class->id];")
+ self.add_decl("const char *{res};")
+ self.add("{res} = class_names[{value}->class->id];")
return res
end
end
var length = self.int_instance(array.length)
self.send(self.get_property("with_native", arraytype), [res, nat, length])
- self.check_init_instance(res)
+ self.check_init_instance(res, arraytype)
self.add("\}")
return res
end