model: rta uses its visitor only to visit FFI extern methods
[nit.git] / src / global_compiler.nit
index 9c17518..004c8a3 100644 (file)
@@ -48,7 +48,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 +87,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]
@@ -223,19 +222,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)
@@ -278,7 +264,7 @@ 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("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} */")
@@ -287,7 +273,7 @@ class GlobalCompilerVisitor
                        # 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
@@ -438,29 +424,60 @@ class GlobalCompilerVisitor
                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)
@@ -482,7 +499,7 @@ class GlobalCompilerVisitor
                                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
@@ -504,7 +521,7 @@ class GlobalCompilerVisitor
                        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
@@ -540,7 +557,7 @@ class GlobalCompilerVisitor
        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)
@@ -795,18 +812,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)
@@ -822,7 +827,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
@@ -947,6 +951,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