[svn] r6001: nemerle/trunk/ncc: generation/ILEmitter.n generation/Typer4.n testsuite/positive/general-tail...

malekith svnadmin at nemerle.org
Tue Dec 6 14:20:58 CET 2005


Log:
Fix some uses cases of general tail call opt. Doesn't work with boot yet.

Author: malekith
Date: Tue Dec  6 14:20:57 2005
New Revision: 6001

Added:
   nemerle/trunk/ncc/testsuite/positive/general-tail-call-opt.n
Modified:
   nemerle/trunk/ncc/generation/ILEmitter.n
   nemerle/trunk/ncc/generation/Typer4.n
   nemerle/trunk/ncc/typing/TypedTree.n

Modified: nemerle/trunk/ncc/generation/ILEmitter.n
==============================================================================
--- nemerle/trunk/ncc/generation/ILEmitter.n	(original)
+++ nemerle/trunk/ncc/generation/ILEmitter.n	Tue Dec  6 14:20:57 2005
@@ -957,6 +957,8 @@
 
           def ctr_inf = GetConstructorInfo (from, base_ctor);
           _ilg.Emit (OpCodes.Call, ctr_inf);
+          when (expr.GenerateTail)
+            _ilg.Emit (OpCodes.Ret);
 
         /* create a new object */
         | Call (StaticRef (_t, meth is IMethod, _), ctor_params, _) when is_ctor (meth) =>
@@ -965,6 +967,8 @@
 
           def ctr_inf = GetConstructorInfo (_t.SystemType, meth);          
           _ilg.Emit (OpCodes.Newobj, ctr_inf);
+          when (expr.GenerateTail)
+            _ilg.Emit (OpCodes.Ret);
 
 
         /* emit a call to an instance method, basing on the 'this' pointer for value types */
@@ -1134,7 +1138,9 @@
             | ">=.u" => emit_compare (OpCodes.Bge_Un_S)
             | _ =>
               Util.ice (_method_name + ": unmatched TExpr.Opcode (" + opcode + ")")
-          };
+          }
+          when (expr.GenerateTail)
+            _ilg.Emit (OpCodes.Ret);
 
         /* -- EXCEPTION HANDLING ------------------------------------------- */
 
@@ -1684,20 +1690,15 @@
                               method : MethodInfo) : void
     {
       // Message.Debug ($"emc: $(method.Name)");
-      def is_tail =
-        match (expr) {
-          | Call (_, _, true) when Options.GeneralTailCallOpt =>
+      when (expr.GenerateTail)
             _ilg.Emit (OpCodes.Tailcall);
-            true
-          | _ => false
-        };
 
       if (base_is_value_type_or_static)
         _ilg.Emit (OpCodes.Call, method)
       else
         _ilg.Emit (OpCodes.Callvirt, method);
 
-      when (is_tail)
+      when (expr.GenerateTail)
         _ilg.Emit (OpCodes.Ret);
     }
 

Modified: nemerle/trunk/ncc/generation/Typer4.n
==============================================================================
--- nemerle/trunk/ncc/generation/Typer4.n	(original)
+++ nemerle/trunk/ncc/generation/Typer4.n	Tue Dec  6 14:20:57 2005
@@ -94,7 +94,7 @@
             #endif
 
             goto_targets.Clear ();
-            _ = Throws (body', allow_try = true);
+            _ = Throws (body', allow_try = true, is_top = true);
 
             current_fun.body = FunBody.Typed (body');
             when (Options.ShouldDump (current_fun))
@@ -207,9 +207,9 @@
         Message.Error (e.loc, "`throw' is not allowed here");
     }
 
-    static Throws (expr : TExpr, allow_try : bool = false) : bool
+    static Throws (expr : TExpr, allow_try = false, is_top = false) : bool
     {
-      log (STV, expr.loc, $ "{ throws: $expr $(expr.GetType()) ");
+      log (STV, expr.loc, $ "{ throws: top=$is_top $(expr.GetType()) $expr");
       #if CHECK_STV
         when (expr.ty != null) {
           log (STV, expr.loc, $ "( : $(expr.Type)");
@@ -245,14 +245,14 @@
           | DefValIn (_, e1, e2) =>
             if (Throws (e1, allow_try)) {
               if (IsJumpTarget (e2))
-                Throws (e2, allow_try)
+                Throws (e2, allow_try, is_top)
               else true
-            } else Throws (e2, allow_try)
+            } else Throws (e2, allow_try, is_top)
 
           | If (cond, e1, e2) =>
             _ = Throws (cond, allow_try);
-            def th1 = Throws (e1, allow_try);
-            Throws (e2, allow_try) && th1;
+            def th1 = Throws (e1, allow_try, is_top);
+            Throws (e2, allow_try, is_top) && th1;
 
           | Assign (e1, e2) =>
             when (Throws (e1))
@@ -270,20 +270,23 @@
                 true
               } else false
 
-          | TypeConversion (e, _t, _) =>
+          | TypeConversion (e, t, _) =>
             #if CHECK_STV
-              CheckSTV (_t);
+              CheckSTV (t);
             #endif
-            Throws (e, allow_try)
+            if (is_top && Options.GeneralTailCallOpt)
+              Throws (e, allow_try, t.Fix ().Equals (e.MType))
+            else
+              Throws (e, allow_try, false)
 
           | Label (_, e) =>
-            Throws (e, allow_try)
+            Throws (e, allow_try, is_top)
 
           | Switch (idx, defl, opts) =>
             // avoid closure
             mutable all = Throws (idx, allow_try);
             foreach ((_, e) in opts)
-              all = Throws (e, allow_try) && all;
+              all = Throws (e, allow_try, is_top) && all;
             match (defl) {
               | Some (e) => Throws (e) && all
               | None => all // ???
@@ -344,6 +347,7 @@
             
           | Call (func, parms, _) =>
             NoThrowPlease (func);
+            def parm_throws =
             match (parms) {
               | p :: ps =>
                 def fst = Throws (p.expr, allow_try);
@@ -352,6 +356,12 @@
                 
               | [] => false
             }
+            if (parm_throws) true
+            else
+              if (is_top && Options.GeneralTailCallOpt) {
+                expr.GenerateTail = true;
+                true
+              } else false
             
           | Tuple (exprs) =>
             exprs.Iter (NoThrowPlease);

Added: nemerle/trunk/ncc/testsuite/positive/general-tail-call-opt.n
==============================================================================
--- (empty file)
+++ nemerle/trunk/ncc/testsuite/positive/general-tail-call-opt.n	Tue Dec  6 14:20:57 2005
@@ -0,0 +1,20 @@
+// OPTIONS: -Ot
+
+def foo (x)
+{
+  bar (x - 1)
+}
+
+and bar (x : int)
+{
+  if (x < 0) {}
+  else foo (x)
+}
+
+
+foo (100000000);
+
+/*
+BEGIN-OUTPUT
+END-OUTPUT
+*/

Modified: nemerle/trunk/ncc/typing/TypedTree.n
==============================================================================
--- nemerle/trunk/ncc/typing/TypedTree.n	(original)
+++ nemerle/trunk/ncc/typing/TypedTree.n	Tue Dec  6 14:20:57 2005
@@ -413,6 +413,8 @@
     | JumpTarget           = 0x0080
 
     | Constrained          = 0x0100
+
+    | GenerateTail         = 0x0200
   }
 
   public variant TExpr : Located
@@ -482,6 +484,7 @@
     [FlagAccessor (IsAssigned, flags = WantSetter | Internal)]
     [FlagAccessor (JumpTarget, flags = WantSetter | Internal)]
     [FlagAccessor (Visited, flags = WantSetter | Internal)]
+    [FlagAccessor (GenerateTail, flags = WantSetter | Internal)]
     mutable flags : TExprFlags;
 
     #region Typer4 and ILGenerator stuff



More information about the svn mailing list