# Init instance code (allocate and init-arguments)
for t in runtime_type_analysis.live_types do
- if t.ctype != "val*" then continue # skip primitive types
- compiler.generate_init_instance(t)
+ if t.ctype == "val*" then
+ compiler.generate_init_instance(t)
+ else
+ compiler.generate_box_instance(t)
+ end
end
# The main function of the C
if main_method != null then
v.send(main_method, [glob_sys])
end
+ v.add("return 0;")
v.add("\}")
# Compile until all runtime_functions are visited
end
self.toolcontext.info("Total methods to compile to C: {compiler.visitors.length}", 2)
+ var time1 = get_time
+ self.toolcontext.info("*** END VISITING: {time1-time0} ***", 2)
+ write_and_make(compiler)
+ end
+
+ private fun write_and_make(compiler: GlobalCompiler)
+ do
+ var mainmodule = compiler.mainmodule
+
# Generate the .h and .c files
# A single C file regroups many compiled rumtime functions
# Note that we do not try to be clever an a small change in a Nit source file may change the content of all the generated .c files
+ var time0 = get_time
var outname = self.toolcontext.opt_output.value
if outname == null then
ofiles.add(o)
end
# Link edition
- makefile.write("{outname}: {ofiles.join(" ")}\n\t$(CC) $(LDFLAGS) $(LDLIBS) -o {outname} {ofiles.join(" ")}\n\n")
+ makefile.write("{outname}: {ofiles.join(" ")}\n\t$(CC) $(LDFLAGS) -o {outname} {ofiles.join(" ")} $(LDLIBS)\n\n")
# Clean
makefile.write("clean:\n\trm {ofiles.join(" ")} 2>/dev/null\n\n")
makefile.close
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 = new GlobalCompilerVisitor(self)
+
+ 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("res->classid = {self.classid(mtype)};")
+ v.add("res->value = value;")
+ v.add("return (val*)res;")
+ v.add("\}")
+
+ end
+
# look for a needed .h and .c file for a given .nit source-file
# FIXME: bad API, parameter should be a MModule, not its source-file
fun add_extern(file: String)
else
sig.append("void ")
end
- sig.append(mmethoddef.c_name)
- if recv != mmethoddef.mclassdef.bound_mtype then
- sig.append("__{recv.c_name}")
- end
+ sig.append(self.c_name)
sig.append("({recv.ctype} self")
comment.append("(self: {recv}")
arguments.add(selfvar)
do
var ret = self.mmethoddef.msignature.return_mtype
if self.mmethoddef.mproperty.is_new then
- ret = arguments.first.mtype
+ ret = recv
end
if ret != null then
ret = v.resolve_for(ret, arguments.first)
# false (usual value) means that the variable is a mcasttype or a subtype.
var is_exact: Bool = false
+ init(name: String, mtype: MType, mcasttype: MType)
+ do
+ self.name = name
+ self.mtype = mtype
+ self.mcasttype = mcasttype
+ assert not mtype.need_anchor
+ assert not mcasttype.need_anchor
+ end
+
redef fun to_s do return name
redef fun inspect
# Force to get the primitive property named `name' in the instance `recv' or abort
fun get_property(name: String, recv: MType): MMethod
do
- return self.compiler.mainmodule.force_get_primitive_method(name, recv)
+ return self.compiler.modelbuilder.force_get_primitive_method(self.current_node.as(not null), name, recv, self.compiler.mainmodule)
end
# The current Frame
fun autoadapt(value: RuntimeVariable, mtype: MType): RuntimeVariable
do
mtype = self.anchor(mtype)
- if value.mtype.is_subtype(self.compiler.mainmodule, null, mtype) then
+ var valmtype = value.mcasttype
+ if valmtype.is_subtype(self.compiler.mainmodule, null, mtype) then
return value
end
- var valmtype = value.mtype
if valmtype isa MNullableType and valmtype.mtype.is_subtype(self.compiler.mainmodule, null, mtype) then
- var res = new RuntimeVariable(value.name, value.mtype, valmtype.mtype)
+ var res = new RuntimeVariable(value.name, valmtype, valmtype.mtype)
return res
else
- var res = new RuntimeVariable(value.name, value.mtype, mtype)
+ var res = new RuntimeVariable(value.name, valmtype, mtype)
return res
end
end
self.add("printf(\"Dead code executed!\\n\"); exit(1);")
return res
end
- self.add("{res} = GC_MALLOC(sizeof(struct {valtype.c_name})); /* autobox from {value.mtype} to {mtype} */")
- self.add("{res}->classid = {self.compiler.classid(valtype)};")
- self.add("((struct {valtype.c_name}*){res})->value = {value};")
+ self.add("{res} = BOX_{valtype.c_name}({value}); /* autobox from {value.mtype} to {mtype} */")
return res
else
# Bad things will appen!
# Return a new uninitialized local runtime_variable
fun new_var(mtype: MType): RuntimeVariable
do
- if mtype isa MNullType then
- mtype = self.object_type
- else
- mtype = self.anchor(mtype)
- end
+ mtype = self.anchor(mtype)
var name = self.get_name("var")
var res = new RuntimeVariable(name, mtype, mtype)
self.add_decl("{mtype.ctype} {name} /* : {mtype} */;")
return res
end
if args.first.mcasttype isa MNullableType then
+ # The reciever is potentially null, so we have to 3 cases: ==, != or NullPointerException
self.add("if ({args.first} == NULL) \{ /* Special null case */")
if m.name == "==" then
assert res != null
- if args[1].mcasttype.ctype == "val*" then
+ if args[1].mcasttype isa MNullableType then
self.add("{res} = ({args[1]} == NULL);")
+ else if args[1].mcasttype isa MNullType then
+ self.add("{res} = 1; /* is null */")
else
self.add("{res} = 0; /* {args[1].inspect} cannot be null */")
end
else if m.name == "!=" then
assert res != null
- if args[1].mcasttype.ctype == "val*" then
+ if args[1].mcasttype isa MNullableType then
self.add("{res} = ({args[1]} != NULL);")
+ else if args[1].mcasttype isa MNullType then
+ self.add("{res} = 0; /* is null */")
else
self.add("{res} = 1; /* {args[1].inspect} cannot be null */")
end
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
if propdef.mclassdef.mclass.name == "Object" and t.ctype == "val*" then
defaultpropdef = propdef
return res
end
+ # Generate a monomorphic send for the method `m', the type `t' and the arguments `args'
+ fun monomorphic_send(m: MMethod, t: MType, args: Array[RuntimeVariable]): nullable RuntimeVariable
+ do
+ assert t isa MClassType
+ var propdefs = m.lookup_definitions(self.compiler.mainmodule, t)
+ if propdefs.length == 0 then
+ abort
+ 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
+ return self.call(propdef, t, args)
+ end
+
fun check_valid_reciever(recvtype: MClassType)
do
if self.compiler.runtime_type_analysis.live_types.has(recvtype) or recvtype.mclass.name == "Object" then return
else
args = args.to_a
end
- assert args.length == m.msignature.arity + 1 # because of self
+ 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);")
+ debug("NOT YET IMPLEMENTED: Invalid arity for {m}. {args.length} arguments given.")
+ return null
+ end
args.first = recv
var rm = new CustomizedRuntimeFunction(m, recvtype)
fun array_instance(array: Array[RuntimeVariable], elttype: MType): RuntimeVariable
do
elttype = self.anchor(elttype)
- var res = self.init_instance(self.get_class("Array").get_mtype([elttype]))
+ var arraytype = self.get_class("Array").get_mtype([elttype])
+ var res = self.init_instance(arraytype)
self.add("\{ /* {res} = array_instance Array[{elttype}] */")
var nat = self.new_var(self.get_class("NativeArray").get_mtype([elttype]))
nat.is_exact = true
self.add("{nat}[{i}] = {r};")
end
var length = self.int_instance(array.length)
- self.send(self.get_property("with_native", res.mtype), [res, nat, length])
+ self.send(self.get_property("with_native", arraytype), [res, nat, length])
self.check_init_instance(res)
self.add("\}")
return res
var res2 = self.init_instance(mtype)
self.add("{res} = {res2};")
var length = self.int_instance(string.length)
- self.send(self.get_property("with_native", res.mtype), [res, nat, length])
+ self.send(self.get_property("with_native", mtype), [res, nat, length])
self.check_init_instance(res)
self.add("{name} = {res};")
self.add("\}")
end
return
end
- v.add("printf(\"NOT IMPLEMENTED {class_name}:{mpropdef} at {location.to_s}\\n\");")
+ v.add("printf(\"NOT YET IMPLEMENTED {class_name}:{mpropdef} at {location.to_s}\\n\");")
debug("Not implemented {mpropdef}")
end
end
# FIXME: we do not want an ugly static call!
var mpropdefs = mpropdef.mproperty.lookup_super_definitions(mpropdef.mclassdef.mmodule, mpropdef.mclassdef.bound_mtype)
if mpropdefs.length != 1 then
+ v.add("printf(\"NOT YET IMPLEMENTED {class_name} {mpropdef} at {location.to_s}\\n\");")
debug("MPRODFEFS for super {mpropdef} for {recv}: {mpropdefs.join(", ")}")
end
mpropdef = mpropdefs.first