X-Git-Url: http://nitlanguage.org diff --git a/src/global_compiler.nit b/src/global_compiler.nit index 9307579..44ec3a1 100644 --- a/src/global_compiler.nit +++ b/src/global_compiler.nit @@ -26,6 +26,29 @@ module global_compiler 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 @@ -48,7 +71,6 @@ redef class ModelBuilder 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 @@ -88,7 +110,7 @@ class GlobalCompiler 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] @@ -166,6 +188,7 @@ class GlobalCompiler 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 @@ -213,6 +236,7 @@ class GlobalCompiler 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 @@ -223,19 +247,6 @@ class GlobalCompiler 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) @@ -250,12 +261,16 @@ class GlobalCompiler 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. @@ -278,16 +293,18 @@ class GlobalCompilerVisitor 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("PRINT_ERROR(\"Dead code executed!\\n\"); show_backtrace(1);") return res 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) 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("PRINT_ERROR(\"Cast error: Cannot cast %s to %s.\\n\", \"{value.mtype}\", \"{mtype}\"); show_backtrace(1);") return res end end @@ -326,6 +343,9 @@ class GlobalCompilerVisitor 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}));") @@ -389,7 +409,7 @@ class GlobalCompilerVisitor 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 @@ -461,11 +481,7 @@ class GlobalCompilerVisitor # 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);") - 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) @@ -570,8 +586,8 @@ class GlobalCompilerVisitor fun bugtype(recv: RuntimeVariable) 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("PRINT_ERROR(\"BTD BUG: Dynamic type is %s, static type is %s\\n\", class_names[{recv}->classid], \"{recv.mcasttype}\");") + self.add("show_backtrace(1);") end redef fun isset_attribute(a, recv) @@ -713,10 +729,7 @@ class GlobalCompilerVisitor 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 @@ -826,18 +839,6 @@ class GlobalCompilerVisitor 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) @@ -853,7 +854,6 @@ class GlobalCompilerVisitor 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 @@ -929,8 +929,8 @@ private class CustomizedRuntimeFunction 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) @@ -978,6 +978,7 @@ private class CustomizedRuntimeFunction 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