compiler: Refactor `AbstractRuntimeFunction`
[nit.git] / src / compiler / global_compiler.nit
index d2a8a0c..ce61657 100644 (file)
@@ -151,7 +151,7 @@ class GlobalCompiler
                if self.classids.has_key(mtype) then
                        return self.classids[mtype]
                end
-               print "No classid for {mtype}"
+               print_error "No classid for {mtype}"
                abort
        end
 
@@ -330,7 +330,7 @@ class GlobalCompilerVisitor
        redef fun unbox_extern(value, mtype)
        do
                if mtype isa MClassType and mtype.mclass.kind == extern_kind and
-                  mtype.mclass.name != "NativeString" then
+                  mtype.mclass.name != "CString" then
                        var res = self.new_var_extern(mtype)
                        self.add "{res} = ((struct {mtype.c_name}*){value})->value; /* unboxing {value.mtype} */"
                        return res
@@ -342,7 +342,7 @@ class GlobalCompilerVisitor
        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
+                       mtype.mclass.name == "CString" then return value
 
                var valtype = value.mtype.as(MClassType)
                var res = self.new_var(mtype)
@@ -396,16 +396,21 @@ class GlobalCompilerVisitor
                        var recv1 = "((struct {arguments[1].mcasttype.c_name}*){arguments[1]})->values"
                        self.add("memmove({recv1},{recv},{arguments[2]}*sizeof({elttype.ctype}));")
                        return true
+               else if pname == "memmove" then
+                       # fun memmove(start: Int, length: Int, dest: NativeArray[E], dest_start: Int) is intern do
+                       var recv1 = "((struct {arguments[3].mcasttype.c_name}*){arguments[3]})->values"
+                       self.add("memmove({recv1}+{arguments[4]}, {recv}+{arguments[1]}, {arguments[2]}*sizeof({elttype.ctype}));")
+                       return true
                end
                return false
        end
 
-       redef fun native_array_instance(elttype: MType, length: RuntimeVariable): RuntimeVariable
+       redef fun native_array_instance(elttype, length)
        do
                var ret_type = mmodule.native_array_type(elttype)
                ret_type = anchor(ret_type).as(MClassType)
                length = autobox(length, compiler.mainmodule.int_type)
-               return self.new_expr("NEW_{ret_type.c_name}({length})", ret_type)
+               return self.new_expr("NEW_{ret_type.c_name}((int){length})", ret_type)
        end
 
        redef fun native_array_get(nat, i)
@@ -421,11 +426,6 @@ class GlobalCompilerVisitor
                self.add("{recv}[{i}]={val};")
        end
 
-       redef fun calloc_array(ret_type, arguments)
-       do
-               self.ret(self.new_expr("NEW_{ret_type.c_name}({arguments[1]})", ret_type))
-       end
-
        redef fun send(m, args)
        do
                var types = self.collect_types(args.first)
@@ -443,6 +443,10 @@ class GlobalCompilerVisitor
                if args.first.mtype.is_c_primitive then
                        var mclasstype = args.first.mtype.as(MClassType)
                        if not self.compiler.runtime_type_analysis.live_types.has(mclasstype) then
+                               self.add("/* skip, dead class {mclasstype} */")
+                               return res
+                       end
+                       if not mclasstype.has_mproperty(self.compiler.mainmodule, m) then
                                self.add("/* skip, no method {m} */")
                                return res
                        end
@@ -519,7 +523,7 @@ class GlobalCompilerVisitor
        fun check_valid_reciever(recvtype: MClassType)
        do
                if self.compiler.runtime_type_analysis.live_types.has(recvtype) or recvtype.mclass.name == "Object" then return
-               print "{recvtype} is not a live type"
+               print_error "{recvtype} is not a live type"
                abort
        end
 
@@ -922,7 +926,7 @@ class GlobalCompilerVisitor
        end
 end
 
-# A runtime function customized on a specific monomrph receiver type
+# A runtime function customized on a specific monomorph receiver type
 private class CustomizedRuntimeFunction
        super AbstractRuntimeFunction
 
@@ -967,74 +971,51 @@ private class CustomizedRuntimeFunction
                end
        end
 
-       # compile the code customized for the reciever
-       redef fun compile_to_c(compiler)
-       do
-               var recv = self.recv
-               var mmethoddef = self.mmethoddef
-               if not recv.is_subtype(compiler.mainmodule, null, mmethoddef.mclassdef.bound_mtype) then
-                       print("problem: why do we compile {self} for {recv}?")
-                       abort
-               end
-
-               var v = compiler.new_visitor
-               var selfvar = new RuntimeVariable("self", recv, recv)
-               if compiler.runtime_type_analysis.live_types.has(recv) then
-                       selfvar.is_exact = true
-               end
-               var arguments = new Array[RuntimeVariable]
-               var frame = new StaticFrame(v, mmethoddef, recv, arguments)
-               v.frame = frame
-
-               var sig = new FlatBuffer
-               var comment = new FlatBuffer
-               var ret = mmethoddef.msignature.return_mtype
-               if ret != null then
-                       ret = v.resolve_for(ret, selfvar)
-                       sig.append("{ret.ctype} ")
-               else
-                       sig.append("void ")
-               end
-               sig.append(self.c_name)
-               sig.append("({recv.ctype} {selfvar}")
-               comment.append("(self: {recv}")
-               arguments.add(selfvar)
-               for i in [0..mmethoddef.msignature.arity[ do
-                       var mp = mmethoddef.msignature.mparameters[i]
-                       var mtype = mp.mtype
-                       if mp.is_vararg then
-                               mtype = v.mmodule.array_type(mtype)
-                       end
-                       mtype = v.resolve_for(mtype, selfvar)
-                       comment.append(", {mtype}")
-                       sig.append(", {mtype.ctype} p{i}")
-                       var argvar = new RuntimeVariable("p{i}", mtype, mtype)
-                       arguments.add(argvar)
-               end
-               sig.append(")")
-               comment.append(")")
-               if ret != null then
-                       comment.append(": {ret}")
-               end
-               compiler.header.add_decl("{sig};")
-
-               v.add_decl("/* method {self} for {comment} */")
-               v.add_decl("{sig} \{")
-               #v.add("printf(\"method {self} for {comment}\\n\");")
-               if ret != null then
-                       frame.returnvar = v.new_var(ret)
-               end
-               frame.returnlabel = v.get_name("RET_LABEL")
+        redef fun recv_mtype
+        do
+                return recv
+        end
 
-               mmethoddef.compile_inside_to_c(v, arguments)
+        redef var return_mtype
 
-               v.add("{frame.returnlabel.as(not null)}:;")
-               if ret != null then
-                       v.add("return {frame.returnvar.as(not null)};")
+        redef fun resolve_receiver(v)
+        do
+                var selfvar = new RuntimeVariable("self", recv, recv)
+               if v.compiler.runtime_type_analysis.live_types.has(recv) then
+                       selfvar.is_exact = true
                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
+                return selfvar
+        end
+
+        redef fun resolve_return_mtype(v)
+        do
+                var selfvar = v.frame.selfvar
+                if has_return then
+                        var ret = msignature.return_mtype.as(not null)
+                        return_mtype = v.resolve_for(ret, selfvar)
+                end
+        end
+        redef fun resolve_ith_parameter(v, i)
+        do
+                var selfvar = v.frame.selfvar
+                var mp = msignature.mparameters[i]
+                var mtype = mp.mtype
+                if mp.is_vararg then
+                        mtype = v.mmodule.array_type(mtype)
+                end
+                mtype = v.resolve_for(mtype, selfvar)
+                return new RuntimeVariable("p{i}", mtype, mtype)
+        end
+
+        redef fun declare_signature(v, sig)
+        do
+                v.compiler.header.add_decl("{sig};")
+        end
+
+        redef fun end_compile_to_c(v)
+        do
+               if not self.c_name.has_substring("VIRTUAL", 0) then v.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
        do