Merge: nitvm: Basic blocks generation and SSA-algorithm
authorJean Privat <jean@pryen.org>
Wed, 10 Jun 2015 01:46:34 +0000 (21:46 -0400)
committerJean Privat <jean@pryen.org>
Wed, 10 Jun 2015 01:46:34 +0000 (21:46 -0400)
This PR introduces a SSA-algorithm implementation in the nitvm.

First, basic blocks are generated. A basic block is a sequence of instructions without a jump inside.
In this version, basic blocks are generated from the AST and so they contain only the first instruction and the last one.

Then, SSA-algorithm (Single-Static Assignment) is implemented. In SSA algorithm, variables are renamed to have only one assignment per variable.
Each time an assignment is made, a new version of a variable is made.

Some variables (phi-functions) have several assignment and so, several dependances.

The basic block generation and SSA are computed for each method in a lazy way in the nitvm.
The main objective of SSA is to give the dependances for each variable (this will be used in further PR).
This module also collect all object-mechanisms sites during the visit of methods.

Pull-Request: #1425
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Jean Privat <jean@pryen.org>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>

1  2 
src/semantize/scope.nit
src/semantize/typing.nit

diff --combined src/semantize/scope.nit
@@@ -33,13 -33,13 +33,13 @@@ en
  # A local variable (including parameters, automatic variables and self)
  class Variable
        # The name of the variable (as used in the program)
-       var name: String
+       var name: String is writable
  
        # Alias of `name`
        redef fun to_s do return self.name
  
        # The declaration of the variable, if any
-       var location: nullable Location = null
+       var location: nullable Location = null is writable
  
        # Is the local variable not read and need a warning?
        var warn_unread = false is writable
@@@ -429,17 -429,9 +429,17 @@@ redef class AWithExp
        end
  end
  
 +redef class AAssertExpr
 +      redef fun accept_scope_visitor(v)
 +      do
 +              v.enter_visit(n_expr)
 +              v.enter_visit_block(n_else, null)
 +      end
 +end
 +
  redef class AVarFormExpr
        # The associated variable
-       var variable: nullable Variable
+       var variable: nullable Variable is writable
  end
  
  redef class ACallFormExpr
diff --combined src/semantize/typing.nit
@@@ -301,9 -301,15 +301,9 @@@ private class TypeVisito
  
                #debug("recv: {recvtype} (aka {unsafe_type})")
                if recvtype isa MNullType then
 -                      # `null` only accepts some methods of object.
 -                      if name == "==" or name == "!=" or name == "is_same_instance" then
 -                              var objclass = get_mclass(node, "Object")
 -                              if objclass == null then return null # Forward error
 -                              unsafe_type = objclass.mclass_type
 -                      else
 -                              self.error(node, "Error: method `{name}` called on `null`.")
 -                              return null
 -                      end
 +                      var objclass = get_mclass(node, "Object")
 +                      if objclass == null then return null # Forward error
 +                      unsafe_type = objclass.mclass_type
                end
  
                var mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
  
                assert mproperty isa MMethod
  
 +              # `null` only accepts some methods of object.
 +              if recvtype isa MNullType and not mproperty.is_null_safe then
 +                      self.error(node, "Error: method `{name}` called on `null`.")
 +                      return null
 +              else if unsafe_type isa MNullableType and not mproperty.is_null_safe then
 +                      modelbuilder.advice(node, "call-on-nullable", "Warning: method call on a nullable receiver `{recvtype}`.")
 +              end
 +
                if is_toplevel_context and recv_is_self and not mproperty.is_toplevel then
                        error(node, "Error: `{name}` is not a top-level method, thus need a receiver.")
                end
@@@ -648,7 -646,7 +648,7 @@@ en
  
  redef class Variable
        # The declared type of the variable
-       var declared_type: nullable MType
+       var declared_type: nullable MType is writable
  
        # Was the variable type-adapted?
        # This is used to speedup type retrieval while it remains `false`
@@@ -960,7 -958,7 +960,7 @@@ redef class AVarReassignExp
  
                v.set_variable(self, variable, rettype)
  
 -              self.is_typed = true
 +              self.is_typed = rettype != null
        end
  end
  
@@@ -1006,11 -1004,9 +1006,11 @@@ redef class AReturnExp
                        else
                                v.visit_expr(nexpr)
                                v.error(nexpr, "Error: `return` with value in a procedure.")
 +                              return
                        end
                else if ret_type != null then
                        v.error(self, "Error: `return` without value in a function.")
 +                      return
                end
                self.is_typed = true
        end
@@@ -1346,15 -1342,6 +1346,15 @@@ redef class AIntExp
        end
  end
  
 +redef class AByteExpr
 +      redef fun accept_typing(v)
 +      do
 +              var mclass = v.get_mclass(self, "Byte")
 +              if mclass == null then return # Forward error
 +              self.mtype = mclass.mclass_type
 +      end
 +end
 +
  redef class AFloatExpr
        redef fun accept_typing(v)
        do
@@@ -2063,7 -2050,7 +2063,7 @@@ redef class AAttrAssignExp
                var mtype = self.attr_type
  
                v.visit_expr_subtype(self.n_value, mtype)
 -              self.is_typed = true
 +              self.is_typed = mtype != null
        end
  end
  
@@@ -2074,9 -2061,9 +2074,9 @@@ redef class AAttrReassignExp
                var mtype = self.attr_type
                if mtype == null then return # Skip error
  
 -              self.resolve_reassignment(v, mtype, mtype)
 +              var rettype = self.resolve_reassignment(v, mtype, mtype)
  
 -              self.is_typed = true
 +              self.is_typed = rettype != null
        end
  end