for review: last call modulo constructors [1/3]

David Matthew Overton dmo at students.cs.mu.OZ.AU
Mon Jun 22 16:30:42 AEST 1998


Hi Andrew,

Could you please review this, since you are familiar with the alias
branch.  Anyone else who wants to have a look, feel free.

David
-- 
David Overton
MEngSc Student                       Email: dmo at cs.mu.oz.au     
Department of Computer Science       Web: http://www.cs.mu.oz.au/~dmo
The University of Melbourne          Phone: +61 3 9344 9159


Estimated hours taken: 500

- Add support for pass-by-reference in the code generator.
- Add partial support for aliasing between free variables in the mode
  system.
- Use the above changes to implement the last call modulo constructors
  optimisation (LCO).

Current known problems:  LCO does not currently work in conjunction
with value-numbering, termination analysis or follow-code.  The
follow-code problem is with merging alias insts at the end of branch
structures -- Andrew Bromage is working on this.

Tag: alias

compiler/inst.m:
	Add an argument to `free' insts to say whether or not they are
	aliased.

compiler/code_exprn.m:
	Add support for references to `free(alias)' variables in the
	exprn_info and add some new predicates to deal with them.

compiler/hlds_pred.m:
	Add new functors `ref_out' and `ref_in' to the `arg_mode'
	type.  These are for `free(unique) -> free(alias)' and
	`free(alias) -> bound(...)' modes, respectively.

compiler/lco.m:
	Last call modulo constructors optimisation (LCO).
	When a procedure ends with a call followed only by
	construction unifications, move the constructions to before
	the call.  Modify the call and the called procedure to use
	pass-by-reference for arguments which are now `free(alias)'.
	This re-ordering provides more opportunities for tailcall
	optimisation and reduces the number of live variables at the
	call, thus hopefully reducing the number of stack slots
	needed.
	Current limitations: 
	- The caller and callee must both be in the same module.
	- Only one reference is allowed per `free(alias)' variable.
	  This will be fixed by adding a free(alias_many) inst and
	  appropriate changes to the code generator.
	- If any of the constructions are for `no_tag' types then the
	  re-ordering is not done.  Support for some of the
	  constructions being for `no_tag' types will be added soon.
	  (Of course, if _all_ the constructions are for `no_tag'
	  types, there is no point doing the re-ordering.)

compiler/arg_info.m:
compiler/call_gen.m:
compiler/code_info.m:
compiler/follow_vars.m:
compiler/hlds_out.m:
compiler/store_alloc.m:
	Distinguish between pass-by-value and pass-by-reference
	arguments/variables.

compiler/common.m:
compiler/higher_order.m:
compiler/hlds_out.m:
compiler/instmap.m:
compiler/make_hlds.m:
compiler/mercury_to_mercury.m:
compiler/module_qual.m:
compiler/polymorphism.m :
compiler/prog_io_util.m:
compiler/prog_util.m:
compiler/table_gen.m:
	Add an argument to `free' insts to say whether or not they are
	aliased.

compiler/export.m:
	Add `ref_in' and `ref_out' arg_modes to switches in
	`get_input_args' and `copy_output_args'.  But don't produce
	any code for them yet. (XXXs have been added in appropriate
	places).
	
compiler/exprn_aux.m:
	Move declarations for `exprn_aux__lval_contains_lval' and
	`exprn_aux__substitute_lval_in_lval' into the interface so
	they can be used by `code_exprn.m'.

compiler/hlds_goal.m:
	Distinguish between values and references in `follow_vars' and
	`store_map' types.
	Add a new argument to the `goal_info' containing the set of
	live reference vars.  This is needed during code generation to
	update the `exprn_info' correctly in unreachable branches.

compiler/inst_match.m:
	Add new predicates to test for `free(alias)' insts.
	Modify `inst_matches_*' predicates to allow for `free(alias)'
	insts.

compiler/inst_util.m:
	Allow abstract unification of free insts with partially
	instantiated bound insts.

compiler/live_vars.m:
	Add an extra argument to the call to `initial_liveness'.

compiler/liveness.m:
	Add support for `ref_in' and `ref_out' arg_modes.
	Compute the set of live reference vars in the `goal_info'.

compiler/llds.m:
	Add the type `val_or_ref' to indicate whether an argument is a
	value or reference.

compiler/llds_out.m:
	Output a pointer de-reference for `mem_ref' lvals.

compiler/mercury_compile.m:
	Call LCO before dead procedure elimination because LCO may
	cause some procedures to become dead.
	Allow the `module_info' to be threaded through LCO.

compiler/mode_util.m:
	Add support for `free(alias)' insts and `ref_in' and `ref_out'
	arg_modes to `mode_to_arg_mode/4'.

compiler/modecheck_unify.m:
	Add support for `free(alias)' insts.
	Disallow scheduling of constructions of partially instantiated
	data structures until we come up with a better algorithm for
	when this should be done and when it shouldn't.  At the
	moment, partially instantiated data structures are only
	created by LCO, which is called after mode checking.

compiler/par_conj_gen.m:
	Convert `stack_slots' to `store_map' (which are now different
	types) before calling `code_info__generate_branch_end'.

compiler/pd_util.m:
	Pass `io__state' to `simplify__process_goal'.
	Add support for the extra argument to `free' insts.

compiler/simplify.m:
	Call `modecheck_queued_procs' after `recompute_instmap_delta'
	because new unification procs may have been created.
	Don't allow removal of ``excess'' assignments if either of the
	variables has inst `free(alias)' before the assignment.

compiler/unify_gen.m:
	Generate code for construction of partially instantiated data
	structures.
	Place result of constructions in the correct place if the LHS
	variable has mode `ref_in'.
	Generate code for assignments between `free(alias)' and
	`free(unique)' variables.

compiler/stratify.m:
	Fix a spelling mistake (s/_IMelta/_IMDelta/).

compiler/det_util.m:
	Rename a variable (s/IKT/InstTable).

Index: compiler/arg_info.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/arg_info.m,v
retrieving revision 1.23.4.7
diff -u -r1.23.4.7 arg_info.m
--- 1.23.4.7	1998/06/05 08:42:29
+++ arg_info.m	1998/06/22 01:23:56
@@ -48,7 +48,7 @@
 	% Given a list of the head variables and their argument information,
 	% return a list giving the input variables and their initial locations.
 :- pred arg_info__build_input_arg_list(assoc_list(var, arg_info),
-	assoc_list(var, rval)).
+	assoc_list(var, val_or_ref)).
 :- mode arg_info__build_input_arg_list(in, out) is det.
 
 %-----------------------------------------------------------------------------%
@@ -207,6 +207,20 @@
 		ArgReg = OutReg0,
 		InReg1 = InReg0,
 		OutReg1 is OutReg0 + 1
+	;
+		% Treat aliased args as input because we need to pass in 
+		% a pointer to the memory location.
+		ArgMode = ref_in,
+		ArgReg = InReg0,
+		InReg1 is InReg0 + 1,
+		OutReg1 = OutReg0
+	;
+		% Treat ref_out the same as output because we will need to
+		% return a reference.
+		ArgMode = ref_out,
+		ArgReg = OutReg0,
+		InReg1 = InReg0,
+		OutReg1 is OutReg0 + 1
 	),
 	ArgInfo = arg_info(ArgReg, ArgMode),
 	make_arg_infos_compact_list(Modes, Types, InReg1, OutReg1,
@@ -239,11 +253,12 @@
 arg_info__build_input_arg_list([], []).
 arg_info__build_input_arg_list([V - Arg | Rest0], VarArgs) :-
 	Arg = arg_info(Loc, Mode),
-	(
-		Mode = top_in
-	->
+	( Mode = top_in  ->
+		code_util__arg_loc_to_register(Loc, Reg),
+		VarArgs = [V - value(lval(Reg)) | VarArgs0]
+	; Mode = ref_in ->
 		code_util__arg_loc_to_register(Loc, Reg),
-		VarArgs = [V - lval(Reg) | VarArgs0]
+		VarArgs = [V - reference(Reg) | VarArgs0]
 	;
 		VarArgs = VarArgs0
 	),
Index: compiler/call_gen.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/call_gen.m,v
retrieving revision 1.113.4.8
diff -u -r1.113.4.8 call_gen.m
--- 1.113.4.8	1998/06/05 08:42:48
+++ call_gen.m	1998/06/22 01:02:35
@@ -478,7 +478,11 @@
 
 call_gen__save_variables_2([], empty) --> [].
 call_gen__save_variables_2([Var | Vars], Code) -->
-	code_info__save_variable_on_stack(Var, CodeA),
+	( code_info__var_is_free_alias(Var) ->
+		code_info__save_reference_on_stack(Var, CodeA)
+	;
+		code_info__save_variable_on_stack(Var, CodeA)
+	),
 	call_gen__save_variables_2(Vars, CodeB),
 	{ Code = tree(CodeA, CodeB) }.
 
@@ -504,6 +508,11 @@
 		{ code_util__arg_loc_to_register(ArgLoc, Register) },
 		code_info__set_var_location(Var, Register)
 	;
+		{ Mode = ref_out }
+	->
+		{ code_util__arg_loc_to_register(ArgLoc, Register) },
+		code_info__set_var_reference_location(Var, Register)
+	;
 		{ true }
 	),
 	call_gen__rebuild_registers_2(Args).
@@ -582,7 +591,7 @@
 call_gen__partition_args([], [], []).
 call_gen__partition_args([V - arg_info(_Loc,Mode) | Rest], Ins, Outs) :-
 	(
-		Mode = top_in
+		( Mode = top_in ; Mode = ref_in )
 	->
 		call_gen__partition_args(Rest, Ins0, Outs),
 		Ins = [V | Ins0]
@@ -684,7 +693,7 @@
 call_gen__select_out_args([V - arg_info(_Loc, Mode) | Rest], Out) :-
 	call_gen__select_out_args(Rest, Out0),
 	(
-		Mode = top_out
+		( Mode = top_out ; Mode = ref_out )
 	->
 		set__insert(Out0, V, Out)
 	;
@@ -699,7 +708,7 @@
 call_gen__input_args([], []).
 call_gen__input_args([arg_info(Loc, Mode) | Args], Vs) :-
 	(
-		Mode = top_in
+		( Mode = top_in ; Mode = ref_in )
 	->
 		Vs = [Loc |Vs0]
 	;
@@ -712,7 +721,7 @@
 call_gen__input_arg_locs([], []).
 call_gen__input_arg_locs([Var - arg_info(Loc, Mode) | Args], Vs) :-
 	(
-		Mode = top_in
+		( Mode = top_in ; Mode = ref_in )
 	->
 		Vs = [Var - Loc | Vs0]
 	;
@@ -723,7 +732,7 @@
 call_gen__output_arg_locs([], []).
 call_gen__output_arg_locs([Var - arg_info(Loc, Mode) | Args], Vs) :-
 	(
-		Mode = top_out
+		( Mode = top_out ; Mode = ref_out )
 	->
 		Vs = [Var - Loc | Vs0]
 	;
Index: compiler/code_exprn.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/code_exprn.m,v
retrieving revision 1.51.4.5
diff -u -r1.51.4.5 code_exprn.m
--- 1.51.4.5	1998/06/05 08:43:04
+++ code_exprn.m	1998/06/22 01:28:00
@@ -55,7 +55,7 @@
 %		the table of options; this is used to decide what expressions
 %		are considered constants.
 
-:- pred code_exprn__init_state(assoc_list(var, rval), varset, stack_slots,
+:- pred code_exprn__init_state(assoc_list(var, val_or_ref), varset, stack_slots,
 	follow_vars, option_table, exprn_info).
 :- mode code_exprn__init_state(in, in, in, in, in, out) is det.
 
@@ -68,7 +68,8 @@
 %		of variables and lvalues. The new state places the given
 %		variables at their corresponding locations.
 
-:- pred code_exprn__reinit_state(assoc_list(var, rval), exprn_info, exprn_info).
+:- pred code_exprn__reinit_state(assoc_list(var, val_or_ref), exprn_info,
+		exprn_info).
 :- mode code_exprn__reinit_state(in, in, out) is det.
 
 %	code_exprn__clobber_regs(CriticalVars, ExprnInfo0, ExprnInfo)
@@ -91,6 +92,14 @@
 :- pred code_exprn__maybe_set_var_location(var, lval, exprn_info, exprn_info).
 :- mode code_exprn__maybe_set_var_location(in, in, in, out) is det.
 
+%      code_exprn__set_var_reference_location(Var, Lval, ExprnInfo0, ExprnInfo)
+%		Modifies ExprnInfo0 to record that Lval holds an address
+%		where the value of Var will be placed.
+
+:- pred code_exprn__set_var_reference_location(var, lval,
+		exprn_info, exprn_info).
+:- mode code_exprn__set_var_reference_location(in, in, in, out) is det.
+
 :- pred code_exprn__lval_in_use(lval, exprn_info, exprn_info).
 :- mode code_exprn__lval_in_use(in, in, out) is semidet.
 
@@ -123,10 +132,27 @@
 %		ExprnInfo which places the value of each variable
 %		mentioned in the store map into the corresponding location.
 
-:- pred code_exprn__place_vars(assoc_list(var, lval), code_tree,
+:- pred code_exprn__place_vars(assoc_list(var, store_info), code_tree,
 	exprn_info, exprn_info).
 :- mode code_exprn__place_vars(in, out, in, out) is det.
 
+%	code_exprn__place_var_in_references(Var, Code, ExprnInfo0, ExprnInfo)
+% 		If the Var has a set of reference locations associated with
+%		it, place it in these locations and remove them from the
+%		locations set.
+:- pred code_exprn__place_var_in_references(var, code_tree,
+		exprn_info, exprn_info).
+:- mode code_exprn__place_var_in_references(in, out, in, out) is det.
+
+
+%	code_exprn__place_var_reference(Var, Lval, Code, ExprnInfo0, ExprnInfo)
+%		Produces code to place the reference to Var's location
+%		in Lval, if it isn't already there.
+
+:- pred code_exprn__place_var_reference(var, lval, code_tree, exprn_info,
+	exprn_info).
+:- mode code_exprn__place_var_reference(in, in, out, in, out) is det.
+
 %	code_exprn__produce_var(Var, Rval, Code, ExprnInfo0, ExprnInfo)
 %		Produces a code fragment Code to evaluate Var and
 %		provide it as Rval (which may be a const, etc, or an lval).
@@ -152,6 +178,10 @@
 	exprn_info, exprn_info).
 :- mode code_exprn__produce_var_in_reg_or_stack(in, out, out, in, out) is det.
 
+:- pred code_exprn__produce_ref_in_reg_or_stack(var, lval, code_tree,
+	exprn_info, exprn_info).
+:- mode code_exprn__produce_ref_in_reg_or_stack(in, out, out, in, out) is det.
+
 %	code_exprn__materialize_vars_in_rval(Rval0, Rval, Code, ExprnInfo0,
 %		ExprnInfo)
 %		Produces code to materialize any vars that occur in `Rval0'
@@ -239,6 +269,10 @@
 :- pred code_exprn__set_follow_vars(follow_vars, exprn_info, exprn_info).
 :- mode code_exprn__set_follow_vars(in, in, out) is det.
 
+:- pred code_exprn__value_to_rval(val_or_ref::in, rval::out) is semidet.
+
+:- pred code_exprn__reference_to_lval(val_or_ref::in, lval::out) is semidet.
+
 %	code_exprn__max_reg_in_use(MaxReg)
 %		Returns the number of the highest numbered rN register in use.
 
@@ -254,9 +288,27 @@
 :- import_module bool, bag, require, int, term, string, std_util.
 
 :- type var_stat	--->	evaled(set(rval))
-			;	cached(rval).
+			;	cached(rval)
+			;	none
+			.
+
+
+%	var_info stores information about the current status of a variable
+% 	and the set of locations where the variable value should be put when
+%	the cache is flushed.
+:- type var_info	--->
+			var_info(
+				var_refs,
+				var_stat
+					% Current status of variable value.
+			).
+
+% Locations where the value needs to be placed, Each lval in a
+% set(lval) should point to the same place.  The bool is yes if the
+% value is already in this location, otherwise it is no.
+:- type var_refs == set(pair(bool, set(lval))).
 
-:- type var_map	==	map(var, var_stat).
+:- type var_map	==	map(var, var_info).
 
 :- type exprn_info	--->
 		exprn_info(
@@ -291,28 +343,52 @@
 	ExprnInfo = exprn_info(Varset, Vars, Regs, Acqu,
 		StackSlots, FollowVars, ExprnOpts).
 
-:- pred code_exprn__init_state_2(assoc_list(var, rval), var_map, var_map,
+:- pred code_exprn__init_state_2(assoc_list(var, val_or_ref), var_map, var_map,
 	bag(lval), bag(lval)).
 :- mode code_exprn__init_state_2(in, in, out, in, out) is det.
 
 code_exprn__init_state_2([], Vars, Vars, Regs, Regs).
-code_exprn__init_state_2([V - L | Rest], Vars0, Vars, Regs0, Regs) :-
-	(
-		map__search(Vars0, V, evaled(Vals0))
-	->
-		set__insert(Vals0, L, Vals),
-		map__det_update(Vars0, V, evaled(Vals), Vars1)
-	;
-		set__singleton_set(Vals, L),
-		map__det_insert(Vars0, V, evaled(Vals), Vars1)
-	),
-	(
-		L = lval(Loc),
-		Loc = reg(_, _)
-	->
-		bag__insert(Regs0, Loc, Regs1)
-	;
-		Regs1 = Regs0
+code_exprn__init_state_2([V - VVal | Rest], Vars0, Vars, Regs0, Regs) :-
+	( VVal = value(Rval),
+		( map__search(Vars0, V, var_info(Locs0, Stat)) ->
+			( Stat = evaled(Vals0) ->
+				set__insert(Vals0, Rval, Vals),
+				VarInfo = var_info(Locs0, evaled(Vals)),
+				map__det_update(Vars0, V, VarInfo, Vars1)
+			;
+				set__singleton_set(Vals, Rval),
+				VarInfo = var_info(Locs0, evaled(Vals)),
+				map__det_update(Vars0, V, VarInfo, Vars1)
+			)
+		;
+			set__singleton_set(Vals, Rval),
+			set__init(Locs),
+			VarInfo = var_info(Locs, evaled(Vals)),
+			map__det_insert(Vars0, V, VarInfo, Vars1)
+		),
+		(
+			Rval = lval(Loc),
+			Loc = reg(_, _)
+		->
+			bag__insert(Regs0, Loc, Regs1)
+		;
+			Regs1 = Regs0
+		)
+	; VVal = reference(Lval),
+		set__singleton_set(Lvals, Lval),
+		( map__search(Vars0, V, var_info(Locs0, Stat)) ->
+			set__insert(Locs0, no - Lvals, Locs),
+			map__det_update(Vars0, V, var_info(Locs, Stat), Vars1)
+		;
+			set__singleton_set(Locs, no - Lvals),
+			map__det_insert(Vars0, V, var_info(Locs, none),
+				Vars1)
+		),
+		( Lval = reg(_, _) ->
+			bag__insert(Regs0, Lval, Regs1)
+		;
+			Regs1 = Regs0
+		)
 	),
 	code_exprn__init_state_2(Rest, Vars1, Vars, Regs1, Regs).
 
@@ -324,19 +400,24 @@
 	map__init(Locations0),
 	code_exprn__repackage_locations(VarList, Locations0, Locations).
 
-:- pred code_exprn__repackage_locations(assoc_list(var, var_stat),
+:- pred code_exprn__repackage_locations(assoc_list(var, var_info),
 			map(var, set(rval)), map(var, set(rval))).
 :- mode code_exprn__repackage_locations(in, in, out) is det.
 
 code_exprn__repackage_locations([], Loc, Loc).
-code_exprn__repackage_locations([V - Locs | Rest], Loc0, Loc) :-
+code_exprn__repackage_locations([V - var_info(_, Locs) | Rest], Loc0, Loc) :-
 	(
-		Locs = cached(Rval),
-		set__singleton_set(Rvals, Rval)
+		(
+			Locs = cached(Rval),
+			set__singleton_set(Rvals, Rval)
+		;
+			Locs = evaled(Rvals)
+		)
+	->
+		map__set(Loc0, V, Rvals, Loc1)
 	;
-		Locs = evaled(Rvals)
+		Loc1 = Loc0
 	),
-	map__set(Loc0, V, Rvals, Loc1),
 	code_exprn__repackage_locations(Rest, Loc1, Loc).
 
 %------------------------------------------------------------------------------%
@@ -353,12 +434,14 @@
 	{ set__init(Acqu) },
 	code_exprn__set_acquired(Acqu).
 
-:- pred code_exprn__clobber_regs_2(assoc_list(var, var_stat), list(var),
+:- pred code_exprn__clobber_regs_2(assoc_list(var, var_info), list(var),
 						var_map, var_map, var_map).
 :- mode code_exprn__clobber_regs_2(in, in, in, in, out) is det.
 
 code_exprn__clobber_regs_2([], _Critical, _OldVars, Vars, Vars).
-code_exprn__clobber_regs_2([V - Stat | Rest], Critical, OldVars, Vars0, Vars) :-
+code_exprn__clobber_regs_2([V - VarInfo | Rest], Critical, OldVars, Vars0,
+		Vars) :-
+	VarInfo = var_info(Refs0, Stat),
 	(
 		Stat = cached(Exprn),
 		(
@@ -369,10 +452,10 @@
 			->
 				error("code_exprn__clobber_regs: attempt to clobber critical register")
 			;
-				Vars1 = Vars0
+				SetStat = no
 			)
 		;
-			map__set(Vars0, V, Stat, Vars1)
+			SetStat = yes(Stat)
 		)
 	;
 		Stat = evaled(Rvals0),
@@ -385,11 +468,31 @@
 			->
 				error("code_exprn__clobber_regs: attempt to clobber critical register")
 			;
-				Vars1 = Vars0
+				SetStat = no
 			)
 		;
-			map__set(Vars0, V, evaled(Rvals), Vars1)
+			SetStat = yes(evaled(Rvals))
 		)
+	;
+		Stat = none,
+		SetStat = no
+	),
+	code_exprn__filter_out_reg_depending_refs(Refs0, OldVars, Refs),
+	(
+		set__member(_ - Ref, Refs),
+		set__empty(Ref),
+		list__member(V, Critical)
+	->
+		error("code_exprn__clobber_regs: attempt to clobber critical register")
+	;
+		true
+	),
+	( SetStat = yes(NewStat) ->
+		map__set(Vars0, V, var_info(Refs, NewStat), Vars1)
+	; set__empty(Refs) ->
+		Vars1 = Vars0
+	;
+		map__set(Vars0, V, var_info(Refs, none), Vars1)
 	),
 	code_exprn__clobber_regs_2(Rest, Critical, OldVars, Vars1, Vars).
 
@@ -401,7 +504,7 @@
 code_exprn__rval_depends_on_reg(lval(Lval), Vars) :-
 	code_exprn__lval_depends_on_reg(Lval, Vars).
 code_exprn__rval_depends_on_reg(var(Var), Vars) :-
-	map__lookup(Vars, Var, Stat),
+	map__lookup(Vars, Var, var_info(_, Stat)),
 	(
 		Stat = cached(Rval),
 		code_exprn__rval_depends_on_reg(Rval, Vars)
@@ -430,7 +533,7 @@
 
 code_exprn__lval_depends_on_reg(reg(_, _), _Vars).
 code_exprn__lval_depends_on_reg(lvar(Var), Vars) :-
-	map__lookup(Vars, Var, Stat),
+	map__lookup(Vars, Var, var_info(_, Stat)),
 	(
 		Stat = cached(Rval),
 		code_exprn__rval_depends_on_reg(Rval, Vars)
@@ -483,6 +586,23 @@
 		Rvals = [Rval0 | Rvals1]
 	).
 
+:- pred code_exprn__filter_out_reg_depending_refs(var_refs, var_map, var_refs).
+:- mode code_exprn__filter_out_reg_depending_refs(in, in, out) is det.
+
+code_exprn__filter_out_reg_depending_refs(Refs0, Vars, Refs) :-
+	set__to_sorted_list(Refs0, RefList0),
+	list__map(lambda([Ref0::in, Ref::out] is det,
+		(
+			Ref0 = Placed - Lvals0,
+			set__to_sorted_list(Lvals0, LvalList0),
+			list__filter(lambda([Lval::in] is semidet,
+				\+ code_exprn__lval_depends_on_reg(Lval, Vars)),
+				LvalList0, LvalList),
+			set__list_to_set(LvalList, Lvals),
+			Ref = Placed - Lvals
+		)), RefList0, RefList),
+	set__list_to_set(RefList, Refs).
+
 %------------------------------------------------------------------------------%
 
 code_exprn__set_var_location(Var, Lval) -->
@@ -498,13 +618,33 @@
 
 code_exprn__maybe_set_var_location(Var, Lval) -->
 	code_exprn__get_vars(Vars0),
-	{ set__singleton_set(Locs, lval(Lval)) },
-	{ map__set(Vars0, Var, evaled(Locs), Vars) },
+	{ set__singleton_set(Rvals, lval(Lval)) },
+	{ map__search(Vars0, Var, var_info(Locs0, _)) ->
+		Locs = Locs0
+	;
+		set__init(Locs)
+	},
+	{ map__set(Vars0, Var, var_info(Locs, evaled(Rvals)), Vars) },
 	code_exprn__set_vars(Vars),
 	code_exprn__add_lval_reg_dependencies(Lval).
 
 %------------------------------------------------------------------------------%
 
+code_exprn__set_var_reference_location(Var, Lval) -->
+	code_exprn__get_vars(Vars0),
+	{ set__singleton_set(Lvals, Lval) },
+	{ map__search(Vars0, Var, var_info(Refs0, Stat0)) ->
+		Stat = Stat0,
+		set__insert(Refs0, no - Lvals, Refs)
+	;
+		Stat = none,
+		set__singleton_set(Refs, no - Lvals)
+	},
+	{ map__set(Vars0, Var, var_info(Refs, Stat), Vars) },
+	code_exprn__set_vars(Vars).
+
+%------------------------------------------------------------------------------%
+
 code_exprn__lval_in_use(Lval) -->
 	code_exprn__get_vars(Vars),
 	code_exprn__get_regs(Regs),
@@ -515,12 +655,12 @@
 		{ code_exprn__lval_in_use_by_vars(Lval, VarStatList) }
 	).
 
-:- pred code_exprn__lval_in_use_by_vars(lval, assoc_list(var, var_stat)).
+:- pred code_exprn__lval_in_use_by_vars(lval, assoc_list(var, var_info)).
 :- mode code_exprn__lval_in_use_by_vars(in, in) is semidet.
 
-code_exprn__lval_in_use_by_vars(Lval, VarStatList) :-
-	list__member(VarStat, VarStatList),
-	VarStat = _Var - Stat,
+code_exprn__lval_in_use_by_vars(Lval, VarInfoList) :-
+	list__member(VarInfo, VarInfoList),
+	VarInfo = _Var - var_info(Refs, Stat),
 	(
 		Stat = cached(Rval),
 		exprn_aux__rval_contains_lval(Rval, Lval)
@@ -528,6 +668,10 @@
 		Stat = evaled(Rvals),
 		set__member(Rval, Rvals),
 		exprn_aux__rval_contains_lval(Rval, Lval)
+	;
+		set__member(_Placed - Lvals, Refs),
+		set__member(Lval0, Lvals),
+		exprn_aux__lval_contains_lval(Lval0, Lval)
 	).
 
 %------------------------------------------------------------------------------%
@@ -537,15 +681,16 @@
 
 code_exprn__clear_lval_of_synonyms(Lval) -->
 	code_exprn__get_vars(Vars),
-	{ map__to_assoc_list(Vars, VarStatList) },
-	code_exprn__clear_lval_of_synonyms_1(VarStatList, Lval).
+	{ map__to_assoc_list(Vars, VarInfoList) },
+	code_exprn__clear_lval_of_synonyms_1(VarInfoList, Lval).
 
-:- pred code_exprn__clear_lval_of_synonyms_1(assoc_list(var, var_stat), lval,
+:- pred code_exprn__clear_lval_of_synonyms_1(assoc_list(var, var_info), lval,
 	exprn_info, exprn_info).
 :- mode code_exprn__clear_lval_of_synonyms_1(in, in, in, out) is det.
 
 code_exprn__clear_lval_of_synonyms_1([], _) --> [].
-code_exprn__clear_lval_of_synonyms_1([Var - Stat | VarStatList], Lval) -->
+code_exprn__clear_lval_of_synonyms_1([Var - VarInfo0 | VarInfoList], Lval) -->
+	{ VarInfo0 = var_info(Locs, Stat) },
 	(
 		{ Stat = cached(_) }
 	;
@@ -558,11 +703,14 @@
 		;
 			code_exprn__get_vars(Vars0),
 			{ set__sorted_list_to_set(RvalsList, Rvals) },
-			{ map__set(Vars0, Var, evaled(Rvals), Vars) },
+			{ map__set(Vars0, Var, var_info(Locs, evaled(Rvals)),
+				Vars) },
 			code_exprn__set_vars(Vars)
 		)
+	;
+		{ Stat = none }
 	),
-	code_exprn__clear_lval_of_synonyms_1(VarStatList, Lval).
+	code_exprn__clear_lval_of_synonyms_1(VarInfoList, Lval).
 
 :- pred code_exprn__find_rvals_without_lval(list(rval), lval, list(rval)).
 :- mode code_exprn__find_rvals_without_lval(in, in, out) is det.
@@ -726,29 +874,36 @@
 
 code_exprn__var_becomes_dead(Var) -->
 	code_exprn__get_vars(Vars0),
-	(
-		{ map__search(Vars0, Var, Stat) }
-	->
+	( { map__search(Vars0, Var, var_info(_, Stat)) } ->
 		(
-			{ Stat = cached(Rval0) },
-			code_exprn__rem_rval_reg_dependencies(Rval0)
-		;
-			{ Stat = evaled(Rvals0) },
-			{ set__to_sorted_list(Rvals0, RvalList0) },
-			code_exprn__rem_rval_list_reg_dependencies(RvalList0),
-			code_exprn__get_options(ExprnOpts),
 			(
-				{ code_exprn__member_expr_is_constant(RvalList0,
-						Vars0, ExprnOpts, Rval7) }
-			->
-				{ Rval0 = Rval7 }
+				{ Stat = cached(Rval0) },
+				code_exprn__rem_rval_reg_dependencies(Rval0)
 			;
-				{ code_exprn__select_rval(RvalList0, Rval0) }
+				{ Stat = evaled(Rvals0) },
+				{ set__to_sorted_list(Rvals0, RvalList0) },
+				code_exprn__rem_rval_list_reg_dependencies(
+					RvalList0),
+				code_exprn__get_options(ExprnOpts),
+				(
+					{ code_exprn__member_expr_is_constant(
+						RvalList0, Vars0, ExprnOpts,
+						Rval7) }
+				->
+					{ Rval0 = Rval7 }
+				;
+					{ code_exprn__select_rval(RvalList0,
+						Rval0) }
+				)
 			)
-		),
-		{ map__delete(Vars0, Var, Vars1) },
-		code_exprn__set_vars(Vars1),
-		code_exprn__update_dependent_vars(Var, Rval0)
+		->
+			{ map__delete(Vars0, Var, Vars1) },
+			code_exprn__set_vars(Vars1),
+			code_exprn__update_dependent_vars(Var, Rval0)
+		;
+			% Stat = none
+			[]
+		)
 	;
 		% XXX When we make the code generator tighter,
 		% we can reinstate this sanity check. In particular,
@@ -774,13 +929,13 @@
 	{ map__from_assoc_list(VarList, Vars) },
 	code_exprn__set_vars(Vars).
 
-:- pred code_exprn__update_dependent_vars_2(assoc_list(var, var_stat),
-		var, rval, assoc_list(var, var_stat), exprn_info, exprn_info).
+:- pred code_exprn__update_dependent_vars_2(assoc_list(var, var_info),
+		var, rval, assoc_list(var, var_info), exprn_info, exprn_info).
 :- mode code_exprn__update_dependent_vars_2(in, in, in, out, in, out) is det.
 
 code_exprn__update_dependent_vars_2([], _Var, _Rval, []) --> [].
-code_exprn__update_dependent_vars_2([V - Stat0 | Rest0], Var, Rval,
-							[V - Stat | Rest]) -->
+code_exprn__update_dependent_vars_2([V - var_info(Locs, Stat0) | Rest0], Var,
+		Rval, [V - var_info(Locs, Stat) | Rest]) -->
 	(
 		{ Stat0 = cached(Exprn0) },
 		{ exprn_aux__rval_contains_rval(Exprn0, var(Var)) }
@@ -806,7 +961,7 @@
 		{ set__sorted_list_to_set(RvalList, Rvals) },
 		{ Stat = evaled(Rvals) }
 	;
-		% Stat0 = cached(Exprn), \+ contains
+		% Stat0 = (cached(Exprn), \+ contains) ; none
 		{ Stat = Stat0 }
 	),
 	code_exprn__update_dependent_vars_2(Rest0, Var, Rval, Rest).
@@ -890,6 +1045,20 @@
 		code_exprn__select_stackvar(Rs, Rval)
 	).
 
+:- pred code_exprn__select_lval(set(lval), lval).
+:- mode code_exprn__select_lval(in, out) is det.
+
+code_exprn__select_lval(Lvals, Lval) :-
+	set__to_sorted_list(Lvals, LvalList),
+	Lambda = lambda([L::in, R::out] is det, ( R = lval(L) )),
+	list__map(Lambda, LvalList, RvalList),
+	code_exprn__select_rval(RvalList, Rval0),
+	( Rval0 = lval(Lval0) ->
+		Lval = Lval0
+	;
+		error("code_exprn__select_lval: something went wrong")
+	).
+
 %------------------------------------------------------------------------------%
 
 :- pred code_exprn__expr_is_constant(rval, var_map, exprn_opts, rval).
@@ -918,7 +1087,7 @@
 	code_exprn__args_are_constant(Args0, Vars, ExprnOpts, Args).
 
 code_exprn__expr_is_constant(var(Var), Vars, ExprnOpts, Rval) :-
-	map__search(Vars, Var, Stat),
+	map__search(Vars, Var, var_info(_, Stat)),
 	(
 		Stat = cached(Rval0),
 		code_exprn__expr_is_constant(Rval0, Vars, ExprnOpts, Rval)
@@ -960,22 +1129,37 @@
 
 code_exprn__cache_exprn(Var, Rval) -->
 	code_exprn__get_vars(Vars0),
+	{ map__search(Vars0, Var, var_info(Locs0, Stat0)) ->
+		Locs = Locs0,
+		Stat = Stat0
+	;
+		set__init(Locs),
+		Stat = none
+	},
 	(
-		{ map__search(Vars0, Var, _) }
+		{ Stat \= none }
 	->
 		code_exprn__get_var_name(Var, Name),
-		{ string__append("code_exprn__cache_exprn: existing definition of variable ", Name, Msg) },
+		{ term__var_to_int(Var, Num) },
+		{ string__int_to_string(Num, NumStr) },
+		{ string__append_list([
+				"code_exprn__cache_exprn:",
+				"existing definition of variable ",
+				Name, " (", NumStr, ")"
+			], Msg) },
 		{ error(Msg) }
 	;
 		code_exprn__add_rval_reg_dependencies(Rval),
-		(
-			{ exprn_aux__vars_in_rval(Rval, []) }
+		{
+			exprn_aux__vars_in_rval(Rval, [])
 		->
-			{ set__singleton_set(Rvals, Rval) },
-			{ map__det_insert(Vars0, Var, evaled(Rvals), Vars) }
+			set__singleton_set(Rvals, Rval),
+			map__set(Vars0, Var,
+				var_info(Locs, evaled(Rvals)), Vars)
 		;
-			{ map__det_insert(Vars0, Var, cached(Rval), Vars) }
-		),
+			map__set(Vars0, Var, 
+				var_info(Locs, cached(Rval)), Vars)
+		},
 		code_exprn__set_vars(Vars)
 	).
 
@@ -982,8 +1166,14 @@
 %------------------------------------------------------------------------------%
 
 code_exprn__place_vars([], empty) --> [].
-code_exprn__place_vars([Var - Lval | StoreMap], Code) -->
-	code_exprn__place_var(Var, Lval, FirstCode),
+code_exprn__place_vars([Var - store_info(ValOrRef, Lval) | StoreMap], Code) -->
+	(
+		{ ValOrRef = val },
+		code_exprn__place_var(Var, Lval, FirstCode)
+	;
+		{ ValOrRef = ref },
+		code_exprn__place_var_reference(Var, Lval, FirstCode)
+	),
 	code_exprn__place_vars(StoreMap, RestCode),
 	{ Code = tree(FirstCode, RestCode) }.
 
@@ -995,6 +1185,14 @@
 	;
 		{ Stat = evaled(Rvals) },
 		code_exprn__place_evaled(Rvals, Var, Lval, Code)
+	;
+		{ Stat = none },
+		code_exprn__get_var_name(Var, Name),
+		{ term__var_to_int(Var, Num) },
+		{ string__int_to_string(Num, NumStr) },
+		{ string__append_list(["code_exprn__place_var: variable ",
+			Name, " (", NumStr, ") has no value"], Msg) },
+		{ error(Msg) }
 	).
 
 :- pred code_exprn__place_cached(rval, var, lval, code_tree,
@@ -1008,19 +1206,20 @@
 	->
 		{ error("code_exprn__place_var: cached exprn with no vars!") }
 	;
-			% if the variable already has its value stored in the
-			% right place, we don't need to generate any code
+			% If the variable already has its value stored in the
+			% right place, we don't need to generate any code.
 		{ Rval0 = var(Var1) },
-		{ map__search(Vars0, Var1, Stat0) },
+		{ map__search(Vars0, Var1, var_info(_, Stat0)) },
 		{ Stat0 = evaled(VarRvals) },
 		{ set__member(lval(Lval), VarRvals) }
 	->
-			% but we do need to reserve the registers
+			% But we do need to reserve the registers
 			% needed to access Lval
 		code_exprn__add_lval_reg_dependencies(Lval),
-		{ map__det_update(Vars0, Var, Stat0, Vars) },
+		{ map__lookup(Vars0, Var, var_info(Locs, _)) },
+		{ map__det_update(Vars0, Var, var_info(Locs, Stat0), Vars) },
 		code_exprn__set_vars(Vars),
-		{ Code = empty }
+		code_exprn__place_var_in_references(Var, Code)
 	;
 			% If the value of the variable is a constant or
 			% is built up by operations involving only constants,
@@ -1029,12 +1228,59 @@
 		{ code_exprn__expr_is_constant(Rval0, Vars0, ExprnOpts, Rval) }
 	->
 		code_exprn__place_exprn(yes(Lval), yes(Var), Rval, yes, yes,
-			_, Code)
+			_, Code0),
+		code_exprn__place_var_in_references(Var, Code1),
+		{ Code = tree(Code0, Code1) }
 	;
 		code_exprn__place_exprn(yes(Lval), yes(Var), Rval0, no, no,
-			_, Code)
+			_, Code0),
+		code_exprn__place_var_in_references(Var, Code1),
+		{ Code = tree(Code0, Code1) }
+	).
+
+% Remove from the set of references any references that are in Lvals0.
+
+:- pred code_exprn__remove_lval_references(var_refs, set(lval), var_refs).
+:- mode code_exprn__remove_lval_references(in, in, out) is det.
+
+code_exprn__remove_lval_references(Refs0, Lvals0, Refs) :-
+	set__to_sorted_list(Refs0, RefsList0),
+	Filter = lambda([X::in] is semidet,
+		( 
+			X = _ - Lvals1,
+			set__member(L, Lvals0),
+			set__member(L, Lvals1)
+		)),
+	list__filter(Filter, RefsList0, RefsList),
+	set__sorted_list_to_set(RefsList, Refs).
+
+code_exprn__place_var_in_references(Var, Code) -->
+	code_exprn__get_vars(Vars0),
+	{ map__lookup(Vars0, Var, var_info(Refs0, Stat)) },
+
+	% Remove an lval from the set and recursively call place_var.
+	( { get_next_ref_to_place(Refs0, Lvals, Refs1) } ->
+		{ code_exprn__remove_lval_references(Refs1, Lvals, Refs2) },
+		{ set__insert(Refs2, yes - Lvals, Refs) },
+		{ map__det_update(Vars0, Var, var_info(Refs, Stat), Vars) },
+		code_exprn__set_vars(Vars),
+		{ code_exprn__select_lval(Lvals, Lval) },
+		code_exprn__place_var(Var, mem_ref(lval(Lval)), Code)
+	;
+		{ Code = empty }
 	).
 
+:- pred get_next_ref_to_place(var_refs, set(lval), var_refs).
+:- mode get_next_ref_to_place(in, out, out) is semidet.
+
+get_next_ref_to_place(Refs0, Lvals, Refs) :-
+	set__to_sorted_list(Refs0, RefList0),
+	list__takewhile(lambda([X::in] is semidet, X = yes - _),
+		RefList0, RefList1, [no - Lvals | RefList2]),
+	list__append(RefList1, RefList2, RefList),
+	set__sorted_list_to_set(RefList, Refs).
+		
+
 :- pred code_exprn__place_evaled(set(rval), var, lval, code_tree,
 	exprn_info, exprn_info).
 :- mode code_exprn__place_evaled(in, in, in, out, in, out) is det.
@@ -1045,8 +1291,9 @@
 		{ set__member(lval(Lval), Rvals0) }
 	->
 		code_exprn__get_vars(Vars1),
+		{ map__lookup(Vars1, Var, var_info(Refs, _)) },
 		{ Stat = evaled(Rvals0) },
-		{ map__set(Vars1, Var, Stat, Vars) },
+		{ map__set(Vars1, Var, var_info(Refs, Stat), Vars) },
 		code_exprn__set_vars(Vars),
 		{ Code = empty }
 	;
@@ -1092,7 +1339,7 @@
 			% If the variable already has its value stored in an
 			% acceptable place, we don't need to generate any code.
 		{ Rval0 = var(Var1) },
-		{ map__search(Vars0, Var1, Stat0) },
+		{ map__search(Vars0, Var1, var_info(_, Stat0)) },
 		{ Stat0 = evaled(VarRvals) },
 		{ set__to_sorted_list(VarRvals, RvalList) },
 		{
@@ -1222,6 +1469,39 @@
 
 %------------------------------------------------------------------------------%
 
+code_exprn__place_var_reference(Var, Lval, Code) -->
+	code_exprn__get_vars(Vars0),
+	(
+		{ map__search(Vars0, Var, var_info(Refs0, Stat)) },
+
+		% XXX for now we only allow one reference per variable.
+		{ set__singleton_set(Refs0, Placed - Lvals0) }
+	->
+		( { set__member(Lval, Lvals0) } ->
+			{ Code = empty }
+		; 
+			{ code_exprn__select_lval(Lvals0, SelectedLval) },
+			code_exprn__place_exprn(yes(Lval), no,
+				lval(SelectedLval), no, no, _Lval, Code),
+			code_exprn__get_vars(Vars1),
+			{ set__insert(Lvals0, Lval, Lvals) },
+			{ set__delete(Refs0, Placed - Lvals0, Refs1) },
+			{ set__insert(Refs1, Placed - Lvals, Refs) },
+			{ map__set(Vars1, Var, var_info(Refs, Stat), Vars) },
+			code_exprn__set_vars(Vars)
+		)
+	;
+		code_exprn__get_var_name(Var, Name),
+		{ term__var_to_int(Var, Num) },
+		{ string__int_to_string(Num, NumStr) },
+		{ string__append_list([
+			"code_exprn__place_var_reference: variable ",
+			Name, " (", NumStr, ") has 0 or >1 references"], Msg) },
+		{ error(Msg) }
+	).
+
+%------------------------------------------------------------------------------%
+
 :- pred code_exprn__find_real_creates(list(maybe(rval)), list(rval),
 	exprn_info, exprn_info).
 :- mode code_exprn__find_real_creates(in, out, in, out) is det.
@@ -1422,6 +1702,33 @@
 		{ Rval = lval(Lval) }
 	).
 
+code_exprn__produce_ref_in_reg_or_stack(Var, Lval, Code) -->
+	code_exprn__get_vars(Vars0),
+	(
+		{ map__search(Vars0, Var, var_info(RefLocs0, Stat)) },
+		{ set__singleton_set(RefLocs0, Placed - Lvals0) }
+	->
+		(
+			{ set__to_sorted_list(Lvals0, LvalList) },
+			{ code_exprn__select_reg_or_stack_lval(LvalList, Lval0)}
+		->
+			{ Code = empty },
+			{ Lval = Lval0 },
+			{ Vars = Vars0 }
+		;
+			code_exprn__select_preferred_lval(Var, Lval),
+			code_exprn__place_var_reference(Var, Lval, Code),
+			{ set__insert(Lvals0, Lval, Lvals) },
+			{ set__singleton_set(RefLocs, Placed - Lvals) },
+			{ map__det_update(Vars0, Var, var_info(RefLocs, Stat),
+				Vars) }
+		)
+	;
+		{ error("code_exprn__produce_ref_in_reg_or_stack: internal error") }
+	),
+	code_exprn__set_vars(Vars).
+
+
 %------------------------------------------------------------------------------%
 
 :- pred code_exprn__select_reg_rval(list(rval), rval).
@@ -1447,6 +1754,18 @@
 		code_exprn__select_reg_or_stack_rval(Rvals0, Rval)
 	).
 
+:- pred code_exprn__select_reg_or_stack_lval(list(lval), lval).
+:- mode code_exprn__select_reg_or_stack_lval(in, out) is semidet.
+
+code_exprn__select_reg_or_stack_lval([Lval0 | Lvals0], Lval) :-
+	(
+		( Lval0 = reg(_, _) ; Lval0 = stackvar(_) ; Lval0 = framevar(_) )
+	->
+		Lval = Lval0
+	;
+		code_exprn__select_reg_or_stack_lval(Lvals0, Lval)
+	).
+
 %------------------------------------------------------------------------------%
 
 :- pred code_exprn__select_preferred_lval(var, lval, exprn_info, exprn_info).
@@ -1455,7 +1774,7 @@
 code_exprn__select_preferred_lval(Var, Lval) -->
 	code_exprn__get_follow_vars(FollowVars),
 	(
-		{ map__search(FollowVars, Var, PrefLval) }
+		{ map__search(FollowVars, Var, store_info(_, PrefLval)) }
 	->
 		(
 			\+ { unreal_lval(PrefLval) },
@@ -1475,7 +1794,7 @@
 code_exprn__select_preferred_reg(Var, Lval) -->
 	code_exprn__get_follow_vars(FollowVars),
 	(
-		{ map__search(FollowVars, Var, PrefLval) },
+		{ map__search(FollowVars, Var, store_info(_, PrefLval)) },
 		{ PrefLval = reg(_, _) }
 	->
 		(
@@ -1578,13 +1897,13 @@
 		{ Code = empty }
 	).
 
-:- pred code_exprn__relocate_lval(assoc_list(var, var_stat), lval, lval,
-	assoc_list(var, var_stat), exprn_info, exprn_info).
+:- pred code_exprn__relocate_lval(assoc_list(var, var_info), lval, lval,
+	assoc_list(var, var_info), exprn_info, exprn_info).
 :- mode code_exprn__relocate_lval(in, in, in, out, in, out) is det.
 
 code_exprn__relocate_lval([], _OldVal, _NewVal, []) --> [].
-code_exprn__relocate_lval([V - Stat0 | Rest0], OldVal, NewVal,
-		[V - Stat | Rest]) -->
+code_exprn__relocate_lval([V - var_info(Refs0, Stat0) | Rest0], OldVal, NewVal,
+		[V - var_info(Refs, Stat) | Rest]) -->
 	(
 		{ Stat0 = cached(Exprn0) },
 		(
@@ -1605,7 +1924,11 @@
 							NewVal, RvalsList),
 		{ set__sorted_list_to_set(RvalsList, Rvals) },
 		{ Stat = evaled(Rvals) }
+	;
+		{ Stat0 = none },
+		{ Stat = none }
 	),
+	code_exprn__relocate_lval_in_refs(OldVal, NewVal, Refs0, Refs),
 	code_exprn__relocate_lval(Rest0, OldVal, NewVal, Rest).
 
 :- pred code_exprn__relocate_lval_2(list(rval), lval, lval, list(rval),
@@ -1625,6 +1948,28 @@
 	),
 	code_exprn__relocate_lval_2(Rs0, OldVal, NewVal, Rs).
 
+:- pred code_exprn__relocate_lval_in_refs(lval, lval, var_refs, var_refs,
+		exprn_info, exprn_info).
+:- mode code_exprn__relocate_lval_in_refs(in, in, in, out, in, out) is det.
+
+code_exprn__relocate_lval_in_refs(Old, New, Refs0, Refs) -->
+	{ set__to_sorted_list(Refs0, RefsList0) },
+	list__map_foldl(lambda([R0::in, R::out, Exprn0::in, Exprn::out] is det,
+	    (
+		R0 = Placed - Lvals0,
+		set__to_sorted_list(Lvals0, LvalsList0),
+		list__map_foldl(lambda([L0::in, L::out, E0::in, E::out] is det,
+		    (
+			exprn_aux__substitute_lval_in_lval(Old, New, L0, L),
+			code_exprn__rem_lval_reg_dependencies(L0, E0, E1),
+			code_exprn__add_lval_reg_dependencies(L, E1, E)
+		    )), LvalsList0, LvalsList, Exprn0, Exprn),
+		set__list_to_set(LvalsList, Lvals),
+		R = Placed - Lvals
+	    )), RefsList0, RefsList),
+	{ set__list_to_set(RefsList, Refs) }.
+
+
 %------------------------------------------------------------------------------%
 
 :- pred code_exprn__get_var_status(var, var_stat, exprn_info, exprn_info).
@@ -1633,7 +1978,7 @@
 code_exprn__get_var_status(Var, Stat) -->
 	code_exprn__get_vars(Vars0),
 	(
-		{ map__search(Vars0, Var, Stat0) }
+		{ map__search(Vars0, Var, var_info(_, Stat0)) }
 	->
 		{ Stat = Stat0 }
 	;
@@ -1654,7 +1999,12 @@
 	code_exprn__get_vars(Vars0),
 	{ set__list_to_set(RvalList, Rvals) },
 	{ Stat = evaled(Rvals) },
-	{ map__set(Vars0, Var, Stat, Vars) },
+	{ map__search(Vars0, Var, var_info(Refs0, _)) ->
+		Refs = Refs0
+	;
+		set__init(Refs)
+	},
+	{ map__set(Vars0, Var, var_info(Refs, Stat), Vars) },
 	code_exprn__set_vars(Vars).
 
 :- pred code_exprn__maybe_add_evaled(maybe(var), rval, exprn_info, exprn_info).
@@ -1663,7 +2013,7 @@
 code_exprn__maybe_add_evaled(no, _) --> [].
 code_exprn__maybe_add_evaled(yes(Var), NewRval) -->
 	code_exprn__get_vars(Vars0),
-	{ map__lookup(Vars0, Var, Stat0) },
+	{ map__lookup(Vars0, Var, var_info(Locs0, Stat0)) },
 	{
 		Stat0 = evaled(Rvals0),
 		set__insert(Rvals0, NewRval, Rvals)
@@ -1670,11 +2020,24 @@
 	;
 		Stat0 = cached(_),
 		set__singleton_set(Rvals, NewRval)
+	;
+		Stat0 = none,
+		error("code_exprn__maybe_add_evaled: var not cached or evaled")
 	},
 	{ Stat = evaled(Rvals) },
-	{ map__set(Vars0, Var, Stat, Vars) },
+	{ map__set(Vars0, Var, var_info(Locs0, Stat), Vars) },
 	code_exprn__set_vars(Vars).
 
+:- pred code_exprn__remove_rval_from_lvals(rval, set(lval), set(lval)).
+:- mode code_exprn__remove_rval_from_lvals(in, in, out) is det.
+
+code_exprn__remove_rval_from_lvals(Rval, Lvals0, Lvals) :-
+	( Rval = lval(Lval) ->
+		set__delete(Lvals0, Lval, Lvals)
+	;
+		Lvals = Lvals0
+	).
+
 %------------------------------------------------------------------------------%
 
 	% Warning: if you get a reg, you must mark it as in use yourself.
@@ -1787,11 +2150,11 @@
 	set__to_sorted_list(Acquired, ARegs),
 	code_exprn__max_reg_in_use_lvals(ARegs, Max2, Max).
 
-:- pred code_exprn__max_reg_in_use_vars(list(var_stat), int, int).
+:- pred code_exprn__max_reg_in_use_vars(list(var_info), int, int).
 :- mode code_exprn__max_reg_in_use_vars(in, in, out) is det.
 
 code_exprn__max_reg_in_use_vars([], Max, Max).
-code_exprn__max_reg_in_use_vars([Stat | Stats], Max0, Max) :-
+code_exprn__max_reg_in_use_vars([var_info(Refs, Stat) | Infos], Max0, Max) :-
 	(
 		Stat = evaled(RvalSet),
 		set__to_sorted_list(RvalSet, Rvals),
@@ -1799,8 +2162,12 @@
 	;
 		Stat = cached(Rval),
 		code_exprn__max_reg_in_use_rvals([Rval], Max0, Max1)
+	;
+		Stat = none,
+		Max1 = Max0
 	),
-	code_exprn__max_reg_in_use_vars(Stats, Max1, Max).
+	code_exprn__max_reg_in_use_refs(Refs, Max1, Max2),
+	code_exprn__max_reg_in_use_vars(Infos, Max2, Max).
 
 :- pred code_exprn__max_reg_in_use_rvals(list(rval), int, int).
 :- mode code_exprn__max_reg_in_use_rvals(in, in, out) is det.
@@ -1822,6 +2189,18 @@
 
 code_exprn__lval_is_r_reg(reg(r, N), N).
 
+:- pred code_exprn__max_reg_in_use_refs(var_refs, int, int).
+:- mode code_exprn__max_reg_in_use_refs(in, in, out) is det.
+
+code_exprn__max_reg_in_use_refs(Refs, Max0, Max) :-
+	set__to_sorted_list(Refs, RefsList),
+	list__foldl(lambda([Ref::in, N0::in, N::out] is det,
+		(
+			Ref = _Placed - Lvals,
+			set__to_sorted_list(Lvals, LvalsList),
+			code_exprn__max_reg_in_use_lvals(LvalsList, N0, N)
+		)), RefsList, Max0, Max).
+
 %------------------------------------------------------------------------------%
 
 :- pred code_exprn__get_varset(varset, exprn_info, exprn_info).
@@ -1894,3 +2273,6 @@
 
 %------------------------------------------------------------------------------%
 %------------------------------------------------------------------------------%
+code_exprn__value_to_rval(value(Rval), Rval).
+
+code_exprn__reference_to_lval(reference(Lval), Lval).
Index: compiler/code_info.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/code_info.m,v
retrieving revision 1.211.2.10
diff -u -r1.211.2.10 code_info.m
--- 1.211.2.10	1998/06/17 04:12:07
+++ code_info.m	1998/06/22 01:02:40
@@ -804,7 +804,8 @@
 	code_info__make_vars_forward_dead(PostDeaths),
 	{ goal_info_get_post_births(GoalInfo, PostBirths) },
 	code_info__add_forward_live_vars(PostBirths),
-	code_info__make_vars_forward_live(PostBirths),
+	{ goal_info_get_refs(GoalInfo, Refs) },
+	code_info__make_vars_forward_live(PostBirths, Refs),
 	{ goal_info_get_instmap_delta(GoalInfo, InstMapDelta) },
 	code_info__apply_instmap_delta(InstMapDelta).
 
@@ -1138,6 +1139,8 @@
 
 :- implementation.
 
+:- import_module inst_match.
+
 :- type fail_stack	==	stack(failure_cont).
 
 :- type failure_cont
@@ -1161,7 +1164,7 @@
 
 :- type is_known	--->	known ; unknown.
 
-:- type resume_map	==	map(var, set(rval)).
+:- type resume_map	==	map(var, set(val_or_ref)).
 
 :- type resume_maps
 	--->	orig_only(resume_map, code_addr)
@@ -1306,7 +1309,11 @@
 		code_info__get_stack_slots(StackSlots),
 		{ map__select(StackSlots, ResumeVars, StackMap0) },
 		{ map__to_assoc_list(StackMap0, StackList0) },
-		{ code_info__tweak_stacklist(StackList0, StackList) },
+		code_info__get_instmap(InstMap),
+		code_info__get_inst_table(InstTable),
+		code_info__get_module_info(ModuleInfo),
+		{ code_info__stacklist_to_valrefs(StackList0, InstMap,
+			InstTable, ModuleInfo, StackList) },
 		{ map__from_assoc_list(StackList, StackMap) },
 		{ ResumeMaps = stack_only(StackMap, StackAddr) }
 	;
@@ -1315,7 +1322,11 @@
 		code_info__get_stack_slots(StackSlots),
 		{ map__select(StackSlots, ResumeVars, StackMap0) },
 		{ map__to_assoc_list(StackMap0, StackList0) },
-		{ code_info__tweak_stacklist(StackList0, StackList) },
+		code_info__get_instmap(InstMap),
+		code_info__get_inst_table(InstTable),
+		code_info__get_module_info(ModuleInfo),
+		{ code_info__stacklist_to_valrefs(StackList0, InstMap,
+			InstTable, ModuleInfo, StackList) },
 		{ map__from_assoc_list(StackList, StackMap) },
 		{ ResumeMaps = orig_and_stack(OrigMap, OrigAddr,
 			StackMap, StackAddr) }
@@ -1325,7 +1336,11 @@
 		code_info__get_stack_slots(StackSlots),
 		{ map__select(StackSlots, ResumeVars, StackMap0) },
 		{ map__to_assoc_list(StackMap0, StackList0) },
-		{ code_info__tweak_stacklist(StackList0, StackList) },
+		code_info__get_instmap(InstMap),
+		code_info__get_inst_table(InstTable),
+		code_info__get_module_info(ModuleInfo),
+		{ code_info__stacklist_to_valrefs(StackList0, InstMap,
+			InstTable, ModuleInfo, StackList) },
 		{ map__from_assoc_list(StackList, StackMap) },
 		{ ResumeMaps = stack_and_orig(StackMap, StackAddr,
 			OrigMap, OrigAddr) }
@@ -1333,7 +1348,7 @@
 	code_info__push_failure_cont(failure_cont(FailContInfo, ResumeMaps)),
 	{ ModContCode = tree(OrigCode, TempFrameCode) }.
 
-:- pred code_info__produce_resume_vars(list(var), map(var, set(rval)),
+:- pred code_info__produce_resume_vars(list(var), map(var, set(val_or_ref)),
 	code_tree, code_info, code_info).
 :- mode code_info__produce_resume_vars(in, out, out, in, out) is det.
 
@@ -1341,19 +1356,34 @@
 	{ map__init(Map) }.
 code_info__produce_resume_vars([V | Vs], Map, Code) -->
 	code_info__produce_resume_vars(Vs, Map0, Code0),
-	code_info__produce_variable_in_reg_or_stack(V, Code1, Rval),
-	{ set__singleton_set(Rvals, Rval) },
-	{ map__set(Map0, V, Rvals, Map) },
+	( code_info__var_is_free_alias(V) ->
+		code_info__produce_reference_in_reg_or_stack(V, Code1, Lval),
+		{ set__singleton_set(ValRefs, reference(Lval)) }
+	;
+		code_info__produce_variable_in_reg_or_stack(V, Code1, Rval),
+		{ set__singleton_set(ValRefs, value(Rval)) }
+	),
+	{ map__set(Map0, V, ValRefs, Map) },
 	{ Code = tree(Code0, Code1) }.
 
-:- pred code_info__tweak_stacklist(assoc_list(var, lval),
-	assoc_list(var, set(rval))).
-:- mode code_info__tweak_stacklist(in, out) is det.
-
-code_info__tweak_stacklist([], []).
-code_info__tweak_stacklist([V - L | Rest0], [V - Rs | Rest]) :-
-	set__singleton_set(Rs, lval(L)),
-	code_info__tweak_stacklist(Rest0, Rest).
+% Use the instmap to work out which stack slots are values and which are
+% references.
+:- pred code_info__stacklist_to_valrefs(assoc_list(var, lval), instmap, 
+		inst_table, module_info, assoc_list(var, set(val_or_ref))).
+:- mode code_info__stacklist_to_valrefs(in, in, in, in, out) is det.
+
+code_info__stacklist_to_valrefs([], _, _, _, []).
+code_info__stacklist_to_valrefs([V - L | Rest0], InstMap, InstTable,
+		ModuleInfo, [V - Rs | Rest]) :-
+	instmap__lookup_var(InstMap, V, Inst),
+	( inst_is_free_alias(Inst, InstTable, ModuleInfo) ->
+		VVal = reference(L)
+	;
+		VVal = value(lval(L))
+	),
+	set__singleton_set(Rs, VVal),
+	code_info__stacklist_to_valrefs(Rest0, InstMap, InstTable,
+		ModuleInfo, Rest).
 
 %---------------------------------------------------------------------------%
 
@@ -1582,8 +1612,8 @@
 		error("code_info__generate_resume_setup: non-label!")
 	).
 
-:- pred code_info__place_resume_vars(assoc_list(var, set(rval)), code_tree,
-	code_info, code_info).
+:- pred code_info__place_resume_vars(assoc_list(var, set(val_or_ref)),
+	code_tree, code_info, code_info).
 :- mode code_info__place_resume_vars(in, out, in, out) is det.
 
 code_info__place_resume_vars([], empty) --> [].
@@ -1593,14 +1623,16 @@
 	{ Code = tree(FirstCode, RestCode) },
 	code_info__place_resume_vars(Rest, RestCode).
 
-:- pred code_info__place_resume_var(var, list(rval), code_tree,
+:- pred code_info__place_resume_var(var, list(val_or_ref), code_tree,
 	code_info, code_info).
 :- mode code_info__place_resume_var(in, in, out, in, out) is det.
 
 code_info__place_resume_var(_Var, [], empty) --> [].
 code_info__place_resume_var(Var, [Target | Targets], Code) -->
-	( { Target = lval(TargetLval) } ->
+	( { Target = value(lval(TargetLval)) } ->
 		code_info__place_var(Var, TargetLval, FirstCode)
+	; { Target = reference(RefLval) } ->
+		code_info__place_var_reference(Var, RefLval, FirstCode)
 	;
 		{ error("code_info__place_resume_var: not lval") }
 	),
@@ -1611,7 +1643,8 @@
 	% Remember that the variables in the map are available in their
 	% associated rvals; forget about all other variables.
 
-:- pred code_info__set_var_locations(map(var, set(rval)), code_info, code_info).
+:- pred code_info__set_var_locations(map(var, set(val_or_ref)), code_info,
+		code_info).
 :- mode code_info__set_var_locations(in, in, out) is det.
 
 code_info__set_var_locations(Map) -->
@@ -1621,19 +1654,19 @@
 	{ code_exprn__reinit_state(List, Exprn0, Exprn) },
 	code_info__set_exprn_info(Exprn).
 
-:- pred code_info__flatten_varlval_list(assoc_list(var, set(rval)),
-						assoc_list(var, rval)).
+:- pred code_info__flatten_varlval_list(assoc_list(var, set(val_or_ref)),
+						assoc_list(var, val_or_ref)).
 :- mode code_info__flatten_varlval_list(in, out) is det.
 
 code_info__flatten_varlval_list([], []).
-code_info__flatten_varlval_list([V - Rvals | Rest0], All) :-
+code_info__flatten_varlval_list([V - Vvals | Rest0], All) :-
 	code_info__flatten_varlval_list(Rest0, Rest),
-	set__to_sorted_list(Rvals, RvalList),
-	code_info__flatten_varlval_list_2(RvalList, V, Rest1),
+	set__to_sorted_list(Vvals, VvalList),
+	code_info__flatten_varlval_list_2(VvalList, V, Rest1),
 	list__append(Rest1, Rest, All).
 
-:- pred code_info__flatten_varlval_list_2(list(rval), var,
-	assoc_list(var, rval)).
+:- pred code_info__flatten_varlval_list_2(list(val_or_ref), var,
+	assoc_list(var, val_or_ref)).
 :- mode code_info__flatten_varlval_list_2(in, in, out) is det.
 
 code_info__flatten_varlval_list_2([], _V, []).
@@ -1772,10 +1805,23 @@
 		)
 	}.
 
-:- pred code_info__match_resume_loc(resume_map, resume_map).
+:- pred code_info__match_resume_loc(resume_map, map(var, set(rval))).
 :- mode code_info__match_resume_loc(in, in) is semidet.
 
-code_info__match_resume_loc(Map, Locations0) :-
+code_info__match_resume_loc(Map0, Locations0) :-
+	% Convert resume_map to map(var, set(rval)), removing all reference()'s.
+	map__to_assoc_list(Map0, AL0),
+	Filter = lambda([V::in, R::out] is semidet, (
+			V = Variable - VVals,
+			set__to_sorted_list(VVals, Vs),
+			list__filter_map(code_exprn__value_to_rval, Vs, Rs),
+			Rs \= [],
+			set__sorted_list_to_set(Rs, RvalsSet),
+			R = Variable - RvalsSet
+		)),
+	list__filter_map(Filter, AL0, AL),
+	map__from_assoc_list(AL, Map),
+
 	map__keys(Map, KeyList),
 	set__list_to_set(KeyList, Keys),
 	map__select(Locations0, Keys, Locations),
@@ -2198,8 +2244,9 @@
 	% Make these variables appear magically live.
 	% We don't care where they are put.
 
-:- pred code_info__make_vars_forward_live(set(var), code_info, code_info).
-:- mode code_info__make_vars_forward_live(in, in, out) is det.
+:- pred code_info__make_vars_forward_live(set(var), set(var),
+		code_info, code_info).
+:- mode code_info__make_vars_forward_live(in, in, in, out) is det.
 
 code_info__get_known_variables(VarList) -->
 	code_info__get_forward_live_vars(ForwardLiveVars),
@@ -2221,29 +2268,34 @@
 	{ set__difference(Liveness0, Deaths, Liveness) },
 	code_info__set_forward_live_vars(Liveness).
 
-code_info__make_vars_forward_live(Vars) -->
+code_info__make_vars_forward_live(Vars, RefVars) -->
 	code_info__get_stack_slots(StackSlots),
 	code_info__get_exprn_info(Exprn0),
 	{ set__to_sorted_list(Vars, VarList) },
-	{ code_info__make_vars_forward_live_2(VarList, StackSlots, 1,
+	{ code_info__make_vars_forward_live_2(VarList, RefVars, StackSlots, 1,
 		Exprn0, Exprn) },
 	code_info__set_exprn_info(Exprn).
 
-:- pred code_info__make_vars_forward_live_2(list(var), stack_slots, int,
-	exprn_info, exprn_info).
-:- mode code_info__make_vars_forward_live_2(in, in, in, in, out) is det.
-
-code_info__make_vars_forward_live_2([], _, _, Exprn, Exprn).
-code_info__make_vars_forward_live_2([V | Vs], StackSlots, N0, Exprn0, Exprn) :-
-	( map__search(StackSlots, V, Lval0) ->
+:- pred code_info__make_vars_forward_live_2(list(var), set(var), stack_slots,
+	int, exprn_info, exprn_info).
+:- mode code_info__make_vars_forward_live_2(in, in, in, in, in, out) is det.
+
+code_info__make_vars_forward_live_2([], _, _, _, Exprn, Exprn).
+code_info__make_vars_forward_live_2([V | Vs], RefVars, StackSlots, N0) -->
+	=(Exprn0),
+	{ map__search(StackSlots, V, Lval0) ->
 		Lval = Lval0,
 		N1 = N0
 	;
 		code_info__find_unused_reg(N0, Exprn0, N1),
 		Lval = reg(r, N1)
+	},
+	( { set__member(V, RefVars)} ->
+		code_exprn__set_var_reference_location(V, Lval)
+	;
+		code_exprn__maybe_set_var_location(V, Lval)
 	),
-	code_exprn__maybe_set_var_location(V, Lval, Exprn0, Exprn1),
-	code_info__make_vars_forward_live_2(Vs, StackSlots, N1, Exprn1, Exprn).
+	code_info__make_vars_forward_live_2(Vs, RefVars, StackSlots, N1).
 
 :- pred code_info__find_unused_reg(int, exprn_info, int).
 :- mode code_info__find_unused_reg(in, in, out) is det.
@@ -2492,6 +2544,9 @@
 :- pred code_info__set_var_location(var, lval, code_info, code_info).
 :- mode code_info__set_var_location(in, in, in, out) is det.
 
+:- pred code_info__set_var_reference_location(var, lval, code_info, code_info).
+:- mode code_info__set_var_reference_location(in, in, in, out) is det.
+
 :- pred code_info__cache_expression(var, rval, code_info, code_info).
 :- mode code_info__cache_expression(in, in, in, out) is det.
 
@@ -2498,9 +2553,18 @@
 :- pred code_info__place_var(var, lval, code_tree, code_info, code_info).
 :- mode code_info__place_var(in, in, out, in, out) is det.
 
+:- pred code_info__place_var_reference(var, lval, code_tree,
+	code_info, code_info).
+:- mode code_info__place_var_reference(in, in, out, in, out) is det.
+
 :- pred code_info__produce_variable(var, code_tree, rval, code_info, code_info).
 :- mode code_info__produce_variable(in, out, out, in, out) is det.
 
+:- pred code_info__produce_variable_in_references(var, code_tree,
+	code_info, code_info).
+:- mode code_info__produce_variable_in_references(in, out,
+	in, out) is det.
+
 :- pred code_info__produce_variable_in_reg(var, code_tree, rval,
 	code_info, code_info).
 :- mode code_info__produce_variable_in_reg(in, out, out, in, out) is det.
@@ -2567,17 +2631,33 @@
 	code_info, code_info).
 :- mode code_info__save_variables_on_stack(in, out, in, out) is det.
 
+:- pred code_info__save_reference_on_stack(var, code_tree,
+	code_info, code_info).
+:- mode code_info__save_reference_on_stack(in, out, in, out) is det.
+
+:- pred code_info__var_is_free_alias(var, code_info, code_info).
+:- mode code_info__var_is_free_alias(in, in, out) is semidet.
+
 :- pred code_info__max_reg_in_use(int, code_info, code_info).
 :- mode code_info__max_reg_in_use(out, in, out) is det.
 
+:- pred code_info__stack_slots_to_store_map(stack_slots, store_map,
+	code_info, code_info).
+:- mode code_info__stack_slots_to_store_map(in, out, in, out) is det.
+
 %---------------------------------------------------------------------------%
 
 :- implementation.
 
-:- pred code_info__place_vars(assoc_list(var, set(rval)), code_tree,
+:- pred code_info__place_vars(assoc_list(var, set(val_or_ref)), code_tree,
 	code_info, code_info).
 :- mode code_info__place_vars(in, out, in, out) is det.
 
+:- pred code_info__produce_reference_in_reg_or_stack(var, code_tree, lval,
+	code_info, code_info).
+:- mode code_info__produce_reference_in_reg_or_stack(in, out, out, in, out)
+	is det.
+
 code_info__variable_locations(Locations) -->
 	code_info__get_exprn_info(Exprn),
 	{ code_exprn__get_varlocs(Exprn, Locations) }.
@@ -2587,6 +2667,11 @@
 	{ code_exprn__set_var_location(Var, Lval, Exprn0, Exprn) },
 	code_info__set_exprn_info(Exprn).
 
+code_info__set_var_reference_location(Var, Lval) -->
+	code_info__get_exprn_info(Exprn0),
+	{ code_exprn__set_var_reference_location(Var, Lval, Exprn0, Exprn) },
+	code_info__set_exprn_info(Exprn).
+
 code_info__cache_expression(Var, Rval) -->
 	code_info__get_exprn_info(Exprn0),
 	{ code_exprn__cache_exprn(Var, Rval, Exprn0, Exprn) },
@@ -2600,7 +2685,8 @@
 code_info__place_vars([], empty) --> [].
 code_info__place_vars([V - Rs | RestList], Code) -->
 	(
-		{ set__to_sorted_list(Rs, RList) },
+		{ set__to_sorted_list(Rs, VList) },
+		{ list__filter_map(code_exprn__value_to_rval, VList, RList) },
 		{ code_info__lval_in_rval_list(L, RList) }
 	->
 		code_info__place_var(V, L, ThisCode)
@@ -2610,6 +2696,11 @@
 	code_info__place_vars(RestList, RestCode),
 	{ Code = tree(ThisCode, RestCode) }.
 
+code_info__place_var_reference(Var, Lval, Code) -->
+	code_info__get_exprn_info(Exprn0),
+	{ code_exprn__place_var_reference(Var, Lval, Code, Exprn0, Exprn) },
+	code_info__set_exprn_info(Exprn).
+
 :- pred code_info__lval_in_rval_list(lval, list(rval)).
 :- mode code_info__lval_in_rval_list(out, in) is semidet.
 
@@ -2625,6 +2716,11 @@
 	{ code_exprn__produce_var(Var, Rval, Code, Exprn0, Exprn) },
 	code_info__set_exprn_info(Exprn).
 
+code_info__produce_variable_in_references(Var, Code) -->
+	code_info__get_exprn_info(Exprn0),
+	{ code_exprn__place_var_in_references(Var, Code, Exprn0, Exprn) },
+	code_info__set_exprn_info(Exprn).
+
 code_info__produce_variable_in_reg(Var, Code, Rval) -->
 	code_info__get_exprn_info(Exprn0),
 	{ code_exprn__produce_var_in_reg(Var, Rval, Code, Exprn0, Exprn) },
@@ -2636,6 +2732,12 @@
 		Exprn0, Exprn) },
 	code_info__set_exprn_info(Exprn).
 
+code_info__produce_reference_in_reg_or_stack(Var, Code, Lval) -->
+	code_info__get_exprn_info(Exprn0),
+	{ code_exprn__produce_ref_in_reg_or_stack(Var, Lval, Code,
+		Exprn0, Exprn) },
+	code_info__set_exprn_info(Exprn).
+
 code_info__materialize_vars_in_rval(Rval0, Rval, Code) -->
 	code_info__get_exprn_info(Exprn0),
 	{ code_exprn__materialize_vars_in_rval(Rval0, Rval, Code,
@@ -2656,7 +2758,7 @@
 	code_info__get_exprn_info(Exprn0),
 	code_info__get_follow_vars(Follow),
 	(
-		{ map__search(Follow, Var, PrefLval) },
+		{ map__search(Follow, Var, store_info(_, PrefLval)) },
 		{ PrefLval = reg(PrefRegType, PrefRegNum) }
 	->
 		{ code_exprn__acquire_reg_prefer_given(PrefRegType, PrefRegNum,
@@ -2697,17 +2799,16 @@
 
 code_info__remake_with_store_map(StoreMap) -->
 	{ map__to_assoc_list(StoreMap, VarLvals) },
-	{ code_info__fixup_lvallist(VarLvals, VarRvals) },
+	{ list__map(code_info__fixup_lval, VarLvals, VarRvals) },
 	code_info__get_exprn_info(Exprn0),
 	{ code_exprn__reinit_state(VarRvals, Exprn0, Exprn) },
 	code_info__set_exprn_info(Exprn).
 
-:- pred code_info__fixup_lvallist(assoc_list(var, lval), assoc_list(var, rval)).
-:- mode code_info__fixup_lvallist(in, out) is det.
+:- pred code_info__fixup_lval(pair(var, store_info), pair(var, val_or_ref)).
+:- mode code_info__fixup_lval(in, out) is det.
 
-code_info__fixup_lvallist([], []).
-code_info__fixup_lvallist([V - L | Ls], [V - lval(L) | Rs]) :-
-	code_info__fixup_lvallist(Ls, Rs).
+code_info__fixup_lval(V - store_info(val, L), V - value(lval(L))).
+code_info__fixup_lval(V - store_info(ref, L), V - reference(L)).
 
 %---------------------------------------------------------------------------%
 
@@ -2715,16 +2816,23 @@
 code_info__setup_call([V - arg_info(Loc, Mode) | Rest], Direction, Code) -->
 	(
 		{
-			Mode = top_in,
+			( Mode = top_in ; Mode = ref_in ),
 			Direction = caller
 		;
-			Mode = top_out,
+			( Mode = top_out ; Mode = ref_out ),
 			Direction = callee
 		}
 	->
 		{ code_util__arg_loc_to_register(Loc, Reg) },
 		code_info__get_exprn_info(Exprn0),
-		{ code_exprn__place_var(V, Reg, Code0, Exprn0, Exprn1) },
+		( { Mode = ref_in ; Mode = ref_out } ->
+			% (ref_in and caller) or (ref_out and callee)
+			{ code_exprn__place_var_reference(V, Reg, Code0, Exprn0,
+				Exprn1) }
+		;
+			% (top_in and caller) or (top_out and callee)
+			{ code_exprn__place_var(V, Reg, Code0, Exprn0, Exprn1) }
+		),
 			% We need to test that either the variable
 			% is live OR it occurs in the remaining arguments
 			% because of a bug in polymorphism.m which
@@ -2790,6 +2898,19 @@
 	code_info__save_variables_on_stack(Vars, RestCode),
 	{ Code = tree(FirstCode, RestCode) }.
 
+code_info__save_reference_on_stack(Var, Code) -->
+	code_info__get_variable_slot(Var, Slot),
+	code_info__get_exprn_info(Exprn0),
+	{ code_exprn__place_var_reference(Var, Slot, Code, Exprn0, Exprn) },
+	code_info__set_exprn_info(Exprn).
+
+code_info__var_is_free_alias(Var) -->
+	code_info__get_instmap(InstMap),
+	code_info__get_inst_table(InstTable),
+	code_info__get_module_info(ModuleInfo),
+	{ instmap__lookup_var(InstMap, Var, Inst) },
+	{ inst_is_free_alias(Inst, InstTable, ModuleInfo) }.
+
 code_info__max_reg_in_use(Max) -->
 	code_info__get_exprn_info(Exprn),
 	{ code_exprn__max_reg_in_use(Exprn, Max) }.
@@ -3150,4 +3271,14 @@
 	).
 
 %---------------------------------------------------------------------------%
+
+code_info__stack_slots_to_store_map(StackSlots, StoreMap, CodeInfo, CodeInfo) :-
+	map__map_values(lambda([Var::in, Lval::in, StoreInfo::out] is det,
+		( code_info__var_is_free_alias(Var, CodeInfo, _) ->
+			StoreInfo = store_info(ref, Lval)
+		;
+			StoreInfo = store_info(val, Lval)
+		)), StackSlots, StoreMap).
+
+%---------------------------------------------------------------------------%
 %---------------------------------------------------------------------------%
Index: compiler/common.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/common.m,v
retrieving revision 1.44.4.7
diff -u -r1.44.4.7 common.m
--- 1.44.4.7	1998/06/05 08:43:26
+++ common.m	1998/06/22 01:02:43
@@ -373,9 +373,10 @@
 		simplify_info_get_module_info(Info0, ModuleInfo),
 		module_info_pred_proc_info(ModuleInfo, PredId,
 			ProcId, _, ProcInfo),
-		proc_info_argmodes(ProcInfo, argument_modes(ArgInstTable, ArgModes)),
-	    	common__partition_call_args(ModuleInfo, ArgInstTable, ArgModes, Args,
-			InputArgs, OutputArgs)
+		proc_info_argmodes(ProcInfo,
+			argument_modes(ArgInstTable, ArgModes)),
+	    	common__partition_call_args(ModuleInfo, ArgInstTable, ArgModes,
+	    		Args, InputArgs, OutputArgs)
 	->
 		common__optimise_call_2(seen_call(PredId, ProcId), InputArgs,
 			OutputArgs, Goal0, GoalInfo, Goal, Info0, Info)
@@ -575,7 +576,7 @@
 	simplify_info_get_instmap(Info0, InstMap),
 	instmap__lookup_var(InstMap, FromVar, FromVarInst0),
 
-	( FromVarInst0 = free ->
+	( FromVarInst0 = free(unique) ->
 		% This may mean that the variable was local 
 		% to the first unification or call. In that
 		% case we need to recompute the instmap_deltas
Index: compiler/det_util.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/det_util.m,v
retrieving revision 1.12.4.6
diff -u -r1.12.4.6 det_util.m
--- 1.12.4.6	1998/03/26 00:34:05
+++ det_util.m	1998/06/22 01:02:51
@@ -172,11 +172,11 @@
 					bool		% --fully-strict
 				).
 
-det_info_init(ModuleInfo, PredId, ProcId, IKT, Globals, DetInfo) :-
+det_info_init(ModuleInfo, PredId, ProcId, InstTable, Globals, DetInfo) :-
 	globals__lookup_bool_option(Globals, reorder_conj, ReorderConj),
 	globals__lookup_bool_option(Globals, reorder_disj, ReorderDisj),
 	globals__lookup_bool_option(Globals, fully_strict, FullyStrict),
-	DetInfo = det_info(ModuleInfo, PredId, ProcId, IKT,
+	DetInfo = det_info(ModuleInfo, PredId, ProcId, InstTable,
 		ReorderConj, ReorderDisj, FullyStrict).
 
 det_info_get_module_info(det_info(ModuleInfo, _, _, _, _, _, _), ModuleInfo).
Index: compiler/export.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/export.m,v
retrieving revision 1.13.4.5
diff -u -r1.13.4.5 export.m
--- 1.13.4.5	1998/06/05 08:43:58
+++ export.m	1998/06/22 01:02:52
@@ -376,6 +376,14 @@
 	;
 		Mode = top_unused,
 		InputArg = ""
+	;
+		Mode = ref_in,
+		InputArg = ""
+		% XXX will need to change to support exporting pass-by-reference
+		% procedures.
+	;
+		Mode = ref_out,
+		InputArg = ""
 	),
 	get_input_args(ATs, Num, TheRest),
 	string__append(InputArg, TheRest, Result).
@@ -404,6 +412,14 @@
 	;
 		Mode = top_unused,
 		OutputArg = ""
+	;
+		Mode = ref_in,
+		OutputArg = ""
+	;
+		Mode = ref_out,
+		OutputArg = ""
+		% XXX will need to change to support exporting pass-by-reference
+		% procedures.
 	),
 	copy_output_args(ATs, Num, TheRest),
 	string__append(OutputArg, TheRest, Result).
Index: compiler/exprn_aux.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/exprn_aux.m,v
retrieving revision 1.22.4.2
diff -u -r1.22.4.2 exprn_aux.m
--- 1.22.4.2	1998/03/03 00:24:44
+++ exprn_aux.m	1998/06/22 01:02:52
@@ -37,6 +37,9 @@
 :- pred exprn_aux__rval_contains_lval(rval, lval).
 :- mode exprn_aux__rval_contains_lval(in, in) is semidet.
 
+:- pred exprn_aux__lval_contains_lval(lval, lval).
+:- mode exprn_aux__lval_contains_lval(in, in) is semidet.
+
 :- pred exprn_aux__rval_contains_rval(rval, rval).
 :- mode exprn_aux__rval_contains_rval(in, in) is semidet.
 :- mode exprn_aux__rval_contains_rval(in, out) is multidet.
@@ -57,6 +60,9 @@
 :- pred exprn_aux__substitute_rvals_in_rval(assoc_list(rval, rval), rval, rval).
 :- mode exprn_aux__substitute_rvals_in_rval(in, in, out) is det.
 
+:- pred exprn_aux__substitute_lval_in_lval(lval, lval, lval, lval).
+:- mode exprn_aux__substitute_lval_in_lval(in, in, in, out) is det.
+
 :- pred exprn_aux__vars_in_lval(lval, list(var)).
 :- mode exprn_aux__vars_in_lval(in, out) is det.
 
@@ -203,9 +209,6 @@
 		exprn_aux__rval_contains_lval(Rval1, Lval)
 	).
 
-:- pred exprn_aux__lval_contains_lval(lval, lval).
-:- mode exprn_aux__lval_contains_lval(in, in) is semidet.
-
 exprn_aux__lval_contains_lval(Lval0, Lval) :-
 	(
 		Lval0 = Lval
@@ -414,9 +417,6 @@
 		MemRef = heap_ref(Rval, Tag, N)
 	).
 
-:- pred exprn_aux__substitute_lval_in_lval(lval, lval, lval, lval).
-:- mode exprn_aux__substitute_lval_in_lval(in, in, in, out) is det.
-
 exprn_aux__substitute_lval_in_lval(OldLval, NewLval, Lval0, Lval) :-
 	(
 		Lval0 = OldLval
Index: compiler/follow_vars.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/follow_vars.m,v
retrieving revision 1.43.2.9
diff -u -r1.43.2.9 follow_vars.m
--- 1.43.2.9	1998/06/17 04:12:32
+++ follow_vars.m	1998/06/22 01:02:54
@@ -73,10 +73,10 @@
 find_final_follow_vars_2([arg_info(Loc, Mode) | Args], [Var | Vars],
 							Follow0, Follow) :-
 	code_util__arg_loc_to_register(Loc, Reg),
-	(
-		Mode = top_out
-	->
-		map__det_insert(Follow0, Var, Reg, Follow1)
+	( Mode = top_out ->
+		map__det_insert(Follow0, Var, store_info(val, Reg), Follow1)
+	; Mode = ref_out ->
+		map__det_insert(Follow0, Var, store_info(ref, Reg), Follow1)
 	;
 		Follow0 = Follow1
 	),
@@ -281,10 +281,10 @@
 find_follow_vars_from_arginfo_2([arg_info(Loc, Mode) | Args], [Var | Vars],
 							Follow0, Follow) :-
 	code_util__arg_loc_to_register(Loc, Reg),
-	(
-		Mode = top_in
-	->
-		map__set(Follow0, Var, Reg, Follow1)
+	( Mode = top_in ->
+		map__set(Follow0, Var, store_info(val, Reg), Follow1)
+	; Mode = ref_in ->
+		map__set(Follow0, Var, store_info(ref, Reg), Follow1)
 	;
 		Follow0 = Follow1
 	),
Index: compiler/higher_order.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/higher_order.m,v
retrieving revision 1.33.2.11
diff -u -r1.33.2.11 higher_order.m
--- 1.33.2.11	1998/06/17 04:12:42
+++ higher_order.m	1998/06/22 01:02:55
@@ -1216,7 +1216,7 @@
 	PredInstInfo = pred_inst_info(PredOrFunc,
 		argument_modes(CalledArgIT, UnCurriedArgModes), Detism),
 	Inst = ground(shared, yes(PredInstInfo)),
-	Unimode = (free -> Inst) - (Inst -> Inst),
+	Unimode = (free(unique) -> Inst) - (Inst -> Inst),
 	Goal = unify(LVar, Rhs, Unimode, Unify, Context),
 
 	set__list_to_set([LVar | NewHeadVars0], NonLocals),
Index: compiler/hlds_goal.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/hlds_goal.m,v
retrieving revision 1.40.2.7
diff -u -r1.40.2.7 hlds_goal.m
--- 1.40.2.7	1998/06/17 04:12:44
+++ hlds_goal.m	1998/06/22 01:02:55
@@ -223,13 +223,13 @@
 				% The only legal lvals in the range are
 				% stackvars and framevars.
 
-:- type follow_vars	==	map(var, lval).
+:- type follow_vars	==	map(var, store_info).
 				% Advisory information about where variables
 				% ought to be put next. The legal range
 				% includes the nonexistent register r(-1),
 				% which indicates any available register.
 
-:- type store_map	==	map(var, lval).
+:- type store_map	==	map(var, store_info).
 				% Authoritative information about where
 				% variables must be put at the ends of
 				% branches of branched control structures.
@@ -239,6 +239,13 @@
 				% Apart from this, the legal range is
 				% the set of legal lvals.
 
+:- type store_info
+	--->	store_info(store_type, lval).
+
+:- type store_type
+	--->	val	% Lval contains value of variable.
+	;	ref.	% Lval contains pointer to variable location.
+
 	% Initially all unifications are represented as
 	% unify(var, unify_rhs, _, _, _), but mode analysis replaces
 	% these with various special cases (construct/deconstruct/assign/
@@ -438,9 +445,12 @@
 		set(var),	% the post-birth set
 		set(var),	% the pre-death set
 		set(var),	% the post-death set
-				% (all four are computed by liveness.m)
 				% NB for atomic goals, the post-deadness
 				% should be applied _before_ the goal
+		set(var),	% the ref-vars set -- i.e. vars that are
+				% live but have not value yet, only a reference
+				% to where the value should be placed.
+				% (all five are computed by liveness.m)
 
 		determinism, 	% the overall determinism of the goal
 				% (computed during determinism analysis)
@@ -572,6 +582,12 @@
 :- pred goal_info_set_post_deaths(hlds_goal_info, set(var), hlds_goal_info).
 :- mode goal_info_set_post_deaths(in, in, out) is det.
 
+:- pred goal_info_get_refs(hlds_goal_info, set(var)).
+:- mode goal_info_get_refs(in, out) is det.
+
+:- pred goal_info_set_refs(hlds_goal_info, set(var), hlds_goal_info).
+:- mode goal_info_set_refs(in, in, out) is det.
+
 :- pred goal_info_get_code_model(hlds_goal_info, code_model).
 :- mode goal_info_get_code_model(in, out) is det.
 
@@ -746,12 +762,13 @@
 	set__init(PostBirths),
 	set__init(PreDeaths),
 	set__init(PostDeaths),
+	set__init(Refs),
 	instmap_delta_init_unreachable(InstMapDelta),
 	set__init(NonLocals),
 	term__context_init(Context),
 	set__init(Features),
 	GoalInfo = goal_info(PreBirths, PostBirths, PreDeaths, PostDeaths,
-		Detism, InstMapDelta, Context, NonLocals, no, Features,
+		Refs, Detism, InstMapDelta, Context, NonLocals, no, Features,
 		no_resume_point, []).
 
 goal_info_init(NonLocals, InstMapDelta, Detism, GoalInfo) :-
@@ -761,40 +778,44 @@
 	goal_info_set_determinism(GoalInfo2, Detism, GoalInfo).
 
 goal_info_get_pre_births(GoalInfo, PreBirths) :-
-	GoalInfo = goal_info(PreBirths, _, _, _, _, _, _, _, _, _, _, _).
+	GoalInfo = goal_info(PreBirths, _, _, _, _, _, _, _, _, _, _, _, _).
 
 goal_info_get_post_births(GoalInfo, PostBirths) :-
-	GoalInfo = goal_info(_, PostBirths, _, _, _, _, _, _, _, _, _, _).
+	GoalInfo = goal_info(_, PostBirths, _, _, _, _, _, _, _, _, _, _, _).
 
 goal_info_get_pre_deaths(GoalInfo, PreDeaths) :-
-	GoalInfo = goal_info(_, _, PreDeaths, _, _, _, _, _, _, _, _, _).
+	GoalInfo = goal_info(_, _, PreDeaths, _, _, _, _, _, _, _, _, _, _).
 
 goal_info_get_post_deaths(GoalInfo, PostDeaths) :-
-	GoalInfo = goal_info(_, _, _, PostDeaths, _, _, _, _, _, _, _, _).
+	GoalInfo = goal_info(_, _, _, PostDeaths, _, _, _, _, _, _, _, _, _).
+
+goal_info_get_refs(GoalInfo, Refs) :-
+	GoalInfo = goal_info(_, _, _, _, Refs, _, _, _, _, _, _, _, _).
 
 goal_info_get_determinism(GoalInfo, Determinism) :-
-	GoalInfo = goal_info(_, _, _, _, Determinism, _, _, _, _, _, _, _).
+	GoalInfo = goal_info(_, _, _, _, _, Determinism, _, _, _, _, _, _, _).
 
 goal_info_get_instmap_delta(GoalInfo, InstMapDelta) :-
-	GoalInfo = goal_info(_, _, _, _, _, InstMapDelta, _, _, _, _, _, _).
+	GoalInfo = goal_info(_, _, _, _, _, _, InstMapDelta, _, _, _, _, _, _).
 
 goal_info_get_context(GoalInfo, Context) :-
-	GoalInfo = goal_info(_, _, _, _, _, _, Context, _, _, _, _, _).
+	GoalInfo = goal_info(_, _, _, _, _, _, _, Context, _, _, _, _, _).
 
 goal_info_get_nonlocals(GoalInfo, NonLocals) :-
-	GoalInfo = goal_info(_, _, _, _, _, _, _, NonLocals, _, _, _, _).
+	GoalInfo = goal_info(_, _, _, _, _, _, _, _, NonLocals, _, _, _, _).
 
 goal_info_get_follow_vars(GoalInfo, MaybeFollowVars) :-
-	GoalInfo = goal_info(_, _, _, _, _, _, _, _, MaybeFollowVars, _, _, _).
+	GoalInfo = goal_info(_, _, _, _, _, _, _, _, _, MaybeFollowVars,
+		_, _, _).
 
 goal_info_get_features(GoalInfo, Features) :-
-	GoalInfo = goal_info(_, _, _, _, _, _, _, _, _, Features, _, _).
+	GoalInfo = goal_info(_, _, _, _, _, _, _, _, _, _, Features, _, _).
 
 goal_info_get_resume_point(GoalInfo, ResumePoint) :-
-	GoalInfo = goal_info(_, _, _, _, _, _, _, _, _, _, ResumePoint, _).
+	GoalInfo = goal_info(_, _, _, _, _, _, _, _, _, _, _, ResumePoint, _).
 
 goal_info_get_goal_path(GoalInfo, GoalPath) :-
-	GoalInfo = goal_info(_, _, _, _, _, _, _, _, _, _, _, GoalPath).
+	GoalInfo = goal_info(_, _, _, _, _, _, _, _, _, _, _, _, GoalPath).
 
 % :- type hlds_goal_info
 % 	--->	goal_info(
@@ -802,63 +823,68 @@
 % 		B	set(var),	% the post-birth set
 % 		C	set(var),	% the pre-death set
 % 		D	set(var),	% the post-death set
-% 		E	determinism, 	% the overall determinism of the goal
-% 		F	instmap_delta,	% the change in insts over this goal
-% 		G	term__context,
-% 		H	set(var),	% the non-local vars in the goal
-% 		I	maybe(follow_vars),
-% 		J	set(goal_feature),
-%		K	resume_point,
-%		L	goal_path
+%		E	set(var),	% the references set
+% 		F	determinism, 	% the overall determinism of the goal
+% 		G	instmap_delta,	% the change in insts over this goal
+% 		H	term__context,
+% 		I	set(var),	% the non-local vars in the goal
+% 		J	maybe(follow_vars),
+% 		K	set(goal_feature),
+%		L	resume_point,
+%		M	goal_path
 % 	).
 
 goal_info_set_pre_births(GoalInfo0, PreBirths, GoalInfo) :-
-	GoalInfo0 = goal_info(_, B, C, D, E, F, G, H, I, J, K, L),
-	GoalInfo = goal_info(PreBirths, B, C, D, E, F, G, H, I, J, K, L).
+	GoalInfo0 = goal_info(_, B, C, D, E, F, G, H, I, J, K, L, M),
+	GoalInfo = goal_info(PreBirths, B, C, D, E, F, G, H, I, J, K, L, M).
 
 goal_info_set_post_births(GoalInfo0, PostBirths, GoalInfo) :-
-	GoalInfo0 = goal_info(A, _, C, D, E, F, G, H, I, J, K, L),
-	GoalInfo = goal_info(A, PostBirths, C, D, E, F, G, H, I, J, K, L).
+	GoalInfo0 = goal_info(A, _, C, D, E, F, G, H, I, J, K, L, M),
+	GoalInfo = goal_info(A, PostBirths, C, D, E, F, G, H, I, J, K, L, M).
 
 goal_info_set_pre_deaths(GoalInfo0, PreDeaths, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, _, D, E, F, G, H, I, J, K, L),
-	GoalInfo = goal_info(A, B, PreDeaths, D, E, F, G, H, I, J, K, L).
+	GoalInfo0 = goal_info(A, B, _, D, E, F, G, H, I, J, K, L, M),
+	GoalInfo = goal_info(A, B, PreDeaths, D, E, F, G, H, I, J, K, L, M).
 
 goal_info_set_post_deaths(GoalInfo0, PostDeaths, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, _, E, F, G, H, I, J, K, L),
-	GoalInfo = goal_info(A, B, C, PostDeaths, E, F, G, H, I, J, K, L).
+	GoalInfo0 = goal_info(A, B, C, _, E, F, G, H, I, J, K, L, M),
+	GoalInfo = goal_info(A, B, C, PostDeaths, E, F, G, H, I, J, K, L, M).
+
+goal_info_set_refs(GoalInfo0, Refs, GoalInfo) :-
+	GoalInfo0 = goal_info(A, B, C, D, _, F, G, H, I, J, K, L, M),
+	GoalInfo = goal_info(A, B, C, D, Refs, F, G, H, I, J, K, L, M).
 
 goal_info_set_determinism(GoalInfo0, Determinism, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, _, F, G, H, I, J, K, L),
-	GoalInfo = goal_info(A, B, C, D, Determinism, F, G, H, I, J, K, L).
+	GoalInfo0 = goal_info(A, B, C, D, E, _, G, H, I, J, K, L, M),
+	GoalInfo = goal_info(A, B, C, D, E, Determinism, G, H, I, J, K, L, M).
 
 goal_info_set_instmap_delta(GoalInfo0, InstMapDelta, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, E, _, G, H, I, J, K, L),
-	GoalInfo = goal_info(A, B, C, D, E, InstMapDelta, G, H, I, J, K, L).
+	GoalInfo0 = goal_info(A, B, C, D, E, F, _, H, I, J, K, L, M),
+	GoalInfo = goal_info(A, B, C, D, E, F, InstMapDelta, H, I, J, K, L, M).
 
 goal_info_set_context(GoalInfo0, Context, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, E, F, _, H, I, J, K, L),
-	GoalInfo = goal_info(A, B, C, D, E, F, Context, H, I, J, K, L).
+	GoalInfo0 = goal_info(A, B, C, D, E, F, G, _, I, J, K, L, M),
+	GoalInfo = goal_info(A, B, C, D, E, F, G, Context, I, J, K, L, M).
 
 goal_info_set_nonlocals(GoalInfo0, NonLocals, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, E, F, G, _, I, J, K, L),
-	GoalInfo  = goal_info(A, B, C, D, E, F, G, NonLocals, I, J, K, L).
+	GoalInfo0 = goal_info(A, B, C, D, E, F, G, H, _, J, K, L, M),
+	GoalInfo  = goal_info(A, B, C, D, E, F, G, H, NonLocals, J, K, L, M).
 
 goal_info_set_follow_vars(GoalInfo0, FollowVars, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, E, F, G, H, _, J, K, L),
-	GoalInfo  = goal_info(A, B, C, D, E, F, G, H, FollowVars, J, K, L).
+	GoalInfo0 = goal_info(A, B, C, D, E, F, G, H, I, _, K, L, M),
+	GoalInfo  = goal_info(A, B, C, D, E, F, G, H, I, FollowVars, K, L, M).
 
 goal_info_set_features(GoalInfo0, Features, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, E, F, G, H, I, _, K, L),
-	GoalInfo  = goal_info(A, B, C, D, E, F, G, H, I, Features, K, L).
+	GoalInfo0 = goal_info(A, B, C, D, E, F, G, H, I, J, _, L, M),
+	GoalInfo  = goal_info(A, B, C, D, E, F, G, H, I, J, Features, L, M).
 
 goal_info_set_resume_point(GoalInfo0, ResumePoint, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, E, F, G, H, I, J, _, L),
-	GoalInfo  = goal_info(A, B, C, D, E, F, G, H, I, J, ResumePoint, L).
+	GoalInfo0 = goal_info(A, B, C, D, E, F, G, H, I, J, K, _, M),
+	GoalInfo  = goal_info(A, B, C, D, E, F, G, H, I, J, K, ResumePoint, M).
 
 goal_info_set_goal_path(GoalInfo0, GoalPath, GoalInfo) :-
-	GoalInfo0 = goal_info(A, B, C, D, E, F, G, H, I, J, K, _),
-	GoalInfo  = goal_info(A, B, C, D, E, F, G, H, I, J, K, GoalPath).
+	GoalInfo0 = goal_info(A, B, C, D, E, F, G, H, I, J, K, L, _),
+	GoalInfo  = goal_info(A, B, C, D, E, F, G, H, I, J, K, L, GoalPath).
 
 goal_info_get_code_model(GoalInfo, CodeModel) :-
 	goal_info_get_determinism(GoalInfo, Determinism),
Index: compiler/hlds_out.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/hlds_out.m,v
retrieving revision 1.172.2.9
diff -u -r1.172.2.9 hlds_out.m
--- 1.172.2.9	1998/06/17 04:12:47
+++ hlds_out.m	1998/06/22 01:02:56
@@ -1190,7 +1190,8 @@
 			% mode analysis yet
 			{ Unification = complicated_unify(Mode, CanFail) },
 			{ CanFail = can_fail },
-			{ Mode = (free - free -> free - free) }
+			{ Mode = (free(unique) - free(unique) -> 
+					free(unique) - free(unique)) }
 		->
 			hlds_out__write_indent(Indent),
 			io__write_string("% Not yet classified\n")
@@ -1836,20 +1837,27 @@
 
 hlds_out__write_stack_slots(Indent, StackSlots, VarSet, AppendVarnums) -->
 	{ map__to_assoc_list(StackSlots, VarSlotList) },
-	hlds_out__write_var_to_lvals(VarSlotList, VarSet, AppendVarnums,
+	{ list__map(lambda([X::in, Y::out] is det, 
+			( X = V - L, Y = V - store_info(val, L) )),
+		VarSlotList, StoreInfoList) },
+	hlds_out__write_var_to_lvals(StoreInfoList, VarSet, AppendVarnums,
 		Indent).
 
-:- pred hlds_out__write_var_to_lvals(assoc_list(var, lval), varset, bool, int,
-	io__state, io__state).
+:- pred hlds_out__write_var_to_lvals(assoc_list(var, store_info), varset,
+	bool, int, io__state, io__state).
 :- mode hlds_out__write_var_to_lvals(in, in, in, in, di, uo) is det.
 
-hlds_out__write_var_to_lvals([], _, _, _) --> [].
-hlds_out__write_var_to_lvals([Var - Loc | VarLocs], VarSet, AppendVarnums,
-		Indent) -->
+	hlds_out__write_var_to_lvals([], _, _, _) --> [].
+hlds_out__write_var_to_lvals([Var - store_info(ValOrRef, Loc) | VarLocs],
+		VarSet, AppendVarnums, Indent) -->
 	hlds_out__write_indent(Indent),
 	io__write_string("%\t"),
 	mercury_output_var(Var, VarSet, AppendVarnums),
 	io__write_string("\t-> "),
+	( { ValOrRef = ref },
+		io__write_string("*")
+	; { ValOrRef = val }
+	),
 	{ llds_out__lval_to_string(Loc, LocStrPrime) ->
 		LocStr = LocStrPrime
 	;
Index: compiler/hlds_pred.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/hlds_pred.m,v
retrieving revision 1.35.4.9
diff -u -r1.35.4.9 hlds_pred.m
--- 1.35.4.9	1998/06/05 08:44:42
+++ hlds_pred.m	1998/06/22 01:02:56
@@ -137,7 +137,9 @@
 
 :- type arg_mode	--->	top_in
 			;	top_out
-			;	top_unused.
+			;	top_unused
+			;	ref_out
+			;	ref_in.
 
 :- type arg_loc		==	int.
 
Index: compiler/inst.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/compiler/inst.m,v
retrieving revision 1.2.4.6
diff -u -r1.2.4.6 inst.m
--- 1.2.4.6	1998/03/17 00:01:42
+++ inst.m	1998/06/22 01:02:56
@@ -21,8 +21,8 @@
 :- type (inst)
 	--->		any(uniqueness)
 	;		alias(inst_key)
-	;		free
-	;		free(type)
+	;		free(aliasing)
+	;		free(aliasing, type)
 	;		bound(uniqueness, list(bound_inst))
 				% The list(bound_inst) must be sorted
 	;		ground(uniqueness, maybe(pred_inst_info))
@@ -41,6 +41,11 @@
 				% defined (yet).
 	;		abstract_inst(sym_name, list(inst)).
 
+:- type aliasing
+	--->		unique	% No aliases.
+	;		alias.		% An alias exists.
+	% ;		alias_many.	% Many aliases - XXX to be added later.
+
 :- type uniqueness
 	--->		shared		% there might be other references
 	;		unique		% there is only one reference
@@ -406,8 +411,9 @@
 	).
 optimise_inst_keys_in_inst(_OldFwd, _UsedOnce, _Sub,
 		any(Uniq), any(Uniq), IKs, IKs).
-optimise_inst_keys_in_inst(_OldFwd, _UsedOnce, _Sub, free, free, IKs, IKs).
-optimise_inst_keys_in_inst(_OldFwd, _UsedOnce, _Sub, free(T), free(T),
+optimise_inst_keys_in_inst(_OldFwd, _UsedOnce, _Sub, free(A), free(A), 
+		IKs, IKs).
+optimise_inst_keys_in_inst(_OldFwd, _UsedOnce, _Sub, free(A, T), free(A, T),
 		IKs, IKs).
 optimise_inst_keys_in_inst(OldFwd, UsedOnce, Sub,
 		bound(Uniq, Insts0), bound(Uniq, Insts), IKs0, IKs) :-
@@ -578,8 +584,8 @@
 
 inst_keys_in_inst(any(_Uniq), Keys, Keys).
 inst_keys_in_inst(alias(Key), Keys, [Key | Keys]).
-inst_keys_in_inst(free, Keys, Keys).
-inst_keys_in_inst(free(_Type), Keys, Keys).
+inst_keys_in_inst(free(_), Keys, Keys).
+inst_keys_in_inst(free(_, _Type), Keys, Keys).
 inst_keys_in_inst(bound(_Uniq, BoundInsts), Keys0, Keys) :-
 	inst_keys_in_bound_insts(BoundInsts, Keys0, Keys).
 inst_keys_in_inst(ground(_Uniq, _MaybePredInstInfo), Keys, Keys).
@@ -613,8 +619,8 @@
 inst_expand_fully(IKT, alias(Key), Inst) :-
 	inst_key_table_lookup(IKT, Key, Inst0),
 	inst_expand_fully(IKT, Inst0, Inst).
-inst_expand_fully(_IKT, free, free).
-inst_expand_fully(_IKT, free(Type), free(Type)).
+inst_expand_fully(_IKT, free(A), free(A)).
+inst_expand_fully(_IKT, free(A, Type), free(A, Type)).
 inst_expand_fully(IKT, bound(Uniq, BoundInsts0), bound(Uniq, BoundInsts)) :-
 	bound_insts_expand_fully(IKT, BoundInsts0, BoundInsts).
 inst_expand_fully(_IKT, ground(Uniq, PredInstInfo), ground(Uniq, PredInstInfo)).
@@ -645,8 +651,8 @@
 	;
 		Key = Key0
 	).
-inst_apply_sub(_Sub, free, free).
-inst_apply_sub(_Sub, free(Type), free(Type)).
+inst_apply_sub(_Sub, free(Aliasing), free(Aliasing)).
+inst_apply_sub(_Sub, free(Aliasing, Type), free(Aliasing, Type)).
 inst_apply_sub(Sub, bound(Uniq, BoundInsts0), bound(Uniq, BoundInsts)) :-
 	list__map(bound_inst_apply_sub(Sub), BoundInsts0, BoundInsts).
 inst_apply_sub(_Sub, ground(Uniq, MaybePredInstInfo),



More information about the developers mailing list