[m-rev.] for review: hlc.agc bug fix

Fergus Henderson fjh at cs.mu.OZ.AU
Wed Apr 3 02:03:46 AEST 2002


Estimated hours taken: 4
Branches: main

Fix a bug with accurate GC.

compiler/mlds.m:
	Rename the `is_tail_call' enumeration as `call_kind',
	rename the `call' alternative as `ordinary_call', and
	and add a new alternative `no_return_call'.

compiler/ml_call_gen.m:
	Use `no_return_call' rather than `tail_call' for calls to
	procecures with determinism `erroneous'.

compiler/ml_elim_nested.m:
	Fix a bug: when adding code to unchain the stack frame before
	tail calls, add a `return' statement after each tail call, to
	ensure that we don't try to unchain the stack frame twice.
	But don't do this for calls marked `no_return_call', since
	it's not needed in that case.  (This is mandatory, not just
	an optimization: we can't construct a proper return statement
	for no_return_calls, since the return values in a `no_return_call'
	might not match the return types of the caller.)

compiler/mlds_to_c.m:
compiler/mlds_to_gcc.m:
compiler/mlds_to_il.m:
compiler/mlds_to_java.m:
compiler/ml_util.m:
compiler/ml_tailcall.m:
compiler/ml_code_gen.m:
compiler/ml_code_util.m:
	Minor changes to handle the new `no_return_call' alternative
	and the renaming of `call' as `ordinary_call'.

Workspace: /home/ceres/fjh/mercury
Index: compiler/ml_call_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_call_gen.m,v
retrieving revision 1.33
diff -u -d -r1.33 ml_call_gen.m
--- compiler/ml_call_gen.m	20 Mar 2002 12:36:44 -0000	1.33
+++ compiler/ml_call_gen.m	2 Apr 2002 14:55:30 -0000
@@ -451,14 +451,15 @@
 	% build the MLDS call statement
 	%
 	% if the called procedure has determinism `erroneous'
-	% then it's always safe to make this call a tail call.
+	% then mark it as never returning
+	% (this will ensure that it gets treated as a tail call)
 	{ Detism = erroneous ->
-		CallOrTailcall = tail_call
+		CallKind = no_return_call
 	;
-		CallOrTailcall = call
+		CallKind = ordinary_call
 	},
 	{ MLDS_Stmt = call(Signature, FuncRval, ObjectRval, ArgRvals, RetLvals,
-			CallOrTailcall) },
+			CallKind) },
 	{ MLDS_Statement = mlds__statement(MLDS_Stmt,
 			mlds__make_context(Context)) },
 	{ MLDS_Statements = [MLDS_Statement] }.
Index: compiler/ml_code_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_code_gen.m,v
retrieving revision 1.111
diff -u -d -r1.111 ml_code_gen.m
--- compiler/ml_code_gen.m	20 Mar 2002 12:36:45 -0000	1.111
+++ compiler/ml_code_gen.m	2 Apr 2002 14:58:56 -0000
@@ -1861,9 +1861,9 @@
 		),
 		{ RetTypes = [] },
 		{ Signature = mlds__func_signature(ArgTypes, RetTypes) },
-		{ CallOrTailcall = call },
+		{ CallKind = ordinary_call },
 		{ CallStmt = call(Signature, CommitFuncLabelRval, no,
-			ArgRvals, [], CallOrTailcall) },
+			ArgRvals, [], CallKind) },
 		{ CallStatement = mlds__statement(CallStmt,
 			mlds__make_context(Context)) },
 		% Package it all up
Index: compiler/ml_code_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_code_util.m,v
retrieving revision 1.60
diff -u -d -r1.60 ml_code_util.m
--- compiler/ml_code_util.m	27 Mar 2002 15:24:18 -0000	1.60
+++ compiler/ml_code_util.m	2 Apr 2002 15:00:17 -0000
@@ -1928,9 +1928,9 @@
 	{ Signature = mlds__func_signature(ArgTypes, RetTypes) },
 	{ ObjectRval = no },
 	{ RetLvals = [] },
-	{ CallOrTailcall = call },
+	{ CallKind = ordinary_call },
 	{ MLDS_Stmt = call(Signature, FuncRval, ObjectRval, ArgRvals, RetLvals,
-			CallOrTailcall) },
+			CallKind) },
 	{ MLDS_Statement = mlds__statement(MLDS_Stmt,
 			mlds__make_context(Context)) }.
 
@@ -1959,7 +1959,7 @@
 	{ Signature = mlds__func_signature(ArgTypes, RetTypes) },
 	{ ObjectRval = no },
 	{ RetLvals = [] },
-	{ CallOrTailcall = call },
+	{ CallKind = ordinary_call },
 
 	{ MLDS_Context = mlds__make_context(Context) },
 	=(MLDSGenInfo),
@@ -1997,7 +1997,7 @@
 			Rets) },
 
 	{ InnerMLDS_Stmt = call(Signature, InnerFuncRval, ObjectRval, 
-			InnerArgRvals, RetLvals, CallOrTailcall) },
+			InnerArgRvals, RetLvals, CallKind) },
 	{ InnerMLDS_Statement = statement(InnerMLDS_Stmt, MLDS_Context) },
 
 	ml_gen_label_func(1, InnerFuncParams, Context, 
@@ -2019,7 +2019,7 @@
 
 		% Put it inside a block where we call it.
 		MLDS_Stmt = call(ProxySignature, ProxyFuncRval, ObjectRval,
-			ProxyArgRvals, RetLvals, CallOrTailcall),
+			ProxyArgRvals, RetLvals, CallKind),
 		MLDS_Statement = mlds__statement(
 			block([Defn], [statement(MLDS_Stmt, MLDS_Context)]), 
 			MLDS_Context)
@@ -2317,7 +2317,7 @@
 	{ CastVarAddr = unop(cast(CPointerType), mem_addr(VarLval)) },
 	{ MLDS_TraceStatement = mlds__statement(
 		call(Signature, FuncAddr, no,	
-			[TypeInfoRval, CastVarAddr], [], call
+			[TypeInfoRval, CastVarAddr], [], ordinary_call
 		), mlds__make_context(Context)) }.
 
 	% Generate HLDS code to construct the type_info for this type.
Index: compiler/ml_elim_nested.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_elim_nested.m,v
retrieving revision 1.56
diff -u -d -r1.56 ml_elim_nested.m
--- compiler/ml_elim_nested.m	27 Mar 2002 15:24:19 -0000	1.56
+++ compiler/ml_elim_nested.m	2 Apr 2002 15:04:40 -0000
@@ -2223,14 +2223,9 @@
 		{ Stmt0 = computed_goto(_Rval, _Labels) },
 		{ Stmt = Stmt0 }
 	;
-		{ Stmt0 = call(_Sig, _Func, _Obj, _Args, _RetLvals, TailCall) },
-		( { TailCall = tail_call } ->
-			=(ElimInfo),
-			{ Stmt = prepend_unchain_frame(Stmt0, Context,
-				ElimInfo) }
-		;
-			{ Stmt = Stmt0 }
-		)
+		{ Stmt0 = call(_Sig, _Func, _Obj, _Args, RetLvals, CallKind) },
+		add_unchain_stack_to_call(Stmt0, RetLvals, CallKind, Context,
+			Stmt)
 	;
 		{ Stmt0 = return(_Rvals) },
 		=(ElimInfo),
@@ -2245,6 +2240,36 @@
 		{ Stmt = try_commit(Ref, Statement, Handler) }
 	;
 		{ Stmt0 = atomic(_AtomicStmt0) },
+		{ Stmt = Stmt0 }
+	).
+
+:- pred add_unchain_stack_to_call(mlds__stmt, list(mlds__lval),
+		mlds__call_kind, mlds__context, mlds__stmt,
+		elim_info, elim_info).
+:- mode add_unchain_stack_to_call(in, in, in, in, out, in, out) is det.
+add_unchain_stack_to_call(Stmt0, RetLvals, CallKind, Context, Stmt) -->
+	(
+		{ CallKind = no_return_call },
+		% For no-return calls, we just unchain the stack
+		% frame before the call.
+		=(ElimInfo),
+		{ Stmt = prepend_unchain_frame(Stmt0, Context, ElimInfo) }
+	;
+		{ CallKind = tail_call },
+		% For tail calls, we unchain the stack frame before the call,
+		% and then we insert a return statement after the call.
+		% The return statement is needed ensure that the code doesn't
+		% fall through (past the tail call) and then try to unchain
+		% the already-unchained stack frame.
+		=(ElimInfo),
+		{ UnchainFrame = ml_gen_unchain_frame(Context, ElimInfo) },
+		{ Statement0 = mlds__statement(Stmt0, Context) },
+		{ RetRvals = list__map(func(Rval) = lval(Rval), RetLvals) },
+		{ RetStmt = return(RetRvals) },
+		{ RetStatement = mlds__statement(RetStmt, Context) },
+		{ Stmt = block([], [UnchainFrame, Statement0, RetStatement]) }
+	;
+		{ CallKind = ordinary_call },
 		{ Stmt = Stmt0 }
 	).
 
Index: compiler/ml_tailcall.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_tailcall.m,v
retrieving revision 1.16
diff -u -d -r1.16 ml_tailcall.m
--- compiler/ml_tailcall.m	20 Mar 2002 12:36:47 -0000	1.16
+++ compiler/ml_tailcall.m	2 Apr 2002 14:56:18 -0000
@@ -49,7 +49,8 @@
 % any backend support for them.
 %
 % Note that ml_call_gen.m will also mark calls to procedures with determinism
-% `erroneous' as tail calls when it generates them.
+% `erroneous' as `no_return_call's (a special case of tail calls)
+% when it generates them.
 
 %-----------------------------------------------------------------------------%
 
@@ -274,11 +275,12 @@
 		Stmt0 = computed_goto(_, _),
 		Stmt = Stmt0
 	;
-		Stmt0 = call(Sig, Func, Obj, Args, ReturnLvals, _TailCall0),
+		Stmt0 = call(Sig, Func, Obj, Args, ReturnLvals, CallKind0),
 		%
 		% check if we can mark this call as a tail call
 		%
 		(
+			CallKind0 = ordinary_call,
 			%
 			% we must be in a tail position
 			%
@@ -297,9 +299,9 @@
 			check_rvals(Args, Locals)
 		->
 			% mark this call as a tail call
-			TailCall = tail_call,
+			CallKind = tail_call,
 			Stmt = call(Sig, Func, Obj, Args, ReturnLvals,
-					TailCall)
+					CallKind)
 		;
 			% leave this call unchanged
 			Stmt = Stmt0
@@ -606,8 +608,8 @@
 	% nondeterministically find a non-tail call
 	statement_contains_statement(Statement, SubStatement),
 	SubStatement = mlds__statement(SubStmt, Context),
-	SubStmt = call(_CallSig, Func, _This, _Args, _RetVals, IsTailCall),
-	IsTailCall = call,
+	SubStmt = call(_CallSig, Func, _This, _Args, _RetVals, CallKind),
+	CallKind = ordinary_call,
 	% check if this call is a directly recursive call
 	Func = const(code_addr_const(CodeAddr)),
 	( CodeAddr = proc(QualProcLabel, _Sig), MaybeSeqNum = no
Index: compiler/ml_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_util.m,v
retrieving revision 1.18
diff -u -d -r1.18 ml_util.m
--- compiler/ml_util.m	20 Mar 2002 12:36:48 -0000	1.18
+++ compiler/ml_util.m	2 Apr 2002 14:54:08 -0000
@@ -162,11 +162,11 @@
 
 can_optimize_tailcall(Name, Call) :-
 	Call = call(_Signature, FuncRval, MaybeObject, _CallArgs,
-		_Results, IsTailCall),
+		_Results, CallKind),
 	%
 	% check if this call can be optimized as a tail call
 	%
-	IsTailCall = tail_call,
+	( CallKind = tail_call ; CallKind = no_return_call ),
 
 	%
 	% check if the callee adddress is the same as
Index: compiler/mlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds.m,v
retrieving revision 1.87
diff -u -d -r1.87 mlds.m
--- compiler/mlds.m	20 Mar 2002 12:36:48 -0000	1.87
+++ compiler/mlds.m	2 Apr 2002 14:31:08 -0000
@@ -917,7 +917,7 @@
 			list(mlds__rval),	% ordinary function arguments
 			list(mlds__lval),	% places to store the
 						% function return value(s)
-			is_tail_call		% indicates whether this
+			call_kind		% indicates whether this
 						% call is a tail call
 		)
 
@@ -1075,9 +1075,24 @@
 % Extra info for calls
 %
 
-:- type is_tail_call
-	--->	tail_call	% a tail call
-	;	call		% just an ordinary call
+	% The `call_kind' type indicates whether a call is a tail call
+	% and whether the call is know to never return.
+	%
+	% Marking a call as a tail_call is intended as a hint to
+	% the target language that this call can be implemented
+	% by removing the caller's stack frame and jumping to the
+	% destination, rather than a normal call.
+	% However, the target code generator need not obey this hint;
+	% it is permitted for the target code generator to ignore the
+	% hint and generate code which does not remove the caller's
+	% stack frame and/or which falls through to the following
+	% statement.
+	% 
+:- type call_kind
+	--->	no_return_call	% a call that never returns
+				% (this is a special case of a tail call)
+	;	tail_call	% a tail call
+	;	ordinary_call	% just an ordinary call
 	.
 
 %-----------------------------------------------------------------------------%
Index: compiler/mlds_to_c.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_c.m,v
retrieving revision 1.123
diff -u -d -r1.123 mlds_to_c.m
--- compiler/mlds_to_c.m	20 Mar 2002 12:36:49 -0000	1.123
+++ compiler/mlds_to_c.m	2 Apr 2002 14:37:56 -0000
@@ -2216,7 +2216,8 @@
 	% the call -- see below.
 	%
 	% Note that it's only safe to add such a return statement if
-	% the calling procedure has the same argument types as the callee.
+	% the calling procedure has the same return types as the callee,
+	% or if the calling procedure has no return value.
 	% (Calls where the types are different can be marked as tail calls
 	% if they are known to never return.)
 	%
@@ -2224,7 +2225,7 @@
 	{ Signature = mlds__func_signature(_, RetTypes) },
 	{ CallerSignature = mlds__func_signature(_, CallerRetTypes) },
 	(
-		{ IsTailCall = tail_call },
+		{ IsTailCall = tail_call ; IsTailCall = no_return_call },
 		{ Results \= [] },
 		{ RetTypes = CallerRetTypes }
 	->
@@ -2253,9 +2254,8 @@
 	io__write_string(");\n"),
 
 	(
-		{ IsTailCall = tail_call },
-		{ Results = [] },
-		{ RetTypes = CallerRetTypes }
+		{ IsTailCall = tail_call ; IsTailCall = no_return_call },
+		{ CallerRetTypes = [] }
 	->
 		mlds_indent(Context, Indent + 1),
 		io__write_string("return;\n")
Index: compiler/mlds_to_gcc.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_gcc.m,v
retrieving revision 1.67
diff -u -d -r1.67 mlds_to_gcc.m
--- compiler/mlds_to_gcc.m	31 Mar 2002 08:03:25 -0000	1.67
+++ compiler/mlds_to_gcc.m	2 Apr 2002 14:35:09 -0000
@@ -2489,14 +2489,22 @@
 	%
 gen_stmt(DefnInfo, Call, _) -->
 	{ Call = call(_Signature, FuncRval, MaybeObject, CallArgs,
-		Results, IsTailCall) },
+		Results, CallKind) },
 	{ require(unify(MaybeObject, no), this_file ++ ": method call") },
 	build_args(CallArgs, DefnInfo, GCC_ArgList),
 	build_rval(FuncRval, DefnInfo, GCC_FuncRval),
+	{
+		CallKind = no_return_call,
+		IsTailCall = yes
+	;
+		CallKind = tail_call,
+		IsTailCall = yes
+	;
+		CallKind = ordinary_call,
+		IsTailCall = no
+	},
 	% XXX GCC currently ignores the tail call boolean
-	{ IsTailCallBool = (IsTailCall = tail_call -> yes ; no) },
-	gcc__build_call_expr(GCC_FuncRval, GCC_ArgList, IsTailCallBool,
-		GCC_Call),
+	gcc__build_call_expr(GCC_FuncRval, GCC_ArgList, IsTailCall, GCC_Call),
 	( { Results = [ResultLval] } ->
 		build_lval(ResultLval, DefnInfo, GCC_ResultExpr),
 		gcc__gen_assign(GCC_ResultExpr, GCC_Call)
Index: compiler/mlds_to_il.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_il.m,v
retrieving revision 1.110
diff -u -d -r1.110 mlds_to_il.m
--- compiler/mlds_to_il.m	20 Mar 2002 12:36:51 -0000	1.110
+++ compiler/mlds_to_il.m	2 Apr 2002 15:01:26 -0000
@@ -1329,7 +1329,7 @@
 		% XXX should we look for tail calls?
 	CallStatement = statement(
 		call(Signature, CodeRval, no, ArgRvals, ReturnLvals,
-			call), Context),
+			ordinary_call), Context),
 	ReturnStatement = statement(return(ReturnRvals), Context),
 
 	Statement = statement(mlds__block(ReturnVarDecls,
@@ -1563,7 +1563,7 @@
 	atomic_statement_to_il(Atomic, AtomicInstrs),
 	{ Instrs = tree(context_node(Context), AtomicInstrs) }.
 
-statement_to_il(statement(call(Sig, Function, _This, Args, Returns, IsTail), 
+statement_to_il(statement(call(Sig, Function, _This, Args, Returns, CallKind), 
 		Context), Instrs) -->
 	VerifiableCode =^ verifiable_code,
 	ByRefTailCalls =^ il_byref_tailcalls,
@@ -1574,7 +1574,7 @@
 	CallerSig =^ signature,
 	{ CallerSig = signature(_, CallerReturnParam, _) },
 	(
-		{ IsTail = tail_call },
+		{ CallKind = tail_call ; CallKind = no_return_call },
 		% if --verifiable-code is enabled,
 		% and the arguments contain one or more byrefs,
 		% then don't emit the "tail." prefix,
Index: compiler/mlds_to_java.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_java.m,v
retrieving revision 1.26
diff -u -d -r1.26 mlds_to_java.m
--- compiler/mlds_to_java.m	20 Mar 2002 12:36:52 -0000	1.26
+++ compiler/mlds_to_java.m	2 Apr 2002 14:58:00 -0000
@@ -762,7 +762,7 @@
 		CallRetLvals = [ReturnLval]
 	),
 	Call = mlds__call(OrigFuncSignature, CallRval, no, CallArgs,
-			CallRetLvals, call),
+			CallRetLvals, ordinary_call),
 	CallStatement = mlds__statement(Call, Context),
 	%
 	% Create a return statement that returns the result of the call to the

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list