[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