[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