fun run_global_compiler(mainmodule: MModule, runtime_type_analysis: RapidTypeAnalysis)
do
var time0 = get_time
- self.toolcontext.info("*** COMPILING TO C ***", 1)
+ self.toolcontext.info("*** GENERATING C ***", 1)
var compiler = new GlobalCompiler(mainmodule, self, runtime_type_analysis)
compiler.compile_header
- var v = compiler.header
for t in runtime_type_analysis.live_types do
- compiler.declare_runtimeclass(v, t)
+ compiler.declare_runtimeclass(t)
end
compiler.compile_class_names
self.toolcontext.info("Compile {m} ({compiler.seen.length-compiler.todos.length}/{compiler.seen.length})", 3)
m.compile_to_c(compiler)
end
- self.toolcontext.info("Total methods to compile to C: {compiler.visitors.length}", 2)
+ self.toolcontext.info("Total methods to compile to C: {compiler.seen.length}", 2)
compiler.display_stats
var time1 = get_time
- self.toolcontext.info("*** END VISITING: {time1-time0} ***", 2)
+ self.toolcontext.info("*** END GENERATING C: {time1-time0} ***", 2)
write_and_make(compiler)
end
end
init(mainmodule: MModule, modelbuilder: ModelBuilder, runtime_type_analysis: RapidTypeAnalysis)
do
- super
- self.header = new_visitor
+ super(mainmodule, modelbuilder)
+ var file = new_file(mainmodule.name)
+ self.header = new CodeWriter(file)
self.runtime_type_analysis = runtime_type_analysis
self.live_primitive_types = new Array[MClassType]
for t in runtime_type_analysis.live_types do
# Compile class names (for the class_name and output_class_name methods)
protected fun compile_class_names do
+ var v = new_visitor
self.header.add_decl("extern const char const * class_names[];")
- self.header.add("const char const * class_names[] = \{")
+ v.add("const char const * class_names[] = \{")
for t in self.runtime_type_analysis.live_types do
- self.header.add("\"{t}\", /* {self.classid(t)} */")
+ v.add("\"{t}\", /* {self.classid(t)} */")
end
- self.header.add("\};")
+ v.add("\};")
end
# Return the C symbol associated to a live type runtime
protected var classids: HashMap[MClassType, String] = new HashMap[MClassType, String]
# Declaration of structures the live Nit types
- # Each live type is generated as an independent C `struct' type.
+ # Each live type is generated as an independent C `struct` type.
# They only share a common first field `classid` used to implement the polymorphism.
- # Usualy, all C variables that refers to a Nit object are typed on the abstract struct `val' that contains only the `classid` field.
+ # Usualy, all C variables that refers to a Nit object are typed on the abstract struct `val` that contains only the `classid` field.
redef fun compile_header_structs do
self.header.add_decl("typedef struct \{int classid;\} val; /* general C type representing a Nit instance. */")
end
private var seen: HashSet[AbstractRuntimeFunction] = new HashSet[AbstractRuntimeFunction]
# Declare C structures and identifiers for a runtime class
- fun declare_runtimeclass(v: VISITOR, mtype: MClassType)
+ fun declare_runtimeclass(mtype: MClassType)
do
+ var v = self.header
assert self.runtime_type_analysis.live_types.has(mtype)
v.add_decl("/* runtime class {mtype} */")
var idnum = classids.length
res.is_exact = true
if is_native_array then
var mtype_elt = mtype.arguments.first
- v.add("{res} = GC_MALLOC(sizeof(struct {mtype.c_name}) + length*sizeof({mtype_elt.ctype}));")
+ v.add("{res} = nit_alloc(sizeof(struct {mtype.c_name}) + length*sizeof({mtype_elt.ctype}));")
else
- v.add("{res} = GC_MALLOC(sizeof(struct {mtype.c_name}));")
+ v.add("{res} = nit_alloc(sizeof(struct {mtype.c_name}));")
end
v.add("{res}->classid = {self.classid(mtype)};")
self.header.add_decl("val* BOX_{mtype.c_name}({mtype.ctype});")
v.add_decl("/* allocate {mtype} */")
v.add_decl("val* BOX_{mtype.c_name}({mtype.ctype} value) \{")
- v.add("struct {mtype.c_name}*res = GC_MALLOC(sizeof(struct {mtype.c_name}));")
+ v.add("struct {mtype.c_name}*res = nit_alloc(sizeof(struct {mtype.c_name}));")
v.add("res->classid = {self.classid(mtype)};")
v.add("res->value = value;")
v.add("return (val*)res;")
self.add("/* skip, no method {m} */")
return res
end
- var propdefs = m.lookup_definitions(self.compiler.mainmodule, mclasstype)
- if propdefs.length == 0 then
- self.add("/* skip, no method {m} */")
- return res
- end
- assert propdefs.length == 1
- var propdef = propdefs.first
+ var propdef = m.lookup_first_definition(self.compiler.mainmodule, mclasstype)
var res2 = self.call(propdef, mclasstype, args)
if res != null then self.assign(res, res2.as(not null))
return res
var last = types.last
var defaultpropdef: nullable MMethodDef = null
for t in types do
- var propdefs = m.lookup_definitions(self.compiler.mainmodule, t)
- if propdefs.length == 0 then
- self.add("/* skip {t}, no method {m} */")
- continue
- end
- if propdefs.length > 1 then
- self.debug("NOT YET IMPLEMENTED conflict for {t}.{m}: {propdefs.join(" ")}. choose the first")
- end
- var propdef = propdefs.first
+ var propdef = m.lookup_first_definition(self.compiler.mainmodule, t)
if propdef.mclassdef.mclass.name == "Object" and t.ctype == "val*" then
defaultpropdef = propdef
continue
return rm.call(self, args)
end
+ redef fun supercall(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): nullable RuntimeVariable
+ do
+ var types = self.collect_types(args.first)
+
+ var res: nullable RuntimeVariable
+ var ret = m.mproperty.intro.msignature.return_mtype
+ if ret == null then
+ res = null
+ else
+ ret = self.resolve_for(ret, args.first)
+ res = self.new_var(ret)
+ end
+
+ self.add("/* super {m} on {args.first.inspect} */")
+ if args.first.mtype.ctype != "val*" then
+ var mclasstype = args.first.mtype.as(MClassType)
+ if not self.compiler.runtime_type_analysis.live_types.has(mclasstype) then
+ self.add("/* skip, no method {m} */")
+ return res
+ end
+ var propdef = m.lookup_next_definition(self.compiler.mainmodule, mclasstype)
+ var res2 = self.call(propdef, mclasstype, args)
+ if res != null then self.assign(res, res2.as(not null))
+ return res
+ end
+
+ if types.is_empty then
+ self.add("\{")
+ self.add("/*BUG: no live types for {args.first.inspect} . {m}*/")
+ self.bugtype(args.first)
+ self.add("\}")
+ return res
+ end
+
+ self.add("switch({args.first}->classid) \{")
+ var last = types.last
+ for t in types do
+ var propdef = m.lookup_next_definition(self.compiler.mainmodule, t)
+ if not self.compiler.hardening and t == last then
+ self.add("default: /* test {t} */")
+ else
+ self.add("case {self.compiler.classid(t)}: /* test {t} */")
+ end
+ var res2 = self.call(propdef, t, args)
+ if res != null then self.assign(res, res2.as(not null))
+ self.add "break;"
+ end
+ if self.compiler.hardening then
+ self.add("default: /* bug */")
+ self.bugtype(args.first)
+ end
+ self.add("\}")
+ return res
+ end
+
redef fun adapt_signature(m, args)
do
var recv = args.first
return res
end
end
-end
\ No newline at end of file
+end