var compiler = new GlobalCompiler(mainmodule, self, runtime_type_analysis)
compiler.compile_header
+ if mainmodule.model.get_mclasses_by_name("Pointer") != null then
+ runtime_type_analysis.live_types.add(mainmodule.pointer_type)
+ end
for t in runtime_type_analysis.live_types do
compiler.declare_runtimeclass(t)
end
for t in runtime_type_analysis.live_types do
if t.ctype == "val*" then
compiler.generate_init_instance(t)
+ if t.mclass.kind == extern_kind then
+ compiler.generate_box_instance(t)
+ end
else
compiler.generate_box_instance(t)
end
end
# The main function of the C
+ compiler.compile_nitni_global_ref_functions
compiler.compile_main_function
# Compile until all runtime_functions are visited
self.runtime_type_analysis = runtime_type_analysis
self.live_primitive_types = new Array[MClassType]
for t in runtime_type_analysis.live_types do
- if t.ctype != "val*" then
+ if t.ctype != "val*" or t.mclass.name == "Pointer" then
self.live_primitive_types.add(t)
end
end
v.add_decl("{mtype.arguments.first.ctype} values[1];")
end
- if mtype.ctype != "val*" then
+ if mtype.ctype_extern != "val*" then
# Is the Nit type is native then the struct is a box with two fields:
# * the `classid` to be polymorph
# * the `value` that contains the native value.
- v.add_decl("{mtype.ctype} value;")
+ v.add_decl("{mtype.ctype_extern} value;")
end
# Collect all attributes and associate them a field in the structure.
v.add("{res}->classid = {self.classid(mtype)};")
self.generate_init_attr(v, res, mtype)
+ v.set_finalizer res
v.add("return {res};")
v.add("\}")
end
fun generate_box_instance(mtype: MClassType)
do
assert self.runtime_type_analysis.live_types.has(mtype)
- assert mtype.ctype != "val*"
var v = self.new_visitor
self.header.add_decl("val* BOX_{mtype.c_name}({mtype.ctype});")
redef fun compile_nitni_structs
do
- self.header.add_decl("struct nitni_instance \{ val *value; \};")
+ self.header.add_decl """
+struct nitni_instance \{
+ struct nitni_instance *next,
+ *prev; /* adjacent global references in global list */
+ int count; /* number of time this global reference has been marked */
+ val *value;
+\};"""
+ super
end
end
end
end
+ redef fun unbox_extern(value, mtype)
+ do
+ if mtype isa MClassType and mtype.mclass.kind == extern_kind and
+ mtype.mclass.name != "NativeString" then
+ var res = self.new_var_extern(mtype)
+ self.add "{res} = ((struct {mtype.c_name}*){value})->value; /* unboxing {value.mtype} */"
+ return res
+ else
+ return value
+ end
+ end
+
+ redef fun box_extern(value, mtype)
+ do
+ if not mtype isa MClassType or mtype.mclass.kind != extern_kind or
+ mtype.mclass.name == "NativeString" then return value
+
+ var valtype = value.mtype.as(MClassType)
+ 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\"); show_backtrace(1);")
+ return res
+ end
+ self.add("{res} = BOX_{valtype.c_name}({value}); /* boxing {value.mtype} */")
+ return res
+ end
+
# The runtime types that are acceptable for a given receiver.
fun collect_types(recv: RuntimeVariable): Array[MClassType]
do
return
else if pname == "copy_to" then
var recv1 = "((struct {arguments[1].mcasttype.c_name}*){arguments[1]})->values"
- self.add("memcpy({recv1},{recv},{arguments[2]}*sizeof({elttype.ctype}));")
+ self.add("memmove({recv1},{recv},{arguments[2]}*sizeof({elttype.ctype}));")
return
end
end
if res != null then self.assign(res, res2.as(not null))
return res
end
- var consider_null = not self.compiler.modelbuilder.toolcontext.opt_no_check_other.value or m.name == "==" or m.name == "!="
+ var consider_null = not self.compiler.modelbuilder.toolcontext.opt_no_check_null.value or m.name == "==" or m.name == "!="
if args.first.mcasttype isa MNullableType or args.first.mcasttype isa MNullType and consider_null then
# The reciever is potentially null, so we have to 3 cases: ==, != or NullPointerException
self.add("if ({args.first} == NULL) \{ /* Special null case */")
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
+ if m.mproperty.is_toplevel then
+ # Do not customize top-level methods
recvtype = m.mclassdef.bound_mtype
end
return recvtype
do
var recv_type = get_recvtype(m, recvtype, args)
var recv = get_recv(recv_type, args)
+ if m.is_extern then recv = unbox_extern(recv, recv_type)
var new_args = args.to_a
self.varargize(m, m.msignature.as(not null), new_args)
new_args.first = recv
do
var recv_type = get_recvtype(m, recvtype, args)
var recv = get_recv(recv_type, args)
+ if m.is_extern then recv = unbox_extern(recv, recv_type)
var new_args = args.to_a
new_args.first = recv
return finalize_call(m, recv_type, new_args)
end
end
+ redef fun unbox_signature_extern(m, args)
+ do
+ var recv = args.first
+ for i in [0..m.msignature.arity[ do
+ var t = m.msignature.mparameters[i].mtype
+ if i == m.msignature.vararg_rank then
+ t = args[i+1].mtype
+ end
+ t = self.resolve_for(t, recv)
+ if m.is_extern then args[i+1] = self.unbox_extern(args[i+1], t)
+ end
+ end
+
# FIXME: this is currently buggy since recv is not exact
redef fun vararg_instance(mpropdef, recv, varargs, elttype)
do
var ta = a.intro.static_mtype.as(not null)
ta = self.resolve_for(ta, recv2)
var res2 = self.new_expr("((struct {t.c_name}*){recv})->{a.intro.c_name}", ta)
- if not ta isa MNullableType and not self.compiler.modelbuilder.toolcontext.opt_no_check_other.value then
+ if not ta isa MNullableType and not self.compiler.modelbuilder.toolcontext.opt_no_check_attr_isset.value then
if ta.ctype == "val*" then
self.add("if ({res2} == NULL) \{")
self.add_abort("Uninitialized attribute {a.name}")
if not t.is_subtype(self.compiler.mainmodule, null, value2.mcasttype) then continue
s.add "({value1}->classid == {self.compiler.classid(t)} && ((struct {t.c_name}*){value1})->value == ((struct {t.c_name}*){value2})->value)"
end
+
+ if self.compiler.mainmodule.model.get_mclasses_by_name("Pointer") != null then
+ var pointer_type = self.compiler.mainmodule.pointer_type
+ if value1.mcasttype.is_subtype(self.compiler.mainmodule, null, pointer_type) or
+ value2.mcasttype.is_subtype(self.compiler.mainmodule, null, pointer_type) then
+ s.add "(((struct {pointer_type.c_name}*){value1})->value == ((struct {pointer_type.c_name}*){value2})->value)"
+ end
+ end
+
if s.is_empty then
self.add("{res} = {value1} == {value2};")
else