[m-rev.] for review: MLDS back-end: hoist static constants

Fergus Henderson fjh at cs.mu.OZ.AU
Mon Jul 9 06:21:34 AEST 2001


Estimated hours taken: 3
Branches: main

Change the MLDS back-end so that it hoists *all* static constants out
to the top level.

This is required for the IL and Java targets since they don't support
function-local static variables.  It doesn't cost anything for the
C or GCC targets, so for consistency we may as well do it for all targets.

Also some related bug fixes in the IL back-end.
With these changes, string switches now work.

compiler/ml_elim_nested.m:
	Hoist all static constants, rather than just hoisting those that
	might be referenced from nested functions or from other static
	constants that need to be hoisted.

compiler/mlds.m:
	Document that ml_elim_nested.m does not change the access for
	hoisted static constants from `local' to `private'.

compiler/ml_util.m:
	Fix a bug where the behaviour of defn_is_public did not match
	its documentation.  This caused wrong behaviour in mlds_to_c.m
	when handling hoisted static constants.

compiler/mlds_to_il.m:
	Don't assume that variables which are not local vars or arguments
	are defined in foreign code (cpp_code).  Instead, assume that they
	are static fields, unless they come from private_builtin.m.

	Don't assume that all fields have type `il_array_type', i.e.
	`object[]'.  Instead, use the type specified in the MLDS.

Workspace: /home/administrator/ws/ws1
Index: compiler/ml_elim_nested.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_elim_nested.m,v
retrieving revision 1.29
diff -u -d -r1.29 ml_elim_nested.m
--- compiler/ml_elim_nested.m	27 Jun 2001 13:41:30 -0000	1.29
+++ compiler/ml_elim_nested.m	8 Jul 2001 20:17:55 -0000
@@ -829,9 +829,20 @@
 		=(ElimInfo),
 		{ ModuleName = elim_info_get_module_name(ElimInfo) },
 		(
-			{ Name = data(var(VarName)) },
-			{ ml_should_add_local_data(ModuleName, VarName,
-				FollowingDefns, FollowingStatements) }
+			(
+				% For IL and Java, we need to hoist all
+				% static constants out to the top level,
+				% so that they can be initialized in the
+				% class constructor.
+				% To keep things consistent (and reduce
+				% the testing burden), we do the same for
+				% the other back-ends too.
+				{ ml_decl_is_static_const(Defn0) }
+			;
+				{ Name = data(var(VarName)) },
+				{ ml_should_add_local_data(ModuleName, VarName,
+					FollowingDefns, FollowingStatements) }
+			)
 		->
 			elim_info_add_local_data(Defn0),
 			{ Defns = [] }
@@ -859,15 +870,16 @@
 	%
 	% This checks for a nested function definition
 	% or static initializer that references the variable.
-	% This is conservative; we only need to hoist out
+	% This is conservative; for the MLDS->C and MLDS->GCC
+	% back-ends, we only need to hoist out
 	% static variables if they are referenced by
 	% static initializers which themselves need to be
 	% hoisted because they are referenced from a nested
 	% function.  But checking the last part of that
-	% is tricky, so currently we just hoist more
-	% of the static consts than we strictly need to.
-	% Perhaps it would be simpler to just hoist *all*
-	% static consts.
+	% is tricky, and for the Java and IL back-ends we
+	% need to hoist out all static constants anyway,
+	% so to keep things simple we do the same for the
+	% C back-end to, i.e. we always hoist all static constants.
 	%
 :- pred ml_should_add_local_data(mlds_module_name, mlds__var_name,
 		mlds__defns, mlds__statements).
Index: compiler/ml_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_util.m,v
retrieving revision 1.11
diff -u -d -r1.11 ml_util.m
--- compiler/ml_util.m	22 Jun 2001 09:14:34 -0000	1.11
+++ compiler/ml_util.m	8 Jul 2001 20:17:56 -0000
@@ -317,7 +317,7 @@
 
 defn_is_public(Defn) :-
 	Defn = mlds__defn(_Name, _Context, Flags, _Body),
-	access(Flags) \= private.
+	access(Flags) = public.
 
 %-----------------------------------------------------------------------------%
 %
Index: compiler/mlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds.m,v
retrieving revision 1.56
diff -u -d -r1.56 mlds.m
--- compiler/mlds.m	22 Jun 2001 09:14:35 -0000	1.56
+++ compiler/mlds.m	8 Jul 2001 20:17:57 -0000
@@ -600,8 +600,10 @@
 	;	default		% Java "default" access: accessible to anything
 				% defined in the same package.
 	%
-	% used for entities defined in a block/2 statement,
-	% i.e. local variables and nested functions
+	% Used for entities defined in a block/2 statement,
+	% i.e. local variables and nested functions.
+	% Note that ml_elim_nested hoists out static constants to the
+	% top level, but leaves their access flag as `local'.
 	%
 	;	local		% only accessible within the block
 				% in which the entity (variable or
Index: compiler/mlds_to_il.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_il.m,v
retrieving revision 1.37
diff -u -d -r1.37 mlds_to_il.m
--- compiler/mlds_to_il.m	8 Jul 2001 16:40:09 -0000	1.37
+++ compiler/mlds_to_il.m	8 Jul 2001 20:17:59 -0000
@@ -408,7 +408,7 @@
 	{ mangle_dataname(DataName, FieldName) },
 		
 	( 
-		{ Entity = mlds__data(_DataType, DataInitializer) }
+		{ Entity = mlds__data(DataType, DataInitializer) }
 	->
 			% Generate instructions to initialize this data.
 			% There are two sorts of instructions,
@@ -416,11 +416,13 @@
 			% and instructions to initialize it.
 			% See the comments about class constructors to
 			% find out why we do this.
-		data_initializer_to_instrs(DataInitializer, AllocInstrsTree,
-			InitInstrTree),
+		data_initializer_to_instrs(DataInitializer, DataType,
+			AllocInstrsTree, InitInstrTree),
 
 			% Make a field reference for the field
-		{ FieldRef = make_fieldref(il_array_type,
+		DataRep =^ il_data_rep,
+		{ ILDataType = mlds_type_to_ilds_type(DataRep, DataType) },
+		{ FieldRef = make_fieldref(ILDataType,
 			ClassName, FieldName) },
 
 			% If we had to allocate memory, the code
@@ -491,7 +493,7 @@
 
 			% Make a public static field and add the field
 			% and a comment term to the class decls.
-		{ Field = field([public, static], il_array_type,
+		{ Field = field([public, static], ILDataType,
 			FieldName, no, none) },
 		{ ClassDecls = [comment_term(MLDSDefnTerm), Field] }
 	;
@@ -578,8 +580,8 @@
 				{ StoreLvalInstrs = node([]) },
 				{ NameString = "unknown" }
 			),
-			data_initializer_to_instrs(Initializer, AllocInstrs,
-				InitInstrs),
+			data_initializer_to_instrs(Initializer, MLDSType,
+				AllocInstrs, InitInstrs),
 			{ string__append("initializer for ", NameString, 
 				Comment) },
 			{ Tree = tree__list([
@@ -599,21 +601,37 @@
 	% initialize this value, leave it on the stack.
 	% XXX the code generator doesn't box these values
 	% we need to look ahead at them and box them appropriately.
-:- pred data_initializer_to_instrs(mlds__initializer::in,
+:- pred data_initializer_to_instrs(mlds__initializer::in, mlds__type::in,
 	instr_tree::out, instr_tree::out, il_info::in, il_info::out) is det.
-data_initializer_to_instrs(init_obj(Rval), node([]), InitInstrs) --> 
+data_initializer_to_instrs(init_obj(Rval), _Type, node([]), InitInstrs) --> 
 	load(Rval, InitInstrs).
 
 	% Currently, structs are the same as arrays.
-data_initializer_to_instrs(init_struct(InitList), AllocInstrs, InitInstrs) --> 
-	data_initializer_to_instrs(init_array(InitList), AllocInstrs, 
-		InitInstrs).
+data_initializer_to_instrs(init_struct(InitList), Type,
+		AllocInstrs, InitInstrs) --> 
+	data_initializer_to_instrs(init_array(InitList), Type,
+		AllocInstrs, InitInstrs).
 
 	% Put the array allocation in AllocInstrs.
 	% For sub-initializations, we don't worry about keeping AllocInstrs
 	% and InitInstrs apart, since we are only interested in top level
 	% allocations.
-data_initializer_to_instrs(init_array(InitList), AllocInstrs, InitInstrs) -->
+data_initializer_to_instrs(init_array(InitList), Type,
+		AllocInstrs, InitInstrs) -->
+		%
+		% figure out the array element type
+		%
+	DataRep =^ il_data_rep,
+	( { Type = mlds__array_type(ElemType0) } ->
+		{ ElemType = ElemType0 },
+		{ ILElemType = mlds_type_to_ilds_type(DataRep, ElemType) }
+	;
+		% XXX we assume struct fields have type mlds__generic_type
+		% This is probably wrong for --high-level-data
+		{ ElemType = mlds__generic_type },
+		{ ILElemType = il_generic_type }
+	),
+	{ ILElemType = ilds__type(_, ILElemSimpleType) },
 
 		% To initialize an array, we generate the following
 		% code:
@@ -630,21 +648,29 @@
 		%
 		% The initialization will leave the array on the stack.
 		%	
-	{ AllocInstrs = node([ldc(int32, i(list__length(InitList))), 
-		newarr(il_generic_type)]) },
+	{ AllocInstrs = node([
+		ldc(int32, i(list__length(InitList))), 
+		newarr(ILElemType)]) },
 	{ AddInitializer = 
 		(pred(Init0::in, X0 - Tree0::in, (X0 + 1) - Tree::out,
 				in, out) is det -->
-			maybe_box_initializer(Init0, Init),
-			data_initializer_to_instrs(Init, ATree1, ITree1),
+			% we may need to box the arguments
+			% XXX is this right?
+			( { ElemType = mlds__generic_type } ->
+				maybe_box_initializer(Init0, Init)
+			;
+				{ Init = Init0 }
+			),
+			data_initializer_to_instrs(Init, ElemType,
+				ATree1, ITree1),
 			{ Tree = tree(tree(Tree0, node(
 					[dup, ldc(int32, i(X0))])), 
 				tree(tree(ATree1, ITree1), 
-					node([stelem(il_generic_simple_type)]
+					node([stelem(ILElemSimpleType)]
 				))) }
 		) },
 	list__foldl2(AddInitializer, InitList, 0 - empty, _ - InitInstrs).
-data_initializer_to_instrs(no_initializer, node([]), node([])) --> [].
+data_initializer_to_instrs(no_initializer, _, node([]), node([])) --> [].
 
 	% If we are initializing an array or struct, we need to box
 	% all the things inside it.
@@ -1279,8 +1305,7 @@
 		; is_argument(MangledVarStr, Info) ->
 			Instrs = instr_node(ldarg(name(MangledVarStr)))
 		;
-			FieldRef = make_fieldref_for_handdefined_var(DataRep,
-				Var, VarType),
+			FieldRef = make_static_fieldref(DataRep, Var, VarType),
 			Instrs = instr_node(ldsfld(FieldRef))
 		}
 	; { Lval = field(_MaybeTag, Rval, FieldNum, FieldType, ClassType) },
@@ -1365,8 +1390,7 @@
 		; is_argument(MangledVarStr, Info) ->
 			Instrs = instr_node(ldarga(name(MangledVarStr)))
 		;
-			FieldRef = make_fieldref_for_handdefined_var(DataRep,
-				Var, VarType),
+			FieldRef = make_static_fieldref(DataRep, Var, VarType),
 			Instrs = instr_node(ldsfld(FieldRef))
 		}
 	; { Lval = field(_MaybeTag, Rval, FieldNum, FieldType, ClassType) },
@@ -1408,8 +1432,7 @@
 	; is_argument(MangledVarStr, Info) ->
 		Instrs = instr_node(starg(name(MangledVarStr)))
 	;
-		FieldRef = make_fieldref_for_handdefined_var(DataRep, Var,
-			VarType),
+		FieldRef = make_static_fieldref(DataRep, Var, VarType),
 		Instrs = instr_node(stsfld(FieldRef))
 	}.
 
@@ -2123,18 +2146,18 @@
 
 
 	% If an mlds__var is not an argument or a local, what is it?
-	% We assume the given variable is a handwritten RTTI reference or a
+	% We assume the given variable is a static field;
+	% either a compiler-generated static,
+	% or possibly a handwritten RTTI reference or a
 	% reference to some hand-written code in the
-	% modulename__cpp_code class.  This is OK so long as the
-	% code generator uses real 'field' lvals to reference
-	% fields in the modulename class.
+	% modulename__cpp_code class.
 
-:- func make_fieldref_for_handdefined_var(il_data_rep, mlds__var, mlds__type)
+:- func make_static_fieldref(il_data_rep, mlds__var, mlds__type)
 	 = fieldref.
-make_fieldref_for_handdefined_var(DataRep, Var, VarType) = FieldRef :-
-	Var = qual(ModuleName, _),
+make_static_fieldref(DataRep, Var, VarType) = FieldRef :-
+	Var = qual(ModuleName, VarName),
 	mangle_mlds_var(Var, MangledVarStr),
-	mangle_dataname_module(no, ModuleName, NewModuleName),
+	mangle_dataname_module(yes(var(VarName)), ModuleName, NewModuleName),
 	ClassName = mlds_module_name_to_class_name(NewModuleName, yes),
 	FieldRef = make_fieldref(
 		mlds_type_to_ilds_type(DataRep, VarType), ClassName,
@@ -2173,35 +2196,40 @@
 		SymName = mlds_module_name_to_sym_name(ModuleName0),
 		SymName = qualified(unqualified("mercury"),
 			LibModuleName0),
-		DataName = rtti(rtti_type_id(_, Name, Arity),
-			_RttiName),
-		( LibModuleName0 = "builtin",
-			( 
-			  Name = "int", Arity = 0 
-			; Name = "string", Arity = 0
-			; Name = "float", Arity = 0
-			; Name = "character", Arity = 0
-			; Name = "void", Arity = 0
-			; Name = "c_pointer", Arity = 0
-			; Name = "pred", Arity = 0
-			; Name = "func", Arity = 0
-			)
-		; LibModuleName0 = "array", 
-			(
-			  Name = "array", Arity = 1
-			)
-		; LibModuleName0 = "std_util",
-			( 
-			  Name = "type_desc", Arity = 0
-			)
-		; LibModuleName0 = "private_builtin",
-			( 
-			  Name = "type_ctor_info", Arity = 1
-			; Name = "type_info", Arity = 1
-			; Name = "base_typeclass_info", Arity = 1
-			; Name = "typeclass_info", Arity = 1
-			)
-		)		  
+		(
+			DataName = rtti(rtti_type_id(_, Name, Arity),
+				_RttiName),
+			( LibModuleName0 = "builtin",
+				( 
+				  Name = "int", Arity = 0 
+				; Name = "string", Arity = 0
+				; Name = "float", Arity = 0
+				; Name = "character", Arity = 0
+				; Name = "void", Arity = 0
+				; Name = "c_pointer", Arity = 0
+				; Name = "pred", Arity = 0
+				; Name = "func", Arity = 0
+				)
+			; LibModuleName0 = "array", 
+				(
+				  Name = "array", Arity = 1
+				)
+			; LibModuleName0 = "std_util",
+				( 
+				  Name = "type_desc", Arity = 0
+				)
+			; LibModuleName0 = "private_builtin",
+				( 
+				  Name = "type_ctor_info", Arity = 1
+				; Name = "type_info", Arity = 1
+				; Name = "base_typeclass_info", Arity = 1
+				; Name = "typeclass_info", Arity = 1
+				)
+			)		  
+		;
+			DataName = var(_),
+			LibModuleName0 = "private_builtin"
+		)
 	->
 		string__append(LibModuleName0, "__cpp_code",
 			LibModuleName),
-- 
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