import abstract_compiler
import rapid_type_analysis
+redef class ToolContext
+ # option --global
+ var opt_global = new OptionBool("Use global compilation", "--global")
+
+ var global_compiler_phase = new GlobalCompilerPhase(self, null)
+
+ redef init do
+ super
+ option_context.add_option(opt_global)
+ end
+end
+
+class GlobalCompilerPhase
+ super Phase
+ redef fun process_mainmodule(mainmodule, given_mmodules) do
+ if not toolcontext.opt_global.value then return
+
+ var modelbuilder = toolcontext.modelbuilder
+ var analysis = modelbuilder.do_rapid_type_analysis(mainmodule)
+ modelbuilder.run_global_compiler(mainmodule, analysis)
+ end
+end
+
redef class ModelBuilder
# Entry point to performs a global compilation on the AST of a complete program.
# `mainmodule` is the main module of the program
for t in runtime_type_analysis.live_types do
if t.ctype == "val*" then
compiler.generate_init_instance(t)
- compiler.generate_check_init_instance(t)
else
compiler.generate_box_instance(t)
end
if mtype.mclass.name == "NativeArray" then
# NativeArrays are just a instance header followed by an array of values
+ v.add_decl("int length;")
v.add_decl("{mtype.arguments.first.ctype} values[1];")
end
if is_native_array then
var mtype_elt = mtype.arguments.first
v.add("{res} = nit_alloc(sizeof(struct {mtype.c_name}) + length*sizeof({mtype_elt.ctype}));")
+ v.add("((struct {mtype.c_name}*){res})->length = length;")
else
v.add("{res} = nit_alloc(sizeof(struct {mtype.c_name}));")
end
v.add("\}")
end
- redef fun generate_check_init_instance(mtype)
- do
- if self.modelbuilder.toolcontext.opt_no_check_initialization.value then return
-
- var v = self.new_visitor
- var res = new RuntimeVariable("self", mtype, mtype)
- self.header.add_decl("void CHECK_NEW_{mtype.c_name}({mtype.ctype});")
- v.add_decl("/* allocate {mtype} */")
- v.add_decl("void CHECK_NEW_{mtype.c_name}({mtype.ctype} {res}) \{")
- self.generate_check_attr(v, res, mtype)
- v.add("\}")
- end
-
fun generate_box_instance(mtype: MClassType)
do
assert self.runtime_type_analysis.live_types.has(mtype)
v.add("res->value = value;")
v.add("return (val*)res;")
v.add("\}")
-
end
redef fun new_visitor do return new GlobalCompilerVisitor(self)
private var collect_types_cache: HashMap[MType, Array[MClassType]] = new HashMap[MType, Array[MClassType]]
+
+ redef fun compile_nitni_structs
+ do
+ self.header.add_decl("struct nitni_instance \{ val *value; \};")
+ end
end
# A visitor on the AST of property definition that generate the C code.
end
self.add("{res} = BOX_{valtype.c_name}({value}); /* autobox from {value.mtype} to {mtype} */")
return res
+ else if value.mtype.ctype == "void*" and mtype.ctype == "void*" then
+ return value
else
# Bad things will appen!
var res = self.new_var(mtype)
else if pname == "[]=" then
self.add("{recv}[{arguments[1]}]={arguments[2]};")
return
+ else if pname == "length" then
+ self.ret(self.new_expr("((struct {arguments[0].mcasttype.c_name}*){arguments[0]})->length", ret_type.as(not null)))
+ 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("{res} = 1; /* {args[1].inspect} cannot be null */")
end
else
- self.add_abort("Reciever is null")
+ self.add_abort("Receiver is null")
end
self.add "\} else"
end
# 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\"); show_backtrace(1);")
- debug("NOT YET IMPLEMENTED: Invalid arity for {m}. {args.length} arguments given.")
- return null
- end
+ assert args.length == m.msignature.arity + 1 else debug("Invalid arity for {m}. {args.length} arguments given.")
var rm = new CustomizedRuntimeFunction(m, recvtype)
return rm.call(self, args)
redef fun type_test(value, mtype, tag)
do
mtype = self.anchor(mtype)
- var mclasstype = mtype
- if mtype isa MNullableType then mclasstype = mtype.mtype
- assert mclasstype isa MClassType
- if not self.compiler.runtime_type_analysis.live_cast_types.has(mclasstype) then
+ if not self.compiler.runtime_type_analysis.live_cast_types.has(mtype) then
debug "problem: {mtype} was detected cast-dead"
abort
end
return res
end
- redef fun check_init_instance(recv, mtype)
- do
- if self.compiler.modelbuilder.toolcontext.opt_no_check_initialization.value then return
-
- mtype = self.anchor(mtype).as(MClassType)
- if not self.compiler.runtime_type_analysis.live_types.has(mtype) then
- debug "problem: {mtype} was detected dead"
- end
-
- self.add("CHECK_NEW_{mtype.c_name}({recv});")
- end
-
redef fun array_instance(array, elttype)
do
elttype = self.anchor(elttype)
end
var length = self.int_instance(array.length)
self.send(self.get_property("with_native", arraytype), [res, nat, length])
- self.check_init_instance(res, arraytype)
self.add("\}")
return res
end
var frame = new Frame(v, mmethoddef, recv, arguments)
v.frame = frame
- var sig = new Buffer
- var comment = new Buffer
+ var sig = new FlatBuffer
+ var comment = new FlatBuffer
var ret = mmethoddef.msignature.return_mtype
if ret != null then
ret = v.resolve_for(ret, selfvar)
v.add("return {frame.returnvar.as(not null)};")
end
v.add("\}")
+ if not self.c_name.has_substring("VIRTUAL", 0) then compiler.names[self.c_name] = "{mmethoddef.mclassdef.mmodule.name}::{mmethoddef.mclassdef.mclass.name}::{mmethoddef.mproperty.name} ({mmethoddef.location.file.filename}:{mmethoddef.location.line_start})"
end
redef fun call(v: VISITOR, arguments: Array[RuntimeVariable]): nullable RuntimeVariable