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
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(mainmodule, modelbuilder)
- var file = new_file(mainmodule.name)
+ var file = new_file("{mainmodule.name}.nitgg")
self.header = new CodeWriter(file)
self.runtime_type_analysis = runtime_type_analysis
self.live_primitive_types = new Array[MClassType]
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
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;")
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);")
+ self.add("printf(\"Dead code executed!\\n\"); show_backtrace(1);")
return res
end
self.add("{res} = BOX_{valtype.c_name}({value}); /* autobox from {value.mtype} to {mtype} */")
# 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);")
+ self.add("printf(\"Cast error: Cannot cast %s to %s.\\n\", \"{value.mtype}\", \"{mtype}\"); show_backtrace(1);")
return res
end
end
abort
end
- redef fun call(m, recvtype, args)
+ # Subpart of old call function
+ #
+ # Checks if the type of the receiver is valid and corrects it if necessary
+ private fun get_recvtype(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): MClassType
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
recvtype = m.mclassdef.bound_mtype
end
- var recv = self.autobox(args.first, recvtype)
- recv = self.autoadapt(recv, recvtype)
+ return recvtype
+ end
+
+ # Subpart of old call function
+ # Gets the receiver boxed and casted if necessary
+ private fun get_recv(recvtype: MClassType, args: Array[RuntimeVariable]): RuntimeVariable
+ do
+ return self.autoadapt(self.autobox(args.first, recvtype), recvtype)
+ end
- args = args.to_a
- self.varargize(m, m.msignature.as(not null), args)
+ # Finalizes a call to a method ´m´ on type ´recvtype´ with arguments ´args´
+ private fun finalize_call(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): nullable RuntimeVariable
+ do
if args.length != m.msignature.arity + 1 then # because of self
- add("printf(\"NOT YET IMPLEMENTED: Invalid arity for {m}. {args.length} arguments given.\\n\"); exit(1);")
+ add("printf(\"NOT YET IMPLEMENTED: Invalid arity for {m}. {args.length} arguments given.\\n\"); show_backtrace(1);")
debug("NOT YET IMPLEMENTED: Invalid arity for {m}. {args.length} arguments given.")
return null
end
- args.first = recv
var rm = new CustomizedRuntimeFunction(m, recvtype)
return rm.call(self, args)
end
+ redef fun call(m, recvtype, args)
+ do
+ var recv_type = get_recvtype(m, recvtype, args)
+ var recv = get_recv(recv_type, args)
+ var new_args = args.to_a
+ self.varargize(m, m.msignature.as(not null), new_args)
+ new_args.first = recv
+ return finalize_call(m, recv_type, new_args)
+ end
+
+ # Does a call without encapsulating varargs into an array
+ # Avoids multiple encapsulation when calling a super in a variadic function
+ fun call_without_varargize(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): nullable RuntimeVariable
+ do
+ var recv_type = get_recvtype(m, recvtype, args)
+ var recv = get_recv(recv_type, args)
+ var new_args = args.to_a
+ new_args.first = recv
+ return finalize_call(m, recv_type, new_args)
+ end
+
redef fun supercall(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): nullable RuntimeVariable
do
var types = self.collect_types(args.first)
return res
end
var propdef = m.lookup_next_definition(self.compiler.mainmodule, mclasstype)
- var res2 = self.call(propdef, mclasstype, args)
+ var res2 = self.call_without_varargize(propdef, mclasstype, args)
if res != null then self.assign(res, res2.as(not null))
return res
end
else
self.add("case {self.compiler.classid(t)}: /* test {t} */")
end
- var res2 = self.call(propdef, t, args)
+ var res2 = self.call_without_varargize(propdef, t, args)
if res != null then self.assign(res, res2.as(not null))
self.add "break;"
end
do
if recv.mtype.ctype != "val*" then return
self.add("fprintf(stderr, \"BTD BUG: Dynamic type is %s, static type is %s\\n\", class_names[{recv}->classid], \"{recv.mcasttype}\");")
- self.add("exit(1);")
+ self.add("show_backtrace(1);")
end
redef fun isset_attribute(a, recv)