[m-rev.] diff: four space most of ml*.m
Zoltan Somogyi
zs at cs.mu.OZ.AU
Tue Sep 13 11:19:38 AEST 2005
compiler/ml_*.m:
Convert these modules to four space indentation, and clean up
departures from our coding standards.
cvs diff: Diffing .
cvs diff: Diffing analysis
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/doc
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/ml_backend.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/ml_backend.m,v
retrieving revision 1.10
diff -u -b -r1.10 ml_backend.m
--- compiler/ml_backend.m 22 Mar 2005 06:40:08 -0000 1.10
+++ compiler/ml_backend.m 12 Sep 2005 10:06:09 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 2002-2005 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -14,10 +16,10 @@
% and a wrapper for the assembler back-end,
% each of which convert MLDS to their respective target language.
%
-% The main part of the assembler back-end, which converts MLDS
-% to GCC's internal abstract syntax trees and then invokes the
-% GCC back-end to convert this to assembler, is in a package of
-% its own, so that this package doesn't depend on the GCC back-end.
+% The main part of the assembler back-end, which converts MLDS to GCC's
+% internal abstract syntax trees and then invokes the GCC back-end to convert
+% this to assembler, is in a package of its own, so that this package doesn't
+% depend on the GCC back-end.
%
:- module ml_backend.
:- interface.
@@ -31,8 +33,8 @@
:- include_module ml_util.
% Phase 4-ml: MLDS-specific HLDS to HLDS transformations and annotations.
-:- include_module add_heap_ops.
-:- include_module add_trail_ops. % transformations
+:- include_module add_heap_ops. % transformation
+:- include_module add_trail_ops. % transformation
:- include_module mark_static_terms. % annotation
% Phase 5-ml: compile HLDS to MLDS
Index: compiler/ml_call_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/ml_call_gen.m,v
retrieving revision 1.53
diff -u -b -r1.53 ml_call_gen.m
--- compiler/ml_call_gen.m 12 Sep 2005 05:24:13 -0000 1.53
+++ compiler/ml_call_gen.m 12 Sep 2005 13:19:55 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 1999-2005 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -28,15 +30,14 @@
% Generate MLDS code for an HLDS generic_call goal.
% This includes boxing/unboxing the arguments if necessary.
+ %
:- pred ml_gen_generic_call(generic_call::in, list(prog_var)::in,
list(mode)::in, determinism::in, prog_context::in,
mlds__defns::out, mlds__statements::out,
ml_gen_info::in, ml_gen_info::out) is det.
- %
% ml_gen_call(PredId, ProcId, ArgNames, ArgLvals, ArgTypes,
- % CodeModel, Context, ForClosureWrapper,
- % Defns, Statements):
+ % CodeModel, Context, ForClosureWrapper, Defns, Statements):
%
% Generate MLDS code for an HLDS procedure call, making sure to
% box/unbox the arguments if necessary.
@@ -52,7 +53,6 @@
prog_context::in, bool::in, mlds__defns::out, mlds__statements::out,
ml_gen_info::in, ml_gen_info::out) is det.
- %
% Generate MLDS code for a call to a builtin procedure.
%
:- pred ml_gen_builtin(pred_id::in, proc_id::in, list(prog_var)::in,
@@ -60,7 +60,6 @@
mlds__defns::out, mlds__statements::out,
ml_gen_info::in, ml_gen_info::out) is det.
- %
% Generate MLDS code for a cast. The list of argument variables
% must have only two elements, the input and the output.
%
@@ -68,15 +67,14 @@
mlds__defns::out, mlds__statements::out,
ml_gen_info::in, ml_gen_info::out) is det.
- %
% Generate an rval containing the address of the specified procedure.
%
:- pred ml_gen_proc_addr_rval(pred_id::in, proc_id::in, mlds__rval::out,
ml_gen_info::in, ml_gen_info::out) is det.
- % Given a source type and a destination type,
- % and given an source rval holding a value of the source type,
- % produce an rval that converts the source rval to the destination type.
+ % Given a source type and a destination type, and given an source rval
+ % holding a value of the source type, produce an rval that converts
+ % the source rval to the destination type.
%
:- pred ml_gen_box_or_unbox_rval(prog_type::in, prog_type::in,
mlds__rval::in, mlds__rval::out,
@@ -86,21 +84,19 @@
% Context, ForClosureWrapper, ArgNum,
% ArgLval, ConvDecls, ConvInputStatements, ConvOutputStatements):
%
- % This is like `ml_gen_box_or_unbox_rval', except that it
- % works on lvals rather than rvals.
- % Given a source type and a destination type,
- % a source lval holding a value of the source type,
- % and a name to base the name of the local temporary variable on,
- % this procedure produces an lval of the destination type,
- % the declaration for the local temporary used (if any),
- % code to assign from the source lval (suitable converted)
- % to the destination lval, and code to assign from the
- % destination lval (suitable converted) to the source lval.
+ % This is like `ml_gen_box_or_unbox_rval', except that it works on lvals
+ % rather than rvals. Given a source type and a destination type,
+ % a source lval holding a value of the source type, and a name to base
+ % the name of the local temporary variable on, this procedure produces
+ % an lval of the destination type, the declaration for the local temporary
+ % used (if any), code to assign from the source lval (suitable converted)
+ % to the destination lval, and code to assign from the destination lval
+ % (suitable converted) to the source lval.
%
% If ForClosureWrapper = yes, then the type_info for type variables
- % in CallerType may not be available in the current procedure, so
- % the GC tracing code for the ConvDecls (if any) should obtain the
- % type_info from the ArgNum-th entry in the `type_params' local.
+ % in CallerType may not be available in the current procedure, so the GC
+ % tracing code for the ConvDecls (if any) should obtain the type_info
+ % from the ArgNum-th entry in the `type_params' local.
% (If ForClosureWrapper = no, then ArgNum is unused.)
%
:- pred ml_gen_box_or_unbox_lval(prog_type::in, prog_type::in, mlds__lval::in,
@@ -109,12 +105,11 @@
ml_gen_info::in, ml_gen_info::out) is det.
% Generate the appropriate MLDS type for a continuation function
- % for a nondet procedure whose output arguments have the
- % specified types.
+ % for a nondet procedure whose output arguments have the specified types.
%
- % WARNING: this does not fill in the maybe_gc_trace_code for the
- % function parameters. It is the caller's responsibility to fill
- % these in properly if needed.
+ % WARNING: this does not fill in the maybe_gc_trace_code for the function
+ % parameters. It is the caller's responsibility to fill these in properly
+ % if needed.
%
:- pred ml_gen_cont_params(list(mlds__type)::in, mlds__func_params::out,
ml_gen_info::in, ml_gen_info::out) is det.
@@ -149,13 +144,8 @@
% Code for procedure calls
%
- %
- % Generate MLDS code for an HLDS generic_call goal.
- % This includes boxing/unboxing the arguments if necessary.
- %
% XXX For typeclass method calls, we do some unnecessary
% boxing/unboxing of the arguments.
- %
ml_gen_generic_call(higher_order(_, _, _, _) @ GenericCall, ArgVars, ArgModes,
Determinism, Context, Decls, Statements, !Info) :-
ml_gen_generic_call_2(GenericCall, ArgVars, ArgModes, Determinism,
@@ -168,7 +158,7 @@
Decls, Statements, !Info) :-
ml_gen_cast(Context, ArgVars, Decls, Statements, !Info).
ml_gen_generic_call(aditi_builtin(_, _), _, _, _, _, _, _, !Info) :-
- error("ml_gen_generic_call: aditi_builtin").
+ unexpected(this_file, "ml_gen_generic_call: aditi_builtin").
:- pred ml_gen_generic_call_2(generic_call::in, list(prog_var)::in,
list(mode)::in, determinism::in, prog_context::in,
@@ -177,16 +167,12 @@
ml_gen_generic_call_2(GenericCall, ArgVars, ArgModes, Determinism, Context,
Decls, Statements, !Info) :-
- %
- % allocate some fresh type variables to use as the Mercury types
- % of the boxed arguments
- %
+ % Allocate some fresh type variables to use as the Mercury types
+ % of the boxed arguments.
NumArgs = list__length(ArgVars),
BoxedArgTypes = ml_make_boxed_types(NumArgs),
- %
- % create the boxed parameter types for the called function
- %
+ % Create the boxed parameter types for the called function.
ml_gen_info_get_module_info(!.Info, ModuleInfo),
ml_gen_info_get_varset(!.Info, VarSet),
ArgNames = ml_gen_var_names(VarSet, ArgVars),
@@ -195,30 +181,24 @@
Params0 = ml_gen_params(ModuleInfo, ArgNames,
BoxedArgTypes, ArgModes, PredOrFunc, CodeModel),
+ % Insert the `closure_arg' parameter.
%
- % insert the `closure_arg' parameter
- %
- % The GC_TraceCode for `closure_arg' here is wrong,
- % but it doesn't matter, since `closure_arg' is only part
- % of a type (a function parameter in the function type).
- % We won't use the GC tracing code generated here, since we don't
- % generate any actual local variable or parameter for `closure_arg'.
- %
+ % The GC_TraceCode for `closure_arg' here is wrong, but it doesn't matter,
+ % since `closure_arg' is only part of a type (a function parameter in the
+ % function type). We won't use the GC tracing code generated here, since
+ % we don't generate any actual local variable or parameter for
+ % `closure_arg'.
GC_TraceCode = no,
ClosureArgType = mlds__generic_type,
- ClosureArg = mlds__argument(
- data(var(var_name("closure_arg", no))),
+ ClosureArg = mlds__argument(data(var(var_name("closure_arg", no))),
ClosureArgType, GC_TraceCode),
Params0 = mlds__func_params(ArgParams0, RetParam),
Params = mlds__func_params([ClosureArg | ArgParams0], RetParam),
Signature = mlds__get_func_signature(Params),
- %
- % compute the function address
- %
+ % Compute the function address.
(
- GenericCall = higher_order(ClosureVar, _Purity, _PredOrFunc,
- _Arity),
+ GenericCall = higher_order(ClosureVar, _Purity, _PredOrFunc, _Arity),
ml_gen_var(!.Info, ClosureVar, ClosureLval),
FieldId = offset(const(int_const(1))),
% XXX are these types right?
@@ -229,52 +209,44 @@
;
GenericCall = class_method(TypeClassInfoVar, MethodNum,
_ClassId, _PredName),
- %
- % create the lval for the typeclass_info,
- % which is also the closure in this case
- %
+
+ % Create the lval for the typeclass_info, which is also the closure
+ % in this case.
ml_gen_var(!.Info, TypeClassInfoVar, TypeClassInfoLval),
ClosureLval = TypeClassInfoLval,
- %
- % extract the base_typeclass_info from the typeclass_info
- %
- BaseTypeclassInfoFieldId =
- offset(const(int_const(0))),
+
+ % Extract the base_typeclass_info from the typeclass_info.
+ BaseTypeclassInfoFieldId = offset(const(int_const(0))),
BaseTypeclassInfoLval = field(yes(0),
lval(TypeClassInfoLval), BaseTypeclassInfoFieldId,
mlds__generic_type, ClosureArgType),
- %
- % extract the method address from the base_typeclass_info
- %
+
+ % Extract the method address from the base_typeclass_info.
Offset = ml_base_typeclass_info_method_offset,
MethodFieldNum = MethodNum + Offset,
MethodFieldId = offset(const(int_const(MethodFieldNum))),
FuncLval = field(yes(0), lval(BaseTypeclassInfoLval),
- MethodFieldId,
- mlds__generic_type, mlds__generic_type),
+ MethodFieldId, mlds__generic_type, mlds__generic_type),
FuncType = mlds__func_type(Params),
FuncRval = unop(unbox(FuncType), lval(FuncLval))
;
GenericCall = cast(_),
- error("ml_gen_generic_call_2: cast")
+ unexpected(this_file, "ml_gen_generic_call_2: cast")
;
GenericCall = aditi_builtin(_, _),
- error("ml_gen_generic_call_2: aditi_builtin")
+ unexpected(this_file, "ml_gen_generic_call_2: aditi_builtin")
),
- %
- % Assign the function address rval to a new local variable.
- % This makes the generated code slightly more readable.
- % More importantly, this is also necessary when using a
- % non-standard calling convention with GNU C, since GNU C
- % (2.95.2) ignores the function attributes on function
+ % Assign the function address rval to a new local variable. This makes
+ % the generated code slightly more readable. More importantly, this is also
+ % necessary when using a non-standard calling convention with GNU C,
+ % since GNU C (2.95.2) ignores the function attributes on function
% pointer types in casts.
%
ml_gen_info_new_conv_var(ConvVarNum, !Info),
- FuncVarName = var_name(
- string__format("func_%d", [i(ConvVarNum)]), no),
- % the function address is always a pointer to code,
- % not to the heap, so the GC doesn't need to trace it
+ FuncVarName = var_name(string__format("func_%d", [i(ConvVarNum)]), no),
+ % The function address is always a pointer to code,
+ % not to the heap, so the GC doesn't need to trace it.
GC_TraceCode = no,
FuncVarDecl = ml_gen_mlds_var_decl(var(FuncVarName),
FuncType, GC_TraceCode, mlds__make_context(Context)),
@@ -282,11 +254,9 @@
AssignFuncVar = ml_gen_assign(FuncVarLval, FuncRval, Context),
FuncVarRval = lval(FuncVarLval),
- %
- % Generate code to box/unbox the arguments
- % and compute the list of properly converted rvals/lvals
- % to pass as the function call's arguments and return values
- %
+ % Generate code to box/unbox the arguments and compute the list of properly
+ % converted rvals/lvals to pass as the function call's arguments and
+ % return values.
ml_gen_var_list(!.Info, ArgVars, ArgLvals),
ml_variable_types(!.Info, ArgVars, ActualArgTypes),
ml_gen_arg_list(ArgNames, ArgLvals, ActualArgTypes, BoxedArgTypes,
@@ -295,45 +265,39 @@
ConvArgDecls, ConvOutputStatements, !Info),
ClosureRval = unop(unbox(ClosureArgType), lval(ClosureLval)),
- %
- % Prepare to generate the call, passing the closure as the first
- % argument.
+ % Prepare to generate the call, passing the closure as the first argument.
% (We can't actually generate the call yet, since it might be nondet,
- % and we don't yet know what its success continuation will be;
- % instead for now we just construct a higher-order term `DoGenCall',
- % which when called will generate it.)
- %
+ % and we don't yet know what its success continuation will be; instead
+ % for now we just construct a higher-order term `DoGenCall', which when
+ % called will generate it.)
ObjectRval = no,
DoGenCall = ml_gen_mlds_call(Signature, ObjectRval, FuncVarRval,
[ClosureRval | InputRvals], OutputLvals, OutputTypes,
Determinism, Context),
- ( ConvArgDecls = [], ConvOutputStatements = [] ->
+ (
+ ConvArgDecls = [],
+ ConvOutputStatements = []
+ ->
DoGenCall(Decls0, Statements0, !Info)
;
- %
- % Construct a closure to generate code to
- % convert the output arguments and then succeed
- %
+ % Construct a closure to generate code to convert the output arguments
+ % and then succeed.
DoGenConvOutputAndSucceed = (
pred(COAS_Decls::out, COAS_Statements::out,
Info0::in, Info::out) is det :-
COAS_Decls = [],
- ml_gen_success(CodeModel, Context,
- SucceedStmts, Info0, Info),
- COAS_Statements = list__append(
- ConvOutputStatements, SucceedStmts)
+ ml_gen_success(CodeModel, Context, SucceedStmts, Info0, Info),
+ COAS_Statements = ConvOutputStatements ++ SucceedStmts
),
+ % Conjoin the code generated by the two closures that we computed
+ % above. `ml_combine_conj' will generate whatever kind of sequence
+ % is necessary for this code model.
%
- % Conjoin the code generated by the two closures that we
- % computed above. `ml_combine_conj' will generate whatever
- % kind of sequence is necessary for this code model.
- %
- ml_combine_conj(CodeModel, Context,
- DoGenCall, DoGenConvOutputAndSucceed,
- CallAndConvOutputDecls, CallAndConvOutputStatements,
- !Info),
+ ml_combine_conj(CodeModel, Context, DoGenCall,
+ DoGenConvOutputAndSucceed, CallAndConvOutputDecls,
+ CallAndConvOutputStatements, !Info),
Decls0 = ConvArgDecls ++ CallAndConvOutputDecls,
Statements0 = CallAndConvOutputStatements
),
@@ -357,18 +321,15 @@
),
Decls = []
;
- error("ml_gen_cast: wrong number of args for cast")
+ unexpected(this_file, "ml_gen_cast: wrong number of args for cast")
).
%-----------------------------------------------------------------------------%
- %
- % Generate code for the various parts that are needed for
- % a procedure call: declarations of variables needed for
- % boxing/unboxing output arguments,
- % a closure to generate code to call the function
- % with the input arguments appropriate boxed,
- % and code to unbox/box the return values.
+ % Generate code for the various parts that are needed for a procedure call:
+ % declarations of variables needed for boxing/unboxing output arguments,
+ % a closure to generate code to call the function with the input arguments
+ % appropriate boxed, and code to unbox/box the return values.
%
% For example, if the callee is declared as
%
@@ -398,71 +359,56 @@
%
ml_gen_call(PredId, ProcId, ArgNames, ArgLvals, ActualArgTypes, CodeModel,
Context, ForClosureWrapper, Decls, Statements, !Info) :-
- %
- % Compute the function signature
- %
+ % Compute the function signature.
ml_gen_info_get_module_info(!.Info, ModuleInfo),
Params = ml_gen_proc_params(ModuleInfo, PredId, ProcId),
Signature = mlds__get_func_signature(Params),
- %
- % Compute the function address
- %
+ % Compute the function address.
ml_gen_proc_addr_rval(PredId, ProcId, FuncRval, !Info),
- %
- % Compute the callee's Mercury argument types and modes
- %
- module_info_pred_proc_info(ModuleInfo, PredId, ProcId,
- PredInfo, ProcInfo),
+ % Compute the callee's Mercury argument types and modes.
+ module_info_pred_proc_info(ModuleInfo, PredId, ProcId, PredInfo, ProcInfo),
PredOrFunc = pred_info_is_pred_or_func(PredInfo),
pred_info_arg_types(PredInfo, PredArgTypes),
proc_info_argmodes(ProcInfo, ArgModes),
- %
- % Generate code to box/unbox the arguments
- % and compute the list of properly converted rvals/lvals
- % to pass as the function call's arguments and return values
- %
+ % Generate code to box/unbox the arguments and compute the list of properly
+ % converted rvals/lvals to pass as the function call's arguments and
+ % return values.
ml_gen_arg_list(ArgNames, ArgLvals, ActualArgTypes, PredArgTypes,
ArgModes, PredOrFunc, CodeModel, Context, ForClosureWrapper, 1,
InputRvals, OutputLvals, OutputTypes,
ConvArgDecls, ConvOutputStatements, !Info),
- %
- % Construct a closure to generate the call
- % (We can't actually generate the call yet, since it might be nondet,
- % and we don't yet know what its success continuation will be;
- % that's why for now we just construct a closure `DoGenCall'
- % to generate it.)
- %
+ % Construct a closure to generate the call (We can't actually generate
+ % the call yet, since it might be nondet, and we don't yet know what its
+ % success continuation will be; that's why for now we just construct
+ % a closure `DoGenCall' to generate it.)
ObjectRval = no,
proc_info_interface_determinism(ProcInfo, Detism),
DoGenCall = ml_gen_mlds_call(Signature, ObjectRval, FuncRval,
InputRvals, OutputLvals, OutputTypes, Detism, Context),
- ( ConvArgDecls = [], ConvOutputStatements = [] ->
+ (
+ ConvArgDecls = [],
+ ConvOutputStatements = []
+ ->
DoGenCall(Decls, Statements, !Info)
;
- %
- % Construct a closure to generate code to
- % convert the output arguments and then succeed
- %
+ % Construct a closure to generate code to convert the output arguments
+ % and then succeed.
DoGenConvOutputAndSucceed = (
pred(COAS_Decls::out, COAS_Statements::out,
Info0::in, Info::out) is det :-
COAS_Decls = [],
- ml_gen_success(CodeModel, Context,
- SucceedStmts, Info0, Info),
- COAS_Statements = list__append(
- ConvOutputStatements, SucceedStmts)
+ ml_gen_success(CodeModel, Context, SucceedStmts, Info0, Info),
+ COAS_Statements = ConvOutputStatements ++ SucceedStmts
),
- %
- % Conjoin the code generated by the two closures that we
- % computed above. `ml_combine_conj' will generate whatever
- % kind of sequence is necessary for this code model.
- %
+ % Conjoin the code generated by the two closures that we computed
+ % above. `ml_combine_conj' will generate whatever kind of sequence
+ % is necessary for this code model.
ml_combine_conj(CodeModel, Context, DoGenCall,
DoGenConvOutputAndSucceed, CallAndConvOutputDecls,
CallAndConvOutputStatements, !Info),
@@ -470,7 +416,6 @@
Statements = CallAndConvOutputStatements
).
- %
% This generates a call in the specified code model.
% This is a lower-level routine called by both ml_gen_call
% and ml_gen_generic_call.
@@ -483,38 +428,38 @@
ml_gen_mlds_call(Signature, ObjectRval, FuncRval, ArgRvals0, RetLvals0,
RetTypes0, Detism, Context, Decls, Statements, !Info) :-
- %
- % append the extra arguments or return val for this code_model
- %
+ % Append the extra arguments or return val for this code_model.
determinism_to_code_model(Detism, CodeModel),
(
CodeModel = model_non,
- % create a new success continuation, if necessary
+ % Create a new success continuation, if necessary.
ml_gen_success_cont(RetTypes0, RetLvals0, Context,
Cont, ContDecls, !Info),
- % append the success continuation to the ordinary arguments
+ % Append the success continuation to the ordinary arguments.
Cont = success_cont(FuncPtrRval, EnvPtrRval, _, _),
ml_gen_info_use_gcc_nested_functions(!.Info, UseNestedFuncs),
- ( UseNestedFuncs = yes ->
- ArgRvals = list__append(ArgRvals0, [FuncPtrRval])
+ (
+ UseNestedFuncs = yes,
+ ArgRvals = ArgRvals0 ++ [FuncPtrRval]
;
- ArgRvals = list__append(ArgRvals0,
- [FuncPtrRval, EnvPtrRval])
+ UseNestedFuncs = no,
+ ArgRvals = ArgRvals0 ++ [FuncPtrRval, EnvPtrRval]
),
- % for --nondet-copy-out, the output arguments will be
- % passed to the continuation rather than being returned
+ % For --nondet-copy-out, the output arguments will be passed to the
+ % continuation rather than being returned.
ml_gen_info_get_globals(!.Info, Globals),
- globals__lookup_bool_option(Globals, nondet_copy_out,
- NondetCopyOut),
- ( NondetCopyOut = yes ->
+ globals__lookup_bool_option(Globals, nondet_copy_out, NondetCopyOut),
+ (
+ NondetCopyOut = yes,
RetLvals = []
;
+ NondetCopyOut = no,
RetLvals = RetLvals0
),
Decls = ContDecls
;
CodeModel = model_semi,
- % return a bool indicating whether or not it succeeded
+ % Return a bool indicating whether or not it succeeded.
ml_success_lval(!.Info, Success),
ArgRvals = ArgRvals0,
RetLvals = list__append([Success], RetLvals0),
@@ -526,19 +471,17 @@
Decls = []
),
+ % Build the MLDS call statement.
%
- % build the MLDS call statement
- %
- % if the called procedure has determinism `erroneous'
- % then mark it as never returning
- % (this will ensure that it gets treated as a tail call)
+ % If the called procedure has determinism `erroneous', then mark it
+ % as never returning (this will ensure that it gets treated as a tail
+ % call).
( Detism = erroneous ->
CallKind = no_return_call
;
CallKind = ordinary_call
),
- Stmt = call(Signature, FuncRval, ObjectRval, ArgRvals, RetLvals,
- CallKind),
+ Stmt = call(Signature, FuncRval, ObjectRval, ArgRvals, RetLvals, CallKind),
Statement = mlds__statement(Stmt, mlds__make_context(Context)),
Statements = [Statement].
@@ -548,16 +491,14 @@
ml_gen_success_cont(OutputArgTypes, OutputArgLvals, Context,
Cont, ContDecls, !Info) :-
- ml_gen_info_current_success_cont(CurrentCont, !Info),
+ ml_gen_info_current_success_cont(!.Info, CurrentCont),
CurrentCont = success_cont(_FuncPtrRval, _EnvPtrRval,
CurrentContArgTypes, CurrentContArgLvals),
(
- %
- % As an optimization, check if the parameters expected by
- % the current continuation are the same as the ones
- % expected by the new continuation that we're generating;
- % if so, we can just use the current continuation rather
- % than creating a new one.
+ % As an optimization, check if the parameters expected by the current
+ % continuation are the same as the ones expected by the new
+ % continuation that we're generating; if so, we can just use the
+ % current continuation rather than creating a new one.
%
CurrentContArgTypes = OutputArgTypes,
CurrentContArgLvals = OutputArgLvals
@@ -565,27 +506,24 @@
Cont = CurrentCont,
ContDecls = []
;
+ % Create a new continuation function that just copies the outputs
+ % to locals and then calls the original current continuation.
%
- % Create a new continuation function
- % that just copies the outputs to locals
- % and then calls the original current continuation.
- %
- % Note that ml_gen_cont_params does not fill in the
- % maybe_gc_trace_code for the parameters. This is OK,
- % because the parameters of the continuation function
- % will not be live across any heap allocations or
+ % Note that ml_gen_cont_params does not fill in the maybe_gc_trace_code
+ % for the parameters. This is OK, because the parameters of the
+ % continuation function will not be live across any heap allocations or
% procedure calls.
%
ml_gen_cont_params(OutputArgTypes, Params, !Info),
ml_gen_new_func_label(yes(Params),
ContFuncLabel, ContFuncLabelRval, !Info),
- /* push nesting level */
+ % push nesting level
ml_gen_copy_args_to_locals(!.Info, OutputArgLvals,
OutputArgTypes, Context, CopyDecls, CopyStatements),
ml_gen_call_current_success_cont(Context, CallCont, !Info),
CopyStatement = ml_gen_block(CopyDecls,
list__append(CopyStatements, [CallCont]), Context),
- /* pop nesting level */
+ % pop nesting level
ml_gen_label_func(!.Info, ContFuncLabel, Params, Context,
CopyStatement, ContFuncDefn),
ContDecls = [ContFuncDefn],
@@ -599,9 +537,11 @@
ml_gen_cont_params(OutputArgTypes, Params, !Info) :-
ml_gen_cont_params_2(OutputArgTypes, 1, Args0),
ml_gen_info_use_gcc_nested_functions(!.Info, UseNestedFuncs),
- ( UseNestedFuncs = yes ->
+ (
+ UseNestedFuncs = yes,
Args = Args0
;
+ UseNestedFuncs = no,
ml_declare_env_ptr_arg(EnvPtrArg),
Args = list__append(Args0, [EnvPtrArg])
),
@@ -613,14 +553,12 @@
ml_gen_cont_params_2([], _, []).
ml_gen_cont_params_2([Type | Types], ArgNum, [Argument | Arguments]) :-
ArgName = ml_gen_arg_name(ArgNum),
- % Figuring out the correct GC code here is difficult,
- % since doing that requires knowing the HLDS types, but
- % here we only have the MLDS types. So here we just
- % leave it blank. The caller of ml_gen_cont_param has the
+ % Figuring out the correct GC code here is difficult, since doing that
+ % requires knowing the HLDS types, but here we only have the MLDS types.
+ % So here we just leave it blank. The caller of ml_gen_cont_param has the
% reponsibility of fillling this in properly if needed.
Maybe_GC_TraceCode = no,
- Argument = mlds__argument(data(var(ArgName)), Type,
- Maybe_GC_TraceCode),
+ Argument = mlds__argument(data(var(ArgName)), Type, Maybe_GC_TraceCode),
ml_gen_cont_params_2(Types, ArgNum + 1, Arguments).
:- pred ml_gen_copy_args_to_locals(ml_gen_info::in, list(mlds__lval)::in,
@@ -646,30 +584,25 @@
ml_gen_copy_args_to_locals_2(Info, LocalLvals, Types, ArgNum + 1,
Context, Statements).
ml_gen_copy_args_to_locals_2(_Info, [], [_ | _], _, _, _) :-
- error("ml_gen_copy_args_to_locals_2: list length mismatch").
+ unexpected(this_file, "ml_gen_copy_args_to_locals_2: length mismatch").
ml_gen_copy_args_to_locals_2(_Info, [_ | _], [], _, _, _) :-
- error("ml_gen_copy_args_to_locals_2: list length mismatch").
+ unexpected(this_file, "ml_gen_copy_args_to_locals_2: length mismatch").
:- func ml_gen_arg_name(int) = mlds__var_name.
ml_gen_arg_name(ArgNum) = mlds__var_name(ArgName, no) :-
string__format("arg%d", [i(ArgNum)], ArgName).
-%
-% Generate an rval containing the address of the specified procedure
-%
ml_gen_proc_addr_rval(PredId, ProcId, CodeAddrRval, !Info) :-
ml_gen_info_get_module_info(!.Info, ModuleInfo),
ml_gen_pred_label(ModuleInfo, PredId, ProcId, PredLabel, PredModule),
ml_gen_proc_params(PredId, ProcId, Params, !Info),
Signature = mlds__get_func_signature(Params),
QualifiedProcLabel = qual(PredModule, module_qual, PredLabel - ProcId),
- CodeAddrRval = const(code_addr_const(proc(QualifiedProcLabel,
- Signature))).
+ CodeAddrRval = const(code_addr_const(proc(QualifiedProcLabel, Signature))).
-%
-% Generate rvals and lvals for the arguments of a procedure call
-%
+ % Generate rvals and lvals for the arguments of a procedure call
+ %
:- pred ml_gen_arg_list(list(var_name)::in, list(mlds__lval)::in,
list(prog_type)::in, list(prog_type)::in, list(mode)::in,
pred_or_func::in, code_model::in, prog_context::in, bool::in, int::in,
@@ -679,8 +612,8 @@
ml_gen_arg_list(VarNames, VarLvals, CallerTypes, CalleeTypes, Modes,
PredOrFunc, CodeModel, Context, ForClosureWrapper, ArgNum,
- InputRvals, OutputLvals, OutputTypes,
- ConvDecls, ConvOutputStatements, !Info) :-
+ InputRvals, OutputLvals, OutputTypes, ConvDecls, ConvOutputStatements,
+ !Info) :-
(
VarNames = [],
VarLvals = [],
@@ -700,9 +633,8 @@
CalleeTypes = [CalleeType | CalleeTypes1],
Modes = [Mode | Modes1]
->
- ml_gen_arg_list(VarNames1, VarLvals1,
- CallerTypes1, CalleeTypes1, Modes1,
- PredOrFunc, CodeModel, Context, ForClosureWrapper,
+ ml_gen_arg_list(VarNames1, VarLvals1, CallerTypes1, CalleeTypes1,
+ Modes1, PredOrFunc, CodeModel, Context, ForClosureWrapper,
ArgNum + 1, InputRvals1, OutputLvals1, OutputTypes1,
ConvDecls1, ConvOutputStatements1, !Info),
ml_gen_info_get_module_info(!.Info, ModuleInfo),
@@ -712,10 +644,8 @@
; ArgMode = top_unused
)
->
- %
% Exclude arguments of type io__state etc.
% Also exclude those with arg_mode `top_unused'.
- %
InputRvals = InputRvals1,
OutputLvals = OutputLvals1,
OutputTypes = OutputTypes1,
@@ -724,55 +654,41 @@
;
ArgMode = top_in
->
- %
- % it's an input argument
- %
+ % It's an input argument.
( type_util__is_dummy_argument_type(CallerType) ->
- % The variable may not have been declared,
- % so we need to generate a dummy value for it.
- % Using `0' here is more efficient than
- % using private_builtin__dummy_var, which is
- % what ml_gen_var will have generated for this
- % variable.
+ % The variable may not have been declared, so we need to
+ % generate a dummy value for it. Using `0' here is more
+ % efficient than using private_builtin__dummy_var, which is
+ % what ml_gen_var will have generated for this variable.
VarRval = const(int_const(0))
;
VarRval = lval(VarLval)
),
- ml_gen_box_or_unbox_rval(CallerType, CalleeType,
- VarRval, ArgRval, !Info),
+ ml_gen_box_or_unbox_rval(CallerType, CalleeType, VarRval, ArgRval,
+ !Info),
InputRvals = [ArgRval | InputRvals1],
OutputLvals = OutputLvals1,
OutputTypes = OutputTypes1,
ConvDecls = ConvDecls1,
ConvOutputStatements = ConvOutputStatements1
;
- %
- % it's an output argument
- %
- ml_gen_box_or_unbox_lval(CallerType, CalleeType,
- VarLval, VarName, Context, ForClosureWrapper,
- ArgNum, ArgLval, ThisArgConvDecls,
+ % It's an output argument.
+ ml_gen_box_or_unbox_lval(CallerType, CalleeType, VarLval, VarName,
+ Context, ForClosureWrapper, ArgNum, ArgLval, ThisArgConvDecls,
_ThisArgConvInput, ThisArgConvOutput, !Info),
ConvDecls = ThisArgConvDecls ++ ConvDecls1,
- ConvOutputStatements = ThisArgConvOutput
- ++ ConvOutputStatements1,
+ ConvOutputStatements = ThisArgConvOutput ++ ConvOutputStatements1,
ml_gen_info_get_globals(!.Info, Globals),
CopyOut = get_copy_out_option(Globals, CodeModel),
(
(
- %
- % if the target language allows
- % multiple return values, then use them
- %
+ % If the target language allows multiple return values,
+ % then use them.
CopyOut = yes
;
- %
- % if this is the result argument
- % of a model_det function, and it has
- % an output mode, then return it as a
- % value
- %
+ % If this is the result argument of a model_det function,
+ % and it has an output mode, then return it as a value.
VarNames1 = [],
CodeModel = model_det,
PredOrFunc = function,
@@ -784,56 +700,44 @@
ml_gen_type(!.Info, CalleeType, OutputType),
OutputTypes = [OutputType | OutputTypes1]
;
- %
- % otherwise use the traditional C style
- % of passing the address of the output value
- %
- InputRvals = [ml_gen_mem_addr(ArgLval)
- | InputRvals1],
+ % Otherwise use the traditional C style of passing the address
+ % of the output value.
+ InputRvals = [ml_gen_mem_addr(ArgLval) | InputRvals1],
OutputLvals = OutputLvals1,
OutputTypes = OutputTypes1
)
)
;
- error("ml_gen_arg_list: length mismatch")
+ unexpected(this_file, "ml_gen_arg_list: length mismatch")
).
% ml_gen_mem_addr(Lval) returns a value equal to &Lval.
% For the case where Lval = *Rval, for some Rval,
% we optimize &*Rval to just Rval.
+ %
:- func ml_gen_mem_addr(mlds__lval) = mlds__rval.
ml_gen_mem_addr(Lval) =
(if Lval = mem_ref(Rval, _) then Rval else mem_addr(Lval)).
- % Convert VarRval, of type SourceType,
- % to ArgRval, of type DestType.
ml_gen_box_or_unbox_rval(SourceType, DestType, VarRval, ArgRval, !Info) :-
+ % Convert VarRval, of type SourceType, to ArgRval, of type DestType.
(
- %
- % If converting from polymorphic type to concrete type,
- % then unbox.
- %
+ % If converting from polymorphic type to concrete type, then unbox.
SourceType = variable(_, _),
DestType \= variable(_, _)
->
ml_gen_type(!.Info, DestType, MLDS_DestType),
ArgRval = unop(unbox(MLDS_DestType), VarRval)
;
- %
- % If converting from concrete type to polymorphic type,
- % then box.
- %
+ % If converting from concrete type to polymorphic type, then box.
SourceType \= variable(_, _),
DestType = variable(_, _)
->
ml_gen_type(!.Info, SourceType, MLDS_SourceType),
ArgRval = unop(box(MLDS_SourceType), VarRval)
;
- %
- % If converting to float, cast to mlds__generic_type
- % and then unbox.
- %
+ % If converting to float, cast to mlds__generic_type and then unbox.
DestType = builtin(float),
SourceType \= builtin(float)
->
@@ -841,9 +745,7 @@
ArgRval = unop(unbox(MLDS_DestType),
unop(cast(mlds__generic_type), VarRval))
;
- %
% If converting from float, box and then cast the result.
- %
SourceType = builtin(float),
DestType \= builtin(float)
->
@@ -852,14 +754,11 @@
ArgRval = unop(cast(MLDS_DestType),
unop(box(MLDS_SourceType), VarRval))
;
- %
- % If converting from an array(T) to array(X) where
- % X is a concrete instance, we should insert a cast
- % to the concrete instance. Also when converting to
- % array(T) from array(X) we should cast to array(T).
- %
- type_to_ctor_and_args(SourceType, SourceTypeCtor,
- SourceTypeArgs),
+ % If converting from an array(T) to array(X) where X is a concrete
+ % instance, we should insert a cast to the concrete instance.
+ % Also when converting to array(T) from array(X) we should cast
+ % to array(T).
+ type_to_ctor_and_args(SourceType, SourceTypeCtor, SourceTypeArgs),
type_to_ctor_and_args(DestType, DestTypeCtor, DestTypeArgs),
(
type_ctor_is_array(SourceTypeCtor),
@@ -872,31 +771,25 @@
ml_gen_type(!.Info, DestType, MLDS_DestType),
ArgRval = unop(cast(MLDS_DestType), VarRval)
;
+ % If converting from one concrete type to a different one, then cast.
+ % This is needed to handle construction/deconstruction unifications
+ % for no_tag types.
%
- % If converting from one concrete type to a different one, then
- % cast. This is needed to handle construction/deconstruction
- % unifications for no_tag types.
- %
- \+ type_util__type_unify(SourceType, DestType,
- [], map__init, _)
+ \+ type_util__type_unify(SourceType, DestType, [], map__init, _)
->
ml_gen_type(!.Info, DestType, MLDS_DestType),
ArgRval = unop(cast(MLDS_DestType), VarRval)
;
- %
% Otherwise leave unchanged.
- %
ArgRval = VarRval
).
ml_gen_box_or_unbox_lval(CallerType, CalleeType, VarLval, VarName, Context,
ForClosureWrapper, ArgNum, ArgLval, ConvDecls,
ConvInputStatements, ConvOutputStatements, !Info) :-
- %
% First see if we can just convert the lval as an rval;
% if no boxing/unboxing is required, then ml_box_or_unbox_rval
% will return its argument unchanged, and so we're done.
- %
ml_gen_box_or_unbox_rval(CalleeType, CallerType, lval(VarLval),
BoxedRval, !Info),
( BoxedRval = lval(VarLval) ->
@@ -905,14 +798,12 @@
ConvInputStatements = [],
ConvOutputStatements = []
;
- %
% If that didn't work, then we need to declare a fresh variable
% to use as the arg, and to generate statements to box/unbox
% that fresh arg variable and assign it to/from the output
% argument whose address we were passed.
- %
- % generate a declaration for the fresh variable
+ % Generate a declaration for the fresh variable.
%
% Note that generating accurate GC tracing code for this
% variable requires some care, because CalleeType might be a
@@ -926,55 +817,50 @@
ml_gen_info_new_conv_var(ConvVarNum, !Info),
VarName = mlds__var_name(VarNameStr, MaybeNum),
- ArgVarName = mlds__var_name(string__format(
- "conv%d_%s", [i(ConvVarNum), s(VarNameStr)]),
+ ArgVarName = mlds__var_name(
+ string__format("conv%d_%s", [i(ConvVarNum), s(VarNameStr)]),
MaybeNum),
ml_gen_type(!.Info, CalleeType, MLDS_CalleeType),
- ( ForClosureWrapper = yes ->
+ (
+ ForClosureWrapper = yes,
% For closure wrappers, the argument type_infos are
% stored in the `type_params' local, so we need to
% handle the GC tracing code specially
( CallerType = variable(_, _) ->
- ml_gen_local_for_output_arg(ArgVarName,
- CalleeType, ArgNum, Context,
- ArgVarDecl, !Info)
+ ml_gen_local_for_output_arg(ArgVarName, CalleeType, ArgNum,
+ Context, ArgVarDecl, !Info)
;
- unexpected(this_file, "invalid CalleeType " ++
- "for closure wrapper")
+ unexpected(this_file, "invalid CalleeType for closure wrapper")
)
;
- ml_gen_maybe_gc_trace_code(ArgVarName, CalleeType,
- CallerType, Context, GC_TraceCode, !Info),
- ArgVarDecl = ml_gen_mlds_var_decl(var(ArgVarName),
- MLDS_CalleeType, GC_TraceCode,
- mlds__make_context(Context))
+ ForClosureWrapper = no,
+ ml_gen_maybe_gc_trace_code(ArgVarName, CalleeType, CallerType,
+ Context, GC_TraceCode, !Info),
+ ArgVarDecl = ml_gen_mlds_var_decl(var(ArgVarName), MLDS_CalleeType,
+ GC_TraceCode, mlds__make_context(Context))
),
ConvDecls = [ArgVarDecl],
- % create the lval for the variable and use it for the
- % argument lval
+ % Create the lval for the variable and use it for the argument lval.
ml_gen_var_lval(!.Info, ArgVarName, MLDS_CalleeType, ArgLval),
( type_util__is_dummy_argument_type(CallerType) ->
- % if it is a dummy argument type (e.g. io__state),
- % then we don't need to bother assigning it
+ % If it is a dummy argument type (e.g. io__state),
+ % then we don't need to bother assigning it.
ConvInputStatements = [],
ConvOutputStatements = []
;
- %
- % Generate statements to box/unbox the fresh variable
- % and assign it to/from the output argument whose
- % address we were passed.
- %
+ % Generate statements to box/unbox the fresh variable and assign it
+ % to/from the output argument whose address we were passed.
- % assign to the freshly generated arg variable
+ % Assign to the freshly generated arg variable.
ml_gen_box_or_unbox_rval(CallerType, CalleeType,
lval(VarLval), ConvertedVarRval, !Info),
AssignInputStatement = ml_gen_assign(ArgLval,
ConvertedVarRval, Context),
ConvInputStatements = [AssignInputStatement],
- % assign from the freshly generated arg variable
+ % Assign from the freshly generated arg variable.
ml_gen_box_or_unbox_rval(CalleeType, CallerType,
lval(ArgLval), ConvertedArgRval, !Info),
AssignOutputStatement = ml_gen_assign(VarLval,
@@ -1003,15 +889,15 @@
->
SimpleCode = SimpleCode0
;
- error("ml_gen_builtin: unknown builtin predicate")
+ unexpected(this_file, "ml_gen_builtin: unknown builtin predicate")
),
(
CodeModel = model_det,
- ( SimpleCode = assign(Lval, SimpleExpr) ->
(
- % we need to avoid generating assignments to
- % dummy variables introduced for types such
- % as io__state
+ SimpleCode = assign(Lval, SimpleExpr),
+ (
+ % We need to avoid generating assignments to dummy variables
+ % introduced for types such as io__state.
Lval = var(_VarName, VarType),
VarType = mercury_type(ProgDataType, _, _),
type_util__is_dummy_argument_type(ProgDataType)
@@ -1023,21 +909,23 @@
Statements = [Statement]
)
;
- error("Malformed det builtin predicate")
+ SimpleCode = test(_),
+ unexpected(this_file, "malformed det builtin predicate")
)
;
CodeModel = model_semi,
- ( SimpleCode = test(SimpleTest) ->
+ (
+ SimpleCode = test(SimpleTest),
TestRval = ml_gen_simple_expr(SimpleTest),
- ml_gen_set_success(!.Info, TestRval, Context,
- Statement),
+ ml_gen_set_success(!.Info, TestRval, Context, Statement),
Statements = [Statement]
;
- error("Malformed semi builtin predicate")
+ SimpleCode = assign(_, _),
+ unexpected(this_file, "malformed semi builtin predicate")
)
;
CodeModel = model_non,
- error("Nondet builtin predicate")
+ unexpected(this_file, "nondet builtin predicate")
),
Decls = [].
Index: compiler/ml_closure_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/ml_closure_gen.m,v
retrieving revision 1.32
diff -u -b -r1.32 ml_closure_gen.m
--- compiler/ml_closure_gen.m 22 Mar 2005 06:40:09 -0000 1.32
+++ compiler/ml_closure_gen.m 12 Sep 2005 13:12:45 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 1999-2005 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -23,20 +25,19 @@
:- import_module list.
- %
% ml_gen_closure(PredId, ProcId, EvalMethod, Var, ArgVars, ArgModes,
% HowToConstruct, Context, Decls, Statements):
%
- % Generate code to construct a closure for the procedure
- % specified by PredId and ProcId, with the partially applied
- % arguments specified by ArgVars (and ArgModes),
- % and to store the pointer to the resulting closure in Var.
+ % Generate code to construct a closure for the procedure specified
+ % by PredId and ProcId, with the partially applied arguments specified
+ % by ArgVars (and ArgModes), and to store the pointer to the resulting
+ % closure in Var.
+ %
:- pred ml_gen_closure(pred_id::in, proc_id::in, lambda_eval_method::in,
prog_var::in, prog_vars::in, list(uni_mode)::in, how_to_construct::in,
prog_context::in, mlds__defns::out, mlds__statements::out,
ml_gen_info::in, ml_gen_info::out) is det.
- %
% ml_gen_closure_wrapper(PredId, ProcId, Offset, NumClosureArgs,
% Context, WrapperFuncRval, WrapperFuncType):
%
@@ -65,11 +66,12 @@
% ml_gen_local_for_output_arg(VarName, Type, ArgNum, Context,
% LocalVarDefn):
+ %
% Generate a declaration for a local variable with the specified
% VarName and Type. However, don't use the normal GC tracing code;
% instead, generate GC tracing code that gets the typeinfo from
% the ArgNum-th entry in `type_params'.
-
+ %
:- pred ml_gen_local_for_output_arg(var_name::in, prog_type::in, int::in,
prog_context::in, mlds__defn::out,
ml_gen_info::in, ml_gen_info::out) is det.
@@ -96,7 +98,8 @@
:- import_module ll_backend__continuation_info. % needed for
% `generate_closure_layout'
:- import_module ll_backend__llds. % needed for `layout_locn'
-:- import_module ll_backend__stack_layout. % needed for `represent_locn_as_int'
+:- import_module ll_backend__stack_layout. % needed for
+ % `represent_locn_as_int'
:- import_module ml_backend__ml_call_gen.
:- import_module ml_backend__ml_unify_gen.
@@ -127,60 +130,45 @@
sorry(this_file, "`aditi_bottom_up' closures")
),
- %
- % Generate a value for the closure layout;
- % this is a static constant that holds information
- % about how the structure of this closure.
- %
+ % Generate a value for the closure layout; this is a static constant
+ % that holds information about how the structure of this closure.
ml_gen_closure_layout(PredId, ProcId, Context, ClosureLayoutRval0,
ClosureLayoutType0, ClosureLayoutDecls, !Info),
- %
- % Generate a wrapper function which just unboxes the
- % arguments and then calls the specified procedure,
- % and put the address of the wrapper function in the closure.
+ % Generate a wrapper function which just unboxes the arguments and then
+ % calls the specified procedure, and put the address of the wrapper
+ % function in the closure.
%
% ml_gen_closure_wrapper will insert the wrapper function in the
- % extra_defns field in the ml_gen_info; ml_gen_proc will extract
- % it and will insert it before the mlds__defn for the current
- % procedure.
+ % extra_defns field in the ml_gen_info; ml_gen_proc will extract it
+ % and will insert it before the mlds__defn for the current procedure.
%
list__length(ArgVars, NumArgs),
ml_gen_closure_wrapper(PredId, ProcId, higher_order_proc_closure,
NumArgs, Context, WrapperFuncRval0, WrapperFuncType0, !Info),
- %
% Compute the rval which holds the number of arguments
- %
NumArgsRval0 = const(int_const(NumArgs)),
NumArgsType0 = mlds__native_int_type,
- %
- % put all the extra arguments of the closure together
+ % Put all the extra arguments of the closure together
% Note that we need to box these arguments.
- %
NumArgsRval = unop(box(NumArgsType0), NumArgsRval0),
NumArgsType = mlds__generic_type,
WrapperFuncRval = unop(box(WrapperFuncType0), WrapperFuncRval0),
WrapperFuncType = mlds__generic_type,
- ClosureLayoutRval = unop(box(ClosureLayoutType0),
- ClosureLayoutRval0),
+ ClosureLayoutRval = unop(box(ClosureLayoutType0), ClosureLayoutRval0),
ClosureLayoutType = mlds__generic_type,
ExtraArgRvals = [ClosureLayoutRval, WrapperFuncRval, NumArgsRval],
ExtraArgTypes = [ClosureLayoutType, WrapperFuncType, NumArgsType],
- %
- % the pointer will not be tagged (i.e. the tag will be zero)
- %
+ % The pointer will not be tagged (i.e. the tag will be zero).
MaybeConsId = no,
MaybeConsName = no,
PrimaryTag = 0,
MaybeSecondaryTag = no,
- %
- % generate a `new_object' statement (or static constant)
- % for the closure
- %
+ % Generate a `new_object' statement (or static constant) for the closure.
ml_gen_new_object(MaybeConsId, PrimaryTag, MaybeSecondaryTag,
MaybeConsName, Var, ExtraArgRvals, ExtraArgTypes, ArgVars,
ArgModes, HowToConstruct, Context, Decls0, Statements, !Info),
@@ -191,7 +179,6 @@
% we need to check for and eliminate any duplicate definitions here.
Decls = list__remove_dups(Decls1).
- %
% Generate a value for the closure layout struct.
% See MR_Closure_Layout in ../runtime/mercury_ho_call.h.
%
@@ -219,19 +206,16 @@
ml_format_static_const_name(!.Info, "typevar_vector", TvarVectorSeqNum,
TvarVectorName),
ml_stack_layout_construct_tvar_vector(ModuleInfo, TvarVectorName,
- Context, TVarLocnMap, TVarVectorRval, TVarVectorType,
- TVarDefns),
- InitTVarVector = init_obj(unop(box(TVarVectorType),
- TVarVectorRval)),
+ Context, TVarLocnMap, TVarVectorRval, TVarVectorType, TVarDefns),
+ InitTVarVector = init_obj(unop(box(TVarVectorType), TVarVectorRval)),
Inits = [InitProcId, InitTVarVector | InitClosureArgs],
_ArgTypes = [ProcIdType, TVarVectorType | ClosureArgTypes],
ml_gen_info_new_const(LayoutSeqNum, !Info),
- ml_format_static_const_name(!.Info, "closure_layout", LayoutSeqNum,
- Name),
+ ml_format_static_const_name(!.Info, "closure_layout", LayoutSeqNum, Name),
Access = local,
Initializer = init_array(Inits),
- % XXX there's no way in C to properly represent this type,
+ % XXX There's no way in C to properly represent this type,
% since it is a struct that ends with a variable-length array.
% For now we just treat the whole struct as an array.
ClosureLayoutType = mlds__array_type(mlds__generic_type),
@@ -293,11 +277,10 @@
ArgInit - ArgType, !Defns) :-
ClosureArg = closure_arg_info(Type, _Inst),
- % For a stack layout, we can treat all type variables as
- % universally quantified. This is not the argument of a
- % constructor, so we do not need to distinguish between type
- % variables that are and aren't in scope; we can take the
- % variable number directly from the procedure's tvar set.
+ % For a stack layout, we can treat all type variables as universally
+ % quantified. This is not the argument of a constructor, so we do not need
+ % to distinguish between type variables that are and aren't in scope;
+ % we can take the variable number directly from the procedure's tvar set.
ExistQTvars = [],
NumUnivQTvars = -1,
@@ -312,21 +295,20 @@
rtti_maybe_pseudo_type_info::in, mlds__defns::in, mlds__defns::out)
is det.
-ml_gen_maybe_pseudo_type_info_defn(ModuleInfo, MaybePTI, Defns0, Defns) :-
- ml_gen_maybe_pseudo_type_info(ModuleInfo, MaybePTI, _Rval, _Type,
- Defns0, Defns).
+ml_gen_maybe_pseudo_type_info_defn(ModuleInfo, MaybePTI, !Defns) :-
+ ml_gen_maybe_pseudo_type_info(ModuleInfo, MaybePTI, _Rval, _Type, !Defns).
:- pred ml_gen_pseudo_type_info_defn(module_info::in,
rtti_pseudo_type_info::in, mlds__defns::in, mlds__defns::out) is det.
-ml_gen_pseudo_type_info_defn(ModuleInfo, PTI, Defns0, Defns) :-
- ml_gen_pseudo_type_info(ModuleInfo, PTI, _Rval, _Type, Defns0, Defns).
+ml_gen_pseudo_type_info_defn(ModuleInfo, PTI, !Defns) :-
+ ml_gen_pseudo_type_info(ModuleInfo, PTI, _Rval, _Type, !Defns).
:- pred ml_gen_type_info_defn(module_info::in, rtti_type_info::in,
mlds__defns::in, mlds__defns::out) is det.
-ml_gen_type_info_defn(ModuleInfo, TI, Defns0, Defns) :-
- ml_gen_type_info(ModuleInfo, TI, _Rval, _Type, Defns0, Defns).
+ml_gen_type_info_defn(ModuleInfo, TI, !Defns) :-
+ ml_gen_type_info(ModuleInfo, TI, _Rval, _Type, !Defns).
:- pred ml_gen_maybe_pseudo_type_info(module_info::in,
rtti_maybe_pseudo_type_info::in, mlds__rval::out, mlds__type::out,
@@ -336,8 +318,7 @@
!Defns) :-
(
MaybePseudoTypeInfo = pseudo(PseudoTypeInfo),
- ml_gen_pseudo_type_info(ModuleInfo, PseudoTypeInfo, Rval, Type,
- !Defns)
+ ml_gen_pseudo_type_info(ModuleInfo, PseudoTypeInfo, Rval, Type, !Defns)
;
MaybePseudoTypeInfo = plain(TypeInfo),
ml_gen_type_info(ModuleInfo, TypeInfo, Rval, Type, !Defns)
@@ -347,46 +328,36 @@
mlds__rval::out, mlds__type::out,
mlds__defns::in, mlds__defns::out) is det.
-ml_gen_pseudo_type_info(ModuleInfo, PseudoTypeInfo, Rval, Type,
- !Defns) :-
+ml_gen_pseudo_type_info(ModuleInfo, PseudoTypeInfo, Rval, Type, !Defns) :-
( PseudoTypeInfo = type_var(N) ->
- % type variables are represented just as integers
+ % Type variables are represented just as integers.
Rval = const(int_const(N)),
Type = mlds__native_int_type
;
- (
- PseudoTypeInfo =
- plain_arity_zero_pseudo_type_info(RttiTypeCtor0)
- ->
- % for zero-arity types, we just generate a
- % reference to the already-existing type_ctor_info
+ ( PseudoTypeInfo = plain_arity_zero_pseudo_type_info(RttiTypeCtor0) ->
+ % For zero-arity types, we just generate a reference to the
+ % already-existing type_ctor_info.
RttiName = type_ctor_info,
RttiTypeCtor0 = rtti_type_ctor(ModuleName0, _, _),
ModuleName = fixup_builtin_module(ModuleName0),
RttiTypeCtor = RttiTypeCtor0,
RttiId = ctor_rtti_id(RttiTypeCtor, RttiName)
;
- % for other types, we need to generate a definition
- % of the pseudo_type_info for that type,
- % in the the current module
+ % For other types, we need to generate a definition of the
+ % pseudo_type_info for that type, in the the current module.
module_info_name(ModuleInfo, ModuleName),
RttiData = pseudo_type_info(PseudoTypeInfo),
rtti_data_to_id(RttiData, RttiId),
- RttiDefns0 = rtti_data_list_to_mlds(ModuleInfo,
- [RttiData]),
- % rtti_data_list_to_mlds assumes that the result
- % will be at file scope, but here we're generating it
- % as a local, so we need to convert the access
- % to `local'
+ RttiDefns0 = rtti_data_list_to_mlds(ModuleInfo, [RttiData]),
+ % rtti_data_list_to_mlds assumes that the result will be
+ % at file scope, but here we're generating it as a local,
+ % so we need to convert the access to `local'.
RttiDefns = list__map(convert_to_local, RttiDefns0),
!:Defns = RttiDefns ++ !.Defns,
- % Generate definitions of any type_infos and
- % pseudo_type_infos referenced by this
- % pseudo_type_info.
- list__foldl(
- ml_gen_maybe_pseudo_type_info_defn(ModuleInfo),
- arg_maybe_pseudo_type_infos(PseudoTypeInfo),
- !Defns)
+ % Generate definitions of any type_infos and pseudo_type_infos
+ % referenced by this pseudo_type_info.
+ list__foldl(ml_gen_maybe_pseudo_type_info_defn(ModuleInfo),
+ arg_maybe_pseudo_type_infos(PseudoTypeInfo), !Defns)
),
MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName),
Rval = const(data_addr_const(data_addr(MLDS_ModuleName,
@@ -400,33 +371,30 @@
ml_gen_type_info(ModuleInfo, TypeInfo, Rval, Type, !Defns) :-
( TypeInfo = plain_arity_zero_type_info(RttiTypeCtor0) ->
- % for zero-arity types, we just generate a
- % reference to the already-existing type_ctor_info
+ % For zero-arity types, we just generate a reference to the
+ % already-existing type_ctor_info.
RttiName = type_ctor_info,
RttiTypeCtor0 = rtti_type_ctor(ModuleName0, _, _),
ModuleName = fixup_builtin_module(ModuleName0),
RttiId = ctor_rtti_id(RttiTypeCtor0, RttiName)
;
- % for other types, we need to generate a definition
- % of the type_info for that type, in the the current module
+ % For other types, we need to generate a definition of the type_info
+ % for that type, in the the current module.
module_info_name(ModuleInfo, ModuleName),
RttiData = type_info(TypeInfo),
rtti_data_to_id(RttiData, RttiId),
RttiDefns0 = rtti_data_list_to_mlds(ModuleInfo, [RttiData]),
- % rtti_data_list_to_mlds assumes that the result
- % will be at file scope, but here we're generating it
- % as a local, so we need to convert the access
- % to `local'
+ % rtti_data_list_to_mlds assumes that the result will be at file scope,
+ % but here we're generating it as a local, so we need to convert
+ % the access to `local'.
RttiDefns = list__map(convert_to_local, RttiDefns0),
!:Defns = RttiDefns ++ !.Defns,
- % Generate definitions of any type_infos referenced by this
- % type_info.
+ % Generate definitions of any type_infos referenced by this type_info.
list__foldl(ml_gen_type_info_defn(ModuleInfo),
arg_type_infos(TypeInfo), !Defns)
),
MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName),
- Rval = const(data_addr_const(data_addr(MLDS_ModuleName,
- rtti(RttiId)))),
+ Rval = const(data_addr_const(data_addr(MLDS_ModuleName, rtti(RttiId)))),
Type = mlds__rtti_type(item_type(RttiId)).
:- func arg_maybe_pseudo_type_infos(rtti_pseudo_type_info)
@@ -463,8 +431,8 @@
Defns = []
;
Access = local,
- ml_stack_layout_construct_tvar_rvals(TVarLocnMap,
- Vector, _VectorTypes),
+ ml_stack_layout_construct_tvar_rvals(TVarLocnMap, Vector,
+ _VectorTypes),
Initializer = init_array(Vector),
Defn = ml_gen_static_const_defn(TvarVectorName, ArrayType,
Access, Initializer, Context),
@@ -486,14 +454,13 @@
list__length(TypeParamLocs, TypeParamsLength),
LengthRval = const(int_const(TypeParamsLength)),
Vector = [init_obj(LengthRval) | TypeParamLocs],
- VectorTypes = list__duplicate(TypeParamsLength + 1,
- mlds__native_int_type).
-
- % Given a association list of type variables and their locations
- % sorted on the type variables, represent them in an array of
- % location descriptions indexed by the type variable. The next
- % slot to fill is given by the second argument.
+ VectorTypes = list__duplicate(TypeParamsLength + 1, mlds__native_int_type).
+ % Given a association list of type variables and their locations sorted
+ % on the type variables, represent them in an array of location
+ % descriptions indexed by the type variable. The next slot to fill is given
+ % by the second argument.
+ %
:- pred ml_stack_layout_construct_type_param_locn_vector(
assoc_list(tvar, set(layout_locn))::in,
int::in, list(mlds__initializer)::out) is det.
@@ -507,8 +474,7 @@
( set__remove_least(Locns, LeastLocn, _) ->
Locn = LeastLocn
;
- unexpected(this_file,
- "tvar has empty set of locations")
+ unexpected(this_file, "tvar has empty set of locations")
),
stack_layout__represent_locn_as_int(Locn, LocnAsInt),
Rval = const(int_const(LocnAsInt)),
@@ -525,7 +491,6 @@
"unsorted tvars in construct_type_param_locn_vector")
).
- %
% ml_gen_closure_wrapper:
% see comment in interface section for details.
%
@@ -566,8 +531,7 @@
%
% Actually, that is a simplified form.
% Also when calling a special pred then the closure argument isn't
- % required.
- % In full generality, it will look more like this:
+ % required. In full generality, it will look more like this:
%
% #if MODEL_SEMI
% bool
@@ -603,15 +567,13 @@
% #if CLOSURE_KIND == HIGHER_ORDER_PROC_CLOSURE
% closure_layout_ptr =
% ((MR_Closure *)closure_arg)->MR_closure_layout;
- % type_params =
- % MR_materialize_closure_typeinfos(closure_arg);
+ % type_params = MR_materialize_closure_typeinfos(closure_arg);
% #else /* CLOSURE_KIND == TYPECLASS_INFO_CLOSURE */
% {
% static const MR_Closure_Layout closure_layout = ...;
% closure_layout_ptr = &closure_layout;
% }
- % type_params =
- % MR_materialize_closure_typeinfos(closure_arg);
+ % type_params = MR_materialize_closure_typeinfos(closure_arg);
% #endif
% #endif /* GC tracing code */
% #endif
@@ -637,7 +599,6 @@
% }
% #endif
% #endif
- % #endif
%
% #if MODEL_SEMI
% MR_bool succeeded;
@@ -708,12 +669,9 @@
%
ml_gen_closure_wrapper(PredId, ProcId, ClosureKind, NumClosureArgs,
Context, WrapperFuncRval, WrapperFuncType, !Info) :-
- %
- % grab the relevant information about the called procedure
- %
+ % Grab the relevant information about the called procedure.
ml_gen_info_get_module_info(!.Info, ModuleInfo),
- module_info_pred_proc_info(ModuleInfo, PredId, ProcId,
- PredInfo, ProcInfo),
+ module_info_pred_proc_info(ModuleInfo, PredId, ProcId, PredInfo, ProcInfo),
pred_info_get_purity(PredInfo, Purity),
pred_info_arg_types(PredInfo, ProcArgTypes),
PredOrFunc = pred_info_is_pred_or_func(PredInfo),
@@ -724,50 +682,42 @@
ProcArity = list__length(ProcHeadVars),
ProcHeadVarNames = ml_gen_var_names(ProcVarSet, ProcHeadVars),
- %
% allocate some fresh type variables to use as the Mercury types
- % of the boxed arguments
- %
+ % of the boxed arguments.
ProcBoxedArgTypes = ml_make_boxed_types(ProcArity),
- %
- % compute the parameters for the wrapper function
+ % Compute the parameters for the wrapper function
% (void *closure_arg,
% MR_Box wrapper_arg1, MR_Box *wrapper_arg2, ...,
% MR_Box wrapper_argn)
- %
- % first generate the declarations for the boxed arguments
+ % First generate the declarations for the boxed arguments.
(
list__drop(NumClosureArgs, ProcHeadVars, WrapperHeadVars0),
list__drop(NumClosureArgs, ProcArgModes, WrapperArgModes0),
list__drop(NumClosureArgs, ProcArgTypes, WrapperArgTypes0),
- list__drop(NumClosureArgs, ProcBoxedArgTypes,
- WrapperBoxedArgTypes0)
+ list__drop(NumClosureArgs, ProcBoxedArgTypes, WrapperBoxedArgTypes0)
->
WrapperHeadVars = WrapperHeadVars0,
WrapperArgModes = WrapperArgModes0,
WrapperArgTypes = WrapperArgTypes0,
WrapperBoxedArgTypes = WrapperBoxedArgTypes0
;
- unexpected(this_file,
- "ml_gen_closure_wrapper: list__drop failed")
+ unexpected(this_file, "ml_gen_closure_wrapper: list__drop failed")
),
WrapperHeadVarNames = ml_gen_wrapper_head_var_names(1,
list__length(WrapperHeadVars)),
ml_gen_params(WrapperHeadVarNames, WrapperBoxedArgTypes,
WrapperArgModes, PredOrFunc, CodeModel, WrapperParams0, !Info),
WrapperParams0 = mlds__func_params(WrapperArgs0, WrapperRetType),
- % The GC handling for the wrapper arguments is wrong,
- % because we don't have type_infos for the type variables in
- % WrapperBoxedArgTypes. We handle this by just deleting it,
- % since it turns out that it's not needed anyway.
- % We don't need to trace the WrapperParams for accurate GC, since
- % the WrapperParams are only live in the time from the entry of
- % the wrapper function to when it calls the wrapped function,
- % and garbage collection can't occur in that time, since there
- % are no allocations (only an assignment to `closure_arg' and
- % some unbox operations).
+ % The GC handling for the wrapper arguments is wrong, because we don't have
+ % type_infos for the type variables in WrapperBoxedArgTypes. We handle this
+ % by just deleting it, since it turns out that it's not needed anyway.
+ % We don't need to trace the WrapperParams for accurate GC, since the
+ % WrapperParams are only live in the time from the entry of the wrapper
+ % function to when it calls the wrapped function, and garbage collection
+ % can't occur in that time, since there are no allocations (only an
+ % assignment to `closure_arg' and some unbox operations).
WrapperArgs1 = list__map(arg_delete_gc_trace_code, WrapperArgs0),
% then insert the `closure_arg' parameter, if needed.
@@ -788,19 +738,16 @@
),
WrapperParams = mlds__func_params(WrapperArgs, WrapperRetType),
- % also compute the lvals for the parameters,
- % and local declarations for any by-value output parameters
+ % Also compute the lvals for the parameters,
+ % and local declarations for any by-value output parameters.
ml_gen_wrapper_arg_lvals(WrapperHeadVarNames, WrapperBoxedArgTypes,
WrapperArgModes, PredOrFunc, CodeModel, Context, 1,
- WrapperHeadVarDecls, WrapperHeadVarLvals, WrapperCopyOutLvals,
- !Info),
+ WrapperHeadVarDecls, WrapperHeadVarLvals, WrapperCopyOutLvals, !Info),
- %
- % generate code to declare and initialize the closure pointer,
- % if needed
- % XXX we should use a struct type for the closure, but
- % currently we're using a low-level data representation
- % in the closure
+ % Generate code to declare and initialize the closure pointer,
+ % if needed.
+ % XXX We should use a struct type for the closure, but currently we're
+ % using a low-level data representation in the closure.
%
% #if 0 /* HIGH_LEVEL_DATA */
% FooClosure *closure;
@@ -810,13 +757,13 @@
% closure = closure_arg;
%
MLDS_Context = mlds__make_context(Context),
- ( MaybeClosureA = yes({ClosureArgType1, ClosureArgName1}) ->
+ (
+ MaybeClosureA = yes({ClosureArgType1, ClosureArgName1}),
ClosureName = mlds__var_name("closure", no),
ClosureType = mlds__generic_type,
% If we were to generate GC tracing code for the closure
% pointer, it would look like this:
- % ClosureDeclType = list__det_head(
- % ml_make_boxed_types(1)),
+ % ClosureDeclType = list__det_head(ml_make_boxed_types(1)),
% gen_closure_gc_trace_code(ClosureName, ClosureDeclType,
% ClosureKind, WrapperArgTypes, Purity,
% PredOrFunc, Context, ClosureGCTraceCode),
@@ -835,29 +782,28 @@
MaybeClosureB = yes({ClosureDecl, InitClosure}),
MaybeClosureC = yes(ClosureLval)
;
+ MaybeClosureA = no,
MaybeClosureB = no,
MaybeClosureC = no
),
- %
- % if the wrapper function is model_non, then
- % set up the initial success continuation;
- % this is needed by ml_gen_call which we call below
- %
+ % If the wrapper function is model_non, then set up the initial success
+ % continuation; this is needed by ml_gen_call which we call below.
( CodeModel = model_non ->
- globals__lookup_bool_option(Globals, nondet_copy_out,
- NondetCopyOut),
- ( NondetCopyOut = yes ->
+ globals__lookup_bool_option(Globals, nondet_copy_out, NondetCopyOut),
+ (
+ NondetCopyOut = yes,
map__from_corresponding_lists(WrapperHeadVarLvals,
WrapperBoxedArgTypes, WrapperBoxedVarTypes),
WrapperOutputLvals = select_output_vars(ModuleInfo,
WrapperHeadVarLvals, WrapperArgModes,
WrapperBoxedVarTypes),
- WrapperOutputTypes = map__apply_to_list(
- WrapperOutputLvals, WrapperBoxedVarTypes),
+ WrapperOutputTypes = map__apply_to_list(WrapperOutputLvals,
+ WrapperBoxedVarTypes),
ml_initial_cont(!.Info, WrapperOutputLvals,
WrapperOutputTypes, InitialCont)
;
+ NondetCopyOut = no,
ml_initial_cont(!.Info, [], [], InitialCont)
),
ml_gen_info_push_success_cont(InitialCont, !Info)
@@ -865,9 +811,8 @@
true
),
- % generate code to call the function:
- % XXX currently we're using a low-level data representation
- % in the closure
+ % Generate code to call the function:
+ % XXX currently we're using a low-level data representation in the closure.
%
% foo(
% #if HIGH_LEVEL_DATA
@@ -883,7 +828,8 @@
% `Offset' specifies the offset to add to the argument number to
% get the field number within the closure. (Argument numbers start
% from 1, and field numbers start from 0.)
- ( MaybeClosureC = yes(ClosureLval1) ->
+ (
+ MaybeClosureC = yes(ClosureLval1),
(
ClosureKind = higher_order_proc_closure,
Offset = ml_closure_arg_offset
@@ -892,31 +838,30 @@
Offset = ml_typeclass_info_arg_offset
;
ClosureKind = special_pred,
- unexpected(this_file,
- "ml_gen_closure_wrapper: special_pred")
+ unexpected(this_file, "ml_gen_closure_wrapper: special_pred")
),
ml_gen_closure_field_lvals(ClosureLval1, Offset, 1,
NumClosureArgs, ClosureArgLvals, !Info)
;
+ MaybeClosureC = no,
ClosureArgLvals = []
),
CallLvals = list__append(ClosureArgLvals, WrapperHeadVarLvals),
- ml_gen_call(PredId, ProcId, ProcHeadVarNames, CallLvals,
- ProcBoxedArgTypes, CodeModel, Context, yes,
- Decls0, Statements0, !Info),
+ ml_gen_call(PredId, ProcId, ProcHeadVarNames, CallLvals, ProcBoxedArgTypes,
+ CodeModel, Context, yes, Decls0, Statements0, !Info),
- % insert the stuff to declare and initialize the closure
- ( MaybeClosureB = yes({ClosureDecl1, InitClosure1}) ->
+ % Insert the stuff to declare and initialize the closure.
+ (
+ MaybeClosureB = yes({ClosureDecl1, InitClosure1}),
Decls1 = [ClosureDecl1 | Decls0],
Statements1 = [InitClosure1 | Statements0]
;
+ MaybeClosureB = no,
Decls1 = Decls0,
Statements1 = Statements0
),
- %
- % For semidet code, add the declaration `MR_bool succeeded;'
- %
+ % For semidet code, add the declaration `MR_bool succeeded;'.
( CodeModel = model_semi ->
SucceededVarDecl = ml_gen_succeeded_var_decl(MLDS_Context),
Decls2 = [SucceededVarDecl | Decls1]
@@ -924,46 +869,37 @@
Decls2 = Decls1
),
- % Add an appropriate `return' statement
+ % Add an appropriate `return' statement.
ml_append_return_statement(!.Info, CodeModel, WrapperCopyOutLvals,
Context, Statements1, Statements),
- %
- % generate code to declare and initialize the local variables
- % needed for accurate GC
- %
+ % Generate code to declare and initialize the local variables
+ % needed for accurate GC.
module_info_globals(ModuleInfo, Globals),
(
MaybeClosureA = yes({ClosureArgType2, ClosureArgName2}),
globals__get_gc_method(Globals, accurate)
->
ml_gen_closure_wrapper_gc_decls(ClosureKind, ClosureArgName2,
- ClosureArgType2, PredId, ProcId, Context, GC_Decls,
- !Info)
+ ClosureArgType2, PredId, ProcId, Context, GC_Decls, !Info)
;
GC_Decls = []
),
- %
% Insert the local declarations of the wrapper's output arguments,
% if any (this is needed for functions and for `--(non)det-copy-out'),
% and the `type_params' variable used by the GC code.
- %
Decls = GC_Decls ++ WrapperHeadVarDecls ++ Decls2,
- %
- % if the wrapper function was model_non, then
- % pop the success continuation that we pushed
- %
+ % If the wrapper function was model_non, then pop the success continuation
+ % that we pushed.
( CodeModel = model_non ->
ml_gen_info_pop_success_cont(!Info)
;
true
),
- %
- % Put it all together
- %
+ % Put it all together.
WrapperFuncBody = ml_gen_block(Decls, Statements, Context),
ml_gen_new_func_label(yes(WrapperParams), WrapperFuncName,
WrapperFuncRval, !Info),
@@ -978,8 +914,9 @@
Argument0 = mlds__argument(Name, Type, _GCTraceCode),
Argument = mlds__argument(Name, Type, no).
- % generate the GC tracing code for `closure_arg' or `closure'
+ % Generate the GC tracing code for `closure_arg' or `closure'
% (see ml_gen_closure_wrapper above).
+ %
:- pred gen_closure_gc_trace_code(mlds__var_name::in, prog_type::in,
closure_kind::in, list(prog_type)::in, purity::in, pred_or_func::in,
prog_context::in, mlds__maybe_gc_trace_code::out,
@@ -988,26 +925,23 @@
gen_closure_gc_trace_code(ClosureName, ClosureDeclType,
ClosureKind, WrapperArgTypes, Purity, PredOrFunc,
Context, ClosureGCTraceCode, !Info) :-
- % We can't use WrapperArgTypes here,
- % because we don't have type_infos for the type variables in
- % WrapperArgTypes; those type variables come from the callee.
- % But when copying closures, we don't care what the types of the
- % not-yet-applied arguments are. So we can just use dummy values here.
+ % We can't use WrapperArgTypes here, because we don't have type_infos
+ % for the type variables in WrapperArgTypes; those type variables come from
+ % the callee. But when copying closures, we don't care what the types of
+ %% the not-yet-applied arguments are. So we can just use dummy values here.
HigherOrderArgTypes = list__duplicate(list__length(WrapperArgTypes),
c_pointer_type),
(
ClosureKind = higher_order_proc_closure,
LambdaEvalMethod = normal,
- construct_higher_order_type(Purity, PredOrFunc,
- LambdaEvalMethod, HigherOrderArgTypes,
- ClosureActualType)
+ construct_higher_order_type(Purity, PredOrFunc, LambdaEvalMethod,
+ HigherOrderArgTypes, ClosureActualType)
;
ClosureKind = typeclass_info_closure,
ClosureActualType = sample_typeclass_info_type
;
ClosureKind = special_pred,
- unexpected(this_file,
- "gen_closure_gc_trace_code: special_pred")
+ unexpected(this_file, "gen_closure_gc_trace_code: special_pred")
),
ml_gen_maybe_gc_trace_code(ClosureName, ClosureDeclType,
ClosureActualType, Context, ClosureGCTraceCode, !Info).
@@ -1035,14 +969,12 @@
Names = [mlds__var_name(Name, no) | Names1]
).
- % ml_gen_wrapper_arg_lvals(HeadVarNames, Types, ArgModes,
- % PredOrFunc, CodeModel, Context, ArgNum,
- % LocalVarDefns, HeadVarLvals, CopyOutLvals):
- % Generate lvals for the specified head variables
- % passed in the specified modes.
- % Also generate local definitions for output variables,
- % if those output variables will be copied out,
- % rather than passed by reference.
+ % ml_gen_wrapper_arg_lvals(HeadVarNames, Types, ArgModes, PredOrFunc,
+ % CodeModel, Context, ArgNum, LocalVarDefns, HeadVarLvals, CopyOutLvals):
+ %
+ % Generate lvals for the specified head variables passed in the specified
+ % modes. Also generate local definitions for output variables, if those
+ % output variables will be copied out, rather than passed by reference.
%
:- pred ml_gen_wrapper_arg_lvals(list(var_name)::in, list(prog_type)::in,
list(mode)::in, pred_or_func::in, code_model::in, prog_context::in,
@@ -1064,9 +996,8 @@
Types = [Type | Types1],
Modes = [Mode | Modes1]
->
- ml_gen_wrapper_arg_lvals(Names1, Types1, Modes1,
- PredOrFunc, CodeModel, Context, ArgNum + 1,
- Defns1, Lvals1, CopyOutLvals1, !Info),
+ ml_gen_wrapper_arg_lvals(Names1, Types1, Modes1, PredOrFunc, CodeModel,
+ Context, ArgNum + 1, Defns1, Lvals1, CopyOutLvals1, !Info),
ml_gen_type(!.Info, Type, MLDS_Type),
ml_gen_var_lval(!.Info, Name, MLDS_Type, VarLval),
ml_gen_info_get_module_info(!.Info, ModuleInfo),
@@ -1076,31 +1007,24 @@
CopyOutLvals = CopyOutLvals1,
Defns = Defns1
;
- %
- % handle output variables
- %
+ % Handle output variables.
ml_gen_info_get_globals(!.Info, Globals),
CopyOut = get_copy_out_option(Globals, CodeModel),
(
(
CopyOut = yes
;
- % for model_det functions,
- % output mode function results
- % are mapped to MLDS return values
+ % For model_det functions, output mode function results
+ % are mapped to MLDS return values.
PredOrFunc = function,
CodeModel = model_det,
ArgMode = top_out,
Types1 = [],
- \+ type_util__is_dummy_argument_type(
- Type)
+ \+ type_util__is_dummy_argument_type( Type)
)
->
- %
- % output arguments are copied out,
- % so we need to generate a local declaration
- % for them here
- %
+ % Output arguments are copied out, so we need to generate
+ % a local declaration for them here.
Lval = VarLval,
( type_util__is_dummy_argument_type(Type) ->
CopyOutLvals = CopyOutLvals1,
@@ -1112,10 +1036,8 @@
Defns = [Defn | Defns1]
)
;
- %
- % output arguments are passed by reference,
- % so we need to dereference them
- %
+ % Output arguments are passed by reference, so we need to
+ % dereference them.
Lval = mem_ref(lval(VarLval), MLDS_Type),
CopyOutLvals = CopyOutLvals1,
Defns = Defns1
@@ -1123,8 +1045,7 @@
),
Lvals = [Lval | Lvals1]
;
- sorry(this_file,
- "ml_gen_wrapper_arg_lvals: length mismatch")
+ sorry(this_file, "ml_gen_wrapper_arg_lvals: length mismatch")
).
% This is used for accurate GC with the MLDS->C back-end.
@@ -1151,16 +1072,14 @@
PredId, ProcId, Context, GC_Decls, !Info) :-
MLDS_Context = mlds__make_context(Context),
- ml_gen_var_lval(!.Info, ClosureArgName, ClosureArgType,
- ClosureArgLval),
+ ml_gen_var_lval(!.Info, ClosureArgName, ClosureArgType, ClosureArgLval),
ClosureLayoutPtrName = var_name("closure_layout_ptr", no),
% This type is really `const MR_Closure_Layout *', but there's no easy
% way to represent that in the MLDS; using MR_Box instead works fine.
ClosureLayoutPtrType = mlds__generic_type,
ClosureLayoutPtrDecl = ml_gen_mlds_var_decl(var(ClosureLayoutPtrName),
- ClosureLayoutPtrType, yes(ClosureLayoutPtrGCInit),
- MLDS_Context),
+ ClosureLayoutPtrType, yes(ClosureLayoutPtrGCInit), MLDS_Context),
ml_gen_var_lval(!.Info, ClosureLayoutPtrName, ClosureLayoutPtrType,
ClosureLayoutPtrLval),
@@ -1170,8 +1089,7 @@
TypeParamsType = mlds__generic_type,
TypeParamsDecl = ml_gen_mlds_var_decl(var(TypeParamsName),
TypeParamsType, yes(TypeParamsGCInit), MLDS_Context),
- ml_gen_var_lval(!.Info, TypeParamsName, TypeParamsType,
- TypeParamsLval),
+ ml_gen_var_lval(!.Info, TypeParamsName, TypeParamsType, TypeParamsLval),
(
ClosureKind = higher_order_proc_closure,
ClosureLayoutPtrGCInitFragments = [
@@ -1200,8 +1118,7 @@
ClosureLayoutDefns,
[mlds__statement(atomic(
assign(ClosureLayoutPtrLval,
- unop(box(ClosureLayoutType),
- ClosureLayoutRval)
+ unop(box(ClosureLayoutType), ClosureLayoutRval)
)), MLDS_Context)]
), MLDS_Context),
TypeParamsGCInitFragments = [
@@ -1216,8 +1133,7 @@
]
;
ClosureKind = special_pred,
- unexpected(this_file,
- "ml_gen_closure_wrapper_gc_decls: special_pred")
+ unexpected(this_file, "ml_gen_closure_wrapper_gc_decls: special_pred")
),
TypeParamsGCInit = mlds__statement(atomic(inline_target_code(
@@ -1226,11 +1142,9 @@
ml_gen_local_for_output_arg(VarName, Type, ArgNum, Context, LocalVarDefn,
!Info) :-
- %
% Generate a declaration for a corresponding local variable.
% However, don't use the normal GC tracing code; instead,
- % we need to get the typeinfo from `type_params', using
- % the following code:
+ % we need to get the typeinfo from `type_params', using the following code:
%
% MR_TypeInfo type_info;
% MR_MemoryList allocated_memory_cells = NULL;
@@ -1259,13 +1173,12 @@
TypeParamsLval),
TypeInfoName = var_name("type_info", no),
- % the type for this should match the type of the first argument
- % of private_builtin__gc_trace/1, i.e. `mutvar(T)', which is
- % a no_tag type whose representation is c_pointer.
+ % The type for this should match the type of the first argument
+ % of private_builtin__gc_trace/1, i.e. `mutvar(T)', which is a no_tag type
+ % whose representation is c_pointer.
ml_gen_info_get_module_info(!.Info, ModuleInfo),
TypeInfoMercuryType = c_pointer_type,
- TypeInfoType = mercury_type_to_mlds_type(ModuleInfo,
- TypeInfoMercuryType),
+ TypeInfoType = mercury_type_to_mlds_type(ModuleInfo, TypeInfoMercuryType),
ml_gen_var_lval(!.Info, TypeInfoName, TypeInfoType, TypeInfoLval),
TypeInfoDecl = ml_gen_mlds_var_decl(var(TypeInfoName), TypeInfoType,
no_initializer, no, MLDS_Context),
@@ -1273,14 +1186,13 @@
ml_gen_maybe_gc_trace_code_with_typeinfo(VarName, Type,
lval(TypeInfoLval), Context, MaybeGCTraceCode0, !Info),
- ( MaybeGCTraceCode0 = yes(CallTraceFuncCode) ->
+ (
+ MaybeGCTraceCode0 = yes(CallTraceFuncCode),
MakeTypeInfoCode = atomic(inline_target_code(lang_C, [
raw_target_code("{\n", []),
- raw_target_code(
- "MR_MemoryList allocated_mem = NULL;\n", []),
+ raw_target_code("MR_MemoryList allocated_mem = NULL;\n", []),
target_code_output(TypeInfoLval),
- raw_target_code(
- " = (MR_C_Pointer) " ++
+ raw_target_code(" = (MR_C_Pointer) " ++
"MR_make_type_info_maybe_existq(\n\t", []),
target_code_input(lval(TypeParamsLval)),
raw_target_code(", ((MR_Closure_Layout *)\n\t", []),
@@ -1299,9 +1211,9 @@
CallTraceFuncCode,
mlds__statement(DeallocateCode, MLDS_Context)
]),
- MaybeGCTraceCode = yes(mlds__statement(GCTraceCode,
- MLDS_Context))
+ MaybeGCTraceCode = yes(mlds__statement(GCTraceCode, MLDS_Context))
;
+ MaybeGCTraceCode0 = no,
MaybeGCTraceCode = MaybeGCTraceCode0
),
LocalVarDefn = ml_gen_mlds_var_decl(var(VarName),
@@ -1316,16 +1228,12 @@
( ArgNum > NumClosureArgs ->
ClosureArgLvals = []
;
- %
- % generate `MR_field(MR_mktag(0), closure, <N>)'
- %
+ % Generate `MR_field(MR_mktag(0), closure, <N>)'.
FieldId = offset(const(int_const(ArgNum + Offset))),
- % XXX these types might not be right
+ % XXX These types might not be right.
FieldLval = field(yes(0), lval(ClosureLval), FieldId,
mlds__generic_type, mlds__generic_type),
- %
- % recursively handle the remaining fields
- %
+ % Recursively handle the remaining fields.
ml_gen_closure_field_lvals(ClosureLval, Offset, ArgNum + 1,
NumClosureArgs, ClosureArgLvals0, !Info),
ClosureArgLvals = [FieldLval | ClosureArgLvals0]
Index: compiler/ml_code_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/ml_code_gen.m,v
retrieving revision 1.155
diff -u -b -r1.155 ml_code_gen.m
--- compiler/ml_code_gen.m 12 Sep 2005 05:24:13 -0000 1.155
+++ compiler/ml_code_gen.m 12 Sep 2005 13:08:19 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 1999-2005 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -154,32 +156,27 @@
% - exiting nested functions via gotos to
% their containing functions
%
-% The MLDS data structure abstracts away these differences
-% using the `try_commit' and `do_commit' instructions.
-% The comments below show the MLDS try_commit/do_commit version first,
-% but for clarity I've also included sample code using each of the three
-% different techniques. This shows how the MLDS->target back-end can map
-% mlds__commit_type, do_commit and try_commit into target language
-% constructs.
-%
-% Note that if we're using GCC's __builtin_longjmp(),
-% then it is important that the call to __builtin_longjmp() be
-% put in its own function, to ensure that it is not in the same
-% function as the __builtin_setjmp().
-% The code generation schema below does that automatically.
-% We will need to be careful with MLDS optimizations to
-% ensure that we preserve that invariant, though.
-% (Alternatively, we could just call a function that
-% calls __builtin_longjmp() rather than calling it directly.
-% But that would be a little less efficient.)
-%
-% If those methods turn out to be too inefficient,
-% another alternative would be to change the generated
-% code so that after every function call, it would check a flag,
-% and if that flag was set, it would return.
-% Then MR_DO_COMMIT would just set the flag and return.
-% The flag could be in a global (or thread-local) variable,
-% or it could be an additional value returned from each function.
+% The MLDS data structure abstracts away these differences using the
+% `try_commit' and `do_commit' instructions. The comments below show
+% the MLDS try_commit/do_commit version first, but for clarity I've also
+% included sample code using each of the three different techniques.
+% This shows how the MLDS->target back-end can map mlds__commit_type,
+% do_commit and try_commit into target language constructs.
+%
+% Note that if we're using GCC's __builtin_longjmp(), then it is important
+% that the call to __builtin_longjmp() be put in its own function, to ensure
+% that it is not in the same function as the __builtin_setjmp(). The code
+% generation schema below does that automatically. We will need to be careful
+% with MLDS optimizations to ensure that we preserve that invariant, though.
+% (Alternatively, we could just call a function that calls __builtin_longjmp()
+% rather than calling it directly. But that would be a little less efficient.)
+%
+% If those methods turn out to be too inefficient, another alternative would be
+% to change the generated code so that after every function call, it would
+% check a flag, and if that flag was set, it would return. Then MR_DO_COMMIT
+% would just set the flag and return. The flag could be in a global
+% (or thread-local) variable, or it could be an additional value returned
+% from each function.
% model_non in semi context: (using try_commit/do_commit)
% <succeeded = Goal>
@@ -208,11 +205,11 @@
% succeeded = MR_TRUE;
% }
-% The above is using C++ syntax. Here COMMIT is an exception type,
-% which can be defined trivially (e.g. "class COMMIT {};").
-% Note that when using catch/throw, we don't need the "ref" argument
-% at all; the target language's exception handling implementation
-% keeps track of all the information needed to unwind the stack.
+% The above is using C++ syntax. Here COMMIT is an exception type, which
+% can be defined trivially (e.g. "class COMMIT {};"). Note that when using
+% catch/throw, we don't need the "ref" argument at all; the target language's
+% exception handling implementation keeps track of all the information needed
+% to unwind the stack.
% model_non in semi context: (using setjmp/longjmp)
% <succeeded = Goal>
@@ -363,20 +360,17 @@
% <Goals>;
% }
%
-% The actual code generation scheme we use is slightly
-% different to that: we hoist any declarations generated
-% for <Goals> to the outer scope, rather than keeping
-% them inside the `if', so that they remain in
-% scope for any later goals which follow this.
-% This is needed for declarations of static consts.
-
-% For model_non goals, there are a couple of different
-% ways that we could generate code, depending on whether
-% we are aiming to maximize readability, or whether we
-% prefer to generate code that may be more efficient
-% but is a little less readable. The more readable method
-% puts the generated goals in the same order that
-% they occur in the source code:
+% The actual code generation scheme we use is slightly different to that:
+% we hoist any declarations generated for <Goals> to the outer scope,
+% rather than keeping them inside the `if', so that they remain in scope
+% for any later goals which follow this. This is needed for declarations
+% of static consts.
+
+% For model_non goals, there are a couple of different ways that we could
+% generate code, depending on whether we are aiming to maximize readability,
+% or whether we prefer to generate code that may be more efficient but is
+% a little less readable. The more readable method puts the generated goals
+% in the same order that they occur in the source code:
%
% model_non Goal (optimized for readability)
% <Goal, Goals>
@@ -390,10 +384,9 @@
%
% entry_func();
%
-% The more efficient method generates the goals in
-% reverse order, so it's less readable, but it has fewer
-% function calls and can make it easier for the C compiler
-% to inline things:
+% The more efficient method generates the goals in reverse order, so it's less
+% readable, but it has fewer function calls and can make it easier for the C
+% compiler to inline things:
%
% model_non Goal (optimized for efficiency):
% <Goal, Goals>
@@ -406,8 +399,7 @@
%
% The more efficient method is the one we actually use.
%
-% Here's how those two methods look on longer
-% conjunctions of nondet goals:
+% Here's how those two methods look on longer conjunctions of nondet goals:
%
% model_non goals (optimized for readability):
% <Goal1, Goal2, Goal3, Goals>
@@ -441,8 +433,8 @@
% }
% <Goal1 && label1_func()>;
%
-% Note that it might actually make more sense to generate
-% conjunctions of nondet goals like this:
+% Note that it might actually make more sense to generate conjunctions
+% of nondet goals like this:
%
% model_non goals (optimized for efficiency, alternative version):
% <Goal1, Goal2, Goal3, Goals>
@@ -459,20 +451,18 @@
%
% <Goal1 && label1_func()>;
%
-% This would avoid the undesirable deep nesting that we sometimes get
-% with our current scheme. However, if we're eliminating nested
-% functions, as is normally the case, then after the ml_elim_nested
-% transformation all the functions and variables have been hoisted
-% to the top level, so there is no difference between these two.
-%
-% As with semidet conjunctions, we hoist declarations
-% out so that they remain in scope for any following goals.
-% This is needed for declarations of static consts.
-% However, we want to keep the declarations of non-static
-% variables local, since accessing local variables is more
-% efficient that accessing variables in the environment
-% from a nested function. So we only hoist declarations
-% of static constants.
+% This would avoid the undesirable deep nesting that we sometimes get with
+% our current scheme. However, if we're eliminating nested functions, as is
+% normally the case, then after the ml_elim_nested transformation all the
+% functions and variables have been hoisted to the top level, so there is
+% no difference between these two.
+%
+% As with semidet conjunctions, we hoist declarations out so that they remain
+% in scope for any following goals. This is needed for declarations of static
+% consts. However, we want to keep the declarations of non-static variables
+% local, since accessing local variables is more efficient that accessing
+% variables in the environment from a nested function. So we only hoist
+% declarations of static constants.
%-----------------------------------------------------------------------------%
%
@@ -580,12 +570,10 @@
% <Else>
% }
-% /*
-% ** XXX The following transformation does not do as good a job of GC
-% ** as it could. Ideally we ought to ensure that stuff used only
-% ** in the `Else' part will be reclaimed if a GC occurs during
-% ** the `Then' part. But that is a bit tricky to achieve.
-% */
+% XXX The following transformation does not do as good a job of GC as it could.
+% Ideally we ought to ensure that stuff used only in the `Else' part will be
+% reclaimed if a GC occurs during the `Then' part. But that is a bit tricky
+% to achieve.
%
% model_non Cond:
% <(Cond -> Then ; Else)>
@@ -602,10 +590,10 @@
% if (!cond_<N>) {
% <Else>
% }
-% except that we hoist any declarations generated
-% for <Cond> to the top of the scope, so that they
-% are in scope for the <Then> goal
-% (this is needed for declarations of static consts)
+%
+% except that we hoist any declarations generated for <Cond> to the top
+% of the scope, so that they are in scope for the <Then> goal
+% (this is needed for declarations of static consts).
%-----------------------------------------------------------------------------%
%
@@ -738,17 +726,16 @@
%
:- pred ml_code_gen(module_info::in, mlds::out, io::di, io::uo) is det.
- % Generate MLDS code for the specified goal in the
- % specified code model. Return the result as a single statement
- % (which may be a block statement containing nested declarations).
+ % Generate MLDS code for the specified goal in the specified code model.
+ % Return the result as a single statement (which may be a block statement
+ % containing nested declarations).
%
:- pred ml_gen_goal(code_model::in, hlds_goal::in, mlds__statement::out,
ml_gen_info::in, ml_gen_info::out) is det.
- % Generate MLDS code for the specified goal in the
- % specified code model. Return the result as two lists,
- % one containing the necessary declarations and the other
- % containing the generated statements.
+ % Generate MLDS code for the specified goal in the specified code model.
+ % Return the result as two lists, one containing the necessary declarations
+ % and the other containing the generated statements.
%
:- pred ml_gen_goal(code_model::in, hlds_goal::in,
mlds__defns::out, mlds__statements::out,
@@ -757,12 +744,11 @@
% ml_gen_wrap_goal(OuterCodeModel, InnerCodeModel, Context,
% Statements0, Statements):
%
- % OuterCodeModel is the code model expected by the
- % context in which a goal is called. InnerCodeModel
- % is the code model which the goal actually has.
- % This predicate converts the code generated for
- % the goal using InnerCodeModel into code that uses
- % the calling convention appropriate for OuterCodeModel.
+ % OuterCodeModel is the code model expected by the context in which a goal
+ % is called. InnerCodeModel is the code model which the goal actually has.
+ % This predicate converts the code generated for the goal using
+ % InnerCodeModel into code that uses the calling convention appropriate
+ % for OuterCodeModel.
%
:- pred ml_gen_wrap_goal(code_model::in, code_model::in, prog_context::in,
mlds__statements::in, mlds__statements::out,
@@ -816,8 +802,6 @@
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
- % Generate MLDS code for an entire module.
- %
ml_code_gen(ModuleInfo, MLDS, !IO) :-
module_info_name(ModuleInfo, ModuleName),
ml_gen_foreign_code(ModuleInfo, ForeignCode, !IO),
@@ -834,8 +818,7 @@
module_info_get_foreign_decl(ModuleInfo, ForeignDecls),
module_info_get_foreign_import_module(ModuleInfo, ForeignImports),
module_info_get_foreign_body_code(ModuleInfo, ForeignBodys),
- globals__io_get_backend_foreign_languages(BackendForeignLanguages,
- !IO),
+ globals__io_get_backend_foreign_languages(BackendForeignLanguages, !IO),
WantedForeignImports = list__condense(
list__map((func(L) = Imports :-
@@ -860,26 +843,26 @@
_OtherForeignBodys),
ConvBody = (func(foreign_body_code(L, S, C)) =
user_foreign_code(L, S, C)),
- MLDSWantedForeignBodys = list__map(ConvBody,
- WantedForeignBodys),
- % XXX exports are only implemented for
- % C and IL at the moment
- ( ( Lang = c ; Lang = il ) ->
+ MLDSWantedForeignBodys = list__map(ConvBody, WantedForeignBodys),
+ % XXX Exports are only implemented for C and IL at the moment.
+ (
+ ( Lang = c
+ ; Lang = il
+ )
+ ->
ml_gen_pragma_export(ModuleInfo, MLDS_PragmaExports)
;
MLDS_PragmaExports = []
),
MLDS_ForeignCode = mlds__foreign_code(WantedForeignDecls,
- WantedForeignImports, MLDSWantedForeignBodys,
- MLDS_PragmaExports),
+ WantedForeignImports, MLDSWantedForeignBodys, MLDS_PragmaExports),
map__det_insert(Map0, Lang, MLDS_ForeignCode, Map).
:- pred ml_gen_imports(module_info::in, mlds__imports::out) is det.
ml_gen_imports(ModuleInfo, MLDS_ImportList) :-
% Determine all the mercury imports.
- % XXX This is overly conservative,
- % i.e. we import more than we really need.
+ % XXX This is overly conservative, i.e. we import more than we really need.
module_info_globals(ModuleInfo, Globals),
globals__get_target(Globals, Target),
module_info_get_all_deps(ModuleInfo, AllImports0),
@@ -889,12 +872,11 @@
P = (func(Name) = mercury_import(compiler_visible_interface,
mercury_module_name_to_mlds(Name))),
- % For every foreign type determine the import needed to
- % find the declaration for that type.
+ % For every foreign type determine the import needed to find
+ % the declaration for that type.
module_info_types(ModuleInfo, Types),
ForeignTypeImports = list__condense(
- list__map(foreign_type_required_imports(Target),
- map__values(Types))),
+ list__map(foreign_type_required_imports(Target), map__values(Types))),
MLDS_ImportList = ForeignTypeImports ++
list__map(P, set__to_sorted_list(AllImports)).
@@ -905,10 +887,7 @@
foreign_type_required_imports(c, _) = [].
foreign_type_required_imports(il, TypeDefn) = Imports :-
hlds_data__get_type_defn_body(TypeDefn, Body),
- (
- Body = foreign_type(foreign_type_body(MaybeIL, _MaybeC,
- _MaybeJava))
- ->
+ ( Body = foreign_type(foreign_type_body(MaybeIL, _MaybeC, _MaybeJava)) ->
(
MaybeIL = yes(Data),
Data = foreign_type_lang_data(il(_, Location, _), _, _)
@@ -916,7 +895,6 @@
Name = il_assembly_name(mercury_module_name_to_mlds(
unqualified(Location))),
Imports = [foreign_import(Name)]
-
;
unexpected(this_file, "no IL type")
)
@@ -935,10 +913,8 @@
%-----------------------------------------------------------------------------%
%
-% For each pragma export declaration we associate with it the
-% information used to generate the function prototype for the MLDS
-% entity.
-%
+% For each pragma export declaration we associate with it the information
+% used to generate the function prototype for the MLDS entity.
:- pred ml_gen_pragma_export(module_info::in, list(mlds__pragma_export)::out)
is det.
@@ -952,8 +928,7 @@
mlds__pragma_export::out) is det.
ml_gen_pragma_export_proc(ModuleInfo,
- pragma_exported_proc(PredId, ProcId, C_Name, ProgContext),
- Defn) :-
+ pragma_exported_proc(PredId, ProcId, C_Name, ProgContext), Defn) :-
ml_gen_proc_label(ModuleInfo, PredId, ProcId, Name, ModuleName),
FuncParams = ml_gen_proc_params(ModuleInfo, PredId, ProcId),
@@ -966,8 +941,8 @@
% Stuff to generate MLDS code for HLDS predicates & functions.
%
- % Generate MLDS definitions for all the non-imported
- % predicates (and functions) in the HLDS.
+ % Generate MLDS definitions for all the non-imported predicates
+ % (and functions) in the HLDS.
%
:- pred ml_gen_preds(module_info::in, mlds__defns::out, io::di, io::uo) is det.
@@ -975,8 +950,7 @@
module_info_preds(ModuleInfo, PredTable),
map__keys(PredTable, PredIds),
PredDefns0 = [],
- ml_gen_preds_2(ModuleInfo, PredIds, PredTable, PredDefns0, PredDefns,
- !IO).
+ ml_gen_preds_2(ModuleInfo, PredIds, PredTable, PredDefns0, PredDefns, !IO).
:- pred ml_gen_preds_2(module_info::in, list(pred_id)::in, pred_table::in,
mlds__defns::in, mlds__defns::out, io::di, io::uo) is det.
@@ -987,14 +961,14 @@
map__lookup(PredTable, PredId, PredInfo),
pred_info_import_status(PredInfo, ImportStatus),
(
- ( ImportStatus = imported(_)
- ; pred_info_is_aditi_relation(PredInfo)
-
- % We generate incorrect and unnecessary
- % code for the external special preds
- % which are pseudo_imported, so just
- % ignore them.
- ; is_unify_or_compare_pred(PredInfo),
+ (
+ ImportStatus = imported(_)
+ ;
+ pred_info_is_aditi_relation(PredInfo)
+ ;
+ % We generate incorrect and unnecessary code for the external
+ % special preds which are pseudo_imported, so just ignore them.
+ is_unify_or_compare_pred(PredInfo),
ImportStatus = external(pseudo_imported)
)
->
@@ -1008,12 +982,12 @@
PredIds0 = []
).
- % Generate MLDS definitions for all the non-imported
- % procedures of a given predicate (or function).
+ % Generate MLDS definitions for all the non-imported procedures
+ % of a given predicate (or function).
%
:- pred ml_gen_pred(module_info::in, pred_id::in, pred_info::in,
- import_status::in, mlds__defns::in, mlds__defns::out,
- io::di, io::uo) is det.
+ import_status::in, mlds__defns::in, mlds__defns::out, io::di, io::uo)
+ is det.
ml_gen_pred(ModuleInfo, PredId, PredInfo, ImportStatus, !Defns, !IO) :-
( ImportStatus = external(_) ->
@@ -1027,13 +1001,11 @@
write_pred_progress_message("% Generating MLDS code for ",
PredId, ModuleInfo, !IO),
pred_info_procedures(PredInfo, ProcTable),
- ml_gen_procs(ProcIds, ModuleInfo, PredId, PredInfo,
- ProcTable, !Defns)
+ ml_gen_procs(ProcIds, ModuleInfo, PredId, PredInfo, ProcTable, !Defns)
).
:- pred ml_gen_procs(list(proc_id)::in, module_info::in, pred_id::in,
- pred_info::in, proc_table::in, mlds__defns::in, mlds__defns::out)
- is det.
+ pred_info::in, proc_table::in, mlds__defns::in, mlds__defns::out) is det.
ml_gen_procs([], _, _, _, _, !Defns).
ml_gen_procs([ProcId | ProcIds], ModuleInfo, PredId, PredInfo, ProcTable,
@@ -1054,27 +1026,23 @@
ml_gen_proc(ModuleInfo, PredId, ProcId, _PredInfo, ProcInfo, !Defns) :-
proc_info_context(ProcInfo, Context),
-
ml_gen_proc_label(ModuleInfo, PredId, ProcId, Name, _ModuleName),
MLDS_Context = mlds__make_context(Context),
DeclFlags = ml_gen_proc_decl_flags(ModuleInfo, PredId, ProcId),
ml_gen_proc_defn(ModuleInfo, PredId, ProcId, ProcDefnBody, ExtraDefns),
ProcDefn = mlds__defn(Name, MLDS_Context, DeclFlags, ProcDefnBody),
!:Defns = list__append(ExtraDefns, [ProcDefn | !.Defns]),
- ml_gen_maybe_add_table_var(ModuleInfo, PredId, ProcId, ProcInfo,
- !Defns).
+ ml_gen_maybe_add_table_var(ModuleInfo, PredId, ProcId, ProcInfo, !Defns).
:- pred ml_gen_maybe_add_table_var(module_info::in, pred_id::in, proc_id::in,
proc_info::in, mlds__defns::in, mlds__defns::out) is det.
-ml_gen_maybe_add_table_var(ModuleInfo, PredId, ProcId, ProcInfo,
- Defns0, Defns) :-
+ml_gen_maybe_add_table_var(ModuleInfo, PredId, ProcId, ProcInfo, !Defns) :-
proc_info_eval_method(ProcInfo, EvalMethod),
(
eval_method_has_per_proc_tabling_pointer(EvalMethod) = yes
->
- ml_gen_pred_label(ModuleInfo, PredId, ProcId,
- PredLabel, _PredModule),
+ ml_gen_pred_label(ModuleInfo, PredId, ProcId, PredLabel, _PredModule),
Var = tabling_pointer(PredLabel - ProcId),
Type = mlds__generic_type,
Initializer = init_obj(const(null(Type))),
@@ -1084,25 +1052,22 @@
globals__get_gc_method(Globals, GC_Method),
GC_Method = accurate
->
- % XXX To handle this case properly, the GC would
- % need to trace through the global variable
- % that we generate for the table pointer.
- % Support for this is not yet implemented.
- % Also, we'd need to add GC support (stack
- % frame registration, and calls to MR_GC_check())
- % to MR_make_long_lived() and MR_deep_copy()
- % so that we do garbage collection of the
- % "global heap" which is used to store the tables.
+ % XXX To handle this case properly, the GC would need to trace
+ % through the global variable that we generate for the table
+ % pointer. Support for this is not yet implemented. Also, we'd need
+ % to add GC support (stack frame registration, and calls to
+ % MR_GC_check()) to MR_make_long_lived() and MR_deep_copy()
+ % so that we do garbage collection of the "global heap" which is
+ % used to store the tables.
sorry(this_file, "tabling and `--gc accurate'")
;
GC_TraceCode = no
),
- TablePointerVarDefn = ml_gen_mlds_var_decl(
- Var, Type, Initializer, GC_TraceCode,
- mlds__make_context(Context)),
- Defns = [TablePointerVarDefn | Defns0]
+ TablePointerVarDefn = ml_gen_mlds_var_decl(Var, Type, Initializer,
+ GC_TraceCode, mlds__make_context(Context)),
+ !:Defns = [TablePointerVarDefn | !.Defns]
;
- Defns = Defns0
+ true
).
% Return the declaration flags appropriate for a procedure definition.
@@ -1140,14 +1105,12 @@
proc_info_argmodes(ProcInfo, Modes),
proc_info_goal(ProcInfo, Goal0),
- %
- % The HLDS front-end sometimes over-estimates
- % the set of non-locals. We need to restrict
- % the set of non-locals for the top-level goal
- % to just the headvars, because otherwise variables
- % which occur in the top-level non-locals but which
- % are not really non-local will not be declared.
- %
+ % The HLDS front-end sometimes over-estimates the set of non-locals.
+ % We need to restrict the set of non-locals for the top-level goal
+ % to just the headvars, because otherwise variables which occur in the
+ % top-level non-locals but which are not really non-local will not be
+ % declared.
+
Goal0 = GoalExpr - GoalInfo0,
goal_info_get_code_gen_nonlocals(GoalInfo0, NonLocals0),
set__list_to_set(HeadVars, HeadVarsSet),
@@ -1157,48 +1120,47 @@
goal_info_get_context(GoalInfo, Context),
- Info0 = ml_gen_info_init(ModuleInfo, PredId, ProcId),
+ some [!Info] (
+ !:Info = ml_gen_info_init(ModuleInfo, PredId, ProcId),
( ImportStatus = external(_) ->
- %
- % For Mercury procedures declared `:- external', we generate
- % an MLDS definition for them with no function body.
- % The MLDS -> target code pass can treat this accordingly,
- % e.g. for C it outputs a function declaration with no
- % corresponding definition, making sure that the function
- % is declared as `extern' rather than `static'.
+ % For Mercury procedures declared `:- external', we generate an
+ % MLDS definition for them with no function body. The MLDS ->
+ % target code pass can treat this accordingly, e.g. for C
+ % it outputs a function declaration with no corresponding
+ % definition, making sure that the function is declared as `extern'
+ % rather than `static'.
%
FunctionBody = external,
ExtraDefns = [],
- ml_gen_proc_params(PredId, ProcId, MLDS_Params, Info0, _Info)
+ ml_gen_proc_params(PredId, ProcId, MLDS_Params, !.Info, _Info)
;
% Set up the initial success continuation, if any.
- % Also figure out which output variables are returned by
- % value (rather than being passed by reference) and remove
- % them from the byref_output_vars field in the ml_gen_info.
+ % Also figure out which output variables are returned by value
+ % (rather than being passed by reference) and remove them from
+ % the byref_output_vars field in the ml_gen_info.
( CodeModel = model_non ->
- ml_set_up_initial_succ_cont(ModuleInfo,
- CopiedOutputVars, Info0, Info1)
+ ml_set_up_initial_succ_cont(ModuleInfo, CopiedOutputVars,
+ !Info)
;
- ml_det_copy_out_vars(ModuleInfo,
- CopiedOutputVars, Info0, Info1)
+ ml_det_copy_out_vars(ModuleInfo, CopiedOutputVars, !Info)
),
% This would generate all the local variables at the top of
% the function:
% ml_gen_all_local_var_decls(Goal,
- % VarSet, VarTypes, HeadVars, MLDS_LocalVars,
- % Info1, Info2)
+ % VarSet, VarTypes, HeadVars, MLDS_LocalVars, Info1, Info2)
% But instead we now generate them locally for each goal.
% We just declare the `succeeded' var here, plus locals
% for any output arguments that are returned by value
% (e.g. if --nondet-copy-out is enabled, or for det function
% return values).
- ( CopiedOutputVars = [] ->
- % optimize common case
- OutputVarLocals = [],
- Info2 = Info1
+ (
+ CopiedOutputVars = [],
+ % Optimize common case.
+ OutputVarLocals = []
;
+ CopiedOutputVars = [_ | _],
proc_info_varset(ProcInfo, VarSet),
proc_info_vartypes(ProcInfo, VarTypes),
% note that for headvars we must use the types from
@@ -1207,36 +1169,34 @@
ArgTypes),
ml_gen_local_var_decls(VarSet,
map__overlay(VarTypes, HeadVarTypes),
- Context, CopiedOutputVars, OutputVarLocals,
- Info1, Info2)
+ Context, CopiedOutputVars, OutputVarLocals, !Info)
),
MLDS_Context = mlds__make_context(Context),
MLDS_LocalVars = [ml_gen_succeeded_var_decl(MLDS_Context) |
OutputVarLocals],
modes_to_arg_modes(ModuleInfo, Modes, ArgTypes, ArgModes),
ml_gen_proc_body(CodeModel, HeadVars, ArgTypes, ArgModes,
- CopiedOutputVars, Goal, Decls0, Statements,
- Info2, Info3),
- ml_gen_proc_params(PredId, ProcId, MLDS_Params, Info3, Info),
- ml_gen_info_get_extra_defns(Info, ExtraDefns),
+ CopiedOutputVars, Goal, Decls0, Statements, !Info),
+ ml_gen_proc_params(PredId, ProcId, MLDS_Params, !Info),
+ ml_gen_info_get_extra_defns(!.Info, ExtraDefns),
Decls = list__append(MLDS_LocalVars, Decls0),
Statement = ml_gen_block(Decls, Statements, Context),
FunctionBody = defined_here(Statement)
+ )
),
pred_info_get_attributes(PredInfo, Attributes),
attributes_to_attribute_list(Attributes, AttributeList),
- MLDS_Attributes = attributes_to_mlds_attributes(ModuleInfo,
- AttributeList),
+ MLDS_Attributes = attributes_to_mlds_attributes(ModuleInfo, AttributeList),
- ProcDefnBody = mlds__function(yes(proc(PredId, ProcId)),
- MLDS_Params, FunctionBody, MLDS_Attributes).
+ ProcDefnBody = mlds__function(yes(proc(PredId, ProcId)), MLDS_Params,
+ FunctionBody, MLDS_Attributes).
- % for model_det and model_semi procedures,
- % figure out which output variables are returned by
- % value (rather than being passed by reference) and remove
- % them from the byref_output_vars field in the ml_gen_info.
+ % For model_det and model_semi procedures, figure out which output
+ % variables are returned by value (rather than being passed by reference)
+ % and remove them from the byref_output_vars field in the ml_gen_info.
+ %
:- pred ml_det_copy_out_vars(module_info::in, list(prog_var)::out,
ml_gen_info::in, ml_gen_info::out) is det.
@@ -1245,52 +1205,49 @@
module_info_globals(ModuleInfo, Globals),
globals__lookup_bool_option(Globals, det_copy_out, DetCopyOut),
(
- % if --det-copy-out is enabled, all output variables
- % are returned by value, rather than passing
- % them by reference.
+ % If --det-copy-out is enabled, all output variables are returned
+ % by value, rather than passing them by reference.
DetCopyOut = yes
->
ByRefOutputVars = [],
CopiedOutputVars = OutputVars
;
- % for det functions, the function result variable
- % is returned by value, and any remaining output
- % variables are passed by reference
+ % For det functions, the function result variable is returned by value,
+ % and any remaining output variables are passed by reference.
ml_gen_info_get_pred_id(!.Info, PredId),
ml_gen_info_get_proc_id(!.Info, ProcId),
- ml_is_output_det_function(ModuleInfo, PredId, ProcId,
- ResultVar)
+ ml_is_output_det_function(ModuleInfo, PredId, ProcId, ResultVar)
->
CopiedOutputVars = [ResultVar],
list__delete_all(OutputVars, ResultVar, ByRefOutputVars)
;
- % otherwise, all output vars are passed by reference
+ % Otherwise, all output vars are passed by reference.
CopiedOutputVars = [],
ByRefOutputVars = OutputVars
),
ml_gen_info_set_byref_output_vars(ByRefOutputVars, !Info),
ml_gen_info_set_value_output_vars(CopiedOutputVars, !Info).
- % for model_non procedures,
- % figure out which output variables are returned by
- % value (rather than being passed by reference) and remove
- % them from the byref_output_vars field in the ml_gen_info,
- % and construct the initial success continuation.
+ % For model_non procedures, figure out which output variables are returned
+ % by value (rather than being passed by reference) and remove them from
+ % the byref_output_vars field in the ml_gen_info, and construct the
+ % initial success continuation.
+ %
:- pred ml_set_up_initial_succ_cont(module_info::in, list(prog_var)::out,
ml_gen_info::in, ml_gen_info::out) is det.
ml_set_up_initial_succ_cont(ModuleInfo, NondetCopiedOutputVars, !Info) :-
module_info_globals(ModuleInfo, Globals),
- globals__lookup_bool_option(Globals, nondet_copy_out,
- NondetCopyOut),
- ( NondetCopyOut = yes ->
- % for --nondet-copy-out, we generate local variables
- % for the output variables and then pass them to the
- % continuation, rather than passing them by reference.
- ml_gen_info_get_byref_output_vars(!.Info,
- NondetCopiedOutputVars),
+ globals__lookup_bool_option(Globals, nondet_copy_out, NondetCopyOut),
+ (
+ NondetCopyOut = yes,
+ % For --nondet-copy-out, we generate local variables for the output
+ % variables and then pass them to the continuation, rather than
+ % passing them by reference.
+ ml_gen_info_get_byref_output_vars(!.Info, NondetCopiedOutputVars),
ml_gen_info_set_byref_output_vars([], !Info)
;
+ NondetCopyOut = no,
NondetCopiedOutputVars = []
),
ml_gen_info_set_value_output_vars(NondetCopiedOutputVars, !Info),
@@ -1302,9 +1259,8 @@
% Generate MLDS definitions for all the local variables in a function.
%
% Note that this function generates all the local variables at the
- % top of the function. It might be a better idea to instead
- % generate local declarations for all the variables used in
- % each sub-goal.
+ % top of the function. It might be a better idea to instead generate
+ % local declarations for all the variables used in each sub-goal.
%
:- pred ml_gen_all_local_var_decls(hlds_goal::in, prog_varset::in,
map(prog_var, prog_type)::in, list(prog_var)::in, mlds__defns::out,
@@ -1331,13 +1287,11 @@
map__lookup(VarTypes, Var, Type),
( type_util__is_dummy_argument_type(Type) ->
% no declaration needed for this variable
- ml_gen_local_var_decls(VarSet, VarTypes, Context, Vars,
- Defns, !Info)
+ ml_gen_local_var_decls(VarSet, VarTypes, Context, Vars, Defns, !Info)
;
VarName = ml_gen_var_name(VarSet, Var),
ml_gen_var_decl(VarName, Type, Context, Defn, !Info),
- ml_gen_local_var_decls(VarSet, VarTypes, Context, Vars,
- Defns0, !Info),
+ ml_gen_local_var_decls(VarSet, VarTypes, Context, Vars, Defns0, !Info),
Defns = [Defn | Defns0]
).
@@ -1353,12 +1307,9 @@
Goal = _ - GoalInfo,
goal_info_get_context(GoalInfo, Context),
- %
% First just generate the code for the procedure's goal.
- %
DoGenGoal = ml_gen_goal(CodeModel, Goal),
- %
% In certain cases -- for example existentially typed procedures,
% or unification/compare procedures for equivalence types --
% the parameters types may not match the types of the head variables.
@@ -1366,12 +1317,10 @@
% We also grab the original (uncast) lvals for the copied output
% variables (if any) here, since for the return statement that
% we append below, we want the original vars, not their cast versions.
- %
- ml_gen_var_list(!.Info, CopiedOutputVars,
- CopiedOutputVarOriginalLvals),
+
+ ml_gen_var_list(!.Info, CopiedOutputVars, CopiedOutputVarOriginalLvals),
ml_gen_convert_headvars(HeadVars, ArgTypes, ArgModes, CopiedOutputVars,
- Context, ConvDecls, ConvInputStatements, ConvOutputStatements,
- !Info),
+ Context, ConvDecls, ConvInputStatements, ConvOutputStatements, !Info),
(
ConvDecls = [],
ConvInputStatements = [],
@@ -1380,40 +1329,31 @@
% No boxing/unboxing/casting required.
DoGenGoal(Decls, Statements1, !Info)
;
- % Boxing/unboxing/casting required.
- % We need to convert the input arguments,
- % generate the goal, convert the output arguments,
+ % Boxing/unboxing/casting required. We need to convert the input
+ % arguments, generate the goal, convert the output arguments,
% and then succeeed.
DoConvOutputs = (pred(NewDecls::out, NewStatements::out,
Info0::in, Info::out) is det :-
- ml_gen_success(CodeModel, Context, SuccStatements,
- Info0, Info),
+ ml_gen_success(CodeModel, Context, SuccStatements, Info0, Info),
NewDecls = [],
- NewStatements = list__append(ConvOutputStatements,
- SuccStatements)
+ NewStatements = list__append(ConvOutputStatements, SuccStatements)
),
- ml_combine_conj(CodeModel, Context,
- DoGenGoal, DoConvOutputs,
+ ml_combine_conj(CodeModel, Context, DoGenGoal, DoConvOutputs,
Decls0, Statements0, !Info),
- Statements1 = list__append(ConvInputStatements,
- Statements0),
- Decls = list__append(ConvDecls, Decls0)
+ Statements1 = ConvInputStatements ++ Statements0,
+ Decls = ConvDecls ++ Decls0
),
- %
% Finally append an appropriate `return' statement, if needed.
- %
- ml_append_return_statement(!.Info, CodeModel,
- CopiedOutputVarOriginalLvals, Context,
- Statements1, Statements).
+ ml_append_return_statement(!.Info, CodeModel, CopiedOutputVarOriginalLvals,
+ Context, Statements1, Statements).
-%
-% In certain cases -- for example existentially typed procedures,
-% or unification/compare procedures for equivalence types --
-% the parameter types may not match the types of the head variables.
-% In such cases, we need to box/unbox/cast them to the right type.
-% This procedure handles that.
-%
+ % In certain cases -- for example existentially typed procedures,
+ % or unification/compare procedures for equivalence types --
+ % the parameter types may not match the types of the head variables.
+ % In such cases, we need to box/unbox/cast them to the right type.
+ % This procedure handles that.
+ %
:- pred ml_gen_convert_headvars(list(prog_var)::in, list(prog_type)::in,
list(arg_mode)::in, list(prog_var)::in, prog_context::in,
mlds__defns::out, mlds__statements::out, mlds__statements::out,
@@ -1422,7 +1362,6 @@
ml_gen_convert_headvars(Vars, HeadTypes, ArgModes, CopiedOutputVars, Context,
Decls, InputStatements, OutputStatements, !Info) :-
(
- % base case
Vars = [],
HeadTypes = [],
ArgModes = []
@@ -1431,96 +1370,66 @@
InputStatements = [],
OutputStatements = []
;
- % recursive case
Vars = [Var | Vars1],
HeadTypes = [HeadType | HeadTypes1],
ArgModes = [ArgMode | ArgModes1]
->
ml_variable_type(!.Info, Var, BodyType),
(
- %
- % Arguments with mode `top_unused' do not need
- % to be converted
- %
+ % Arguments with mode `top_unused' do not need to be converted.
ArgMode = top_unused
->
- % just recursively process the remaining arguments
ml_gen_convert_headvars(Vars1, HeadTypes1, ArgModes1,
CopiedOutputVars, Context, Decls,
InputStatements, OutputStatements, !Info)
;
- %
% Check whether HeadType is the same as BodyType
- % (modulo the term__contexts).
- % If so, no conversion is needed.
- %
+ % (modulo the term__contexts). If so, no conversion is needed.
map__init(Subst0),
type_unify(HeadType, BodyType, [], Subst0, Subst),
map__is_empty(Subst)
->
- % just recursively process the remaining arguments
ml_gen_convert_headvars(Vars1, HeadTypes1, ArgModes1,
CopiedOutputVars, Context, Decls,
InputStatements, OutputStatements, !Info)
;
- %
- % generate the lval for the head variable
- %
- ml_gen_var_with_type(!.Info, Var, HeadType,
- HeadVarLval),
+ % Generate the lval for the head variable.
+ ml_gen_var_with_type(!.Info, Var, HeadType, HeadVarLval),
- %
- % generate code to box or unbox that head variable,
- % to convert its type from HeadType to BodyType
- %
+ % Generate code to box or unbox that head variable,
+ % to convert its type from HeadType to BodyType.
ml_gen_info_get_varset(!.Info, VarSet),
VarName = ml_gen_var_name(VarSet, Var),
- ml_gen_box_or_unbox_lval(HeadType, BodyType,
- HeadVarLval, VarName, Context, no, 0, BodyLval,
- ConvDecls, ConvInputStatements,
+ ml_gen_box_or_unbox_lval(HeadType, BodyType, HeadVarLval, VarName,
+ Context, no, 0, BodyLval, ConvDecls, ConvInputStatements,
ConvOutputStatements, !Info),
- %
- % Ensure that for any uses of this variable in the
- % procedure body, we use the BodyLval (which has type
- % BodyType) rather than the HeadVarLval (which has
- % type HeadType).
- %
+ % Ensure that for any uses of this variable in the procedure body,
+ % we use the BodyLval (which has type BodyType) rather than the
+ % HeadVarLval (which has type HeadType).
ml_gen_info_set_var_lval(Var, BodyLval, !Info),
- %
- % Recursively process the remaining arguments
- %
ml_gen_convert_headvars(Vars1, HeadTypes1, ArgModes1,
CopiedOutputVars, Context, Decls1,
InputStatements1, OutputStatements1, !Info),
- %
% Add the code to convert this input or output.
- %
- ml_gen_info_get_byref_output_vars(!.Info,
- ByRefOutputVars),
+ ml_gen_info_get_byref_output_vars(!.Info, ByRefOutputVars),
(
( list__member(Var, ByRefOutputVars)
; list__member(Var, CopiedOutputVars)
)
->
InputStatements = InputStatements1,
- OutputStatements =
- list__append(OutputStatements1,
- ConvOutputStatements)
- ;
- InputStatements =
- list__append(ConvInputStatements,
- InputStatements1),
+ OutputStatements = OutputStatements1 ++ ConvOutputStatements
+ ;
+ InputStatements = ConvInputStatements ++ InputStatements1,
OutputStatements = OutputStatements1
),
list__append(ConvDecls, Decls1, Decls)
)
;
- % neither base case nor recursive case matched
- unexpected(this_file,
- "ml_gen_convert_headvars: length mismatch")
+ unexpected(this_file, "ml_gen_convert_headvars: length mismatch")
).
%-----------------------------------------------------------------------------%
@@ -1528,9 +1437,9 @@
% Stuff to generate code for goals.
%
- % Generate MLDS code for the specified goal in the
- % specified code model. Return the result as a single statement
- % (which may be a block statement containing nested declarations).
+ % Generate MLDS code for the specified goal in the specified code model.
+ % Return the result as a single statement (which may be a block statement
+ % containing nested declarations).
%
ml_gen_goal(CodeModel, Goal, Statement, !Info) :-
ml_gen_goal(CodeModel, Goal, Decls, Statements, !Info),
@@ -1538,26 +1447,22 @@
goal_info_get_context(GoalInfo, Context),
Statement = ml_gen_block(Decls, Statements, Context).
- % Generate MLDS code for the specified goal in the
- % specified code model. Return the result as two lists,
- % one containing the necessary declarations and the other
- % containing the generated statements.
+ % Generate MLDS code for the specified goal in the specified code model.
+ % Return the result as two lists, one containing the necessary declarations
+ % and the other containing the generated statements.
%
ml_gen_goal(CodeModel, Goal, Decls, Statements, !Info) :-
Goal = GoalExpr - GoalInfo,
goal_info_get_context(GoalInfo, Context),
- %
- % Generate the local variables for this goal.
- % We need to declare any variables which
- % are local to this goal (including its subgoals),
- % but which are not local to a subgoal.
- % (If they're local to a subgoal, they'll be declared
- % when we generate code for that subgoal.)
- %
- % We need to make sure that we declare any type_info or
- % type_classinfo variables *before* any other variables,
- % since the GC tracing code for the other variables may
- % refer to the type_info variables, so they need to be in scope.
+ % Generate the local variables for this goal. We need to declare any
+ % variables which are local to this goal (including its subgoals),
+ % but which are not local to a subgoal. (If they're local to a subgoal,
+ % they'll be declared when we generate code for that subgoal.)
+ %
+ % We need to make sure that we declare any type_info or type_classinfo
+ % variables *before* any other variables, since the GC tracing code
+ % for the other variables may refer to the type_info variables, so they
+ % need to be in scope.
Locals = goal_local_vars(Goal),
SubGoalLocals = union_of_direct_subgoal_locals(Goal),
@@ -1569,17 +1474,13 @@
ml_gen_local_var_decls(VarSet, VarTypes, Context, VarsList, VarDecls,
!Info),
- %
% Generate code for the goal in its own code model.
- %
goal_info_get_code_model(GoalInfo, GoalCodeModel),
ml_gen_goal_expr(GoalExpr, GoalCodeModel, Context,
GoalDecls, GoalStatements0, !Info),
- %
- % Add whatever wrapper is needed to convert the goal's
- % code model to the desired code model.
- %
+ % Add whatever wrapper is needed to convert the goal's code model
+ % to the desired code model.
ml_gen_wrap_goal(CodeModel, GoalCodeModel, Context,
GoalStatements0, GoalStatements, !Info),
@@ -1588,12 +1489,13 @@
% Return the set of variables which occur in the specified goal
% (including in its subgoals) and which are local to that goal.
+ %
:- func goal_local_vars(hlds_goal) = set(prog_var).
goal_local_vars(Goal) = LocalVars :-
- % find all the variables in the goal
+ % Find all the variables in the goal.
goal_util__goal_vars(Goal, GoalVars),
- % delete the non-locals
+ % Delete the non-locals.
Goal = _ - GoalInfo,
goal_info_get_code_gen_nonlocals(GoalInfo, NonLocalVars),
set__difference(GoalVars, NonLocalVars, LocalVars).
@@ -1614,28 +1516,16 @@
SubGoalLocals = goal_local_vars(SubGoal),
set__union(UnionOfSubGoalLocals0, SubGoalLocals, UnionOfSubGoalLocals).
- % ml_gen_wrap_goal(OuterCodeModel, InnerCodeModel, Context,
- % Statements0, Statements):
- %
- % OuterCodeModel is the code model expected by the
- % context in which a goal is called. InnerCodeModel
- % is the code model which the goal actually has.
- % This predicate converts the code generated for
- % the goal using InnerCodeModel into code that uses
- % the calling convention appropriate for OuterCodeModel.
-
- %
- % If the inner and outer code models are equal,
- % we don't need to do anything special.
+ % If the inner and outer code models are equal, we don't need to do
+ % anything special.
ml_gen_wrap_goal(model_det, model_det, _, !Statements, !Info).
ml_gen_wrap_goal(model_semi, model_semi, _, !Statements, !Info).
ml_gen_wrap_goal(model_non, model_non, _, !Statements, !Info).
- % If the inner code model is more precise than the outer code
- % model, then we need to append some statements to convert
- % the calling convention for the inner code model to that of
- % the outer code model.
+ % If the inner code model is more precise than the outer code model,
+ % then we need to append some statements to convert the calling convention
+ % for the inner code model to that of the outer code model.
ml_gen_wrap_goal(model_semi, model_det, Context, !Statements, !Info) :-
%
@@ -1680,11 +1570,14 @@
% to indicate that a commit is needed.
ml_gen_wrap_goal(model_det, model_semi, _, _, _, !Info) :-
- error("ml_gen_wrap_goal: code model mismatch -- semi in det").
+ unexpected(this_file,
+ "ml_gen_wrap_goal: code model mismatch -- semi in det").
ml_gen_wrap_goal(model_det, model_non, _, _, _, !Info) :-
- error("ml_gen_wrap_goal: code model mismatch -- nondet in det").
+ unexpected(this_file,
+ "ml_gen_wrap_goal: code model mismatch -- nondet in det").
ml_gen_wrap_goal(model_semi, model_non, _, _, _, !Info) :-
- error("ml_gen_wrap_goal: code model mismatch -- nondet in semi").
+ unexpected(this_file,
+ "ml_gen_wrap_goal: code model mismatch -- nondet in semi").
% Generate code for a commit.
%
@@ -1738,66 +1631,52 @@
% commit_func();
% #endif
- ml_gen_maybe_make_locals_for_output_args(GoalInfo,
- LocalVarDecls, CopyLocalsToOutputArgs,
- OrigVarLvalMap, !Info),
-
- % generate the `success()' function
- ml_gen_new_func_label(no, SuccessFuncLabel,
- SuccessFuncLabelRval, !Info),
- /* push nesting level */
+ ml_gen_maybe_make_locals_for_output_args(GoalInfo, LocalVarDecls,
+ CopyLocalsToOutputArgs, OrigVarLvalMap, !Info),
+
+ % Generate the `success()' function.
+ ml_gen_new_func_label(no, SuccessFuncLabel, SuccessFuncLabelRval,
+ !Info),
+ % push nesting level
MLDS_Context = mlds__make_context(Context),
ml_gen_info_new_commit_label(CommitLabelNum, !Info),
CommitRef = mlds__var_name(string__format("commit_%d",
[i(CommitLabelNum)]), no),
- ml_gen_var_lval(!.Info, CommitRef, mlds__commit_type,
- CommitRefLval),
- CommitRefDecl = ml_gen_commit_var_decl(MLDS_Context,
- CommitRef),
+ ml_gen_var_lval(!.Info, CommitRef, mlds__commit_type, CommitRefLval),
+ CommitRefDecl = ml_gen_commit_var_decl(MLDS_Context, CommitRef),
DoCommitStmt = do_commit(lval(CommitRefLval)),
- DoCommitStatement =
- mlds__statement(DoCommitStmt, MLDS_Context),
- /* pop nesting level */
+ DoCommitStatement = mlds__statement(DoCommitStmt, MLDS_Context),
+ % pop nesting level
ml_gen_nondet_label_func(!.Info, SuccessFuncLabel, Context,
DoCommitStatement, SuccessFunc),
ml_get_env_ptr(!.Info, EnvPtrRval),
- SuccessCont = success_cont(SuccessFuncLabelRval,
- EnvPtrRval, [], []),
+ SuccessCont = success_cont(SuccessFuncLabelRval, EnvPtrRval, [], []),
ml_gen_info_push_success_cont(SuccessCont, !Info),
ml_gen_goal(model_non, Goal, GoalDecls, GoalStatements, !Info),
- % hoist any static constant declarations for Goal
- % out to the top level
+ % Hoist any static constant declarations for Goal out to the top level.
list__filter(ml_decl_is_static_const, GoalDecls,
GoalStaticDecls, GoalOtherDecls),
- GoalStatement = ml_gen_block(GoalOtherDecls,
- GoalStatements, GoalContext),
+ GoalStatement = ml_gen_block(GoalOtherDecls, GoalStatements,
+ GoalContext),
ml_gen_info_pop_success_cont(!Info),
- ml_gen_set_success(!.Info, const(false), Context,
- SetSuccessFalse),
- ml_gen_set_success(!.Info, const(true), Context,
- SetSuccessTrue),
+ ml_gen_set_success(!.Info, const(false), Context, SetSuccessFalse),
+ ml_gen_set_success(!.Info, const(true), Context, SetSuccessTrue),
TryCommitStmt = try_commit(CommitRefLval,
- ml_gen_block([], [GoalStatement, SetSuccessFalse],
- Context),
+ ml_gen_block([], [GoalStatement, SetSuccessFalse], Context),
ml_gen_block([], list__append(CopyLocalsToOutputArgs,
[SetSuccessTrue]), Context)),
- TryCommitStatement = mlds__statement(TryCommitStmt,
- MLDS_Context),
- CommitFuncLocalDecls = [CommitRefDecl, SuccessFunc |
- GoalStaticDecls],
+ TryCommitStatement = mlds__statement(TryCommitStmt, MLDS_Context),
+ CommitFuncLocalDecls = [CommitRefDecl, SuccessFunc | GoalStaticDecls],
maybe_put_commit_in_own_func(CommitFuncLocalDecls,
- [TryCommitStatement], Context,
- CommitFuncDecls, Statements, !Info),
+ [TryCommitStatement], Context, CommitFuncDecls, Statements, !Info),
Decls = LocalVarDecls ++ CommitFuncDecls,
ml_gen_info_set_var_lvals(OrigVarLvalMap, !Info)
-
;
GoalCodeModel = model_non,
CodeModel = model_det
->
-
% model_non in det context: (using try_commit/do_commit)
% <do Goal>
% ===>
@@ -1829,93 +1708,80 @@
% commit_func();
% #endif
- ml_gen_maybe_make_locals_for_output_args(GoalInfo,
- LocalVarDecls, CopyLocalsToOutputArgs,
- OrigVarLvalMap, !Info),
-
- % generate the `success()' function
- ml_gen_new_func_label(no,
- SuccessFuncLabel, SuccessFuncLabelRval, !Info),
- /* push nesting level */
+ ml_gen_maybe_make_locals_for_output_args(GoalInfo, LocalVarDecls,
+ CopyLocalsToOutputArgs, OrigVarLvalMap, !Info),
+
+ % Generate the `success()' function.
+ ml_gen_new_func_label(no, SuccessFuncLabel, SuccessFuncLabelRval,
+ !Info),
+ % push nesting level
MLDS_Context = mlds__make_context(Context),
ml_gen_info_new_commit_label(CommitLabelNum, !Info),
CommitRef = mlds__var_name(
- string__format("commit_%d", [i(CommitLabelNum)]),
- no),
- ml_gen_var_lval(!.Info, CommitRef, mlds__commit_type,
- CommitRefLval),
- CommitRefDecl = ml_gen_commit_var_decl(MLDS_Context,
- CommitRef),
+ string__format("commit_%d", [i(CommitLabelNum)]), no),
+ ml_gen_var_lval(!.Info, CommitRef, mlds__commit_type, CommitRefLval),
+ CommitRefDecl = ml_gen_commit_var_decl(MLDS_Context, CommitRef),
DoCommitStmt = do_commit(lval(CommitRefLval)),
- DoCommitStatement = mlds__statement(DoCommitStmt,
- MLDS_Context),
- /* pop nesting level */
+ DoCommitStatement = mlds__statement(DoCommitStmt, MLDS_Context),
+ % pop nesting level
ml_gen_nondet_label_func(!.Info, SuccessFuncLabel, Context,
DoCommitStatement, SuccessFunc),
ml_get_env_ptr(!.Info, EnvPtrRval),
- SuccessCont = success_cont(SuccessFuncLabelRval,
- EnvPtrRval, [], []),
+ SuccessCont = success_cont(SuccessFuncLabelRval, EnvPtrRval, [], []),
ml_gen_info_push_success_cont(SuccessCont, !Info),
ml_gen_goal(model_non, Goal, GoalDecls, GoalStatements, !Info),
- % hoist any static constant declarations for Goal
- % out to the top level
+ % Hoist any static constant declarations for Goal out to the top level.
list__filter(ml_decl_is_static_const, GoalDecls,
GoalStaticDecls, GoalOtherDecls),
- GoalStatement = ml_gen_block(GoalOtherDecls,
- GoalStatements, GoalContext),
+ GoalStatement = ml_gen_block(GoalOtherDecls, GoalStatements,
+ GoalContext),
ml_gen_info_pop_success_cont(!Info),
TryCommitStmt = try_commit(CommitRefLval, GoalStatement,
ml_gen_block([], CopyLocalsToOutputArgs, Context)),
- TryCommitStatement = mlds__statement(TryCommitStmt,
- MLDS_Context),
- CommitFuncLocalDecls = [CommitRefDecl, SuccessFunc |
- GoalStaticDecls],
+ TryCommitStatement = mlds__statement(TryCommitStmt, MLDS_Context),
+ CommitFuncLocalDecls = [CommitRefDecl, SuccessFunc | GoalStaticDecls],
maybe_put_commit_in_own_func(CommitFuncLocalDecls,
- [TryCommitStatement], Context,
- CommitFuncDecls, Statements, !Info),
+ [TryCommitStatement], Context, CommitFuncDecls, Statements, !Info),
Decls = LocalVarDecls ++ CommitFuncDecls,
ml_gen_info_set_var_lvals(OrigVarLvalMap, !Info)
;
- % no commit required
+ % No commit required.
ml_gen_goal(CodeModel, Goal, Decls, Statements, !Info)
).
% maybe_put_commit_in_own_func(Defns0, Stmts0, Defns, Stmts):
- % if the --put-commit-in-own-func option is set, put
- % the commit in its own function. This is needed for
- % the high-level C back-end, to handle problems with
- % setjmp()/longjmp() clobbering non-volatile local variables.
+ %
+ % If the --put-commit-in-own-func option is set, put the commit in its
+ % own function. This is needed for the high-level C back-end, to handle
+ % problems with setjmp()/longjmp() clobbering non-volatile local variables.
%
% Detailed explanation:
%
% For the high-level C back-end, we implement commits using
- % setjmp()/longjmp(). Unfortunately for us, ANSI/ISO C says
- % that longjmp() is allowed to clobber the values of any
- % non-volatile local variables in the function that called
- % setjmp() which have been modified between the setjmp()
- % and the longjmp().
- %
- % To avoid this, whenever we generate a commit, we put
- % it in its own nested function, with the local variables
- % (e.g. `succeeded', plus any outputs from the goal that
- % we're committing over) remaining in the containing function.
- % This ensures that none of the variables which get modified
- % between the setjmp() and the longjmp() and which get
- % referenced after the longjmp() are local variables in the
- % function containing the setjmp().
- %
- % [The obvious alternative of declaring the local variables in
- % the function containing setjmp() as `volatile' doesn't work,
- % since the assignments to those output variables may be deep
- % in some function called indirectly from the goal that we're
- % committing across, and assigning to a volatile-qualified
- % variable via a non-volatile pointer is undefined behaviour.
- % The only way to make it work would be to be to declare
- % *every* output argument that we pass by reference as
- % `volatile T *'. But that would impose distributed fat and
- % would make interoperability difficult.]
+ % setjmp()/longjmp(). Unfortunately for us, ANSI/ISO C says that longjmp()
+ % is allowed to clobber the values of any non-volatile local variables
+ % in the function that called setjmp() which have been modified between
+ % the setjmp() and the longjmp().
+ %
+ % To avoid this, whenever we generate a commit, we put it in its own
+ % nested function, with the local variables (e.g. `succeeded', plus any
+ % outputs from the goal that we're committing over) remaining in the
+ % containing function. This ensures that none of the variables which
+ % get modified between the setjmp() and the longjmp() and which get
+ % referenced after the longjmp() are local variables in the function
+ % containing the setjmp().
+ %
+ % [The obvious alternative of declaring the local variables in the function
+ % containing setjmp() as `volatile' doesn't work, since the assignments
+ % to those output variables may be deep in some function called indirectly
+ % from the goal that we're committing across, and assigning to a
+ % volatile-qualified variable via a non-volatile pointer is undefined
+ % behaviour. The only way to make it work would be to be to declare
+ % *every* output argument that we pass by reference as `volatile T *'.
+ % But that would impose distributed fat and would make interoperability
+ % difficult.]
%
:- pred maybe_put_commit_in_own_func(mlds__defns::in, mlds__statements::in,
prog_context::in, mlds__defns::out, mlds__statements::out,
@@ -1924,27 +1790,27 @@
maybe_put_commit_in_own_func(CommitFuncLocalDecls, TryCommitStatements,
Context, Decls, Statements, !Info) :-
ml_gen_info_put_commit_in_own_func(!.Info, PutCommitInOwnFunc),
- ( PutCommitInOwnFunc = yes ->
- %
+ (
+ PutCommitInOwnFunc = yes,
+
% Generate the `void commit_func() { ... }' wrapper
% around the main body that we generated above
- %
- ml_gen_new_func_label(no, CommitFuncLabel,
- CommitFuncLabelRval, !Info),
- /* push nesting level */
+ ml_gen_new_func_label(no, CommitFuncLabel, CommitFuncLabelRval, !Info),
+ % push nesting level
CommitFuncBody = ml_gen_block(CommitFuncLocalDecls,
TryCommitStatements, Context),
- /* pop nesting level */
+ % pop nesting level
ml_gen_nondet_label_func(!.Info, CommitFuncLabel, Context,
CommitFuncBody, CommitFunc),
- %
+
% Generate the call to `commit_func();'
- %
ml_gen_info_use_gcc_nested_functions(!.Info, UseNestedFuncs),
- ( UseNestedFuncs = yes ->
+ (
+ UseNestedFuncs = yes,
ArgRvals = [],
ArgTypes = []
;
+ UseNestedFuncs = no,
ml_get_env_ptr(!.Info, EnvPtrRval),
ArgRvals = [EnvPtrRval],
ArgTypes = [mlds__generic_env_ptr_type]
@@ -1952,26 +1818,24 @@
RetTypes = [],
Signature = mlds__func_signature(ArgTypes, RetTypes),
CallKind = ordinary_call,
- CallStmt = call(Signature, CommitFuncLabelRval, no,
- ArgRvals, [], CallKind),
- CallStatement = mlds__statement(CallStmt,
- mlds__make_context(Context)),
- % Package it all up
+ CallStmt = call(Signature, CommitFuncLabelRval, no, ArgRvals, [],
+ CallKind),
+ CallStatement = mlds__statement(CallStmt, mlds__make_context(Context)),
+ % Package it all up.
Statements = [CallStatement],
Decls = [CommitFunc]
;
+ PutCommitInOwnFunc = no,
Statements = TryCommitStatements,
Decls = CommitFuncLocalDecls
).
- %
- % In commits, you have model_non code called from a model_det or
- % model_semi context. With --nondet-copy-out, when generating code
- % for commits, if the context is a model_det or model_semi procedure
- % with output arguments passed by reference, then we need to introduce
- % local variables corresponding to those output arguments,
- % and at the end of the commit we'll copy the local variables into
- % the output arguments.
+ % In commits, you have model_non code called from a model_det or model_semi
+ % context. With --nondet-copy-out, when generating code for commits,
+ % if the context is a model_det or model_semi procedure with output
+ % arguments passed by reference, then we need to introduce local variables
+ % corresponding to those output arguments, and at the end of the commit
+ % we'll copy the local variables into the output arguments.
%
:- pred ml_gen_maybe_make_locals_for_output_args(hlds_goal_info::in,
mlds__defns::out, mlds__statements::out,
@@ -1982,18 +1846,18 @@
CopyLocalsToOutputArgs, OrigVarLvalMap, !Info) :-
ml_gen_info_get_var_lvals(!.Info, OrigVarLvalMap),
ml_gen_info_get_globals(!.Info, Globals),
- globals__lookup_bool_option(Globals, nondet_copy_out,
- NondetCopyOut),
- ( NondetCopyOut = yes ->
+ globals__lookup_bool_option(Globals, nondet_copy_out, NondetCopyOut),
+ (
+ NondetCopyOut = yes,
goal_info_get_context(GoalInfo, Context),
goal_info_get_nonlocals(GoalInfo, NonLocals),
ml_gen_info_get_byref_output_vars(!.Info, ByRefOutputVars),
VarsToCopy = set__intersect(set__list_to_set(ByRefOutputVars),
NonLocals),
- ml_gen_make_locals_for_output_args(
- set__to_sorted_list(VarsToCopy), Context,
- LocalVarDecls, CopyLocalsToOutputArgs, !Info)
+ ml_gen_make_locals_for_output_args(set__to_sorted_list(VarsToCopy),
+ Context, LocalVarDecls, CopyLocalsToOutputArgs, !Info)
;
+ NondetCopyOut = no,
LocalVarDecls = [],
CopyLocalsToOutputArgs = []
).
@@ -2005,8 +1869,8 @@
ml_gen_make_locals_for_output_args([], _, [], [], !Info).
ml_gen_make_locals_for_output_args([Var | Vars], Context,
LocalDefns, Assigns, !Info) :-
- ml_gen_make_locals_for_output_args(Vars, Context,
- LocalDefns0, Assigns0, !Info),
+ ml_gen_make_locals_for_output_args(Vars, Context, LocalDefns0, Assigns0,
+ !Info),
ml_variable_type(!.Info, Var, Type),
( type_util__is_dummy_argument_type(Type) ->
LocalDefns = LocalDefns0,
@@ -2024,13 +1888,10 @@
ml_gen_make_local_for_output_arg(OutputVar, Type, Context,
LocalVarDefn, Assign, !Info) :-
- %
- % Look up the name of the output variable
- %
+ % Look up the name of the output variable.
ml_gen_info_get_varset(!.Info, VarSet),
OutputVarName = ml_gen_var_name(VarSet, OutputVar),
- %
% Generate a declaration for a corresponding local variable.
OutputVarName = mlds__var_name(OutputVarNameStr, MaybeNum),
LocalVarName = mlds__var_name(
@@ -2041,19 +1902,15 @@
LocalVarDefn = ml_gen_mlds_var_decl(var(LocalVarName), MLDS_Type,
GC_TraceCode, mlds__make_context(Context)),
- %
- % Generate code to assign from the local var to the output var
- %
+ % Generate code to assign from the local var to the output var.
ml_gen_var(!.Info, OutputVar, OutputVarLval),
ml_gen_var_lval(!.Info, LocalVarName, MLDS_Type, LocalVarLval),
Assign = ml_gen_assign(OutputVarLval, lval(LocalVarLval), Context),
- %
- % Update the lval for this variable so that any references to it
- % inside the commit refer to the local variable rather than
- % to the output argument.
- % (Note that we reset all the var lvals at the end of the commit.)
- %
+ % Update the lval for this variable so that any references to it inside
+ % the commit refer to the local variable rather than to the output
+ % argument. (Note that we reset all the var lvals at the end of the
+ % commit.)
ml_gen_info_set_var_lval(OutputVar, LocalVarLval, !Info).
% Generate the declaration for the `commit' variable.
@@ -2080,8 +1937,7 @@
ml_gen_goal_expr(if_then_else(_Vars, Cond, Then, Else),
CodeModel, Context, Decls, Statements, !Info) :-
- ml_gen_ite(CodeModel, Cond, Then, Else, Context,
- Decls, Statements, !Info).
+ ml_gen_ite(CodeModel, Cond, Then, Else, Context, Decls, Statements, !Info).
ml_gen_goal_expr(not(Goal), CodeModel, Context,
Decls, Statements, !Info) :-
@@ -2097,10 +1953,8 @@
ml_gen_goal_expr(par_conj(Goals), CodeModel, Context,
Decls, Statements, !Info) :-
- %
% XXX currently we treat parallel conjunction the same as
% sequential conjunction -- parallelism is not yet implemented
- %
ml_gen_conj(Goals, CodeModel, Context, Decls, Statements, !Info).
ml_gen_goal_expr(generic_call(GenericCall, Vars, Modes, Detism), CodeModel,
@@ -2127,12 +1981,11 @@
ml_gen_goal_expr(unify(_LHS, _RHS, _Mode, Unification, _UnifyContext),
CodeModel, Context, Decls, Statements, !Info) :-
- ml_gen_unification(Unification, CodeModel, Context,
- Decls, Statements, !Info).
+ ml_gen_unification(Unification, CodeModel, Context, Decls, Statements,
+ !Info).
ml_gen_goal_expr(foreign_proc(Attributes, PredId, ProcId, Args, ExtraArgs,
- PragmaImpl), CodeModel, OuterContext, Decls, Statements,
- !Info) :-
+ PragmaImpl), CodeModel, OuterContext, Decls, Statements, !Info) :-
(
PragmaImpl = ordinary(ForeignCode, MaybeContext),
(
@@ -2168,14 +2021,10 @@
ml_gen_goal_expr(shorthand(_), _, _, _, _, !Info) :-
% these should have been expanded out by now
- error("ml_gen_goal_expr: unexpected shorthand").
-
-% :- module ml_foreign.
-%
-% ml_foreign creates MLDS code to execute foreign language code.
-%
-%
+ unexpected(this_file, "ml_gen_goal_expr: unexpected shorthand").
+ % ml_foreign creates MLDS code to execute foreign language code.
+ %
:- pred ml_gen_nondet_pragma_foreign_proc(code_model::in,
pragma_foreign_proc_attributes::in,
pred_id::in, proc_id::in, list(foreign_arg)::in,
@@ -2228,13 +2077,12 @@
% }
% #undef MR_PROC_LABEL
%
- % We insert a #define for MR_PROC_LABEL, so that the C code in
- % the Mercury standard library that allocates memory manually
- % can use MR_PROC_LABEL as the procname argument to
- % incr_hp_msg(), for memory profiling. Hard-coding the procname
- % argument in the C code would be wrong, since it wouldn't
- % handle the case where the original pragma c_code procedure
- % gets inlined and optimized away. Of course we also need to
+ % We insert a #define for MR_PROC_LABEL, so that the C code in the Mercury
+ % standard library that allocates memory manually can use MR_PROC_LABEL
+ % as the procname argument to incr_hp_msg(), for memory profiling.
+ % Hard-coding the procname argument in the C code would be wrong,
+ % since it wouldn't handle the case where the original pragma foreign_proc
+ % procedure gets inlined and optimized away. Of course we also need to
% #undef it afterwards.
%
ml_gen_nondet_pragma_foreign_proc(CodeModel, Attributes, PredId, _ProcId,
@@ -2248,9 +2096,8 @@
;
true
),
- %
+
% Generate <declaration of one local variable for each arg>
- %
ml_gen_pragma_c_decls(!.Info, Lang, Args, ArgDeclsList),
%
@@ -2270,32 +2117,22 @@
" #undef LOCALS\n"
], HashUndefs),
- %
% Generate code to set the values of the input variables.
- %
ml_gen_pragma_c_input_arg_list(Lang, Args, AssignInputsList, !Info),
- %
% Generate code to assign the values of the output variables.
- %
ml_gen_pragma_c_output_arg_list(Lang, Args, Context,
AssignOutputsList, ConvDecls, ConvStatements, !Info),
- %
- % Generate code fragments to obtain and release the global lock
- %
+ % Generate code fragments to obtain and release the global lock.
ThreadSafe = thread_safe(Attributes),
ml_gen_obtain_release_global_lock(!.Info, ThreadSafe, PredId,
ObtainLock, ReleaseLock),
- %
- % Generate the MR_PROC_LABEL #define
- %
+ % Generate the MR_PROC_LABEL #define.
ml_gen_hash_define_mr_proc_label(!.Info, HashDefine),
- %
- % Put it all together
- %
+ % Put it all together.
Starting_C_Code = list__condense([
[raw_target_code("{\n", [])],
HashDefine,
@@ -2328,21 +2165,20 @@
globals__get_target(Globals, Target),
( CodeModel = model_non ->
- % For IL code, we can't call continutations because there is
- % no syntax for calling managed function pointers in
- % managed C++. Instead we have to call back into IL and make
- % the continuation call in IL. This is called an "indirect"
- % success continuation call.
+ % For IL code, we can't call continutations because there is no syntax
+ % for calling managed function pointers in managed C++. Instead we have
+ % to call back into IL and make the continuation call in IL. This is
+ % called an "indirect" success continuation call.
( Target = il ->
- ml_gen_call_current_success_cont_indirectly(Context,
- CallCont, !Info)
- ;
- ml_gen_call_current_success_cont(Context, CallCont,
+ ml_gen_call_current_success_cont_indirectly(Context, CallCont,
!Info)
+ ;
+ ml_gen_call_current_success_cont(Context, CallCont, !Info)
)
;
- error("ml_gen_nondet_pragma_c_code: unexpected code model")
+ unexpected(this_file,
+ "ml_gen_nondet_pragma_c_code: unexpected code model")
),
Ending_C_Code = [
raw_target_code("\t\t}\n", []),
@@ -2378,8 +2214,7 @@
ml_gen_info::in, ml_gen_info::out) is det.
ml_gen_ordinary_pragma_foreign_proc(CodeModel, Attributes, PredId, ProcId,
- Args, ExtraArgs, Foreign_Code, Context, Decls, Statements,
- !Info) :-
+ Args, ExtraArgs, Foreign_Code, Context, Decls, Statements, !Info) :-
Lang = foreign_language(Attributes),
(
CodeModel = model_det,
@@ -2401,8 +2236,8 @@
OrdinaryDespiteDetism = ordinary_despite_detism(Attributes),
(
OrdinaryDespiteDetism = no,
- error("ml_gen_ordinary_pragma_foreign_proc: " ++
- "unexpected code model")
+ unexpected(this_file,
+ "ml_gen_ordinary_pragma_foreign_proc: unexpected code model")
;
OrdinaryDespiteDetism = yes,
OrdinaryKind = kind_semi
@@ -2444,31 +2279,25 @@
ml_gen_info::in, ml_gen_info::out) is det.
ml_gen_ordinary_pragma_java_proc(_CodeModel, Attributes, _PredId, _ProcId,
- Args, ExtraArgs, JavaCode, Context, Decls, Statements,
- !Info) :-
+ Args, ExtraArgs, JavaCode, Context, Decls, Statements, !Info) :-
Lang = foreign_language(Attributes),
- %
+
% Generate <declaration of one local variable for each arg>
- %
ml_gen_pragma_c_decls(!.Info, Lang, Args, ArgDeclsList),
require(unify(ExtraArgs, []),
"ml_gen_ordinary_pragma_java_proc: extra args"),
- %
+
% Generate code to set the values of the input variables.
- %
ml_gen_pragma_c_input_arg_list(Lang, Args, AssignInputsList, !Info),
- %
- % Generate MLDS statements to assign the values of the output
- % variables.
- %
+
+ % Generate MLDS statements to assign the values of the output variables.
ml_gen_pragma_java_output_arg_list(Lang, Args, Context,
AssignOutputsList, ConvDecls, ConvStatements, !Info),
- %
+
% Put it all together
% XXX FIXME need to handle model_semi code here,
% i.e. provide some equivalent to SUCCESS_INDICATOR.
- %
Java_Code = list__condense([
ArgDeclsList,
AssignInputsList,
@@ -2493,7 +2322,7 @@
% For ordinary (not model_non) pragma foreign_code in C# or MC++,
% we generate a call to an out-of-line procedure that contains
% the user's code.
-
+ %
:- pred ml_gen_ordinary_pragma_managed_proc(ordinary_pragma_kind::in,
pragma_foreign_proc_attributes::in, pred_id::in, proc_id::in,
list(foreign_arg)::in, list(foreign_arg)::in, string::in,
@@ -2501,8 +2330,7 @@
ml_gen_info::in, ml_gen_info::out) is det.
ml_gen_ordinary_pragma_managed_proc(OrdinaryKind, Attributes, _PredId, _ProcId,
- Args, ExtraArgs, ForeignCode, Context, Decls, Statements,
- !Info) :-
+ Args, ExtraArgs, ForeignCode, Context, Decls, Statements, !Info) :-
ml_gen_outline_args(Args, OutlineArgs, !Info),
require(unify(ExtraArgs, []),
@@ -2541,7 +2369,8 @@
SuccessIndicatorStatements = [SuccessIndicatorStatement]
;
OrdinaryKind = kind_failure,
- error("ml_gen_ordinary_pragma_managed_proc: " ++
+ unexpected(this_file,
+ "ml_gen_ordinary_pragma_managed_proc: " ++
"kind_failure not yet implemented")
),
@@ -2567,11 +2396,14 @@
\+ var_is_singleton(ArgName)
->
mode_to_arg_mode(ModuleInfo, Mode, OrigType, ArgMode),
- ( ArgMode = top_in,
+ (
+ ArgMode = top_in,
OutlineArg = in(MldsType, ArgName, lval(VarLval))
- ; ArgMode = top_out,
+ ;
+ ArgMode = top_out,
OutlineArg = out(MldsType, ArgName, VarLval)
- ; ArgMode = top_unused,
+ ;
+ ArgMode = top_unused,
OutlineArg = unused
)
;
@@ -2585,8 +2417,7 @@
ml_gen_info::in, ml_gen_info::out) is det.
ml_gen_ordinary_pragma_il_proc(_CodeModel, Attributes, PredId, ProcId,
- Args, ExtraArgs, ForeignCode, Context, Decls, Statements,
- !Info) :-
+ Args, ExtraArgs, ForeignCode, Context, Decls, Statements, !Info) :-
require(unify(ExtraArgs, []),
"ml_gen_ordinary_pragma_managed_proc: extra args"),
@@ -2620,19 +2451,19 @@
build_arg_map(Args, map__init, ArgMap),
- % Generate statements to assign by-ref output arguments
+ % Generate statements to assign by-ref output arguments.
list__filter_map(ml_gen_pragma_il_proc_assign_output(ModuleInfo,
MLDSModuleName, ArgMap, VarSet, Context, yes),
ByRefOutputVars, ByRefAssignStatements),
- % Generate statements to assign copied output arguments
+ % Generate statements to assign copied output arguments.
list__filter_map(ml_gen_pragma_il_proc_assign_output(ModuleInfo,
MLDSModuleName, ArgMap, VarSet, Context, no),
CopiedOutputVars, CopiedOutputStatements),
ArgVars = list__map(foreign_arg_var, Args),
- % Generate declarations for all the variables, and
- % initializers for input variables.
+ % Generate declarations for all the variables, and initializers for
+ % input variables.
list__map(ml_gen_pragma_il_proc_var_decl_defn(ModuleInfo,
MLDSModuleName, ArgMap, VarSet, MLDSContext,
ByRefOutputVars, CopiedOutputVars),
@@ -2646,8 +2477,7 @@
ILCodeFragment = mlds__statement(atomic(OutlineStmt), MLDSContext),
Statements = [statement(block(VarLocals,
- [ILCodeFragment] ++ ByRefAssignStatements
- ++ CopiedOutputStatements),
+ [ILCodeFragment] ++ ByRefAssignStatements ++ CopiedOutputStatements),
mlds__make_context(Context))],
Decls = [].
@@ -2676,8 +2506,7 @@
QualVarName = qual(MLDSModuleName, module_qual, VarName),
(
IsByRef = yes,
- OutputVarLval = mem_ref(lval(var(QualVarName, MLDSType)),
- MLDSType)
+ OutputVarLval = mem_ref(lval(var(QualVarName, MLDSType)), MLDSType)
;
IsByRef = no,
OutputVarLval = var(QualVarName, MLDSType)
@@ -2700,15 +2529,16 @@
map__lookup(ArgMap, Var, ForeignArg),
ForeignArg = foreign_arg(_, MaybeNameMode, Type),
VarName = ml_gen_var_name(VarSet, Var),
- ( MaybeNameMode = yes(UserVarNameString - _) ->
+ (
+ MaybeNameMode = yes(UserVarNameString - _),
NonMangledVarName = mlds__var_name(UserVarNameString, no)
;
+ MaybeNameMode = no,
sorry(this_file, "no variable name for var")
),
- % Dummy arguments are just mapped to integers,
- % since they shouldn't be used in any
- % way that requires them to have a real value.
+ % Dummy arguments are just mapped to integers, since they shouldn't be
+ % used in any way that requires them to have a real value.
( type_util__is_dummy_argument_type(Type) ->
Initializer = no_initializer,
MLDSType = mlds__native_int_type
@@ -2719,11 +2549,9 @@
Initializer = no_initializer,
MLDSType = mercury_type_to_mlds_type(ModuleInfo, Type)
;
- MLDSType = mercury_type_to_mlds_type(
- ModuleInfo, Type),
+ MLDSType = mercury_type_to_mlds_type(ModuleInfo, Type),
QualVarName = qual(MLDSModuleName, module_qual, VarName),
- Initializer = init_obj(
- lval(var(QualVarName, MLDSType)))
+ Initializer = init_obj(lval(var(QualVarName, MLDSType)))
),
% XXX Accurate GC is not supported for IL foreign code;
% this would only be useful if interfacing to
@@ -2797,43 +2625,30 @@
ml_gen_info::in, ml_gen_info::out) is det.
ml_gen_ordinary_pragma_c_proc(OrdinaryKind, Attributes, PredId, _ProcId,
- OrigArgs, ExtraArgs, C_Code, Context, Decls, Statements,
- !Info) :-
+ OrigArgs, ExtraArgs, C_Code, Context, Decls, Statements, !Info) :-
Lang = foreign_language(Attributes),
- %
% Generate <declaration of one local variable for each arg>
- %
list__append(OrigArgs, ExtraArgs, Args),
ml_gen_pragma_c_decls(!.Info, Lang, Args, ArgDeclsList),
- %
% Generate code to set the values of the input variables.
- %
ml_gen_pragma_c_input_arg_list(Lang, Args, AssignInputsList, !Info),
- %
% Generate code to assign the values of the output variables.
- %
ml_gen_pragma_c_output_arg_list(Lang, Args, Context,
AssignOutputsList, ConvDecls, ConvStatements, !Info),
- %
- % Generate code fragments to obtain and release the global lock
- %
+ % Generate code fragments to obtain and release the global lock.
ThreadSafe = thread_safe(Attributes),
ml_gen_obtain_release_global_lock(!.Info, ThreadSafe, PredId,
ObtainLock, ReleaseLock),
- %
- % Generate the MR_PROC_LABEL #define
- %
+ % Generate the MR_PROC_LABEL #define.
ml_gen_hash_define_mr_proc_label(!.Info, HashDefine),
- %
- % Put it all together
- %
+ % Put it all together.
(
OrdinaryKind = kind_det,
Starting_C_Code = list__condense([
@@ -2916,8 +2731,7 @@
Decls = ConvDecls.
% Generate code fragments to obtain and release the global lock
- % (this is used for ensuring thread safety in a concurrent
- % implementation)
+ % (this is used for ensuring thread safety in a concurrent implementation).
%
:- pred ml_gen_obtain_release_global_lock(ml_gen_info::in, thread_safe::in,
pred_id::in, string::out, string::out) is det.
@@ -2956,8 +2770,7 @@
ml_gen_info_get_proc_id(Info, ProcId),
ml_gen_proc_label(ModuleInfo, PredId, ProcId, Name, Module),
HashDefine = [raw_target_code("#define MR_PROC_LABEL ", []),
- name(qual(Module, module_qual, Name)),
- raw_target_code("\n", [])].
+ name(qual(Module, module_qual, Name)), raw_target_code("\n", [])].
:- func get_target_code_attributes(foreign_language,
pragma_foreign_proc_extra_attributes) = target_code_attributes.
@@ -2974,9 +2787,9 @@
%---------------------------------------------------------------------------%
-% ml_gen_pragma_c_decls generates C code to declare the arguments
-% for a `pragma foreign_proc' declaration.
-%
+ % ml_gen_pragma_c_decls generates C code to declare the arguments
+ % for a `pragma foreign_proc' declaration.
+ %
:- pred ml_gen_pragma_c_decls(ml_gen_info::in, foreign_language::in,
list(foreign_arg)::in, list(target_code_component)::out) is det.
@@ -2988,9 +2801,9 @@
ml_gen_pragma_c_decl(Info, Lang, Arg, Decl),
ml_gen_pragma_c_decls(Info, Lang, Args, Decls).
-% ml_gen_pragma_c_decl generates C code to declare an argument
-% of a `pragma foreign_proc' declaration.
-%
+ % ml_gen_pragma_c_decl generates C code to declare an argument
+ % of a `pragma foreign_proc' declaration.
+ %
:- pred ml_gen_pragma_c_decl(ml_gen_info::in, foreign_language::in,
foreign_arg::in, target_code_component::out) is det.
@@ -3002,26 +2815,25 @@
\+ var_is_singleton(ArgName)
->
TypeString = foreign__to_type_string(Lang, ModuleInfo, Type),
- string__format("\t%s %s;\n", [s(TypeString), s(ArgName)],
- DeclString)
+ string__format("\t%s %s;\n", [s(TypeString), s(ArgName)], DeclString)
;
- % if the variable doesn't occur in the ArgNames list,
- % it can't be used, so we just ignore it
+ % If the variable doesn't occur in the ArgNames list,
+ % it can't be used, so we just ignore it.
DeclString = ""
),
Decl = raw_target_code(DeclString, []).
%-----------------------------------------------------------------------------%
-% var_is_singleton determines whether or not a given pragma_c variable
-% is singleton (i.e. starts with an underscore)
-%
-% Singleton vars should be ignored when generating the declarations for
-% pragma_c arguments because:
-%
-% - they should not appear in the C code
-% - they could clash with the system name space
-%
+ % var_is_singleton determines whether or not a given foreign_proc variable
+ % is singleton (i.e. starts with an underscore)
+ %
+ % Singleton vars should be ignored when generating the declarations for
+ % foreign_proc arguments because:
+ %
+ % - they should not appear in the C code
+ % - they could clash with the system name space
+ %
:- pred var_is_singleton(string::in) is semidet.
var_is_singleton(Name) :-
@@ -3029,8 +2841,8 @@
%-----------------------------------------------------------------------------%
- % XXX Maybe this ought to be renamed as it works for, and
- % is used by the Java back-end as well.
+ % XXX Maybe this ought to be renamed as it works for, and is used
+ % by the Java back-end as well.
%
:- pred ml_gen_pragma_c_input_arg_list(foreign_language::in,
list(foreign_arg)::in, list(target_code_component)::out,
@@ -3073,20 +2885,18 @@
ml_variable_type(!.Info, Var, VarType),
ml_gen_var(!.Info, Var, VarLval),
( type_util__is_dummy_argument_type(VarType) ->
- % The variable may not have been declared, so we need
- % to generate a dummy value for it. Using `0' here
- % is more efficient than using private_builtin__dummy_var,
- % which is what ml_gen_var will have generated for this
- % variable.
+ % The variable may not have been declared, so we need to generate
+ % a dummy value for it. Using `0' here is more efficient than using
+ % private_builtin__dummy_var, which is what ml_gen_var will have
+ % generated for this variable.
ArgRval = const(int_const(0))
;
ml_gen_box_or_unbox_rval(VarType, OrigType, lval(VarLval),
ArgRval, !Info)
),
- % At this point we have an rval with the right type for
- % *internal* use in the code generated by the Mercury
- % compiler's MLDS back-end. We need to convert this to
- % the appropriate type to use for the C interface.
+ % At this point we have an rval with the right type for *internal* use
+ % in the code generated by the Mercury compiler's MLDS back-end. We need
+ % to convert this to the appropriate type to use for the C interface.
ml_gen_info_get_module_info(!.Info, ModuleInfo),
ExportedType = foreign__to_exported_type(ModuleInfo, OrigType),
TypeString = foreign__to_type_string(Lang, ExportedType),
@@ -3106,43 +2916,32 @@
MaybeCast = yes("(" ++ TypeString ++ ") ")
)
->
- % In the usual case, we can just use an assignment
- % and perhaps a cast.
+ % In the usual case, we can just use an assignment and perhaps a cast.
module_info_globals(ModuleInfo, Globals),
- globals__lookup_bool_option(Globals, highlevel_data,
- HighLevelData),
+ globals__lookup_bool_option(Globals, highlevel_data, HighLevelData),
(
HighLevelData = yes,
- % In general, the types used for the C
- % interface are not the same as the types
- % used by --high-level-data, so we always
- % use a cast here.
- % (Strictly speaking the cast is not needed for
- % a few cases like `int', but it doesn't do
- % any harm.)
+ % In general, the types used for the C interface are not the same
+ % as the types used by --high-level-data, so we always use a cast
+ % here. (Strictly speaking the cast is not needed for a few cases
+ % like `int', but it doesn't do any harm.)
string__format("(%s)", [s(TypeString)], Cast)
;
HighLevelData = no,
- % For --no-high-level-data, we only need to use
- % a cast is for polymorphic types, which are
- % `Word' in the C interface but `MR_Box' in the
- % MLDS back-end.
- % Except for MC++, where polymorphic types are MR_Box,
- % but we get here only if Lang is c or java.
- (
- OrigType = variable(_, _)
- ->
+ % For --no-high-level-data, we only need to use a cast is for
+ % polymorphic types, which are `Word' in the C interface but
+ % `MR_Box' in the MLDS back-end. Except for MC++, where
+ % polymorphic types are MR_Box, but we get here only if Lang
+ % is c or java.
+ ( OrigType = variable(_, _) ->
Cast = "(MR_Word) "
- ;
- MaybeCast = yes(CastPrime)
- ->
+ ; MaybeCast = yes(CastPrime) ->
Cast = CastPrime
;
Cast = ""
)
),
- string__format("\t%s = %s\n", [s(ArgName), s(Cast)],
- AssignToArgName),
+ string__format("\t%s = %s\n", [s(ArgName), s(Cast)], AssignToArgName),
AssignInput = [
raw_target_code(AssignToArgName, []),
target_code_input(ArgRval),
@@ -3176,10 +2975,9 @@
ConvDecls = ConvDecls1 ++ ConvDecls2,
ConvStatements = ConvStatements1 ++ ConvStatements2.
-% ml_gen_pragma_java_output_arg generates MLDS statements to
-% assign the value of an output arg for a `pragma foreign_proc'
-% declaration.
-%
+ % ml_gen_pragma_java_output_arg generates MLDS statements to assign the
+ % value of an output arg for a `pragma foreign_proc' declaration.
+ %
:- pred ml_gen_pragma_java_output_arg(foreign_language::in,
foreign_arg::in, prog_context::in, mlds__statements::out,
mlds__defns::out, mlds__statements::out,
@@ -3195,18 +2993,16 @@
not type_util__is_dummy_argument_type(OrigType),
mode_to_arg_mode(ModuleInfo, Mode, OrigType, top_out)
->
- % Create a target lval with the right type for *internal*
- % use in the code generated by the Mercury compiler's
- % MLDS back-end.
+ % Create a target lval with the right type for *internal* use in the
+ % code generated by the Mercury compiler's MLDS back-end.
ml_variable_type(!.Info, Var, VarType),
ml_gen_var(!.Info, Var, VarLval),
ml_gen_box_or_unbox_lval(VarType, OrigType, VarLval,
mlds__var_name(ArgName, no), Context, no, 0,
ArgLval, ConvDecls, _ConvInputStatements,
ConvOutputStatements, !Info),
- % This is the MLDS type of the original argument, which
- % we need to cast the local (Java) representation of
- % the argument back to.
+ % This is the MLDS type of the original argument, which we need to
+ % cast the local (Java) representation of the argument back to.
MLDSType = mercury_type_to_mlds_type(ModuleInfo, OrigType),
% Construct an MLDS lval for the local Java representation
% of the argument.
@@ -3221,12 +3017,12 @@
% as an mlds__type.
LocalVarLval = var(QualLocalVarName, MLDSType),
% We cast this variable back to the corresponding
- % MLDS type before assigning it to the lval
+ % MLDS type before assigning it to the lval.
Rval = unop(cast(MLDSType), lval(LocalVarLval)),
AssignOutput = [ml_gen_assign(ArgLval, Rval, Context)]
;
- % if the variable doesn't occur in the ArgNames list,
- % it can't be used, so we just ignore it
+ % If the variable doesn't occur in the ArgNames list,
+ % it can't be used, so we just ignore it.
AssignOutput = [],
ConvDecls = [],
ConvOutputStatements = []
@@ -3248,17 +3044,16 @@
ConvDecls = list__append(ConvDecls1, ConvDecls2),
ConvStatements = list__append(ConvStatements1, ConvStatements2).
-% ml_gen_pragma_c_output_arg generates C code to assign the value of an output
-% arg for a `pragma foreign_proc' declaration.
-%
+ % ml_gen_pragma_c_output_arg generates C code to assign the value of
+ % an output arg for a `pragma foreign_proc' declaration.
+ %
:- pred ml_gen_pragma_c_output_arg(foreign_language::in, foreign_arg::in,
prog_context::in, list(target_code_component)::out,
mlds__defns::out, mlds__statements::out,
ml_gen_info::in, ml_gen_info::out) is det.
ml_gen_pragma_c_output_arg(Lang, foreign_arg(Var, MaybeNameAndMode, OrigType),
- Context, AssignOutput, ConvDecls, ConvOutputStatements,
- !Info) :-
+ Context, AssignOutput, ConvDecls, ConvOutputStatements, !Info) :-
ml_gen_info_get_module_info(!.Info, ModuleInfo),
(
MaybeNameAndMode = yes(ArgName - Mode),
@@ -3267,11 +3062,10 @@
mode_to_arg_mode(ModuleInfo, Mode, OrigType, top_out)
->
ml_gen_pragma_c_gen_output_arg(Lang, Var, ArgName, OrigType,
- Context, AssignOutput, ConvDecls, ConvOutputStatements,
- !Info)
+ Context, AssignOutput, ConvDecls, ConvOutputStatements, !Info)
;
- % if the variable doesn't occur in the ArgNames list,
- % it can't be used, so we just ignore it
+ % If the variable doesn't occur in the ArgNames list,
+ % it can't be used, so we just ignore it.
AssignOutput = [],
ConvDecls = [],
ConvOutputStatements = []
@@ -3287,13 +3081,11 @@
ml_variable_type(!.Info, Var, VarType),
ml_gen_var(!.Info, Var, VarLval),
ml_gen_box_or_unbox_lval(VarType, OrigType, VarLval,
- mlds__var_name(ArgName, no), Context, no, 0,
- ArgLval, ConvDecls, _ConvInputStatements,
- ConvOutputStatements, !Info),
- % At this point we have an lval with the right type for
- % *internal* use in the code generated by the Mercury
- % compiler's MLDS back-end. We need to convert this to
- % the appropriate type to use for the C interface.
+ mlds__var_name(ArgName, no), Context, no, 0, ArgLval,
+ ConvDecls, _ConvInputStatements, ConvOutputStatements, !Info),
+ % At this point we have an lval with the right type for *internal* use
+ % in the code generated by the Mercury compiler's MLDS back-end. We need
+ % to convert this to the appropriate type to use for the C interface.
ml_gen_info_get_module_info(!.Info, ModuleInfo),
ExportedType = foreign__to_exported_type(ModuleInfo, OrigType),
TypeString = foreign__to_type_string(Lang, ExportedType),
@@ -3321,22 +3113,19 @@
HighLevelData),
(
HighLevelData = yes,
- % In general, the types used for the C interface
- % are not the same as the types used by
- % --high-level-data, so we always use a cast here.
- % (Strictly speaking the cast is not needed for
- % a few cases like `int', but it doesn't do any harm.)
- % Note that we can't easily obtain the type string
- % for the RHS of the assignment, so instead we cast
- % the LHS.
+ % In general, the types used for the C interface are not the same
+ % as the types used by --high-level-data, so we always use a cast
+ % here. (Strictly speaking the cast is not needed for a few cases
+ % like `int', but it doesn't do any harm.) Note that we can't
+ % easily obtain the type string for the RHS of the assignment,
+ % so instead we cast the LHS.
string__format("*(%s *)&", [s(TypeString)], LHS_Cast),
RHS_Cast = ""
;
HighLevelData = no,
- % For --no-high-level-data, we only need to use
- % a cast is for polymorphic types, which are
- % `Word' in the C interface but `MR_Box' in the
- % MLDS back-end.
+ % For --no-high-level-data, we only need to use a cast is for
+ % polymorphic types, which are `Word' in the C interface but
+ % `MR_Box' in the MLDS back-end.
(
( OrigType = variable(_, _)
; Cast = yes
@@ -3348,8 +3137,8 @@
),
LHS_Cast = ""
),
- string__format(" = %s%s;\n", [s(RHS_Cast),
- s(ArgName)], AssignFromArgName),
+ string__format(" = %s%s;\n", [s(RHS_Cast), s(ArgName)],
+ AssignFromArgName),
string__format("\t%s\n", [s(LHS_Cast)], AssignTo),
AssignOutput = [
raw_target_code(AssignTo, []),
@@ -3360,15 +3149,12 @@
% For foreign types, we need to call MR_MAYBE_BOX_FOREIGN_TYPE.
AssignOutput = [
raw_target_code("\tMR_MAYBE_BOX_FOREIGN_TYPE("
- ++ TypeString ++ ", " ++ ArgName ++
- ", ", []),
+ ++ TypeString ++ ", " ++ ArgName ++ ", ", []),
target_code_output(ArgLval),
raw_target_code(");\n", [])
]
).
-% :- end_module ml_foreign.
-
%-----------------------------------------------------------------------------%
%
% Code for if-then-else
@@ -3387,6 +3173,7 @@
% ===>
% <Cond>
% <Then>
+
CondCodeModel = model_det,
ml_gen_goal(model_det, Cond, CondStatement, !Info),
ml_gen_goal(CodeModel, Then, ThenStatement, !Info),
@@ -3404,26 +3191,21 @@
% } else {
% <Else>
% }
+
CondCodeModel = model_semi,
ml_gen_goal(model_semi, Cond, CondDecls, CondStatements, !Info),
ml_gen_test_success(!.Info, Succeeded),
ml_gen_goal(CodeModel, Then, ThenStatement, !Info),
ml_gen_goal(CodeModel, Else, ElseStatement, !Info),
- IfStmt = if_then_else(Succeeded, ThenStatement,
- yes(ElseStatement)),
- IfStatement = mlds__statement(IfStmt,
- mlds__make_context(Context)),
+ IfStmt = if_then_else(Succeeded, ThenStatement, yes(ElseStatement)),
+ IfStatement = mlds__statement(IfStmt, mlds__make_context(Context)),
Decls = CondDecls,
- Statements = list__append(CondStatements,
- [IfStatement])
+ Statements = CondStatements ++ [IfStatement]
;
- % /*
- % ** XXX The following transformation does not do as
- % ** good a job of GC as it could. Ideally we ought
- % ** to ensure that stuff used only in the `Else' part
- % ** will be reclaimed if a GC occurs during the `Then'
- % ** part. But that is a bit tricky to achieve.
- % */
+ % XXX The following transformation does not do as good a job of GC
+ % as it could. Ideally we ought to ensure that stuff used only
+ % in the `Else' part will be reclaimed if a GC occurs during the `Then'
+ % part. But that is a bit tricky to achieve.
%
% model_non cond:
% <(Cond -> Then ; Else)>
@@ -3440,56 +3222,53 @@
% if (!cond_<N>) {
% <Else>
% }
- % except that we hoist any declarations generated
- % for <Cond> to the top of the scope, so that they
- % are in scope for the <Then> goal
- % (this is needed for declarations of static consts)
+ %
+ % except that we hoist any declarations generated for <Cond> to the top
+ % of the scope, so that they are in scope for the <Then> goal (this
+ % is needed for declarations of static consts)
CondCodeModel = model_non,
- % generate the `cond_<N>' var and the code to initialize it to false
+ % Generate the `cond_<N>' var and the code to initialize it to false.
ml_gen_info_new_cond_var(CondVar, !Info),
MLDS_Context = mlds__make_context(Context),
CondVarDecl = ml_gen_cond_var_decl(CondVar, MLDS_Context),
ml_gen_set_cond_var(!.Info, CondVar, const(false), Context,
SetCondFalse),
- % allocate a name for the `then_func'
- ml_gen_new_func_label(no, ThenFuncLabel, ThenFuncLabelRval,
- !Info),
+ % Allocate a name for the `then_func'.
+ ml_gen_new_func_label(no, ThenFuncLabel, ThenFuncLabelRval, !Info),
- % generate <Cond && then_func()>
+ % Generate <Cond && then_func()>.
ml_get_env_ptr(!.Info, EnvPtrRval),
- SuccessCont = success_cont(ThenFuncLabelRval, EnvPtrRval,
- [], []),
+ SuccessCont = success_cont(ThenFuncLabelRval, EnvPtrRval, [], []),
ml_gen_info_push_success_cont(SuccessCont, !Info),
ml_gen_goal(model_non, Cond, CondDecls, CondStatements, !Info),
ml_gen_info_pop_success_cont(!Info),
- % generate the `then_func'
- /* push nesting level */
+ % Generate the `then_func'.
+ % push nesting level
Then = _ - ThenGoalInfo,
goal_info_get_context(ThenGoalInfo, ThenContext),
ml_gen_set_cond_var(!.Info, CondVar, const(true), ThenContext,
SetCondTrue),
ml_gen_goal(CodeModel, Then, ThenStatement, !Info),
- ThenFuncBody = ml_gen_block([],
- [SetCondTrue, ThenStatement], ThenContext),
- /* pop nesting level */
+ ThenFuncBody = ml_gen_block([], [SetCondTrue, ThenStatement],
+ ThenContext),
+ % pop nesting level
ml_gen_nondet_label_func(!.Info, ThenFuncLabel, ThenContext,
ThenFuncBody, ThenFunc),
- % generate `if (!cond_<N>) { <Else> }'
+ % Generate `if (!cond_<N>) { <Else> }'.
ml_gen_test_cond_var(!.Info, CondVar, CondSucceeded),
ml_gen_goal(CodeModel, Else, ElseStatement, !Info),
IfStmt = if_then_else(unop(std_unop(not), CondSucceeded),
ElseStatement, no),
IfStatement = mlds__statement(IfStmt, MLDS_Context),
- % package it all up in the right order
- Decls = list__append([CondVarDecl | CondDecls], [ThenFunc]),
- Statements = list__append(
- [SetCondFalse | CondStatements], [IfStatement])
+ % Package it all up in the right order.
+ Decls = [CondVarDecl | CondDecls] ++ [ThenFunc],
+ Statements = [SetCondFalse | CondStatements] ++ [IfStatement]
).
%-----------------------------------------------------------------------------%
@@ -3514,6 +3293,7 @@
% /* now ignore the value of succeeded,
% which we know will be MR_FALSE */
% }
+
CodeModel = model_det,
ml_gen_goal(model_semi, Cond, Decls, Statements, !Info)
;
@@ -3522,10 +3302,10 @@
% ===>
% <do Goal>
% succeeded = MR_FALSE;
+
CodeModel = model_semi, CondCodeModel = model_det,
ml_gen_goal(model_det, Cond, CondDecls, CondStatements, !Info),
- ml_gen_set_success(!.Info, const(false), Context,
- SetSuccessFalse),
+ ml_gen_set_success(!.Info, const(false), Context, SetSuccessFalse),
Decls = CondDecls,
Statements = list__append(CondStatements, [SetSuccessFalse])
;
@@ -3534,9 +3314,9 @@
% ===>
% <succeeded = Goal>
% succeeded = !succeeded;
+
CodeModel = model_semi, CondCodeModel = model_semi,
- ml_gen_goal(model_semi, Cond, CondDecls, CondStatements,
- !Info),
+ ml_gen_goal(model_semi, Cond, CondDecls, CondStatements, !Info),
ml_gen_test_success(!.Info, Succeeded),
ml_gen_set_success(!.Info, unop(std_unop(not), Succeeded),
Context, InvertSuccess),
@@ -3544,10 +3324,10 @@
Statements = list__append(CondStatements, [InvertSuccess])
;
CodeModel = model_semi, CondCodeModel = model_non,
- error("ml_gen_negation: nondet cond")
+ unexpected(this_file, "ml_gen_negation: nondet cond")
;
CodeModel = model_non,
- error("ml_gen_negation: nondet negation")
+ unexpected(this_file, "ml_gen_negation: nondet negation")
).
%-----------------------------------------------------------------------------%
@@ -3587,54 +3367,45 @@
mlds__defns::out, mlds__statements::out,
ml_gen_info::in, ml_gen_info::out) is det.
- %
- % handle empty disjunctions (a.ka. `fail')
- %
ml_gen_disj([], CodeModel, Context, [], Statements, !Info) :-
+ % Handle empty disjunctions (a.ka. `fail').
ml_gen_failure(CodeModel, Context, Statements, !Info).
- %
- % handle singleton disjunctions
- % (the HLDS should not contain singleton disjunctions,
- % but this code is needed to handle recursive calls to ml_gen_disj)
- % Note that each arm of the model_non disjunction is placed into
- % a block. This avoids a problem where ml_join_decls can create
- % block nesting proportional to the size of the disjunction.
- % The nesting can hit fixed limit problems in some C compilers.
- %
ml_gen_disj([SingleGoal], CodeModel, Context, [], [Statement], !Info) :-
+ % Handle singleton disjunctions.
+ % (The HLDS should not contain singleton disjunctions, but this code
+ % is needed to handle recursive calls to ml_gen_disj).
+ % Note that each arm of the model_non disjunction is placed into a block.
+ % This avoids a problem where ml_join_decls can create block nesting
+ % proportional to the size of the disjunction. The nesting can hit fixed
+ % limit problems in some C compilers.
ml_gen_goal(CodeModel, SingleGoal, Goal_Decls, Goal_Statements, !Info),
Statement = ml_gen_block(Goal_Decls, Goal_Statements, Context).
ml_gen_disj([First | Rest], CodeModel, Context, Decls, Statements, !Info) :-
Rest = [_ | _],
( CodeModel = model_non ->
- %
% model_non disj:
%
% <(Goal ; Goals) && SUCCEED()>
% ===>
% <Goal && SUCCEED()>
% <Goals && SUCCEED()>
- %
- ml_gen_goal(model_non, First, FirstDecls, FirstStatements,
- !Info),
- ml_gen_disj(Rest, model_non, Context,
- RestDecls, RestStatements, !Info),
+ ml_gen_goal(model_non, First, FirstDecls, FirstStatements, !Info),
+ ml_gen_disj(Rest, model_non, Context, RestDecls, RestStatements,
+ !Info),
(
- RestDecls = []
- ->
- FirstBlock = ml_gen_block(FirstDecls,
- FirstStatements, Context),
+ RestDecls = [],
+ FirstBlock = ml_gen_block(FirstDecls, FirstStatements, Context),
Decls = [],
Statements = [FirstBlock | RestStatements]
;
- error("ml_gen_disj: RestDecls not empty.")
+ RestDecls = [_ | _],
+ unexpected(this_file, "ml_gen_disj: RestDecls not empty.")
)
- ; /* CodeModel is model_det or model_semi */
- %
+ ;
% model_det/model_semi disj:
%
% model_det goal:
@@ -3654,7 +3425,7 @@
% <Goals>;
% }
% }
- %
+
First = _ - FirstGoalInfo,
goal_info_get_code_model(FirstGoalInfo, FirstCodeModel),
(
@@ -3662,24 +3433,20 @@
ml_gen_goal(model_det, First, Decls, Statements, !Info)
;
FirstCodeModel = model_semi,
- ml_gen_goal(model_semi, First,
- FirstDecls, FirstStatements, !Info),
+ ml_gen_goal(model_semi, First, FirstDecls, FirstStatements, !Info),
ml_gen_test_success(!.Info, Succeeded),
ml_gen_disj(Rest, CodeModel, Context,
RestDecls, RestStatements, !Info),
- RestStatement = ml_gen_block(RestDecls,
- RestStatements, Context),
+ RestStatement = ml_gen_block(RestDecls, RestStatements, Context),
IfStmt = if_then_else(unop(std_unop(not), Succeeded),
RestStatement, no),
- IfStatement = mlds__statement(IfStmt,
- mlds__make_context(Context)),
+ IfStatement = mlds__statement(IfStmt, mlds__make_context(Context)),
Decls = FirstDecls,
- Statements = list__append(FirstStatements,
- [IfStatement])
+ Statements = FirstStatements ++ [IfStatement]
;
FirstCodeModel = model_non,
- % simplify.m should get wrap commits around these
- error("model_non disj in model_det disjunction")
+ % simplify.m should get wrap commits around these.
+ unexpected(this_file, "model_non disj in model_det disjunction")
)
).
Index: compiler/ml_code_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/ml_code_util.m,v
retrieving revision 1.92
diff -u -b -r1.92 ml_code_util.m
--- compiler/ml_code_util.m 12 Sep 2005 05:24:13 -0000 1.92
+++ compiler/ml_code_util.m 12 Sep 2005 13:21:53 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 1999-2005 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -36,9 +38,9 @@
%
% Generate an MLDS assignment statement.
+ %
:- func ml_gen_assign(mlds__lval, mlds__rval, prog_context) = mlds__statement.
- %
% Append an appropriate `return' statement for the given code_model
% and returning the given lvals, if needed.
%
@@ -53,30 +55,26 @@
:- func ml_gen_block(mlds__defns, mlds__statements, prog_context)
= mlds__statement.
- % ml_join_decls:
- % Join two statement lists and their corresponding
- % declaration lists in sequence.
- %
- % If the statements have no declarations in common,
- % then their corresponding declaration lists will be
- % concatenated together into a single list of declarations.
- % But if they have any declarations in common, then we
- % put each statement list and its declarations into
- % a block, so that the declarations remain local to
- % each statement list.
+ % Join two statement lists and their corresponding declaration lists
+ % in sequence.
+ %
+ % If the statements have no declarations in common, then their
+ % corresponding declaration lists will be concatenated together into
+ % a single list of declarations. But if they have any declarations
+ % in common, then we put each statement list and its declarations into
+ % a block, so that the declarations remain local to each statement list.
%
:- pred ml_join_decls(mlds__defns::in, mlds__statements::in,
mlds__defns::in, mlds__statements::in, prog_context::in,
mlds__defns::out, mlds__statements::out) is det.
- % ml_combine_conj:
- % Given closures to generate code for two conjuncts,
- % generate code for their conjunction.
-
:- type gen_pred == pred(mlds__defns, mlds__statements,
ml_gen_info, ml_gen_info).
:- inst gen_pred == (pred(out, out, in, out) is det).
+ % Given closures to generate code for two conjuncts, generate code
+ % for their conjunction.
+ %
:- pred ml_combine_conj(code_model::in, prog_context::in,
gen_pred::in(gen_pred), gen_pred::in(gen_pred),
mlds__defns::out, mlds__statements::out,
@@ -97,11 +95,9 @@
mlds__func_params::in, prog_context::in, mlds__statement::in,
mlds__defn::out) is det.
- %
- % Test to see if the procedure is
- % a model_det function whose function result has an output mode
- % (whose type is not a dummy argument type like io__state),
- % and if so, bind RetVar to the procedure's return value.
+ % Test to see if the procedure is a model_det function whose function
+ % result has an output mode (whose type is not a dummy argument type
+ % like io__state), and if so, bind RetVar to the procedure's return value.
% These procedures need to handled specially: for such functions,
% we map the Mercury function result to an MLDS return value.
%
@@ -115,6 +111,7 @@
% conjunction: ml_gen_and(X,Y) = binop((and), X, Y),
% except that it does some constant folding on the result.
+ %
:- func ml_gen_and(mlds__rval, mlds__rval) = mlds__rval.
% negation: ml_gen_not(X) = unop(std_unop(not), X),
@@ -133,8 +130,7 @@
%
:- pred ml_gen_type(ml_gen_info::in, prog_type::in, mlds__type::out) is det.
- % Convert the element type for an array_index operator
- % to an MLDS type.
+ % Convert the element type for an array_index operator to an MLDS type.
%
:- func ml_gen_array_elem_type(builtin_ops__array_elem_type) = mlds__type.
@@ -154,15 +150,17 @@
% Routines for generating function declarations (i.e. mlds__func_params).
%
-% Note that when generating function *definitions*,
-% the versions that take an ml_gen_info pair should be used,
-% since those are the only ones that will generate the
-% correct GC tracing code for the parameters.
+% Note that when generating function *definitions*, the versions that take
+% an ml_gen_info pair should be used, since those are the only ones that will
+% generate the correct GC tracing code for the parameters.
% Generate the function prototype for a given procedure.
%
:- func ml_gen_proc_params(module_info, pred_id, proc_id) = mlds__func_params.
+ % As above, but from the rtti_proc_id rather than from the module_info,
+ % pred_id, and proc_id.
+ %
:- pred ml_gen_proc_params(pred_id::in, proc_id::in, mlds__func_params::out,
ml_gen_info::in, ml_gen_info::out) is det.
@@ -180,8 +178,7 @@
mlds__func_params::out, ml_gen_info::in, ml_gen_info::out) is det.
% Given a list of variables and their corresponding modes,
- % return a list containing only those variables which have
- % an output mode.
+ % return a list containing only those variables which have an output mode.
%
:- func select_output_vars(module_info, list(Var), list(mode),
map(Var, prog_type)) = list(Var).
@@ -197,25 +194,22 @@
:- pred ml_gen_proc_label(module_info::in, pred_id::in, proc_id::in,
mlds__entity_name::out, mlds_module_name::out) is det.
- % Generate an mlds__entity_name for a continuation function
- % with the given sequence number. The pred_id and proc_id
- % specify the procedure that this continuation function
- % is part of.
+ % Generate an mlds__entity_name for a continuation function with the
+ % given sequence number. The pred_id and proc_id specify the procedure
+ % that this continuation function is part of.
%
:- func ml_gen_nondet_label(module_info, pred_id, proc_id, ml_label_func)
= mlds__entity_name.
- % Allocate a new function label and return an rval containing
- % the function's address. If parameters are not given, we
- % assume it's a continuation function, and give it the
- % appropriate arguments (depending on whether we are doing
- % nested functions or not).
+ % Allocate a new function label and return an rval containing the
+ % function's address. If parameters are not given, we assume it is
+ % a continuation function, and give it the appropriate arguments
+ % (depending on whether we are doing nested functions or not).
%
:- pred ml_gen_new_func_label(maybe(mlds__func_params)::in, ml_label_func::out,
mlds__rval::out, ml_gen_info::in, ml_gen_info::out) is det.
- % Generate the mlds__pred_label and module name
- % for a given procedure.
+ % Generate the mlds__pred_label and module name for a given procedure.
%
:- pred ml_gen_pred_label(module_info::in, pred_id::in, proc_id::in,
mlds__pred_label::out, mlds_module_name::out) is det.
@@ -233,8 +227,8 @@
% Routines for dealing with variables
%
- % Generate a list of the mlds__lvals corresponding to a
- % given list of prog_vars.
+ % Generate a list of the mlds__lvals corresponding to a given list
+ % of prog_vars.
%
:- pred ml_gen_var_list(ml_gen_info::in, list(prog_var)::in,
list(mlds__lval)::out) is det.
@@ -290,12 +284,12 @@
:- func ml_gen_mlds_var_decl(mlds__data_name, mlds__type, mlds__initializer,
maybe(mlds__statement), mlds__context) = mlds__defn.
- % Generate declaration flags for a local variable
+ % Generate declaration flags for a local variable.
%
:- func ml_gen_local_var_decl_flags = mlds__decl_flags.
- % Generate declaration flags for a public field
- % of a class.
+ % Return the declaration flags appropriate for a public field
+ % in the derived constructor class of a discriminated union.
%
:- func ml_gen_public_field_decl_flags = mlds__decl_flags.
@@ -308,9 +302,11 @@
%
% ml_format_reserved_object_name(CtorName, CtorArity, ReservedObjName):
+ %
% Generate a name for a specially reserved global variable
- % (or static member variable)
- % whose address is used to represent the specified constructor.
+ % (or static member variable) whose address is used to represent
+ % the specified constructor.
+ %
:- func ml_format_reserved_object_name(string, arity) = mlds__var_name.
% Generate a name for a local static constant.
@@ -318,20 +314,18 @@
:- pred ml_format_static_const_name(ml_gen_info::in, string::in, const_seq::in,
mlds__var_name::out) is det.
- % Generate a definition of a static constant,
- % given the constant's name, type, accessibility,
- % and initializer.
+ % Generate a definition of a static constant, given the constant's name,
+ % type, accessibility, and initializer.
%
:- func ml_gen_static_const_defn(mlds__var_name, mlds__type, mlds__access,
mlds__initializer, prog_context) = mlds__defn.
- % Return the declaration flags appropriate for an
- % initialized local static constant.
+ % Return the declaration flags appropriate for an initialized
+ % local static constant.
%
:- func ml_static_const_decl_flags = mlds__decl_flags.
- % Succeed iff the specified mlds__defn defines
- % a local static constant.
+ % Succeed iff the specified mlds__defn defines a local static constant.
%
:- pred ml_decl_is_static_const(mlds__defn::in) is semidet.
@@ -340,15 +334,16 @@
% Routines for dealing with fields
%
- % Given the user-specified field name, if any,
- % and the argument number (starting from one),
- % generate an MLDS field name.
+ % Given the user-specified field name, if any, and the argument number
+ % (starting from one), generate an MLDS field name.
+ %
:- func ml_gen_field_name(maybe(ctor_field_name), int) = mlds__field_name.
% Succeed iff the specified type must be boxed when used as a field.
- % For the MLDS->C and MLDS->asm back-ends,
- % we need to box types that are not word-sized, because the code
- % for `arg' etc. in std_util.m rely on all arguments being word-sized.
+ % For the MLDS->C and MLDS->asm back-ends, we need to box types that
+ % are not word-sized, because the code % for `arg' etc. in std_util.m
+ % rely on all arguments being word-sized.
+ %
:- pred ml_must_box_field_type(prog_type::in, module_info::in) is semidet.
%-----------------------------------------------------------------------------%
@@ -384,32 +379,26 @@
%
:- pred ml_gen_test_success(ml_gen_info::in, mlds__rval::out) is det.
- % Generate code to set the `succeeded' flag to the
- % specified truth value.
+ % Generate code to set the `succeeded' flag to the specified truth value.
%
:- pred ml_gen_set_success(ml_gen_info::in, mlds__rval::in, prog_context::in,
mlds__statement::out) is det.
- % Generate the declaration for the specified `cond'
- % variable.
+ % Generate the declaration for the specified `cond' variable.
% (`cond' variables are boolean variables used to record
- % the success or failure of model_non conditions of
- % if-then-elses.)
+ % the success or failure of model_non conditions of if-then-elses.)
%
:- func ml_gen_cond_var_decl(cond_seq, mlds__context) = mlds__defn.
% Return the lval for the specified `cond' flag.
% (`cond' variables are boolean variables used to record
- % the success or failure of model_non conditions of
- % if-then-elses.)
+ % the success or failure of model_non conditions of if-then-elses.)
%
:- pred ml_cond_var_lval(ml_gen_info::in, cond_seq::in, mlds__lval::out) is det.
- % Return an rval which will test the value of the specified
- % `cond' variable.
+ % Return an rval which will test the value of the specified `cond' variable.
% (`cond' variables are boolean variables used to record
- % the success or failure of model_non conditions of
- % if-then-elses.)
+ % the success or failure of model_non conditions of if-then-elses.)
%
:- pred ml_gen_test_cond_var(ml_gen_info::in, cond_seq::in, mlds__rval::out)
is det.
@@ -420,19 +409,15 @@
:- pred ml_gen_set_cond_var(ml_gen_info::in, cond_seq::in, mlds__rval::in,
prog_context::in, mlds__statement::out) is det.
- % Return the success continuation that was
- % passed as the current function's argument(s).
- % The success continuation consists of two parts, the
- % `cont' argument, and the `cont_env' argument.
- % The `cont' argument is a continuation function that
- % will be called when a model_non goal succeeds.
- % The `cont_env' argument is a pointer to the environment (set
- % of local variables in the containing procedure) for the continuation
- % function. (If we're using gcc nested function, the `cont_env'
- % is not used.)
- % The output variable lvals and types need to be supplied when
- % generating a continuation using --nondet-copy-out, otherwise
- % they should be empty.
+ % Return the success continuation that was passed as the current function's
+ % argument(s). The success continuation consists of two parts, the `cont'
+ % argument, and the `cont_env' argument. The `cont' argument is a
+ % continuation function that will be called when a model_non goal succeeds.
+ % The `cont_env' argument is a pointer to the environment (set of local
+ % variables in the containing procedure) for the continuation function.
+ % (If we're using gcc nested function, the `cont_env' is not used.)
+ % The output variable lvals and types need to be supplied when generating
+ % a continuation using --nondet-copy-out, otherwise they should be empty.
%
:- pred ml_initial_cont(ml_gen_info::in, list(mlds__lval)::in,
list(prog_type)::in, success_cont::out) is det.
@@ -457,15 +442,17 @@
% used for nested functions.
%
- % Return an rval for a pointer to the current environment
- % (the set of local variables in the containing procedure).
- % Note that we generate this as a dangling reference.
- % The ml_elim_nested pass will insert the declaration
- % of the env_ptr variable.
+ % Return an rval for a pointer to the current environment (the set of local
+ % variables in the containing procedure). Note that we generate this
+ % as a dangling reference. The ml_elim_nested pass will insert the
+ % declaration of the env_ptr variable. At this point, the type of these
+ % rvals is `mlds__unknown_type'.
+ %
:- pred ml_get_env_ptr(ml_gen_info::in, mlds__rval::out) is det.
% Return an mlds__argument for a pointer to the current environment
% (the set of local variables in the containing procedure).
+ %
:- pred ml_declare_env_ptr_arg(mlds__argument::out) is det.
%-----------------------------------------------------------------------------%
@@ -475,31 +462,31 @@
% ml_gen_maybe_gc_trace_code(Var, Type, Context, Code):
%
- % If accurate GC is enabled, and the specified
- % variable might contain pointers, generate code to call
- % `private_builtin__gc_trace' to trace the variable.
+ % If accurate GC is enabled, and the specified variable might contain
+ % pointers, generate code to call `private_builtin__gc_trace' to trace
+ % the variable.
+ %
:- pred ml_gen_maybe_gc_trace_code(var_name::in, prog_type::in,
prog_context::in, maybe(mlds__statement)::out,
ml_gen_info::in, ml_gen_info::out) is det.
% ml_gen_maybe_gc_trace_code(Var, DeclType, ActualType, Context, Code):
%
- % This is the same as the //4 version (above), except that it takes
- % two type arguments, rather than one. The first
- % (DeclType) is the type that the variable was declared with,
- % while the second (ActualType) is that type that the variable
- % is known to have. This is used to generate GC tracing code
- % for the temporaries variables used when calling procedures with
- % polymorphically-typed output arguments.
- % In that case, DeclType may be a type variable from the callee's
- % type declaration, but ActualType will be the type from the caller.
- %
- % We can't just use DeclType to generate the GC trace code,
- % because there's no way to compute the type_info for type variables
- % that come from the callee rather than the current procedure.
- % And we can't just use ActualType, since DeclType may contain
- % pointers even when ActualType doesn't (e.g. because DeclType
- % may be a boxed float). So we need to pass both.
+ % This is the same as the //4 version (above), except that it takes two
+ % type arguments, rather than one. The first (DeclType) is the type that
+ % the variable was declared with, while the second (ActualType) is that
+ % type that the variable is known to have. This is used to generate GC
+ % tracing code for the temporaries variables used when calling procedures
+ % with polymorphically-typed output arguments. In that case, DeclType
+ % may be a type variable from the callee's type declaration, but ActualType
+ % will be the type from the caller.
+ %
+ % We can't just use DeclType to generate the GC trace code, because there's
+ % no way to compute the type_info for type variables that come from the
+ % callee rather than the current procedure. And we can't just use
+ % ActualType, since DeclType may contain pointers even when ActualType
+ % doesn't (e.g. because DeclType may be a boxed float). So we need to pass
+ % both.
%
:- pred ml_gen_maybe_gc_trace_code(var_name::in, prog_type::in, prog_type::in,
prog_context::in, maybe(mlds__statement)::out,
@@ -507,9 +494,9 @@
% ml_gen_maybe_gc_trace_code_with_typeinfo(Var, DeclType, TypeInfoRval,
% Context, Code):
- % This is the same as ml_gen_maybe_gc_trace_code//5,
- % except that rather than passing ActualType,
- % the caller constructs the type-info itself,
+ %
+ % This is the same as ml_gen_maybe_gc_trace_code//5, except that rather
+ % than passing ActualType, the caller constructs the type-info itself,
% and just passes the rval for it to this routine.
%
% This is used by ml_closure_gen.m to generate GC tracing code
@@ -524,17 +511,20 @@
% Magic numbers relating to the representation of
% typeclass_infos, base_typeclass_infos, and closures.
%
- % This function returns the offset to add to the argument
- % number of a closure arg to get its field number.
+
+ % This function returns the offset to add to the argument number
+ % of a closure arg to get its field number.
+ %
:- func ml_closure_arg_offset = int.
- % This function returns the offset to add to the argument
- % number of a typeclass_info arg to get its field number.
+ % This function returns the offset to add to the argument number
+ % of a typeclass_info arg to get its field number.
+ %
:- func ml_typeclass_info_arg_offset = int.
- % This function returns the offset to add to the method number
- % for a type class method to get its field number within the
- % base_typeclass_info.
+ % This function returns the offset to add to the method number for a type
+ % class method to get its field number within the base_typeclass_info.
+ %
:- func ml_base_typeclass_info_method_offset = int.
%-----------------------------------------------------------------------------%
@@ -544,6 +534,7 @@
% Get the value of the appropriate --det-copy-out or --nondet-copy-out
% option, depending on the code model.
+ %
:- func get_copy_out_option(globals, code_model) = bool.
% Add the qualifier `builtin' to any unqualified name.
@@ -551,6 +542,7 @@
% of the `builtin' module, for historical reasons they don't have
% any qualifiers in the HLDS, so we need to add the `builtin'
% qualifier before converting such names to MLDS.
+ %
:- func fixup_builtin_module(module_name) = module_name.
%-----------------------------------------------------------------------------%
@@ -559,19 +551,16 @@
% The `ml_gen_info' ADT.
%
- %
% The `ml_gen_info' type holds information used during
% MLDS code generation for a given procedure.
%
:- type ml_gen_info.
- % initialize the ml_gen_info, so that it is
- % ready for generating code for the given procedure
+ % Initialize the ml_gen_info, so that it is ready for generating code
+ % for the given procedure.
+ %
:- func ml_gen_info_init(module_info, pred_id, proc_id) = ml_gen_info.
- % accessor predicates; these just get the specified
- % information from the ml_gen_info
-
:- pred ml_gen_info_get_module_info(ml_gen_info::in, module_info::out) is det.
:- pred ml_gen_info_get_module_name(ml_gen_info::in, mercury_module_name::out)
is det.
@@ -590,91 +579,90 @@
:- pred ml_gen_info_set_value_output_vars(list(prog_var)::in,
ml_gen_info::in, ml_gen_info::out) is det.
- % lookup the --gcc-nested-functions option
+ % Lookup the --gcc-nested-functions option.
+ %
:- pred ml_gen_info_use_gcc_nested_functions(ml_gen_info::in, bool::out)
is det.
- % lookup the --put-commit-in-nested-func option
+ % Lookup the --put-commit-in-nested-func option.
+ %
:- pred ml_gen_info_put_commit_in_own_func(ml_gen_info::in, bool::out) is det.
% Generate a new label number for use in label statements.
% This is used to give unique names to the case labels generated
% for dense switch statements.
+ %
:- type label_num == int.
:- pred ml_gen_info_new_label(label_num::out,
ml_gen_info::in, ml_gen_info::out) is det.
% A number corresponding to an MLDS nested function which serves as a
% label (i.e. a continuation function).
+ %
:- type ml_label_func == mlds__func_sequence_num.
- % Generate a new function label number.
- % This is used to give unique names to the nested functions
- % used when generating code for nondet procedures.
+ % Generate a new function label number. This is used to give unique names
+ % to the nested functions used when generating code for nondet procedures.
+ %
:- pred ml_gen_info_new_func_label(ml_label_func::out,
ml_gen_info::in, ml_gen_info::out) is det.
- % Increase the function label and const sequence number counters
- % by some amount which is presumed to be sufficient
- % to ensure that if we start again with a fresh
- % ml_gen_info and then call this function,
- % we won't encounter any already-used function labels or constants.
- % (This is used when generating wrapper functions
- % for type class methods.)
+ % Increase the function label and const sequence number counters by some
+ % amount which is presumed to be sufficient to ensure that if we start
+ % again with a fresh ml_gen_info and then call this function, we won't
+ % encounter any already-used function labels or constants. (This is used
+ % when generating wrapper functions for type class methods.)
+ %
:- pred ml_gen_info_bump_counters(ml_gen_info::in, ml_gen_info::out) is det.
- % Generate a new commit label number.
- % This is used to give unique names to the labels
- % used when generating code for commits.
+ % Generate a new commit label number. This is used to give unique names
+ % to the labels used when generating code for commits.
+ %
:- type commit_sequence_num == int.
:- pred ml_gen_info_new_commit_label(commit_sequence_num::out,
ml_gen_info::in, ml_gen_info::out) is det.
- % Generate a new `cond' variable number.
- % This is used to give unique names to the local
- % variables used to hold the results of
- % nondet conditions of if-then-elses.
+ % Generate a new `cond' variable number. This is used to give unique names
+ % to the local variables used to hold the results of nondet conditions
+ % of if-then-elses.
+ %
:- type cond_seq == int.
:- pred ml_gen_info_new_cond_var(cond_seq::out,
ml_gen_info::in, ml_gen_info::out) is det.
- % Generate a new `conv' variable number.
- % This is used to give unique names to the local
- % variables generated by ml_gen_box_or_unbox_lval,
- % which are used to handle boxing/unboxing
- % argument conversions.
+ % Generate a new `conv' variable number. This is used to give unique names
+ % to the local variables generated by ml_gen_box_or_unbox_lval, which are
+ % used to handle boxing/unboxing argument conversions.
+ %
:- type conv_seq == int.
:- pred ml_gen_info_new_conv_var(conv_seq::out,
ml_gen_info::in, ml_gen_info::out) is det.
- % Generate a new `const' sequence number.
- % This is used to give unique names to the local constants
- % generated for --static-ground-terms, closure layouts,
- % string switch hash tables, etc.
+ % Generate a new `const' sequence number. This is used to give unique names
+ % to the local constants generated for --static-ground-terms, closure
+ % layouts, string switch hash tables, etc.
+ %
:- type const_seq == int.
:- pred ml_gen_info_new_const(const_seq::out,
ml_gen_info::in, ml_gen_info::out) is det.
- % Set the `const' sequence number
- % corresponding to a given HLDS variable.
+ % Set the `const' sequence number corresponding to a given HLDS variable.
%
:- pred ml_gen_info_set_const_num(prog_var::in, const_seq::in,
ml_gen_info::in, ml_gen_info::out) is det.
- % Lookup the `const' sequence number
- % corresponding to a given HLDS variable.
+ % Lookup the `const' sequence number corresponding to a given HLDS
+ % variable.
%
:- pred ml_gen_info_lookup_const_num(ml_gen_info::in, prog_var::in,
const_seq::out) is det.
- %
- % A success continuation specifies the (rval for the variable
- % holding the address of the) function that a nondet procedure
- % should call if it succeeds, and possibly also the
- % (rval for the variable holding) the environment pointer
- % for that function, and possibly also the (list of rvals
- % for the) arguments to the continuation.
- %
+ % A success continuation specifies the (rval for the variable holding
+ % the address of the) function that a nondet procedure should call
+ % if it succeeds, and possibly also the (rval for the variable holding)
+ % the environment pointer for that function, and possibly also the
+ % (list of rvals for the) arguments to the continuation.
+
:- type success_cont
---> success_cont(
mlds__rval, % function pointer
@@ -684,61 +672,58 @@
% pointer will not be used
list(mlds__type), % argument types, if any
list(mlds__lval) % arguments, if any
- % The arguments will only be non-empty if the
- % --nondet-copy-out option is enabled.
- % They do not include the environment pointer.
+ % The arguments will only be non-empty
+ % if the --nondet-copy-out option is
+ % enabled. They do not include the
+ % environment pointer.
).
- %
% The ml_gen_info contains a stack of success continuations.
% The following routines provide access to that stack.
- %
:- pred ml_gen_info_push_success_cont(success_cont::in,
ml_gen_info::in, ml_gen_info::out) is det.
:- pred ml_gen_info_pop_success_cont(ml_gen_info::in, ml_gen_info::out) is det.
-:- pred ml_gen_info_current_success_cont(success_cont::out,
- ml_gen_info::in, ml_gen_info::out) is det.
+:- pred ml_gen_info_current_success_cont(ml_gen_info::in, success_cont::out)
+ is det.
- %
- % We keep a partial mapping from vars to lvals.
- % This is used in special cases to override the normal
- % lval for a variable. ml_gen_var will check this
- % map first, and if the variable is not in this map,
- % then it will go ahead and generate an lval for it
- % as usual.
- %
+ % We keep a partial mapping from vars to lvals. This is used in special
+ % cases to override the normal lval for a variable. ml_gen_var will check
+ % this map first, and if the variable is not in this map, then it will go
+ % ahead and generate an lval for it as usual.
% Set the lval for a variable.
+ %
:- pred ml_gen_info_set_var_lval(prog_var::in, mlds__lval::in,
ml_gen_info::in, ml_gen_info::out) is det.
% Get the partial mapping from variables to lvals.
+ %
:- pred ml_gen_info_get_var_lvals(ml_gen_info::in,
map(prog_var, mlds__lval)::out) is det.
% Set the partial mapping from variables to lvals.
+ %
:- pred ml_gen_info_set_var_lvals(map(prog_var, mlds__lval)::in,
ml_gen_info::in, ml_gen_info::out) is det.
- %
- % The ml_gen_info contains a list of extra definitions
- % of functions or global constants which should be inserted
- % before the definition of the function for the current procedure.
- % This is used for the definitions of the wrapper functions needed
- % for closures. When generating code for a procedure that creates
- % a closure, we insert the definition of the wrapper function used
- % for that closure into this list.
- %
+ % The ml_gen_info contains a list of extra definitions of functions or
+ % global constants which should be inserted before the definition of the
+ % function for the current procedure. This is used for the definitions
+ % of the wrapper functions needed for closures. When generating code
+ % for a procedure that creates a closure, we insert the definition of
+ % the wrapper function used for that closure into this list.
% Insert an extra definition at the start of the list of extra
% definitions.
+ %
:- pred ml_gen_info_add_extra_defn(mlds__defn::in,
ml_gen_info::in, ml_gen_info::out) is det.
% Get the list of extra definitions.
+ %
:- pred ml_gen_info_get_extra_defns(ml_gen_info::in, mlds__defns::out) is det.
%-----------------------------------------------------------------------------%
@@ -777,16 +762,11 @@
% Code for various utility routines
%
- % Generate an MLDS assignment statement.
ml_gen_assign(Lval, Rval, Context) = Statement :-
Assign = assign(Lval, Rval),
Stmt = atomic(Assign),
Statement = mlds__statement(Stmt, mlds__make_context(Context)).
- %
- % Append an appropriate `return' statement for the given code_model
- % and returning the given OutputVarLvals, if needed.
- %
ml_append_return_statement(Info, CodeModel, CopiedOutputVarLvals, Context,
!Statements) :-
(
@@ -801,7 +781,7 @@
!:Statements = list__append(!.Statements, [ReturnStatement])
;
CodeModel \= model_non,
- CopiedOutputVarLvals \= []
+ CopiedOutputVarLvals = [_ | _]
->
CopiedOutputVarRvals = list__map(func(Lval) = lval(Lval),
CopiedOutputVarLvals),
@@ -813,10 +793,6 @@
true
).
- % Generate a block statement, i.e. `{ <Decls>; <Statements>; }'.
- % But if the block consists only of a single statement with no
- % declarations, then just return that statement.
- %
ml_gen_block(VarDecls, Statements, Context) =
(
VarDecls = [],
@@ -828,18 +804,6 @@
mlds__make_context(Context))
).
- % ml_join_decls:
- % Join two statement lists and their corresponding
- % declaration lists in sequence.
- %
- % If the statements have no declarations in common,
- % then their corresponding declaration lists will be
- % concatenated together into a single list of declarations.
- % But if they have any declarations in common, then we
- % put each statement list and its declarations into
- % a block, so that the declarations remain local to
- % each statement list.
- %
ml_join_decls(FirstDecls, FirstStatements, RestDecls, RestStatements, Context,
Decls, Statements) :-
(
@@ -855,10 +819,6 @@
Statements = list__append(FirstStatements, RestStatements)
).
- % ml_combine_conj:
- % Given closures to generate code for two conjuncts,
- % generate code for their conjunction.
- %
ml_combine_conj(FirstCodeModel, Context, DoGenFirst, DoGenRest,
Decls, Statements, !Info) :-
(
@@ -871,9 +831,8 @@
FirstCodeModel = model_det,
DoGenFirst(FirstDecls, FirstStatements, !Info),
DoGenRest(RestDecls, RestStatements, !Info),
- ml_join_decls(FirstDecls, FirstStatements,
- RestDecls, RestStatements, Context,
- Decls, Statements)
+ ml_join_decls(FirstDecls, FirstStatements, RestDecls, RestStatements,
+ Context, Decls, Statements)
;
% model_semi goal:
% <Goal, Goals>
@@ -884,11 +843,11 @@
% if (succeeded) {
% <Goals>;
% }
- % except that we hoist any declarations generated
- % for <Goals> to the outer scope, rather than
- % inside the `if', so that they remain in
- % scope for any later goals which follow this
- % (this is needed for declarations of static consts)
+ % except that we hoist any declarations generated for <Goals>
+ % to the outer scope, rather than inside the `if', so that they remain
+ % in scope for any later goals which follow this (this is needed for
+ % declarations of static consts).
+
FirstCodeModel = model_semi,
DoGenFirst(FirstDecls, FirstStatements, !Info),
ml_gen_test_success(!.Info, Succeeded),
@@ -908,90 +867,71 @@
% }
%
% <First && succ_func()>;
- % except that we hoist any declarations generated
- % for <First> and any _static_ declarations generated
- % for <Rest> to the top of the scope, rather
- % than inside or after the succ_func(), so that they
- % remain in scope for any code following them
- % (this is needed for declarations of static consts).
- %
- % We take care to only hoist _static_ declarations
- % outside nested functions, since access to non-local
- % variables is less efficient.
%
- % XXX The pattern above leads to deep nesting for long
- % conjunctions; we should avoid that.
+ % except that we hoist any declarations generated for <First> and
+ % any _static_ declarations generated for <Rest> to the top of the
+ % scope, rather than inside or after the succ_func(), so that they
+ % remain in scope for any code following them (this is needed for
+ % declarations of static consts).
+ %
+ % We take care to only hoist _static_ declarations outside nested
+ % functions, since access to non-local variables is less efficient.
+ %
+ % XXX The pattern above leads to deep nesting for long conjunctions;
+ % we should avoid that.
%
FirstCodeModel = model_non,
% allocate a name for the `succ_func'
- ml_gen_new_func_label(no, RestFuncLabel, RestFuncLabelRval,
- !Info),
+ ml_gen_new_func_label(no, RestFuncLabel, RestFuncLabelRval, !Info),
% generate <First && succ_func()>
ml_get_env_ptr(!.Info, EnvPtrRval),
- SuccessCont = success_cont(RestFuncLabelRval,
- EnvPtrRval, [], []),
+ SuccessCont = success_cont(RestFuncLabelRval, EnvPtrRval, [], []),
ml_gen_info_push_success_cont(SuccessCont, !Info),
DoGenFirst(FirstDecls, FirstStatements, !Info),
ml_gen_info_pop_success_cont(!Info),
% generate the `succ_func'
- /* push nesting level */
+ % push nesting level
DoGenRest(RestDecls, RestStatements, !Info),
list__filter(ml_decl_is_static_const, RestDecls,
RestStaticDecls, RestOtherDecls),
- RestStatement = ml_gen_block(RestOtherDecls, RestStatements,
- Context),
- /* pop nesting level */
+ RestStatement = ml_gen_block(RestOtherDecls, RestStatements, Context),
+ % pop nesting level
ml_gen_nondet_label_func(!.Info, RestFuncLabel, Context,
RestStatement, RestFunc),
- Decls = list__condense(
- [FirstDecls, RestStaticDecls, [RestFunc]]),
+ Decls = list__condense([FirstDecls, RestStaticDecls, [RestFunc]]),
Statements = FirstStatements
).
- % Succeed iff the specified mlds__defn defines
- % a static constant.
- %
ml_decl_is_static_const(Defn) :-
Defn = mlds__defn(Name, _Context, Flags, _DefnBody),
Name = data(_),
Flags = ml_static_const_decl_flags.
- % Given a function label and the statement which will comprise
- % the function body for that function, generate an mlds__defn
- % which defines that function.
- %
ml_gen_nondet_label_func(Info, FuncLabel, Context, Statement, Func) :-
ml_gen_info_use_gcc_nested_functions(Info, UseNested),
- ( UseNested = yes ->
+ (
+ UseNested = yes,
FuncParams = mlds__func_params([], [])
;
+ UseNested = no,
ml_declare_env_ptr_arg(EnvPtrArg),
FuncParams = mlds__func_params([EnvPtrArg], [])
),
- ml_gen_label_func(Info, FuncLabel, FuncParams, Context, Statement,
- Func).
+ ml_gen_label_func(Info, FuncLabel, FuncParams, Context, Statement, Func).
- % Given a function label, the function parameters, and the statement
- % which will comprise the function body for that function,
- % generate an mlds__defn which defines that function.
- %
ml_gen_label_func(Info, FuncLabel, FuncParams, Context, Statement, Func) :-
- %
- % compute the function name
- %
+ % Compute the function name.
ml_gen_info_get_module_info(Info, ModuleInfo),
ml_gen_info_get_pred_id(Info, PredId),
ml_gen_info_get_proc_id(Info, ProcId),
FuncName = ml_gen_nondet_label(ModuleInfo, PredId, ProcId, FuncLabel),
- %
- % compute the function definition
- %
+ % Compute the function definition.
DeclFlags = ml_gen_label_func_decl_flags,
MaybePredProcId = no,
Attributes = [],
@@ -1000,11 +940,11 @@
Func = mlds__defn(FuncName, mlds__make_context(Context), DeclFlags,
FuncDefn).
- % Return the declaration flags appropriate for a label func
- % (a label func is a function used as a continuation
- % when generating nondet code).
+ % Return the declaration flags appropriate for a label func (a label func
+ % is a function used as a continuation when generating nondet code).
%
:- func ml_gen_label_func_decl_flags = mlds__decl_flags.
+
ml_gen_label_func_decl_flags = DeclFlags :-
Access = local,
PerInstance = per_instance,
@@ -1012,8 +952,8 @@
Finality = overridable,
Constness = modifiable,
Abstractness = concrete,
- DeclFlags = init_decl_flags(Access, PerInstance,
- Virtuality, Finality, Constness, Abstractness).
+ DeclFlags = init_decl_flags(Access, PerInstance, Virtuality, Finality,
+ Constness, Abstractness).
%-----------------------------------------------------------------------------%
%
@@ -1021,11 +961,11 @@
%
ml_gen_and(X, Y) =
- (if X = const(true) then
+ ( X = const(true) ->
Y
- else if Y = const(true) then
+ ; Y = const(true) ->
X
- else
+ ;
binop((and), X, Y)
).
@@ -1044,8 +984,8 @@
ml_gen_array_elem_type(elem_type_int) = mlds__native_int_type.
ml_gen_array_elem_type(elem_type_generic) = mlds__generic_type.
-ml_string_type = mercury_type(string_type, str_type,
- non_foreign_type(string_type)).
+ml_string_type =
+ mercury_type(string_type, str_type, non_foreign_type(string_type)).
ml_make_boxed_types(Arity) = BoxedTypes :-
varset__init(TypeVarSet0),
@@ -1057,8 +997,6 @@
% Code for generating function declarations (i.e. mlds__func_params).
%
- % Generate the function prototype for a given procedure.
- %
ml_gen_proc_params(ModuleInfo, PredId, ProcId) = FuncParams :-
module_info_pred_proc_info(ModuleInfo, PredId, ProcId,
PredInfo, ProcInfo),
@@ -1083,9 +1021,9 @@
proc_info_argmodes(ProcInfo, HeadModes),
proc_info_interface_code_model(ProcInfo, CodeModel),
HeadVarNames = ml_gen_var_names(VarSet, HeadVars),
- % we must not generate GC tracing code for no_type_info_builtin
+ % We must not generate GC tracing code for no_type_info_builtin
% procedures, because the generated GC tracing code would refer
- % to type_infos that don't get passed
+ % to type_infos that don't get passed.
PredModule = pred_info_module(PredInfo),
PredName = pred_info_name(PredInfo),
PredArity = pred_info_orig_arity(PredInfo),
@@ -1097,9 +1035,6 @@
CodeModel, FuncParams, !Info)
).
- % As above, but from the rtti_proc_id rather than
- % from the module_info, pred_id, and proc_id.
- %
ml_gen_proc_params_from_rtti(ModuleInfo, RttiProcId) = FuncParams :-
HeadVars = RttiProcId ^ proc_headvars,
ArgTypes = RttiProcId ^ proc_arg_types,
@@ -1114,9 +1049,6 @@
ml_gen_params_base(ModuleInfo, HeadVarNames, ArgTypes, ArgModes,
PredOrFunc, CodeModel, FuncParams, no, _).
- % Generate the function prototype for a procedure with the
- % given argument types, modes, and code model.
- %
ml_gen_params(ModuleInfo, HeadVarNames, HeadTypes, HeadModes, PredOrFunc,
CodeModel) = FuncParams :-
modes_to_arg_modes(ModuleInfo, HeadModes, HeadTypes, ArgModes),
@@ -1130,10 +1062,12 @@
ml_gen_params_base(ModuleInfo, HeadVarNames,
HeadTypes, ArgModes, PredOrFunc, CodeModel, FuncParams,
yes(!.Info), MaybeInfo),
- ( MaybeInfo = yes(Info) ->
+ (
+ MaybeInfo = yes(Info),
!:Info = Info
;
- error("ml_gen_params: missing ml_gen_info")
+ MaybeInfo = no,
+ unexpected(this_file, "ml_gen_params: missing ml_gen_info")
).
:- pred ml_gen_params_base(module_info::in, list(mlds__var_name)::in,
@@ -1149,10 +1083,8 @@
CopyOut, FuncArgs0, RetTypes0, !MaybeInfo),
(
CodeModel = model_det,
- %
- % for model_det Mercury functions whose result argument has an
- % output mode, make the result into the MLDS return type
- %
+ % For model_det Mercury functions whose result argument has an
+ % output mode, make the result into the MLDS return type.
(
RetTypes0 = [],
PredOrFunc = function,
@@ -1162,12 +1094,11 @@
\+ type_util__is_dummy_argument_type(ResultType)
->
pred_args_to_func_args(FuncArgs0, FuncArgs, RetArg),
- RetArg = mlds__argument(_RetArgName, RetTypePtr,
- _GC_TraceCode),
+ RetArg = mlds__argument(_RetArgName, RetTypePtr, _GC_TraceCode),
( RetTypePtr = mlds__ptr_type(RetType) ->
RetTypes = [RetType]
;
- error("output mode function result " ++
+ unexpected(this_file, "output mode function result " ++
"doesn't have pointer type")
)
;
@@ -1176,21 +1107,19 @@
)
;
CodeModel = model_semi,
- %
- % for model_semi procedures, return a bool
- %
+ % For model_semi procedures, return a bool.
FuncArgs = FuncArgs0,
RetTypes = [mlds__native_bool_type | RetTypes0]
;
CodeModel = model_non,
- %
- % for model_non procedures, we return values
- % by passing them to the continuation
- %
- ( CopyOut = yes ->
+ % For model_non procedures, we return values by passing them
+ % to the continuation.
+ (
+ CopyOut = yes,
ContType = mlds__cont_type(RetTypes0),
RetTypes = []
;
+ CopyOut = no,
ContType = mlds__cont_type([]),
RetTypes = RetTypes0
),
@@ -1201,11 +1130,10 @@
ContArg = mlds__argument(ContName, ContType, ContGCTraceCode),
ContEnvType = mlds__generic_env_ptr_type,
ContEnvName = data(var(var_name("cont_env_ptr", no))),
- % The cont_env_ptr always points to the stack,
- % since continuation environments are always allocated
- % on the stack (unless put_nondet_env_on_heap is true,
- % which won't be the case when doing our own GC --
- % this is enforced in handle_options.m).
+ % The cont_env_ptr always points to the stack, since continuation
+ % environments are always allocated on the stack (unless
+ % put_nondet_env_on_heap is true, which won't be the case when doing
+ % our own GC -- this is enforced in handle_options.m).
% So the GC doesn't need to trace it.
ContEnvGCTraceCode = no,
ContEnvArg = mlds__argument(ContEnvName, ContEnvType,
@@ -1213,10 +1141,10 @@
globals__lookup_bool_option(Globals, gcc_nested_functions,
NestedFunctions),
(
- NestedFunctions = yes
- ->
+ NestedFunctions = yes,
FuncArgs = FuncArgs0 ++ [ContArg]
;
+ NestedFunctions = no,
FuncArgs = FuncArgs0 ++ [ContArg, ContEnvArg]
)
),
@@ -1248,10 +1176,8 @@
ml_gen_arg_decls(ModuleInfo, Vars, Types, Modes, CopyOut,
FuncArgs0, RetTypes0, !MaybeInfo),
(
- %
% Exclude types such as io__state, etc.
% Also exclude values with arg_mode `top_unused'.
- %
( type_util__is_dummy_argument_type(Type)
; Mode = top_unused
)
@@ -1259,9 +1185,7 @@
FuncArgs = FuncArgs0,
RetTypes = RetTypes0
;
- %
- % for by-value outputs, generate a return type
- %
+ % For by-value outputs, generate a return type.
Mode = top_out,
CopyOut = yes
->
@@ -1269,17 +1193,13 @@
RetTypes = [RetType | RetTypes0],
FuncArgs = FuncArgs0
;
- %
- % for inputs and by-reference outputs,
- % generate argument
- %
- ml_gen_arg_decl(ModuleInfo, Var, Type, Mode, FuncArg,
- !MaybeInfo),
+ % For inputs and by-reference outputs, generate argument.
+ ml_gen_arg_decl(ModuleInfo, Var, Type, Mode, FuncArg, !MaybeInfo),
FuncArgs = [FuncArg | FuncArgs0],
RetTypes = RetTypes0
)
;
- error("ml_gen_arg_decls: length mismatch")
+ unexpected(this_file, "ml_gen_arg_decls: length mismatch")
).
% Given an argument variable, and its type and mode,
@@ -1297,21 +1217,22 @@
MLDS_ArgType = MLDS_Type
),
Name = data(var(Var)),
- ( !.MaybeInfo = yes(Info0) ->
- % XXX We should fill in this Context properly
+ (
+ !.MaybeInfo = yes(Info0),
+ % XXX We should fill in this Context properly.
term__context_init(Context),
- ml_gen_maybe_gc_trace_code(Var, Type, Context,
- Maybe_GC_TraceCode, Info0, Info),
+ ml_gen_maybe_gc_trace_code(Var, Type, Context, Maybe_GC_TraceCode,
+ Info0, Info),
!:MaybeInfo = yes(Info)
;
+ !.MaybeInfo = no,
Maybe_GC_TraceCode = no,
!:MaybeInfo = no
),
FuncArg = mlds__argument(Name, MLDS_ArgType, Maybe_GC_TraceCode).
ml_is_output_det_function(ModuleInfo, PredId, ProcId, RetArgVar) :-
- module_info_pred_proc_info(ModuleInfo, PredId, ProcId, PredInfo,
- ProcInfo),
+ module_info_pred_proc_info(ModuleInfo, PredId, ProcId, PredInfo, ProcInfo),
pred_info_is_pred_or_func(PredInfo) = function,
proc_info_interface_code_model(ProcInfo, model_det),
@@ -1335,13 +1256,12 @@
% function corresponding to a given procedure.
%
ml_gen_proc_label(ModuleInfo, PredId, ProcId, MLDS_Name, MLDS_ModuleName) :-
- ml_gen_func_label(ModuleInfo, PredId, ProcId, no,
- MLDS_Name, MLDS_ModuleName).
+ ml_gen_func_label(ModuleInfo, PredId, ProcId, no, MLDS_Name,
+ MLDS_ModuleName).
- % Generate an mlds__entity_name for a continuation function
- % with the given sequence number. The pred_id and proc_id
- % specify the procedure that this continuation function
- % is part of.
+ % Generate an mlds__entity_name for a continuation function with the given
+ % sequence number. The pred_id and proc_id specify the procedure that this
+ % continuation function is part of.
%
ml_gen_nondet_label(ModuleInfo, PredId, ProcId, SeqNum) = MLDS_Name :-
ml_gen_func_label(ModuleInfo, PredId, ProcId, yes(SeqNum),
@@ -1368,12 +1288,16 @@
ml_gen_pred_label(ModuleInfo, PredId, ProcId,
PredLabel, PredModule),
ml_gen_info_use_gcc_nested_functions(!.Info, UseNestedFuncs),
- ( MaybeParams = yes(Params) ->
+ (
+ MaybeParams = yes(Params),
Signature = mlds__get_func_signature(Params)
;
- ( UseNestedFuncs = yes ->
+ MaybeParams = no,
+ (
+ UseNestedFuncs = yes,
ArgTypes = []
;
+ UseNestedFuncs = no,
ArgTypes = [mlds__generic_env_ptr_type]
),
Signature = mlds__func_signature(ArgTypes, [])
@@ -1382,8 +1306,7 @@
FuncLabelRval = const(code_addr_const(internal(ProcLabel,
FuncLabel, Signature))).
- % Generate the mlds__pred_label and module name
- % for a given procedure.
+ % Generate the mlds__pred_label and module name for a given procedure.
%
ml_gen_pred_label(ModuleInfo, PredId, ProcId, MLDS_PredLabel, MLDS_Module) :-
RttiProcLabel = rtti__make_rtti_proc_label(ModuleInfo, PredId, ProcId),
@@ -1407,8 +1330,7 @@
type_ctor_is_tuple(TypeCtor),
mercury_public_builtin_module(TypeModule)
;
- TypeCtor = qualified(TypeModule, TypeName)
- - TypeArity
+ TypeCtor = qualified(TypeModule, TypeName) - TypeArity
)
->
(
@@ -1416,19 +1338,18 @@
SpecialPred = unify,
\+ hlds_pred__in_in_unification_proc_id(ProcId)
->
- % This is a locally-defined instance
- % of a unification procedure for a type
- % defined in some other module
+ % This is a locally-defined instance of a unification procedure
+ % for a type defined in some other module.
DefiningModule = ThisModule,
MaybeDeclaringModule = yes(TypeModule)
;
- % the module declaring the type is the same as
- % the module defining this special pred
+ % The module declaring the type is the same as the module
+ % defining this special pred.
DefiningModule = TypeModule,
MaybeDeclaringModule = no
),
- MLDS_PredLabel = special_pred(PredName,
- MaybeDeclaringModule, TypeName, TypeArity)
+ MLDS_PredLabel = special_pred(PredName, MaybeDeclaringModule,
+ TypeName, TypeArity)
;
string__append_list(["ml_gen_pred_label:\n",
"cannot make label for special pred `",
@@ -1437,25 +1358,23 @@
)
;
(
- % Work out which module supplies the code for
- % the predicate.
+ % Work out which module supplies the code for the predicate.
ThisModule \= PredModule,
PredIsImported = no
->
- % This predicate is a specialized version of
- % a pred from a `.opt' file.
+ % This predicate is a specialized version of a pred from a
+ % `.opt' file.
DefiningModule = ThisModule,
MaybeDeclaringModule = yes(PredModule)
;
- % The predicate was declared in the same module
- % that it is defined in
+ % The predicate was declared in the same module that it is
+ % defined in
DefiningModule = PredModule,
MaybeDeclaringModule = no
),
(
PredOrFunc = function,
- \+ ml_is_output_det_function(ModuleInfo, PredId,
- ProcId, _)
+ \+ ml_is_output_det_function(ModuleInfo, PredId, ProcId, _)
->
NonOutputFunc = yes
;
@@ -1476,43 +1395,31 @@
% Code for dealing with variables
%
- % Generate a list of the mlds__lvals corresponding to a
- % given list of prog_vars.
- %
ml_gen_var_list(_Info, [], []).
ml_gen_var_list(Info, [Var | Vars], [Lval | Lvals]) :-
ml_gen_var(Info, Var, Lval),
ml_gen_var_list(Info, Vars, Lvals).
- % Generate the mlds__lval corresponding to a given prog_var.
- %
ml_gen_var(Info, Var, Lval) :-
- %
- % First check the var_lvals override mapping;
- % if an lval has been set for this variable, use it
- %
+ % First check the var_lvals override mapping; if an lval has been set
+ % for this variable, use it.
+
ml_gen_info_get_var_lvals(Info, VarLvals),
( map__search(VarLvals, Var, VarLval) ->
Lval = VarLval
;
- %
- % Otherwise just look up the variable's type
- % and generate an lval for it using the ordinary
- % algorithm.
- %
+ % Otherwise just look up the variable's type and generate an lval
+ % for it using the ordinary algorithm.
+
ml_variable_type(Info, Var, Type),
ml_gen_var_with_type(Info, Var, Type, Lval)
).
- % Generate the mlds__lval corresponding to a given prog_var,
- % with a given type.
- %
ml_gen_var_with_type(Info, Var, Type, Lval) :-
( type_util__is_dummy_argument_type(Type) ->
- %
- % The variable won't have been declared, so
- % we need to generate a dummy lval for this variable.
- %
+ % The variable won't have been declared, so we need to generate
+ % a dummy lval for this variable.
+
mercury_private_builtin_module(PrivateBuiltin),
MLDS_Module = mercury_module_name_to_mlds(PrivateBuiltin),
ml_gen_type(Info, Type, MLDS_Type),
@@ -1523,9 +1430,8 @@
VarName = ml_gen_var_name(VarSet, Var),
ml_gen_type(Info, Type, MLDS_Type),
ml_gen_var_lval(Info, VarName, MLDS_Type, VarLval),
- %
- % output variables may be passed by reference...
- %
+
+ % Output variables may be passed by reference...
ml_gen_info_get_byref_output_vars(Info, OutputVars),
( list__member(Var, OutputVars) ->
Lval = mem_ref(lval(VarLval), MLDS_Type)
@@ -1534,48 +1440,33 @@
)
).
- % Lookup the types of a list of variables.
- %
ml_variable_types(_Info, [], []).
ml_variable_types(Info, [Var | Vars], [Type | Types]) :-
ml_variable_type(Info, Var, Type),
ml_variable_types(Info, Vars, Types).
- % Lookup the type of a variable.
- %
ml_variable_type(Info, Var, Type) :-
ml_gen_info_get_var_types(Info, VarTypes),
map__lookup(VarTypes, Var, Type).
- % Generate the MLDS variable names for a list of HLDS variables.
- %
ml_gen_var_names(VarSet, Vars) = list__map(ml_gen_var_name(VarSet), Vars).
- % Generate the MLDS variable name for an HLDS variable.
- %
ml_gen_var_name(VarSet, Var) = UniqueVarName :-
varset__lookup_name(VarSet, Var, VarName),
term__var_to_int(Var, VarNumber),
UniqueVarName = mlds__var_name(VarName, yes(VarNumber)).
- % ml_format_reserved_object_name(CtorName, CtorArity, ReservedObjName):
- % Generate a name for a specially reserved global variable
- % (or static member variable)
- % whose address is used to represent the specified constructor.
- %
- % We add the "obj_" prefix to avoid any potential name clashes.
- %
ml_format_reserved_object_name(CtorName, CtorArity) = ReservedObjName :-
+ % We add the "obj_" prefix to avoid any potential name clashes.
+
Name = string__format("obj_%s_%d", [s(CtorName), i(CtorArity)]),
ReservedObjName = var_name(Name, no).
- % Generate a name for a local static constant.
- %
- % To ensure that the names are unique, we qualify them with the
- % pred_id and proc_id numbers, as well as a sequence number.
- % This is needed to allow ml_elim_nested.m to hoist
- % such constants out to top level.
ml_format_static_const_name(Info, BaseName, SequenceNum, ConstName) :-
+ % To ensure that the names are unique, we qualify them with the pred_id
+ % and proc_id numbers, as well as a sequence number. This is needed to
+ % allow ml_elim_nested.m to hoist such constants out to top level.
+
ml_gen_info_get_pred_id(Info, PredId),
ml_gen_info_get_proc_id(Info, ProcId),
pred_id_to_int(PredId, PredIdNum),
@@ -1584,34 +1475,22 @@
string__format("const_%d_%d_%d_%s", [i(PredIdNum),
i(ProcIdNum), i(SequenceNum), s(BaseName)]), no).
- % Qualify the name of the specified variable
- % with the current module name.
- %
ml_gen_var_lval(Info, VarName, VarType, QualifiedVarLval) :-
ml_gen_info_get_module_name(Info, ModuleName),
MLDS_Module = mercury_module_name_to_mlds(ModuleName),
- QualifiedVarLval = var(qual(MLDS_Module, module_qual, VarName),
- VarType).
+ QualifiedVarLval = var(qual(MLDS_Module, module_qual, VarName), VarType).
- % Generate a declaration for an MLDS variable, given its HLDS type.
- %
ml_gen_var_decl(VarName, Type, Context, Defn, !Info) :-
ml_gen_info_get_module_info(!.Info, ModuleInfo),
- ml_gen_maybe_gc_trace_code(VarName, Type, Context, GC_TraceCode,
- !Info),
+ ml_gen_maybe_gc_trace_code(VarName, Type, Context, GC_TraceCode, !Info),
Defn = ml_gen_mlds_var_decl(var(VarName),
mercury_type_to_mlds_type(ModuleInfo, Type),
GC_TraceCode, mlds__make_context(Context)).
- % Generate a declaration for an MLDS variable, given its MLDS type.
- %
ml_gen_mlds_var_decl(DataName, MLDS_Type, GC_TraceCode, Context) =
ml_gen_mlds_var_decl(DataName, MLDS_Type, no_initializer, GC_TraceCode,
Context).
- % Generate a declaration for an MLDS variable, given its MLDS type
- % and initializer.
- %
ml_gen_mlds_var_decl(DataName, MLDS_Type, Initializer, GC_TraceCode, Context) =
MLDS_Defn :-
Name = data(DataName),
@@ -1619,9 +1498,6 @@
DeclFlags = ml_gen_local_var_decl_flags,
MLDS_Defn = mlds__defn(Name, Context, DeclFlags, Defn).
- % Generate a definition of a local static constant,
- % given the constant's name, type, and initializer.
- %
ml_gen_static_const_defn(ConstName, ConstType, Access, Initializer, Context) =
MLDS_Defn :-
Name = data(var(ConstName)),
@@ -1634,9 +1510,6 @@
MLDS_Context = mlds__make_context(Context),
MLDS_Defn = mlds__defn(Name, MLDS_Context, DeclFlags, Defn).
- % Return the declaration flags appropriate for a public field
- % in the derived constructor class of a discriminated union.
- %
ml_gen_public_field_decl_flags = DeclFlags :-
Access = public,
PerInstance = per_instance,
@@ -1647,7 +1520,6 @@
DeclFlags = init_decl_flags(Access, PerInstance,
Virtuality, Finality, Constness, Abstractness).
- % Return the declaration flags appropriate for a local variable.
ml_gen_local_var_decl_flags = DeclFlags :-
Access = local,
PerInstance = per_instance,
@@ -1658,12 +1530,9 @@
DeclFlags = init_decl_flags(Access, PerInstance,
Virtuality, Finality, Constness, Abstractness).
- % Return the declaration flags appropriate for an
- % initialized local static constant.
+ml_static_const_decl_flags = DeclFlags :-
% Note that rtti_decl_flags, in rtti_to_mlds.m,
% must be the same as this apart from the access.
- %
-ml_static_const_decl_flags = DeclFlags :-
Access = local,
PerInstance = one_copy,
Virtuality = non_virtual,
@@ -1682,15 +1551,12 @@
% Code for dealing with fields
%
- % Given the user-specified field name, if any,
- % and the argument number (starting from one),
- % generate an MLDS field name.
+ % Given the user-specified field name, if any, and the argument number
+ % (starting from one), generate an MLDS field name.
%
ml_gen_field_name(MaybeFieldName, ArgNum) = FieldName :-
- %
% If the programmer specified a field name, we use that,
% otherwise we just use `F' followed by the field number.
- %
(
MaybeFieldName = yes(QualifiedFieldName),
unqualify_name(QualifiedFieldName, FieldName)
@@ -1700,12 +1566,13 @@
).
% Succeed iff the specified type must be boxed when used as a field.
- % For the MLDS->C and MLDS->asm back-ends,
- % we need to box types that are not word-sized, because the code
- % for `arg' etc. in std_util.m rely on all arguments being word-sized.
- % XXX Currently we box such types even for the other MLDS based
- % back-ends that don't need it, e.g. the .NET and Java back-ends.
- % This routine should be modified to check the target.
+ % For the MLDS->C and MLDS->asm back-ends, we need to box types that are
+ % not word-sized, because the code for `arg' etc. in std_util.m rely
+ % on all arguments being word-sized.
+ % XXX Currently we box such types even for the other MLDS based back-ends
+ % that don't need it, e.g. the .NET and Java back-ends. This routine should
+ % be modified to check the target.
+ %
ml_must_box_field_type(Type, ModuleInfo) :-
classify_type(ModuleInfo, Type) = Category,
ml_must_box_field_type_category(Category) = yes.
@@ -1732,8 +1599,6 @@
% Code for handling success and failure
%
- % Generate code to succeed in the given code_model.
- %
ml_gen_success(model_det, _, Statements, !Info) :-
%
% det succeed:
@@ -1759,10 +1624,7 @@
%
ml_gen_call_current_success_cont(Context, CallCont, !Info).
- % Generate code to fail in the given code_model.
- %
ml_gen_failure(model_det, _, _, !Info) :-
- % this should never happen
error("ml_code_gen: `fail' has determinism `det'").
ml_gen_failure(model_semi, Context, [SetSuccessFalse], !Info) :-
%
@@ -1783,30 +1645,18 @@
%-----------------------------------------------------------------------------%
- % Generate the declaration for the built-in `succeeded' variable.
- %
ml_gen_succeeded_var_decl(Context) =
ml_gen_mlds_var_decl(var(var_name("succeeded", no)),
mlds__native_bool_type, no, Context).
- % Return the lval for the `succeeded' flag.
- % (`succeeded' is a boolean variable used to record
- % the success or failure of model_semi procedures.)
ml_success_lval(Info, SucceededLval) :-
ml_gen_var_lval(Info, var_name("succeeded", no), mlds__native_bool_type,
SucceededLval).
- % Return an rval which will test the value of the `succeeded' flag.
- % (`succeeded' is a boolean variable used to record
- % the success or failure of model_semi procedures.)
- %
ml_gen_test_success(Info, SucceededRval) :-
ml_success_lval(Info, SucceededLval),
SucceededRval = lval(SucceededLval).
- % Generate code to set the `succeeded' flag to the
- % specified truth value.
- %
ml_gen_set_success(Info, Value, Context, Statement) :-
ml_success_lval(Info, Succeeded),
Statement = ml_gen_assign(Succeeded, Value, Context).
@@ -1843,10 +1693,10 @@
ml_skip_dummy_argument_types(OutputVarTypes0, OutputVarLvals0,
OutputVarTypes, OutputVarLvals),
list__map(ml_gen_type(Info), OutputVarTypes, MLDS_OutputVarTypes),
- %
+
% We expect OutputVarlvals0 and OutputVarTypes0 to be empty if
% `--nondet-copy-out' is not enabled.
- %
+
ml_gen_var_lval(Info, mlds__var_name("cont", no),
mlds__cont_type(MLDS_OutputVarTypes), ContLval),
ml_gen_var_lval(Info, mlds__var_name("cont_env_ptr", no),
@@ -1873,52 +1723,47 @@
ml_skip_dummy_argument_types([], [_|_], _, _) :-
error("ml_skip_dummy_argument_types: length mismatch").
- % Generate code to call the current success continuation.
- % This is used for generating success when in a model_non context.
- %
ml_gen_call_current_success_cont(Context, Statement, !Info) :-
- ml_gen_info_current_success_cont(SuccCont, !Info),
- SuccCont = success_cont(FuncRval, EnvPtrRval,
- ArgTypes0, ArgLvals0),
+ ml_gen_info_current_success_cont(!.Info, SuccCont),
+ SuccCont = success_cont(FuncRval, EnvPtrRval, ArgTypes0, ArgLvals0),
ArgRvals0 = list__map(func(Lval) = lval(Lval), ArgLvals0),
ml_gen_info_use_gcc_nested_functions(!.Info, UseNestedFuncs),
- ( UseNestedFuncs = yes ->
+ (
+ UseNestedFuncs = yes,
ArgTypes = ArgTypes0,
ArgRvals = ArgRvals0
;
- ArgTypes = list__append(ArgTypes0,
- [mlds__generic_env_ptr_type]),
- ArgRvals = list__append(ArgRvals0, [EnvPtrRval])
+ UseNestedFuncs = no,
+ ArgTypes = ArgTypes0 ++ [mlds__generic_env_ptr_type],
+ ArgRvals =ArgRvals0 ++ [EnvPtrRval]
),
RetTypes = [],
Signature = mlds__func_signature(ArgTypes, RetTypes),
ObjectRval = no,
RetLvals = [],
CallKind = ordinary_call,
- Stmt = call(Signature, FuncRval, ObjectRval, ArgRvals, RetLvals,
- CallKind),
+ Stmt = call(Signature, FuncRval, ObjectRval, ArgRvals, RetLvals, CallKind),
Statement = mlds__statement(Stmt, mlds__make_context(Context)).
+ml_gen_call_current_success_cont_indirectly(Context, Statement, !Info) :-
% XXX this code is quite similar to some of the existing code
% for calling continuations when doing copy-in/copy-out.
% Sharing code should be investigated.
-ml_gen_call_current_success_cont_indirectly(Context, Statement, !Info) :-
-
- % We generate a call to the success continuation, just
- % as usual.
- ml_gen_info_current_success_cont(SuccCont, !Info),
+ % We generate a call to the success continuation, just as usual.
+ ml_gen_info_current_success_cont(!.Info, SuccCont),
SuccCont = success_cont(ContinuationFuncRval, EnvPtrRval,
ArgTypes0, ArgLvals0),
ArgRvals0 = list__map(func(Lval) = lval(Lval), ArgLvals0),
ml_gen_info_use_gcc_nested_functions(!.Info, UseNestedFuncs),
- ( UseNestedFuncs = yes ->
+ (
+ UseNestedFuncs = yes,
ArgTypes = ArgTypes0,
ArgRvals = ArgRvals0
;
- ArgTypes = list__append(ArgTypes0,
- [mlds__generic_env_ptr_type]),
- ArgRvals = list__append(ArgRvals0, [EnvPtrRval])
+ UseNestedFuncs = no,
+ ArgTypes = ArgTypes0 ++ [mlds__generic_env_ptr_type],
+ ArgRvals = ArgRvals0 ++ [EnvPtrRval]
),
RetTypes = [],
Signature = mlds__func_signature(ArgTypes, RetTypes),
@@ -1930,30 +1775,27 @@
ml_gen_info_get_module_name(!.Info, PredModule),
MLDS_Module = mercury_module_name_to_mlds(PredModule),
- % We generate a nested function that does the real call
- % to the continuation.
+ % We generate a nested function that does the real call to the
+ % continuation.
+ %
+ % All we do is change the call rvals to be the input variables, and the
+ % func rval to be the input variable for the continuation.
%
- % All we do is change the call rvals to be the input
- % variables, and the func rval to be the input variable
- % for the continuation.
- %
- % Note that ml_gen_cont_params does not fill in the
- % gc_trace_code for the parameters. This is OK, because
- % the parameters will not be used again after the call.
- % (Also currently this is only used for IL, for which GC
- % is the .NET CLR implementation's problem, not ours.)
+ % Note that ml_gen_cont_params does not fill in the gc_trace_code
+ % for the parameters. This is OK, because the parameters will not be used
+ % again after the call. (Also currently this is only used for IL, for which
+ % GC is the .NET CLR implementation's problem, not ours.)
%
ml_gen_cont_params(ArgTypes0, InnerFuncParams0, !Info),
InnerFuncParams0 = func_params(InnerArgs0, Rets),
InnerArgRvals = list__map(
(func(mlds__argument(Data, Type, _GC) )
- = lval(var(qual(MLDS_Module, module_qual,
- VarName), Type)) :-
+ = lval(var(qual(MLDS_Module, module_qual, VarName), Type)) :-
( Data = data(var(VarName0)) ->
VarName = VarName0
;
- error("expected variable name " ++
- "in continuation parameters")
+ unexpected(this_file,
+ "expected variable name in continuation parameters")
)
), InnerArgs0),
InnerFuncArgType = mlds__cont_type(ArgTypes0),
@@ -1965,27 +1807,24 @@
InnerFuncArgType, PassedContGCTraceCode),
InnerFuncRval = lval(var(qual(MLDS_Module, module_qual,
PassedContVarName), InnerFuncArgType)),
- InnerFuncParams = func_params([PassedContArg | InnerArgs0],
- Rets),
+ InnerFuncParams = func_params([PassedContArg | InnerArgs0], Rets),
InnerStmt = call(Signature, InnerFuncRval, ObjectRval,
InnerArgRvals, RetLvals, CallKind),
InnerStatement = statement(InnerStmt, MLDS_Context),
- ml_gen_label_func(!.Info, 1, InnerFuncParams, Context,
- InnerStatement, Defn),
+ ml_gen_label_func(!.Info, 1, InnerFuncParams, Context, InnerStatement,
+ Defn),
ProxySignature = mlds__func_signature([InnerFuncArgType | ArgTypes],
RetTypes),
ProxyArgRvals = [ContinuationFuncRval | ArgRvals],
(
Defn = mlds__defn(function(PredLabel, ProcId,
- yes(SeqNum), _), _, _, function(_, _,
- defined_here(_), _))
+ yes(SeqNum), _), _, _, function(_, _, defined_here(_), _))
->
% We call the proxy function.
- QualProcLabel = qual(MLDS_Module, module_qual,
- PredLabel - ProcId),
+ QualProcLabel = qual(MLDS_Module, module_qual, PredLabel - ProcId),
ProxyFuncRval = const(code_addr_const(
internal(QualProcLabel, SeqNum, ProxySignature))),
@@ -1993,10 +1832,10 @@
Stmt = call(ProxySignature, ProxyFuncRval, ObjectRval,
ProxyArgRvals, RetLvals, CallKind),
Statement = mlds__statement(
- block([Defn], [statement(Stmt, MLDS_Context)]),
- MLDS_Context)
+ block([Defn], [statement(Stmt, MLDS_Context)]), MLDS_Context)
;
- error("success continuation generated was not a function")
+ unexpected(this_file,
+ "success continuation generated was not a function")
).
%-----------------------------------------------------------------------------%
@@ -2005,27 +1844,17 @@
% used for nested functions.
%
- % Return an rval for a pointer to the current environment
- % (the set of local variables in the containing procedure).
- % Note that we generate this as a dangling reference.
- % The ml_elim_nested pass will insert the declaration
- % of the env_ptr variable. At this point the type of these rvals
- % is `mlds__unknown_type'.
- %
ml_get_env_ptr(Info, lval(EnvPtrLval)) :-
ml_gen_var_lval(Info, mlds__var_name("env_ptr", no),
mlds__unknown_type, EnvPtrLval).
- % Return an rval for a pointer to the current environment
- % (the set of local variables in the containing procedure).
ml_declare_env_ptr_arg(mlds__argument(Name, Type, GC_TraceCode)) :-
Name = data(var(mlds__var_name("env_ptr_arg", no))),
Type = mlds__generic_env_ptr_type,
- % The env_ptr_arg always points to the stack,
- % since continuation environments are always allocated
- % on the stack (unless put_nondet_env_on_heap is true,
- % which won't be the case when doing our own GC --
- % this is enforced in handle_options.m).
+ % The env_ptr_arg always points to the stack, since continuation
+ % environments are always allocated on the stack (unless
+ % put_nondet_env_on_heap is true, which won't be the case when
+ % doing our own GC -- this is enforced in handle_options.m).
% So the GC doesn't need to trace it.
GC_TraceCode = no.
@@ -2034,10 +1863,6 @@
% Code to handle accurate GC
%
- % If accurate GC is enabled, and the specified
- % variable might contain pointers, generate code to call
- % `private_builtin__gc_trace' to trace the variable.
- %
ml_gen_maybe_gc_trace_code(VarName, Type, Context, Maybe_GC_TraceCode,
!Info) :-
ml_gen_maybe_gc_trace_code(VarName, Type, Type, Context,
@@ -2071,13 +1896,11 @@
globals__get_gc_method(Globals, GC),
(
GC = accurate,
- MLDS_DeclType = mercury_type_to_mlds_type(ModuleInfo,
- DeclType),
+ MLDS_DeclType = mercury_type_to_mlds_type(ModuleInfo, DeclType),
ml_type_might_contain_pointers(MLDS_DeclType) = yes,
% don't generate GC tracing code in no_type_info_builtins
ml_gen_info_get_pred_id(!.Info, PredId),
- predicate_id(ModuleInfo, PredId, PredModule, PredName,
- PredArity),
+ predicate_id(ModuleInfo, PredId, PredModule, PredName, PredArity),
\+ no_type_info_builtin(PredModule, PredName, PredArity)
->
(
@@ -2093,40 +1916,35 @@
Context, GC_TraceCode, !Info)
;
HowToGetTypeInfo = already_provided(TypeInfoRval),
- ml_gen_trace_var(!.Info, VarName, DeclType,
- TypeInfoRval, Context, GC_TraceCode)
+ ml_gen_trace_var(!.Info, VarName, DeclType, TypeInfoRval,
+ Context, GC_TraceCode)
),
Maybe_GC_TraceCode = yes(GC_TraceCode)
;
Maybe_GC_TraceCode = no
).
- % Return `yes' if the type needs to be traced by
- % the accurate garbage collector, i.e. if it might
- % contain pointers.
- %
- % Any type for which we return `yes' here must be word-sized,
- % because we will call private_builtin__gc_trace with its address,
- % and that procedure assumes that its argument is an `MR_Word *'.
+ % Return `yes' if the type needs to be traced by the accurate garbage
+ % collector, i.e. if it might contain pointers.
+ %
+ % Any type for which we return `yes' here must be word-sized, because
+ % we will call private_builtin__gc_trace with its address, and that
+ % procedure assumes that its argument is an `MR_Word *'.
%
% For floats, we can (and must) return `no' even though they might
- % get boxed in some circumstances, because if they are
- % boxed then they will be represented as mlds__generic_type.
+ % get boxed in some circumstances, because if they are boxed then they will
+ % be represented as mlds__generic_type.
+ %
+ % Note that with --gcc-nested-functions, cont_type will be a function
+ % pointer that may point to a trampoline function, which might in fact
+ % contain pointers. But the pointers will only be pointers to code and
+ % pointers to the stack, not pointers to the heap, so we don't need to
+ % trace them for accurate GC. Hence we can return `no' here for
+ % mlds__cont_type.
+ %
+ % Similarly, the only pointers in type_ctor_infos and base_typeclass_infos
+ % are to static code and/or static data, which do not need to be traced.
%
- % Note that with --gcc-nested-functions,
- % cont_type will be a function pointer that
- % may point to a trampoline function,
- % which might in fact contain pointers.
- % But the pointers will only be pointers to
- % code and pointers to the stack, not pointers
- % to the heap, so we don't need to trace them
- % for accurate GC.
- % Hence we can return `no' here for mlds__cont_type.
- %
- % Similarly, the only pointers in type_ctor_infos and
- % base_typeclass_infos are to static code and/or static data,
- % which do not need to be traced.
-
:- func ml_type_might_contain_pointers(mlds__type) = bool.
ml_type_might_contain_pointers(mercury_type(_Type, TypeCategory, _)) =
@@ -2154,6 +1972,7 @@
ml_type_might_contain_pointers(mlds__unknown_type) = yes.
:- func ml_type_category_might_contain_pointers(type_category) = bool.
+
ml_type_category_might_contain_pointers(int_type) = no.
ml_type_category_might_contain_pointers(char_type) = no.
ml_type_category_might_contain_pointers(str_type) = yes.
@@ -2170,9 +1989,10 @@
ml_type_category_might_contain_pointers(user_ctor_type) = yes.
% trace_type_info_type(Type, RealType):
- % Succeed iff Type is a type_info-related type
- % which needs to be copied as if it were some other type,
- % binding RealType to that other type.
+ %
+ % Succeed iff Type is a type_info-related type which needs to be copied
+ % as if it were some other type, binding RealType to that other type.
+ %
:- pred trace_type_info_type(prog_type::in, prog_type::out) is semidet.
trace_type_info_type(Type, RealType) :-
@@ -2206,33 +2026,31 @@
goal_info_init(NonLocals, InstMapDelta, det, impure, GoalInfo),
conj_list_to_goal(HLDS_TypeInfoGoals, GoalInfo, Conj),
- % Convert this HLDS code to MLDS
+ % Convert this HLDS code to MLDS.
ml_gen_goal(model_det, Conj, MLDS_TypeInfoStatement0, !Info),
- % Replace all heap allocation (new_object instructions)
- % with stack allocation (local variable declarations)
- % in the code to construct type_infos. This is safe
- % because those type_infos will only be used in the
- % immediately following call to gc_trace/1.
+ % Replace all heap allocation (new_object instructions) with stack
+ % allocation (local variable declarations) in the code to construct
+ % type_infos. This is safe because those type_infos will only be used
+ % in the immediately following call to gc_trace/1.
ml_gen_info_get_module_info(!.Info, ModuleInfo),
module_info_name(ModuleInfo, ModuleName),
fixup_newobj(MLDS_TypeInfoStatement0,
mercury_module_name_to_mlds(ModuleName),
MLDS_TypeInfoStatement, MLDS_NewobjLocals),
- % Build MLDS code to trace the variable
+ % Build MLDS code to trace the variable.
ml_gen_var(!.Info, TypeInfoVar, TypeInfoLval),
ml_gen_trace_var(!.Info, VarName, DeclType, lval(TypeInfoLval), Context,
MLDS_TraceStatement),
% Generate declarations for any type_info variables used.
%
- % Note: this will generate local declarations even for
- % type_info variables which are not local to this goal.
- % However, fortunately ml_elim_nested.m will transform
- % the GC code to use the original definitions, which will
- % get put in the GC frame, rather than these declarations,
- % which will get ignored.
+ % Note: this will generate local declarations even for type_info variables
+ % which are not local to this goal. However, fortunately ml_elim_nested.m
+ % will transform the GC code to use the original definitions, which will
+ % get put in the GC frame, rather than these declarations, which will get
+ % ignored.
% XXX This is not a very robust way of doing things...
ml_gen_info_get_varset(!.Info, VarSet),
ml_gen_info_get_var_types(!.Info, VarTypes),
@@ -2242,18 +2060,15 @@
LocalVarName = ml_gen_var_name(VarSet, Var),
map__lookup(VarTypes, Var, LocalVarType),
MLDS_Defn = ml_gen_mlds_var_decl(var(LocalVarName),
- mercury_type_to_mlds_type(ModuleInfo,
- LocalVarType),
+ mercury_type_to_mlds_type(ModuleInfo, LocalVarType),
no, MLDS_Context)
),
set__to_sorted_list(NonLocals, NonLocalVarList),
MLDS_NonLocalVarDecls = list__map(GenLocalVarDecl, NonLocalVarList),
% Combine the MLDS code fragments together.
- GC_TraceCode = ml_gen_block(
- MLDS_NewobjLocals ++ MLDS_NonLocalVarDecls,
- [MLDS_TypeInfoStatement] ++ [MLDS_TraceStatement],
- Context).
+ GC_TraceCode = ml_gen_block(MLDS_NewobjLocals ++ MLDS_NonLocalVarDecls,
+ [MLDS_TypeInfoStatement] ++ [MLDS_TraceStatement], Context).
% ml_gen_trace_var(VarName, DeclType, TypeInfo, Context, Code):
% Generate a call to `private_builtin__gc_trace'
@@ -2264,15 +2079,12 @@
mlds__rval::in, prog_context::in, mlds__statement::out) is det.
ml_gen_trace_var(Info, VarName, Type, TypeInfoRval, Context, TraceStatement) :-
- %
- % Generate the lval for Var
- %
+ % Generate the lval for Var.
ml_gen_info_get_module_info(Info, ModuleInfo),
MLDS_Type = mercury_type_to_mlds_type(ModuleInfo, Type),
ml_gen_var_lval(Info, VarName, MLDS_Type, VarLval),
- %
- % Generate the address of `private_builtin__gc_trace/1#0'
- %
+
+ % Generate the address of `private_builtin__gc_trace/1#0'.
PredName = "gc_trace",
PredOrigArity = 1,
Pred = pred((predicate), no, PredName, PredOrigArity, model_det, no),
@@ -2285,10 +2097,9 @@
ArgTypes = [mlds__pseudo_type_info_type, CPointerType],
Signature = mlds__func_signature(ArgTypes, []),
FuncAddr = const(code_addr_const(proc(Proc, Signature))),
- %
+
% Generate the call
% `private_builtin__gc_trace(TypeInfo, (MR_C_Pointer) &Var);'.
- %
CastVarAddr = unop(cast(CPointerType), mem_addr(VarLval)),
TraceStatement = mlds__statement(
call(Signature, FuncAddr, no,
@@ -2302,35 +2113,27 @@
ml_gen_info::in, ml_gen_info::out) is det.
ml_gen_make_type_info_var(Type, Context, TypeInfoVar, TypeInfoGoals, !Info) :-
- %
- % Extract the relevant information from the ml_gen_info
- %
ModuleInfo0 = !.Info ^ module_info,
PredId = !.Info ^ pred_id,
ProcId = !.Info ^ proc_id,
module_info_pred_proc_info(ModuleInfo0, PredId, ProcId,
PredInfo0, ProcInfo0),
- %
- % Call polymorphism.m to generate the HLDS code to
- % create the type_infos.
- %
+ % Call polymorphism.m to generate the HLDS code to create the type_infos.
create_poly_info(ModuleInfo0, PredInfo0, ProcInfo0, PolyInfo0),
polymorphism__make_type_info_var(Type, Context,
TypeInfoVar, TypeInfoGoals, PolyInfo0, PolyInfo),
poly_info_extract(PolyInfo, PredInfo0, PredInfo,
ProcInfo0, ProcInfo, ModuleInfo1),
- %
- % Save the new information back in the ml_gen_info
- %
+ % Save the new information back in the ml_gen_info.
module_info_set_pred_proc_info(PredId, ProcId, PredInfo, ProcInfo,
ModuleInfo1, ModuleInfo),
proc_info_varset(ProcInfo, VarSet),
proc_info_vartypes(ProcInfo, VarTypes),
- !:Info = (((!.Info ^ module_info := ModuleInfo)
- ^ varset := VarSet)
- ^ var_types := VarTypes).
+ !:Info = !.Info ^ module_info := ModuleInfo,
+ !:Info = !.Info ^ varset := VarSet,
+ !:Info = !.Info ^ var_types := VarTypes.
%-----------------------------------------------------------------------------%
@@ -2338,20 +2141,23 @@
---> fixup_newobj_info(
module_name :: mlds_module_name,
% the current module
+
context :: mlds__context,
% the current context
+
locals :: mlds__defns,
% the local variable declarations
% accumulated so far
+
next_id :: counter
% a counter used to allocate
% variable names
).
- % Replace all heap allocation (new_object instructions)
- % with stack allocation (local variable declarations)
- % in the specified statement, returning the local
- % variable declarations needed for the stack allocation.
+ % Replace all heap allocation (new_object instructions) with stack
+ % allocation (local variable declarations) in the specified statement,
+ % returning the local variable declarations needed for the stack
+ % allocation.
%
:- pred fixup_newobj(mlds__statement::in, mlds_module_name::in,
mlds__statement::out, mlds__defns::out) is det.
@@ -2454,56 +2260,49 @@
fixup_newobj_in_atomic_statement(AtomicStatement0, Stmt, !Fixup) :-
(
- AtomicStatement0 = new_object(Lval, MaybeTag, _HasSecTag,
- PointerType, _MaybeSizeInWordsRval, _MaybeCtorName,
- ArgRvals, _ArgTypes)
+ AtomicStatement0 = new_object(Lval, MaybeTag, _HasSecTag, PointerType,
+ _MaybeSizeInWordsRval, _MaybeCtorName, ArgRvals, _ArgTypes)
->
+ % Generate the declaration of the new local variable.
%
- % generate the declaration of the new local variable
- %
- % XXX Using array(generic_type) is wrong for
- % --high-level-data.
- %
- % We need to specify an initializer to tell the
- % C back-end what the length of the array is.
- % We initialize it with null pointers and then
- % later generate assignment statements to fill
- % in the values properly (see below).
+ % XXX Using array(generic_type) is wrong for --high-level-data.
%
+ % We need to specify an initializer to tell the C back-end what the
+ % length of the array is. We initialize it with null pointers and then
+ % later generate assignment statements to fill in the values properly
+ % (see below).
counter__allocate(Id, !.Fixup ^ next_id, NextId),
VarName = var_name("new_obj", yes(Id)),
VarType = mlds__array_type(mlds__generic_type),
NullPointers = list__duplicate(list__length(ArgRvals),
init_obj(const(mlds__null(mlds__generic_type)))),
Initializer = init_array(NullPointers),
- % this is used for the type_infos allocated during tracing,
- % and we don't need to trace them
+ % This is used for the type_infos allocated during tracing,
+ % and we don't need to trace them.
MaybeGCTraceCode = no,
Context = !.Fixup ^ context,
VarDecl = ml_gen_mlds_var_decl(var(VarName),
VarType, Initializer, MaybeGCTraceCode, Context),
!:Fixup = !.Fixup ^ next_id := NextId,
!:Fixup= !.Fixup ^ locals := !.Fixup ^ locals ++ [VarDecl],
- %
+
% Generate code to initialize the variable.
%
- % Note that we need to use assignment statements,
- % rather than an initializer, to initialize the
- % local variable, because the initialization code
- % needs to occur at exactly the point where the
- % atomic_statement occurs, rather than at the
- % local variable declaration.
- %
+ % Note that we need to use assignment statements, rather than an
+ % initializer, to initialize the local variable, because the
+ % initialization code needs to occur at exactly the point where the
+ % atomic_statement occurs, rather than at the local variable
+ % declaration.
+
VarLval = mlds__var(qual(!.Fixup ^ module_name, module_qual,
VarName), VarType),
PtrRval = mlds__unop(cast(PointerType), mem_addr(VarLval)),
list__map_foldl(
init_field_n(PointerType, PtrRval, Context),
ArgRvals, ArgInitStatements, 0, _NumFields),
- %
- % generate code to assign the address of the new local
- % variable to the Lval
- %
+
+ % Generate code to assign the address of the new local variable
+ % to the Lval.
TaggedPtrRval = maybe_tag_rval(MaybeTag, PointerType, PtrRval),
AssignStmt = atomic(assign(Lval, TaggedPtrRval)),
AssignStatement = mlds__statement(AssignStmt, Context),
@@ -2536,7 +2335,6 @@
% The definition of the `ml_gen_info' ADT.
%
-%
% The `ml_gen_info' type holds information used during MLDS code generation
% for a given procedure.
%
@@ -2544,18 +2342,14 @@
% `var_lvals', `success_cont_stack', and `extra_defns' fields are mutable;
% the others are set when the `ml_gen_info' is created and then never
% modified.
-%
:- type ml_gen_info
---> ml_gen_info(
- %
- % these fields remain constant for each procedure
- %
+ % These fields remain constant for each procedure
% (unless accurate GC is enabled, in which case the
% varset and var_types may get updated if we create
% fresh variables for type_info variables needed
- % for calls to private_builtin__gc_trace)
- %
+ % for calls to private_builtin__gc_trace).
module_info :: module_info,
pred_id :: pred_id,
@@ -2569,10 +2363,7 @@
% output arguments that are returned
% as values
- %
- % these fields get updated as we traverse
- % each procedure
- %
+ % These fields get updated as we traverse each procedure.
func_label :: counter,
commit_label :: counter,
@@ -2582,14 +2373,14 @@
const_num :: counter,
const_num_map :: map(prog_var, const_seq),
success_cont_stack :: stack(success_cont),
- % a partial mapping from vars to lvals,
+ % A partial mapping from vars to lvals,
% used to override the normal lval
- % that we use for a variable
+ % that we use for a variable.
var_lvals :: map(prog_var, mlds__lval),
- % definitions of functions or global
+ % Definitions of functions or global
% constants which should be inserted
% before the definition of the function
- % for the current procedure
+ % for the current procedure.
extra_defns :: mlds__defns
).
@@ -2673,97 +2464,104 @@
ml_gen_info_get_module_info(Info, ModuleInfo),
module_info_globals(ModuleInfo, Globals).
-ml_gen_info_new_label(Label, Info0, Info) :-
- Counter0 = Info0 ^ label,
+ml_gen_info_new_label(Label, !Info) :-
+ Counter0 = !.Info ^ label,
counter__allocate(Label, Counter0, Counter),
- Info = Info0 ^ label := Counter.
+ !:Info = !.Info ^ label := Counter.
-ml_gen_info_new_func_label(Label, Info0, Info) :-
- Counter0 = Info0 ^ func_label,
+ml_gen_info_new_func_label(Label, !Info) :-
+ Counter0 = !.Info ^ func_label,
counter__allocate(Label, Counter0, Counter),
- Info = Info0 ^ func_label := Counter.
+ !:Info = !.Info ^ func_label := Counter.
-ml_gen_info_bump_counters(Info0, Info) :-
- FuncLabelCounter0 = Info0 ^ func_label,
- ConstNumCounter0 = Info0 ^ const_num,
+ml_gen_info_bump_counters(!Info) :-
+ FuncLabelCounter0 = !.Info ^ func_label,
+ ConstNumCounter0 = !.Info ^ const_num,
counter__allocate(FuncLabel, FuncLabelCounter0, _),
counter__allocate(ConstNum, ConstNumCounter0, _),
FuncLabelCounter = counter__init(FuncLabel + 10000),
ConstNumCounter = counter__init(ConstNum + 10000),
- Info = ((Info0 ^ func_label := FuncLabelCounter)
- ^ const_num := ConstNumCounter).
+ !:Info = !.Info ^ func_label := FuncLabelCounter,
+ !:Info = !.Info ^ const_num := ConstNumCounter.
-ml_gen_info_new_commit_label(CommitLabel, Info0, Info) :-
- Counter0 = Info0 ^ commit_label,
+ml_gen_info_new_commit_label(CommitLabel, !Info) :-
+ Counter0 = !.Info ^ commit_label,
counter__allocate(CommitLabel, Counter0, Counter),
- Info = Info0 ^ commit_label := Counter.
+ !:Info = !.Info ^ commit_label := Counter.
-ml_gen_info_new_cond_var(CondVar, Info0, Info) :-
- Counter0 = Info0 ^ cond_var,
+ml_gen_info_new_cond_var(CondVar, !Info) :-
+ Counter0 = !.Info ^ cond_var,
counter__allocate(CondVar, Counter0, Counter),
- Info = Info0 ^ cond_var := Counter.
+ !:Info = !.Info ^ cond_var := Counter.
-ml_gen_info_new_conv_var(ConvVar, Info0, Info) :-
- Counter0 = Info0 ^ conv_var,
+ml_gen_info_new_conv_var(ConvVar, !Info) :-
+ Counter0 = !.Info ^ conv_var,
counter__allocate(ConvVar, Counter0, Counter),
- Info = Info0 ^ conv_var := Counter.
+ !:Info = !.Info ^ conv_var := Counter.
-ml_gen_info_new_const(ConstVar, Info0, Info) :-
- Counter0 = Info0 ^ const_num,
+ml_gen_info_new_const(ConstVar, !Info) :-
+ Counter0 = !.Info ^ const_num,
counter__allocate(ConstVar, Counter0, Counter),
- Info = Info0 ^ const_num := Counter.
+ !:Info = !.Info ^ const_num := Counter.
-ml_gen_info_set_const_num(Var, ConstVar, Info,
- Info ^ const_num_map := map__set(Info ^ const_num_map, Var, ConstVar)).
+ml_gen_info_set_const_num(Var, ConstVar, !Info) :-
+ !:Info = !.Info ^ const_num_map :=
+ map__set(!.Info ^ const_num_map, Var, ConstVar).
ml_gen_info_lookup_const_num(Info, Var, ConstVar) :-
ConstVar = map__lookup(Info ^ const_num_map, Var).
-ml_gen_info_push_success_cont(SuccCont, Info,
- Info ^ success_cont_stack :=
- stack__push(Info ^ success_cont_stack, SuccCont)).
+ml_gen_info_push_success_cont(SuccCont, !Info) :-
+ !:Info = !.Info ^ success_cont_stack :=
+ stack__push(!.Info ^ success_cont_stack, SuccCont).
-ml_gen_info_pop_success_cont(Info0, Info) :-
- Stack0 = Info0 ^ success_cont_stack,
+ml_gen_info_pop_success_cont(!Info) :-
+ Stack0 = !.Info ^ success_cont_stack,
stack__pop_det(Stack0, _SuccCont, Stack),
- Info = (Info0 ^ success_cont_stack := Stack).
+ !:Info = !.Info ^ success_cont_stack := Stack.
-ml_gen_info_current_success_cont(SuccCont, Info, Info) :-
+ml_gen_info_current_success_cont(Info, SuccCont) :-
stack__top_det(Info ^ success_cont_stack, SuccCont).
-ml_gen_info_set_var_lval(Var, Lval, Info,
- Info ^ var_lvals := map__set(Info ^ var_lvals, Var, Lval)).
+ml_gen_info_set_var_lval(Var, Lval, !Info) :-
+ !:Info = !.Info ^ var_lvals := map__set(!.Info ^ var_lvals, Var, Lval).
ml_gen_info_get_var_lvals(Info, Info ^ var_lvals).
-ml_gen_info_set_var_lvals(VarLvals, Info, Info ^ var_lvals := VarLvals).
+ml_gen_info_set_var_lvals(VarLvals, !Info) :-
+ !:Info = !.Info ^ var_lvals := VarLvals.
-ml_gen_info_add_extra_defn(ExtraDefn, Info,
- Info ^ extra_defns := [ExtraDefn | Info ^ extra_defns]).
+ml_gen_info_add_extra_defn(ExtraDefn, !Info) :-
+ !:Info = !.Info ^ extra_defns := [ExtraDefn | !.Info ^ extra_defns].
ml_gen_info_get_extra_defns(Info, Info ^ extra_defns).
%-----------------------------------------------------------------------------%
- % Given a list of variables and their corresponding modes,
- % return a list containing only those variables which have
- % an output mode.
- %
select_output_vars(ModuleInfo, HeadVars, HeadModes, VarTypes) = OutputVars :-
- ( HeadVars = [], HeadModes = [] ->
+ (
+ HeadVars = [],
+ HeadModes = [],
OutputVars = []
- ; HeadVars = [Var|Vars], HeadModes = [Mode|Modes] ->
+ ;
+ HeadVars = [Var | Vars],
+ HeadModes = [Mode | Modes],
map__lookup(VarTypes, Var, VarType),
(
mode_to_arg_mode(ModuleInfo, Mode, VarType, top_out)
->
- OutputVars1 = select_output_vars(ModuleInfo,
- Vars, Modes, VarTypes),
+ OutputVars1 = select_output_vars(ModuleInfo, Vars, Modes,
+ VarTypes),
OutputVars = [Var | OutputVars1]
;
- OutputVars = select_output_vars(ModuleInfo,
- Vars, Modes, VarTypes)
+ OutputVars = select_output_vars(ModuleInfo, Vars, Modes, VarTypes)
)
;
+ HeadVars = [],
+ HeadModes = [_ | _],
+ error("select_output_vars: length mismatch")
+ ;
+ HeadVars = [_ | _],
+ HeadModes = [],
error("select_output_vars: length mismatch")
).
@@ -2809,18 +2607,13 @@
% Miscellaneous routines
%
- % Get the value of the appropriate --det-copy-out or --nondet-copy-out
- % option, depending on the code model.
get_copy_out_option(Globals, CodeModel) = CopyOut :-
( CodeModel = model_non ->
- globals__lookup_bool_option(Globals,
- nondet_copy_out, CopyOut)
+ globals__lookup_bool_option(Globals, nondet_copy_out, CopyOut)
;
- globals__lookup_bool_option(Globals,
- det_copy_out, CopyOut)
+ globals__lookup_bool_option(Globals, det_copy_out, CopyOut)
).
- % Add the qualifier `builtin' to any unqualified name.
fixup_builtin_module(ModuleName0) = ModuleName :-
( ModuleName0 = unqualified("") ->
mercury_public_builtin_module(ModuleName)
@@ -2831,9 +2624,9 @@
%-----------------------------------------------------------------------------%
:- func this_file = string.
+
this_file = "ml_code_util.m".
:- end_module ml_code_util.
-%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
Index: compiler/ml_elim_nested.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/ml_elim_nested.m,v
retrieving revision 1.71
diff -u -b -r1.71 ml_elim_nested.m
--- compiler/ml_elim_nested.m 1 Sep 2005 09:06:33 -0000 1.71
+++ compiler/ml_elim_nested.m 12 Sep 2005 13:47:33 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 1999-2005 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -31,17 +33,16 @@
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
-% Note that this module does not attempt to handle arbitrary MLDS
-% as input; it will only work with the output of the current MLDS
-% code generator. In particular, it assumes that local variables
-% in nested functions can be hoisted into the outermost function's
-% environment. That's not true in general (e.g. if the nested
-% functions are recursive), but it's true for the code that ml_code_gen
-% generates.
-
-% As well as eliminating nested functions, this transformation
-% also has the effect of fixing up the dangling `env_ptr' references
-% that ml_code_gen.m leaves in the code.
+% Note that this module does not attempt to handle arbitrary MLDS as input;
+% it will only work with the output of the current MLDS code generator.
+% In particular, it assumes that local variables in nested functions can be
+% hoisted into the outermost function's environment. That's not true
+% in general (e.g. if the nested functions are recursive), but it's true
+% for the code that ml_code_gen generates.
+
+% As well as eliminating nested functions, this transformation also has
+% the effect of fixing up the dangling `env_ptr' references that ml_code_gen.m
+% leaves in the code.
%-----------------------------------------------------------------------------%
% TRANSFORMATION SUMMARY
@@ -140,105 +141,94 @@
%
% SUMMARY
%
-% This is an MLDS-to-MLDS transformation that transforms the
-% MLDS code to add the information needed to do accurate GC
-% when compiling to C (or to assembler).
-%
-% Basically what we do is to put all local variables that might
-% contain pointers in structs, with one struct for each stack frame,
-% and chain these structs together. At GC time, we traverse the chain
-% of structs. This allows us to accurately scan the C stack.
+% This is an MLDS-to-MLDS transformation that transforms the MLDS code
+% to add the information needed to do accurate GC when compiling to C
+% (or to assembler).
+%
+% Basically what we do is to put all local variables that might contain
+% pointers in structs, with one struct for each stack frame, and chain
+% these structs together. At GC time, we traverse the chain of structs.
+% This allows us to accurately scan the C stack.
%
% This is described in more detail in the following paper:
+%
% Fergus Henderson <fjh at cs.mu.oz.au>,
% "Accurate garbage collection in an uncooperative environment".
% International Symposium on Memory Management, Berlin, Germany, 2002.
%
-% In theory accurate GC is now fully implemented,
-% i.e. it should support the whole Mercury language,
-% modulo the caveats below.
+% In theory accurate GC is now fully implemented, i.e. it should support
+% the whole Mercury language, modulo the caveats below.
+%
% TODO:
% - XXX Need to test the GC tracing code for type class methods.
-% This code in theory ought to work, I think, but it has not
-% really been tested.
+% This code in theory ought to work, I think, but it has not really been
+% tested.
%
% - XXX The garbage collector should resize the heap if/when it fills up.
% We should allocate a large amount of virtual memory for each heap,
% but we should collect when we've allocated a small part of it.
%
% - Heap reclamation on failure is not yet supported.
-% One difficulty is that when resetting the heap,
-% we need to also reset all the local variables which might
-% point to reclaimed garbage, otherwise the collector might
-% try to trace through them, which can result in an error
-% since the data pointed to isn't of the right type
-% because it has been overwritten.
-%
-% - The garbage collector should collect the solutions heap
-% and the global heap as well as the ordinary heap.
-%
-% Note that this is currently not an issue, since
-% currently we don't use these heaps, because we don't support
-% heap reclamation on failure or tabling (respectively).
-%
-% Actually I think GC of these heaps should almost work already,
-% or would once we start using these heaps, because we never
-% allocate on the solutions heap or the global heap directly,
-% instead we swap heaps to make the heap that we want to
-% allocate on the main heap. Then if that heap runs out of
-% space, we will invoke a garbage collection, and everything
+% One difficulty is that when resetting the heap, we need to also reset
+% all the local variables which might point to reclaimed garbage, otherwise
+% the collector might try to trace through them, which can result in an error
+% since the data pointed to isn't of the right type because it has been
+% overwritten.
+%
+% - The garbage collector should collect the solutions heap and the global heap
+% as well as the ordinary heap.
+%
+% Note that this is currently not an issue, since currently we don't use
+% these heaps, because we don't support heap reclamation on failure or
+% tabling (respectively).
+%
+% Actually I think GC of these heaps should almost work already, or would
+% once we start using these heaps, because we never allocate on the
+% solutions heap or the global heap directly, instead we swap heaps to make
+% the heap that we want to allocate on the main heap. Then if that heap
+% runs out of space, we will invoke a garbage collection, and everything
% should work fine. However, there are a couple of problems.
%
-% First, GC will swap the to-space heap and the from-space heap.
-% So if the different heaps are different sizes, we may end up
-% with the to-space heap being too small (e.g. because it was
-% originally the solutions heap). To fix that, we can just
-% allocate large total sizes for all the heaps; see the point above
-% about heap resizing.
-%
-% Second, for GC of the global heap to work,
-% the runtime routines which allocate stuff on that heap need
-% to be modified to support GC. In particular, MR_deep_copy()
-% and MR_make_long_lived() and its callers need be modified so that
-% they are safe for GC (i.e. they must record all parameters
-% and locals that point to the heap on the GC's shadow stack),
-% and MR_deep_copy() needs to call MR_GC_check() before each
-% heap allocation.
+% First, GC will swap the to-space heap and the from-space heap. So if the
+% different heaps are different sizes, we may end up with the to-space heap
+% being too small (e.g. because it was originally the solutions heap).
+% To fix that, we can just allocate large total sizes for all the heaps;
+% see the point above about heap resizing.
+%
+% Second, for GC of the global heap to work, the runtime routines which
+% allocate stuff on that heap need to be modified to support GC.
+% In particular, MR_deep_copy() and MR_make_long_lived() and its callers
+% need be modified so that they are safe for GC (i.e. they must record
+% all parameters and locals that point to the heap on the GC's shadow stack),
+% and MR_deep_copy() needs to call MR_GC_check() before each heap allocation.
%
% - XXX We need to handle `pragma export'.
%
-% The C interface in general is a bit problematic for GC.
-% But for code which does not call back to Mercury,
-% the way we currently handle it is fairly safe even
-% if the C code uses pointers to the Mercury heap
-% or allocates on the Mercury heap, because such code will
-% not invoke the GC. So the worst that can go wrong is a heap
-% overflow. Provided that the C code does not allocate too
-% much (more than MR_heap_margin_size), it won't overflow
-% the heap, and the heap will get GC'd next time you call
-% some Mercury code which does a heap allocation.
-% Of course you may run into problems if there is
-% a loop that calls C code which allocates on the Mercury heap,
-% and the loop contains no intervening calls to Mercury code that
-% allocates heap space (and hence calls MR_GC_check()).
-%
-% But if Mercury code calls C code which calls back to Mercury
-% code, and the C code uses pointers to the Mercury heap,
-% then there could be serious problems (i.e. dangling pointers).
-% Even if you just use `pragma export' to export a procedure
-% and `pragma import' to import it back again, there may be
-% trouble.
-% The code generated for the exported functions can include
-% calls to MR_MAYBE_BOX_FOREIGN_TYPE, which may allocate heap;
-% we ought to register the frame and call MR_GC_check() before
-% each call to MR_MAYBE_BOX_FOREIGN_TYPE, but currently we don't.
-%
-% Even if that was solved, there is still
-% the issue of what to do about any heap pointers
-% held by user-written C code; we need to provide an API for
-% registering pointers on the stack.
-% (MR_agc_add_root() only works for globals, really, since
-% there's no MR_agc_remove_root()).
+% The C interface in general is a bit problematic for GC. But for code which
+% does not call back to Mercury, the way we currently handle it is fairly
+% safe even if the C code uses pointers to the Mercury heap or allocates
+% on the Mercury heap, because such code will not invoke the GC. So the worst
+% that can go wrong is a heap overflow. Provided that the C code does not
+% allocate too much (more than MR_heap_margin_size), it won't overflow the
+% heap, and the heap will get GC'd next time you call some Mercury code
+% which does a heap allocation. Of course you may run into problems if
+% there is a loop that calls C code which allocates on the Mercury heap,
+% and the loop contains no intervening calls to Mercury code that allocates
+% heap space (and hence calls MR_GC_check()).
+%
+% But if Mercury code calls C code which calls back to Mercury code,
+% and the C code uses pointers to the Mercury heap, then there could be
+% serious problems (i.e. dangling pointers). Even if you just use
+% `pragma export' to export a procedure and `pragma import' to import it back
+% again, there may be trouble. The code generated for the exported functions
+% can include calls to MR_MAYBE_BOX_FOREIGN_TYPE, which may allocate heap;
+% we ought to register the frame and call MR_GC_check() before each call
+% to MR_MAYBE_BOX_FOREIGN_TYPE, but currently we don't.
+%
+% Even if that was solved, there is still the issue of what to do about
+% any heap pointers held by user-written C code; we need to provide an API
+% for registering pointers on the stack. (MR_agc_add_root() only works
+% for globals, really, since there's no MR_agc_remove_root()).
% Various optional features of Mercury are not yet supported, e.g.
%
@@ -251,15 +241,14 @@
%
% - multithreading
%
-% There are also some things that could be done to improve efficiency,
-% e.g.
+% There are also some things that could be done to improve efficiency, e.g.
%
% - optimize away temporary variables
%
% - put stack_chain and/or heap pointer in global register variables
%
-% - move termination conditions (check for base case)
-% outside of stack frame setup & GC check where possible
+% - move termination conditions (check for base case) outside of stack frame
+% setup & GC check where possible
%
%-----------------------------------------------------------------------------%
%
@@ -281,42 +270,38 @@
% void (*trace)(void *this_frame);
% };
%
-% Actually, rather than using a nested structure,
-% we just put these fields directly in the <function_name>_frame struct.
-% (This turned out to be a little easier.)
+% Actually, rather than using a nested structure, we just put these fields
+% directly in the <function_name>_frame struct. (This turned out to be
+% a little easier.)
%
% The prev field holds a link to the entry for this function's caller.
-% The trace field is the address of a function to
-% trace everything pointed to by this stack frame.
+% The trace field is the address of a function to trace everything pointed
+% to by this stack frame.
%
% To ensure that we don't try to traverse uninitialized fields,
% we zero-initialize each struct before inserting it into the chain.
%
-% We need to keep a link to the topmost frame on the stack.
-% There's two possible ways that we could handle this.
-% One way is to pass it down as an parameter.
-% Each function would get an extra parameter `stack_chain' which
-% points to the caller's struct.
-% An alternative approach is to just have a global variable
-% `stack_chain' that points to the top of the stack. We need extra code
-% to set this pointer when entering and returning from functions.
-% To make this approach thread-safe, the variable would actually
-% need to be thread-local rather than global.
-% This approach would probably work best if the variable is
-% a GNU C global register variable, which would make it both
-% efficient and thread-safe.
+% We need to keep a link to the topmost frame on the stack. There are two
+% possible ways that we could handle this. One way is to pass it down
+% as an parameter. Each function would get an extra parameter `stack_chain'
+% which points to the caller's struct. An alternative approach is to just
+% have a global variable `stack_chain' that points to the top of the stack.
+% We need extra code to set this pointer when entering and returning from
+% functions. To make this approach thread-safe, the variable would actually
+% need to be thread-local rather than global. This approach would probably
+% work best if the variable is a GNU C global register variable, which would
+% make it both efficient and thread-safe.
% XXX Currently, for simplicity, we're using a global variable.
%
-% At each allocation, we do a call to MR_GC_check(),
-% which checks for heap exhaustion, and if necessary
-% calls MR_garbage_collect() in runtime/mercury_accurate_gc.c
-% to do the collection. The calls to MR_GC_check() are
-% inserted by compiler/mlds_to_c.m.
-%
-% As an optimization, we ought to not bother allocating a struct for
-% functions that don't have any variables that might contain pointers.
-% We also ought to not bother allocating a struct for leaf functions that
-% don't contain any functions calls or memory allocations.
+% At each allocation, we do a call to MR_GC_check(), which checks for heap
+% exhaustion, and if necessary calls MR_garbage_collect() in
+% runtime/mercury_accurate_gc.c to do the collection. The calls to
+% MR_GC_check() are inserted by compiler/mlds_to_c.m.
+%
+% As an optimization, we ought to not bother allocating a struct for functions
+% that don't have any variables that might contain pointers. We also ought
+% to not bother allocating a struct for leaf functions that don't contain
+% any functions calls or memory allocations.
% XXX These optimizations are not yet implemented!
%
%-----------------------------------------------------------------------------%
@@ -447,6 +432,7 @@
% accurate GC.
% Process the whole MLDS, performing the indicated action.
+ %
:- pred ml_elim_nested(action::in, mlds::in, mlds::out, io::di, io::uo) is det.
%-----------------------------------------------------------------------------%
@@ -455,19 +441,19 @@
:- implementation.
:- import_module check_hlds__type_util.
+:- import_module libs__globals.
+:- import_module libs__options.
:- import_module ml_backend__ml_code_util.
:- import_module ml_backend__ml_util.
+:- import_module parse_tree__error_util.
:- import_module parse_tree__prog_util.
-% the following imports are needed for mangling pred names
+% The following imports are needed for mangling pred names.
:- import_module hlds__hlds_pred.
:- import_module mdbcomp__prim_data.
:- import_module parse_tree__prog_data.
:- import_module parse_tree__prog_out.
-:- import_module libs__globals.
-:- import_module libs__options.
-
:- import_module bool.
:- import_module counter.
:- import_module int.
@@ -484,8 +470,7 @@
MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName),
OuterVars = [],
DefnsList = list__map(
- ml_elim_nested_defns(Action, MLDS_ModuleName, Globals,
- OuterVars),
+ ml_elim_nested_defns(Action, MLDS_ModuleName, Globals, OuterVars),
Defns0),
Defns1 = list__condense(DefnsList),
% The MLDS code generator sometimes generates two definitions of the
@@ -500,18 +485,15 @@
% Hoist out any nested function occurring in a single mlds__defn.
% Return a list of mlds__defns that contains no nested functions.
%
- % Or handle accurate GC:
- % put all variables that might contain pointers in structs
- % and chain these structs together into a "shadow stack".
- % Extract out the code to trace these variables,
- % putting it in a function whose address is stored in
- % the shadow stack frame.
+ % Or handle accurate GC: put all variables that might contain pointers
+ % in structs and chain these structs together into a "shadow stack".
+ % Extract out the code to trace these variables, putting it in a function
+ % whose address is stored in the shadow stack frame.
%
:- func ml_elim_nested_defns(action, mlds_module_name, globals, outervars,
mlds__defn) = list(mlds__defn).
-ml_elim_nested_defns(Action, ModuleName, Globals, OuterVars, Defn0)
- = Defns :-
+ml_elim_nested_defns(Action, ModuleName, Globals, OuterVars, Defn0) = Defns :-
Defn0 = mlds__defn(Name, Context, Flags, DefnBody0),
(
DefnBody0 = mlds__function(PredProcId, Params0,
@@ -526,23 +508,20 @@
)
->
EnvName = ml_env_name(Name, Action),
- EnvTypeName = ml_create_env_type_name(EnvName,
- ModuleName, Globals),
+ EnvTypeName = ml_create_env_type_name(EnvName, ModuleName, Globals),
EnvPtrTypeName = ml_make_env_ptr_type(Globals, EnvTypeName),
- %
- % traverse the function body, finding (and removing)
- % any nested functions, and fixing up any references
- % to the arguments or to local variables or local
- % static constants that need to be put in the environment
- % structure (e.g. because they occur in nested functions,
+ % Traverse the function body, finding (and removing) any nested
+ % functions, and fixing up any references to the arguments or to local
+ % variables or local static constants that need to be put in the
+ % environment structure (e.g. because they occur in nested functions,
% or to make them visible to the garbage collector)
%
- % Also, for accurate GC, add code to save and restore the
- % stack chain pointer at any `try_commit' statements.
+ % Also, for accurate GC, add code to save and restore the stack chain
+ % pointer at any `try_commit' statements.
%
- ElimInfo0 = elim_info_init(Action, ModuleName,
- OuterVars, EnvTypeName, EnvPtrTypeName, Globals),
+ ElimInfo0 = elim_info_init(Action, ModuleName, OuterVars,
+ EnvTypeName, EnvPtrTypeName, Globals),
Params0 = mlds__func_params(Arguments0, RetValues),
ml_maybe_add_args(Arguments0, FuncBody0, ModuleName,
Context, ElimInfo0, ElimInfo1),
@@ -550,78 +529,55 @@
flatten_statement(FuncBody0, FuncBody1, ElimInfo2, ElimInfo),
elim_info_finish(ElimInfo, NestedFuncs0, Locals),
- %
- % Split the locals that we need to process
- % into local variables and local static constants
- %
- list__filter(ml_decl_is_static_const, Locals,
- LocalStatics, LocalVars),
- %
- % Fix up access flags on the statics that we're going to hoist:
- % convert "local" to "private"
- %
- HoistedStatics = list__map(convert_local_to_global,
- LocalStatics),
+ % Split the locals that we need to process into local variables
+ % and local static constants.
+ list__filter(ml_decl_is_static_const, Locals, LocalStatics, LocalVars),
+ % Fix up access flags on the statics that we're going to hoist:
+ % convert "local" to "private".
+ HoistedStatics = list__map(convert_local_to_global, LocalStatics),
(
- %
- % When hoisting nested functions,
- % if there were no nested functions, then we just
- % hoist the local static constants
- %
+ % When hoisting nested functions, if there were no nested
+ % functions, then we just hoist the local static constants.
Action = hoist_nested_funcs,
NestedFuncs0 = []
->
FuncBody = FuncBody1,
HoistedDefns = HoistedStatics
;
- %
- % Likewise, when doing accurate GC,
- % if there were no local variables (or arguments)
- % that contained pointers, then we don't need to
- % chain a stack frame for this function.
- %
+ % Likewise, when doing accurate GC, if there were no local
+ % variables (or arguments) that contained pointers, then we don't
+ % need to chain a stack frame for this function.
Action = chain_gc_stack_frames,
Locals = []
->
FuncBody = FuncBody1,
HoistedDefns = HoistedStatics
;
- %
- % Create a struct to hold the local variables,
- % and initialize the environment pointers for
- % both the containing function and the nested
- % functions. Also generate the GC tracing function,
+ % Create a struct to hold the local variables, and initialize
+ % the environment pointers for both the containing function
+ % and the nested functions. Also generate the GC tracing function,
% if Action = chain_gc_stack_frames.
%
- ml_create_env(Action, EnvName, EnvTypeName, LocalVars,
- Context, ModuleName, Name, Globals,
- EnvTypeDefn, EnvDecls, InitEnv,
+ ml_create_env(Action, EnvName, EnvTypeName, LocalVars, Context,
+ ModuleName, Name, Globals, EnvTypeDefn, EnvDecls, InitEnv,
GCTraceFuncDefns),
list__map_foldl(
- ml_insert_init_env(Action, EnvTypeName,
- ModuleName, Globals),
- NestedFuncs0, NestedFuncs,
- no, InsertedEnv),
-
- % Hoist out the local statics and the nested functions
- HoistedDefns0 = HoistedStatics ++ GCTraceFuncDefns ++
- NestedFuncs,
-
- %
- % When hoisting nested functions,
- % it's possible that none of the nested
- % functions reference the arguments or locals of
- % the parent function. In that case, there's no
- % need to create an environment, we just need to
- % flatten the functions.
- %
- % Note that we don't generate the
- % env_ptr_args in this module (instead they are
- % generated when the nested functions are
- % generated). This means that we don't avoid
- % generating these arguments. This is not
- % really a big problem, since the code
+ ml_insert_init_env(Action, EnvTypeName, ModuleName, Globals),
+ NestedFuncs0, NestedFuncs, no, InsertedEnv),
+
+ % Hoist out the local statics and the nested functions.
+ HoistedDefns0 = HoistedStatics ++ GCTraceFuncDefns ++ NestedFuncs,
+
+ % When hoisting nested functions, it's possible that none of the
+ % nested functions reference the arguments or locals of the parent
+ % function. In that case, there's no need to create an environment,
+ % we just need to flatten the functions.
+ %
+ % Note that we don't generate the env_ptr_args in this module
+ % (instead they are generated when the nested functions are
+ % generated). This means that we don't avoid generating these
+ % arguments. This is not really a big problem, since the code
% that generates these arguments needs them.
%
(
@@ -631,78 +587,59 @@
FuncBody = FuncBody1,
HoistedDefns = HoistedDefns0
;
- %
- % If the function's arguments are
- % referenced by nested functions,
- % or (for accurate GC) may contain pointers,
- % then we need to copy them to local
- % variables in the environment
- % structure.
- %
- ml_maybe_copy_args(Arguments1, FuncBody0,
- ElimInfo, EnvTypeName, EnvPtrTypeName,
- Context, _ArgsToCopy, CodeToCopyArgs),
+ % If the function's arguments are referenced by nested
+ % functions, or (for accurate GC) may contain pointers,
+ % then we need to copy them to local variables in the
+ % environment structure.
+ ml_maybe_copy_args(Arguments1, FuncBody0, ElimInfo,
+ EnvTypeName, EnvPtrTypeName, Context,
+ _ArgsToCopy, CodeToCopyArgs),
- %
- % Insert code to unlink this stack frame
- % before doing any tail calls or returning
- % from the function, either explicitly
+ % Insert code to unlink this stack frame before doing any tail
+ % calls or returning from the function, either explicitly
% or implicitly.
%
- % add unlink statements before
- % any explicit returns or tail calls
+ % Add unlink statements before any explicit returns or tail
+ % calls.
( Action = chain_gc_stack_frames ->
- add_unchain_stack_to_statement(
- FuncBody1, FuncBody2,
+ add_unchain_stack_to_statement(FuncBody1, FuncBody2,
ElimInfo, _ElimInfo)
;
FuncBody2 = FuncBody1
),
- % add a final unlink statement
- % at the end of the function,
- % if needed. This is only needed if
- % the function has no return values --
- % if there is a return value, then the
- % function must exit with an explicit
- % return statement.
+ % Add a final unlink statement at the end of the function,
+ % if needed. This is only needed if the function has no
+ % return values -- if there is a return value, then the
+ % function must exit with an explicit return statement.
(
Action = chain_gc_stack_frames,
RetValues = []
->
- UnchainFrame = [ml_gen_unchain_frame(
- Context, ElimInfo)]
+ UnchainFrame = [ml_gen_unchain_frame(Context, ElimInfo)]
;
UnchainFrame = []
),
- %
- % insert the definition and
- % initialization of the environment
- % struct variable at the start of the
- % top-level function's body,
- % and append the final unlink statement
- % (if any) at the end
- %
+ % Insert the definition and initialization of the environment
+ % struct variable at the start of the top-level function's
+ % body, and append the final unlink statement (if any)
+ % at the end.
FuncBody = ml_block(EnvDecls,
- InitEnv ++ CodeToCopyArgs ++
- [FuncBody2] ++ UnchainFrame,
+ InitEnv ++ CodeToCopyArgs ++ [FuncBody2] ++ UnchainFrame,
Context),
- %
- % insert the environment struct type at
- % the start of the list of hoisted definitions
- % (preceding the previously nested functions
- % and static constants in HoistedDefns0),
+ % Insert the environment struct type at the start of the list
+ % of hoisted definitions (preceding the previously nested
+ % functions and static constants in HoistedDefns0),
%
HoistedDefns = [EnvTypeDefn | HoistedDefns0]
)
),
(
Action = chain_gc_stack_frames,
- % This pass will have put the GC tracing code for the
- % arguments in the GC tracing function. So we don't
- % need the GC tracing code annotation on the arguments
- % anymore. We delete them here, because otherwise
- % the `#if 0 ... #endif' blocks output for the
+ % This pass will have put the GC tracing code for the arguments
+ % in the GC tracing function. So we don't need the GC tracing code
+ % annotation on the arguments anymore. We delete them here, because
+ % otherwise the `#if 0 ... #endif' blocks output for the
% annotations clutter up the generated C files.
Arguments = list__map(strip_gc_trace_code, Arguments1)
;
@@ -715,7 +652,7 @@
Defn = mlds__defn(Name, Context, Flags, DefnBody),
Defns = list__append(HoistedDefns, [Defn])
;
- % leave definitions of things other than functions unchanged
+ % Leave definitions of things other than functions unchanged.
Defns = [Defn0]
).
@@ -725,7 +662,6 @@
Argument0 = mlds__argument(Name, Type, _MaybeGCTraceCode),
Argument = mlds__argument(Name, Type, no).
- %
% Add any arguments which are used in nested functions
% to the local_data field in the elim_info.
%
@@ -736,10 +672,9 @@
ml_maybe_add_args([], _, _, _, !Info).
ml_maybe_add_args([Arg|Args], FuncBody, ModuleName, Context, !Info) :-
(
- Arg = mlds__argument(data(var(VarName)), _Type,
- GC_TraceCode),
- ml_should_add_local_data(!.Info, var(VarName),
- GC_TraceCode, [], [FuncBody])
+ Arg = mlds__argument(data(var(VarName)), _Type, GC_TraceCode),
+ ml_should_add_local_data(!.Info, var(VarName), GC_TraceCode,
+ [], [FuncBody])
->
ml_conv_arg_to_var(Context, Arg, ArgToCopy),
elim_info_add_and_flatten_local_data(ArgToCopy, !Info)
@@ -748,7 +683,6 @@
),
ml_maybe_add_args(Args, FuncBody, ModuleName, Context, !Info).
- %
% Generate code to copy any arguments which are used in nested functions
% to the environment struct.
%
@@ -763,16 +697,13 @@
EnvPtrTypeName, Context, ArgsToCopy0, CodeToCopyArgs0),
ModuleName = elim_info_get_module_name(ElimInfo),
(
- Arg = mlds__argument(data(var(VarName)), FieldType,
- GC_TraceCode),
+ Arg = mlds__argument(data(var(VarName)), FieldType, GC_TraceCode),
ml_should_add_local_data(ElimInfo, var(VarName), GC_TraceCode,
[], [FuncBody])
->
ml_conv_arg_to_var(Context, Arg, ArgToCopy),
- %
- % Generate code to copy this arg to the environment
- % struct:
+ % Generate code to copy this arg to the environment struct:
% env_ptr->foo = foo;
%
QualVarName = qual(ModuleName, mlds__module_qual, VarName),
@@ -784,10 +715,8 @@
Tag = yes(0),
EnvPtrName = env_name_base(ElimInfo ^ action) ++ "_ptr",
EnvPtr = lval(var(qual(ModuleName, mlds__module_qual,
- mlds__var_name(EnvPtrName, no)),
- EnvPtrTypeName)),
- EnvArgLval = field(Tag, EnvPtr, FieldName, FieldType,
- EnvPtrTypeName),
+ mlds__var_name(EnvPtrName, no)), EnvPtrTypeName)),
+ EnvArgLval = field(Tag, EnvPtr, FieldName, FieldType, EnvPtrTypeName),
ArgRval = lval(var(QualVarName, FieldType)),
AssignToEnv = assign(EnvArgLval, ArgRval),
CodeToCopyArg = mlds__statement(atomic(AssignToEnv), Context),
@@ -800,25 +729,27 @@
).
% Create the environment struct type.
+ %
:- func ml_create_env_type_name(mlds__class_name, mlds_module_name, globals) =
mlds__type.
ml_create_env_type_name(EnvClassName, ModuleName, Globals) = EnvTypeName :-
- % If we're allocating it on the heap, then we need to use
- % a class type rather than a struct (value type).
- % This is needed for verifiable code on the IL back-end.
+ % If we're allocating it on the heap, then we need to use a class type
+ % rather than a struct (value type). This is needed for verifiable code
+ % on the IL back-end.
globals__lookup_bool_option(Globals, put_nondet_env_on_heap, OnHeap),
- ( OnHeap = yes ->
+ (
+ OnHeap = yes,
EnvTypeKind = mlds__class
;
+ OnHeap = no,
EnvTypeKind = mlds__struct
),
EnvTypeName = class_type(qual(ModuleName, module_qual, EnvClassName),
0, EnvTypeKind).
- % Create the environment struct type,
- % the declaration of the environment variable,
- % and the declaration and initializer for the environment
+ % Create the environment struct type, the declaration of the environment
+ % variable, and the declaration and initializer for the environment
% pointer variable:
%
% struct <EnvClassName> {
@@ -850,7 +781,6 @@
ml_create_env(Action, EnvClassName, EnvTypeName, LocalVars, Context,
ModuleName, FuncName, Globals, EnvTypeDefn, EnvDecls, InitEnv,
GCTraceFuncDefns) :-
- %
% generate the following type:
%
% struct <EnvClassName> {
@@ -862,14 +792,16 @@
% <LocalVars>
% };
%
- % If we're allocating it on the heap, then we need to use
- % a class type rather than a struct (value type).
- % This is needed for verifiable code on the IL back-end.
+ % If we're allocating it on the heap, then we need to use a class type
+ % rather than a struct (value type). This is needed for verifiable code
+ % on the IL back-end.
globals__lookup_bool_option(Globals, put_nondet_env_on_heap, OnHeap),
- ( OnHeap = yes ->
+ (
+ OnHeap = yes,
EnvTypeKind = mlds__class,
BaseClasses = [mlds__generic_env_ptr_type]
;
+ OnHeap = no,
EnvTypeKind = mlds__struct,
BaseClasses = []
),
@@ -877,26 +809,22 @@
EnvTypeFlags = env_type_decl_flags,
Fields0 = list__map(convert_local_to_field, LocalVars),
- %
- % Extract the GC tracing code from the fields
- %
- list__map2(extract_gc_trace_code, Fields0, Fields1,
- GC_TraceStatements0),
+ % Extract the GC tracing code from the fields.
+ list__map2(extract_gc_trace_code, Fields0, Fields1, GC_TraceStatements0),
GC_TraceStatements = list__condense(GC_TraceStatements0),
( Action = chain_gc_stack_frames ->
- ml_chain_stack_frames(Fields1, GC_TraceStatements,
- EnvTypeName, Context, FuncName, ModuleName, Globals,
- Fields, EnvInitializer, LinkStackChain,
- GCTraceFuncDefns),
+ ml_chain_stack_frames(Fields1, GC_TraceStatements, EnvTypeName,
+ Context, FuncName, ModuleName, Globals, Fields, EnvInitializer,
+ LinkStackChain, GCTraceFuncDefns),
GC_TraceEnv = no
;
- ( GC_TraceStatements = [] ->
+ (
+ GC_TraceStatements = [],
GC_TraceEnv = no
;
- GC_TraceEnv = yes(
- ml_block([], GC_TraceStatements, Context)
- )
+ GC_TraceStatements = [_ | _],
+ GC_TraceEnv = yes(ml_block([], GC_TraceStatements, Context))
),
Fields = Fields1,
EnvInitializer = no_initializer,
@@ -905,15 +833,14 @@
),
Imports = [],
- Ctors = [], % mlds_to_il.m will add an empty constructor if needed
+ Ctors = [], % mlds_to_il.m will add an empty constructor if needed.
Interfaces = [],
EnvTypeDefnBody = mlds__class(mlds__class_defn(EnvTypeKind, Imports,
BaseClasses, Interfaces, Ctors, Fields)),
EnvTypeDefn = mlds__defn(EnvTypeEntityName, Context, EnvTypeFlags,
EnvTypeDefnBody),
- %
- % generate the following variable declaration:
+ % Generate the following variable declaration:
%
% struct <EnvClassName> env; // = { ... }
%
@@ -924,25 +851,23 @@
EnvVarDecl = mlds__defn(EnvVarEntityName, Context, EnvVarFlags,
EnvVarDefnBody),
- %
- % declare the `env_ptr' var, and
- % initialize the `env_ptr' with the address of `env'
- %
+ % Declare the `env_ptr' var, and initialize the `env_ptr' with the
+ % address of `env'.
EnvVar = qual(ModuleName, module_qual, EnvVarName),
+ % Generate code to initialize the environment pointer, either by
+ % allocating an object on the heap, or by taking the address of
+ % the struct we put on the stack.
%
- % generate code to initialize the environment pointer,
- % either by allocating an object on the heap, or by
- % just taking the address of the struct we put on the stack
- %
- ( OnHeap = yes ->
+ (
+ OnHeap = yes,
EnvVarAddr = lval(var(EnvVar, EnvTypeName)),
NewObj = [mlds__statement(
- atomic(new_object(
- var(EnvVar, EnvTypeName),
+ atomic(new_object(var(EnvVar, EnvTypeName),
no, no, EnvTypeName, no, no, [], [])),
Context)]
;
+ OnHeap = no,
EnvVarAddr = mem_addr(var(EnvVar, EnvTypeName)),
NewObj = []
),
@@ -960,24 +885,18 @@
ml_chain_stack_frames(Fields0, GCTraceStatements, EnvTypeName, Context,
FuncName, ModuleName, Globals, Fields,
EnvInitializer, LinkStackChain, GCTraceFuncDefns) :-
- %
- % Generate code to declare and initialize the
- % environment pointer for the GC trace function
- % from that function's `this_frame' parameter:
+ % Generate code to declare and initialize the environment pointer
+ % for the GC trace function from that function's `this_frame' parameter:
%
% struct foo_frame *frame;
% frame = (struct foo_frame *) this_frame;
%
- ThisFrameName = qual(ModuleName, module_qual,
- var_name("this_frame", no)),
- ThisFrameRval = lval(var(ThisFrameName,
- mlds__generic_type)),
- CastThisFrameRval = unop(cast(mlds__ptr_type(EnvTypeName)),
- ThisFrameRval),
+ ThisFrameName = qual(ModuleName, module_qual, var_name("this_frame", no)),
+ ThisFrameRval = lval(var(ThisFrameName, mlds__generic_type)),
+ CastThisFrameRval = unop(cast(mlds__ptr_type(EnvTypeName)), ThisFrameRval),
ml_init_env(chain_gc_stack_frames, EnvTypeName, CastThisFrameRval,
Context, ModuleName, Globals, FramePtrDecl, InitFramePtr),
- %
% Put the environment pointer declaration and initialization
% and the GC tracing code in a function:
%
@@ -986,53 +905,45 @@
% frame = (struct foo_frame *) this_frame;
% <GCTraceStatements>
% }
- %
- gen_gc_trace_func(FuncName, ModuleName,
- FramePtrDecl, [InitFramePtr | GCTraceStatements],
- Context, GCTraceFuncAddr, GCTraceFuncParams,
- GCTraceFuncDefn),
+ gen_gc_trace_func(FuncName, ModuleName, FramePtrDecl,
+ [InitFramePtr | GCTraceStatements], Context, GCTraceFuncAddr,
+ GCTraceFuncParams, GCTraceFuncDefn),
GCTraceFuncDefns = [GCTraceFuncDefn],
+ % Insert the fixed fields in the struct <EnvClassName>:
%
- % insert the fixed fields in the struct <EnvClassName>:
% void *prev;
% void (*trace)(...);
- %
PrevFieldName = data(var(var_name("prev", no))),
PrevFieldFlags = ml_gen_public_field_decl_flags,
PrevFieldType = ml_stack_chain_type,
- PrevFieldDefnBody = mlds__data(PrevFieldType,
- no_initializer, no),
- PrevFieldDecl = mlds__defn(PrevFieldName, Context,
- PrevFieldFlags, PrevFieldDefnBody),
+ PrevFieldDefnBody = mlds__data(PrevFieldType, no_initializer, no),
+ PrevFieldDecl = mlds__defn(PrevFieldName, Context, PrevFieldFlags,
+ PrevFieldDefnBody),
TraceFieldName = data(var(var_name("trace", no))),
TraceFieldFlags = ml_gen_public_field_decl_flags,
TraceFieldType = mlds__func_type(GCTraceFuncParams),
- TraceFieldDefnBody = mlds__data(TraceFieldType,
- no_initializer, no),
- TraceFieldDecl = mlds__defn(TraceFieldName, Context,
- TraceFieldFlags, TraceFieldDefnBody),
+ TraceFieldDefnBody = mlds__data(TraceFieldType, no_initializer, no),
+ TraceFieldDecl = mlds__defn(TraceFieldName, Context, TraceFieldFlags,
+ TraceFieldDefnBody),
Fields = [PrevFieldDecl, TraceFieldDecl | Fields0],
- %
- % Set the initializer so that the `prev' field
- % is initialized to the global stack chain,
- % and the `trace' field is initialized to the
- % address of the GC tracing function:
+ % Set the initializer so that the `prev' field is initialized to the global
+ % stack chain, and the `trace' field is initialized to the address of
+ % the GC tracing function:
%
% ... = { stack_chain, foo_trace };
%
- % Since there no values for the remaining fields in the
- % initializer, this means the remaining fields will get
- % initialized to zero (C99 6.7.8 #21).
- %
- % XXX This uses a non-const initializer, which is a
- % feature that is only supported in C99 and GNU C;
- % it won't work in C89. We should just generate
- % a bunch of assignments to all the fields,
- % rather than relying on initializers like this.
+ % Since there no values for the remaining fields in the initializer,
+ % this means the remaining fields will get initialized to zero
+ % (C99 6.7.8 #21).
+ %
+ % XXX This uses a non-const initializer, which is a feature that is only
+ % supported in C99 and GNU C; it won't work in C89. We should just generate
+ % a bunch of assignments to all the fields, rather than relying on
+ % initializers like this.
%
StackChain = ml_stack_chain_var,
EnvInitializer = init_struct(EnvTypeName, [
@@ -1040,19 +951,15 @@
init_obj(const(code_addr_const(GCTraceFuncAddr)))
]),
- %
% Generate code to set the global stack chain
% to point to the current environment:
%
% stack_chain = frame_ptr;
- %
EnvPtrTypeName = ml_make_env_ptr_type(Globals, EnvTypeName),
EnvPtr = lval(var(qual(ModuleName, module_qual,
- mlds__var_name("frame_ptr", no)),
- EnvPtrTypeName)),
+ mlds__var_name("frame_ptr", no)), EnvPtrTypeName)),
AssignToStackChain = assign(StackChain, EnvPtr),
- LinkStackChain = [mlds__statement(atomic(AssignToStackChain),
- Context)].
+ LinkStackChain = [mlds__statement(atomic(AssignToStackChain), Context)].
:- pred gen_gc_trace_func(mlds__entity_name::in, mlds_module_name::in,
mlds__defn::in, list(mlds__statement)::in, mlds__context::in,
@@ -1060,15 +967,13 @@
gen_gc_trace_func(FuncName, PredModule, FramePointerDecl, GCTraceStatements,
Context, GCTraceFuncAddr, FuncParams, GCTraceFuncDefn) :-
- %
% Compute the signature of the GC tracing function
- %
ArgName = data(var(var_name("this_frame", no))),
ArgType = mlds__generic_type,
Argument = mlds__argument(ArgName, ArgType, no),
FuncParams = mlds__func_params([Argument], []),
Signature = mlds__get_func_signature(FuncParams),
- %
+
% Compute the name of the GC tracing function
%
% To compute the name, we just take the name of the original function
@@ -1077,22 +982,22 @@
% another field to the `function' ctor for mlds__entity_name.
%
( FuncName = function(PredLabel, ProcId, MaybeSeqNum, PredId) ->
- ( MaybeSeqNum = yes(SeqNum)
- ; MaybeSeqNum = no, SeqNum = 0
+ (
+ MaybeSeqNum = yes(SeqNum)
+ ;
+ MaybeSeqNum = no,
+ SeqNum = 0
),
NewSeqNum = SeqNum + 100000,
- GCTraceFuncName = function(PredLabel, ProcId, yes(NewSeqNum),
- PredId),
+ GCTraceFuncName = function(PredLabel, ProcId, yes(NewSeqNum), PredId),
ProcLabel = qual(PredModule, module_qual, PredLabel - ProcId),
GCTraceFuncAddr = internal(ProcLabel, NewSeqNum, Signature)
;
- error("gen_gc_trace_func: not a function")
+ unexpected(this_file, "gen_gc_trace_func: not a function")
),
- %
- % Construct the function definition
- %
- Statement = mlds__statement(
- block([FramePointerDecl], GCTraceStatements),
+
+ % Construct the function definition.
+ Statement = mlds__statement(block([FramePointerDecl], GCTraceStatements),
Context),
DeclFlags = ml_gen_gc_trace_func_decl_flags,
MaybePredProcId = no,
@@ -1129,11 +1034,10 @@
GCTraceStmts = []
).
- % When converting local variables into fields of the
- % environment struct, we need to change `local' access
- % into something else, since `local' is only supposed to be
- % used for entities that are local to a function or block,
- % not for fields. Currently we change it to `public'.
+ % When converting local variables into fields of the environment struct,
+ % we need to change `local' access into something else, since `local'
+ % is only supposed to be used for entities that are local to a function
+ % or block, not for fields. Currently we change it to `public'.
% (Perhaps changing it to `default' might be better?)
%
:- func convert_local_to_field(mlds__defn) = mlds__defn.
@@ -1146,9 +1050,9 @@
Flags = Flags0
).
- % Similarly, when converting local statics into
- % global statics, we need to change `local' access
- % to something else -- we use `private'.
+ % Similarly, when converting local statics into global statics, we need to
+ % change `local' access to something else -- we use `private'.
+ %
:- func convert_local_to_global(mlds__defn) = mlds__defn.
convert_local_to_global(mlds__defn(Name, Context, Flags0, Body)) =
@@ -1160,9 +1064,10 @@
).
% ml_insert_init_env:
- % If the definition is a nested function definition, and it's
- % body makes use of the environment pointer (`env_ptr'), then
- % insert code to declare and initialize the environment pointer.
+ %
+ % If the definition is a nested function definition, and it's body makes
+ % use of the environment pointer (`env_ptr'), then insert code to declare
+ % and initialize the environment pointer.
%
% We transform code of the form
% <Ret> <Func>(<Args>) {
@@ -1196,9 +1101,8 @@
mlds__generic_env_ptr_type)),
EnvPtrVarType = ml_make_env_ptr_type(Globals, TypeName),
- % Insert a cast, to downcast from
- % mlds__generic_env_ptr_type to the specific
- % environment type for this procedure.
+ % Insert a cast, to downcast from mlds__generic_env_ptr_type to the
+ % specific environment type for this procedure.
CastEnvPtrVal = unop(cast(EnvPtrVarType), EnvPtrVal),
ml_init_env(Action, TypeName, CastEnvPtrVal, Context,
@@ -1237,8 +1141,7 @@
ml_init_env(Action, EnvTypeName, EnvPtrVal, Context, ModuleName, Globals,
EnvPtrVarDecl, InitEnvPtr) :-
- %
- % generate the following variable declaration:
+ % Generate the following variable declaration:
%
% <EnvTypeName> *env_ptr;
%
@@ -1246,17 +1149,15 @@
EnvPtrVarEntityName = data(var(EnvPtrVarName)),
EnvPtrVarFlags = ml_gen_local_var_decl_flags,
EnvPtrVarType = ml_make_env_ptr_type(Globals, EnvTypeName),
- % The env_ptr never needs to be traced by the GC,
- % since the environment that it points to will always
- % be on the stack, not into the heap.
+ % The env_ptr never needs to be traced by the GC, since the environment
+ % that it points to will always be on the stack, not into the heap.
GC_TraceCode = no,
EnvPtrVarDefnBody = mlds__data(EnvPtrVarType, no_initializer,
GC_TraceCode),
EnvPtrVarDecl = mlds__defn(EnvPtrVarEntityName, Context,
EnvPtrVarFlags, EnvPtrVarDefnBody),
- %
- % generate the following statement:
+ % Generate the following statement:
%
% env_ptr = <EnvPtrVal>;
%
@@ -1267,10 +1168,10 @@
AssignEnvPtr = assign(var(EnvPtrVar, EnvPtrVarType), EnvPtrVal),
InitEnvPtr = mlds__statement(atomic(AssignEnvPtr), Context).
- % Given the declaration for a function parameter, produce a
- % declaration for a corresponding local variable or environment
- % struct field. We need to do this so as to include function
- % parameter in the environment struct.
+ % Given the declaration for a function parameter, produce a declaration
+ % for a corresponding local variable or environment struct field.
+ % We need to do this so as to include function parameter in the
+ % environment struct.
%
:- pred ml_conv_arg_to_var(mlds__context::in, mlds__argument::in,
mlds__defn::out) is det.
@@ -1283,6 +1184,7 @@
% Return the declaration flags appropriate for an environment struct
% type declaration.
+ %
:- func env_type_decl_flags = mlds__decl_flags.
env_type_decl_flags = MLDS_DeclFlags :-
@@ -1303,9 +1205,12 @@
= mlds__statement.
ml_block(VarDecls, Statements, Context) =
- (if VarDecls = [], Statements = [SingleStatement] then
+ (
+ VarDecls = [],
+ Statements = [SingleStatement]
+ ->
SingleStatement
- else
+ ;
mlds__statement(block(VarDecls, Statements), Context)
).
@@ -1317,7 +1222,8 @@
StackChain = var(qual(MLDS_Module, module_qual,
var_name("stack_chain", no)), ml_stack_chain_type).
- % the type of the `stack_chain' pointer, i.e. `void *'.
+ % The type of the `stack_chain' pointer, i.e. `void *'.
+ %
:- func ml_stack_chain_type = mlds__type.
ml_stack_chain_type = mlds__generic_env_ptr_type.
@@ -1327,36 +1233,35 @@
% This code does some name mangling.
% It essentially duplicates the functionality in mlds_output_name.
%
-% Doing name mangling here is probably a bad idea;
-% it might be better to change the MLDS data structure
-% to allow structured type names, so that we don't have to
-% do any name mangling at this point.
-%
+% Doing name mangling here is probably a bad idea; it might be better
+% to change the MLDS data structure to allow structured type names, so that
+% we don't have to do any name mangling at this point.
% Compute the name to use for the environment struct
% for the specified function.
+ %
:- func ml_env_name(mlds__entity_name, action) = mlds__class_name.
ml_env_name(type(_, _), _) = _ :-
- error("ml_env_name: expected function, got type").
+ unexpected(this_file, "ml_env_name: expected function, got type").
ml_env_name(data(_), _) = _ :-
- error("ml_env_name: expected function, got data").
-ml_env_name(function(PredLabel, ProcId, MaybeSeqNum, _PredId),
- Action) = ClassName :-
+ unexpected(this_file, "ml_env_name: expected function, got data").
+ml_env_name(function(PredLabel, ProcId, MaybeSeqNum, _PredId), Action)
+ = ClassName :-
Base = env_name_base(Action),
PredLabelString = ml_pred_label_name(PredLabel),
proc_id_to_int(ProcId, ModeNum),
- ( MaybeSeqNum = yes(SeqNum) ->
+ (
+ MaybeSeqNum = yes(SeqNum),
string__format("%s_%d_%d_%s",
- [s(PredLabelString), i(ModeNum), i(SeqNum), s(Base)],
- ClassName)
+ [s(PredLabelString), i(ModeNum), i(SeqNum), s(Base)], ClassName)
;
+ MaybeSeqNum = no,
string__format("%s_%d_%s",
- [s(PredLabelString), i(ModeNum), s(Base)],
- ClassName)
+ [s(PredLabelString), i(ModeNum), s(Base)], ClassName)
).
ml_env_name(export(_), _) = _ :-
- error("ml_env_name: expected function, got export").
+ unexpected(this_file, "ml_env_name: expected function, got export").
:- func env_name_base(action) = string.
@@ -1370,40 +1275,38 @@
( PredOrFunc = predicate, Suffix = "p"
; PredOrFunc = function, Suffix = "f"
),
- ( MaybeDefiningModule = yes(DefiningModule) ->
+ (
+ MaybeDefiningModule = yes(DefiningModule),
ModuleNameString = ml_module_name_string(DefiningModule),
string__format("%s_%d_%s_in__%s",
- [s(Name), i(Arity), s(Suffix), s(ModuleNameString)],
- LabelName)
+ [s(Name), i(Arity), s(Suffix), s(ModuleNameString)], LabelName)
;
+ MaybeDefiningModule = no,
string__format("%s_%d_%s",
- [s(Name), i(Arity), s(Suffix)],
- LabelName)
+ [s(Name), i(Arity), s(Suffix)], LabelName)
).
ml_pred_label_name(special_pred(PredName, MaybeTypeModule,
TypeName, TypeArity)) = LabelName :-
- ( MaybeTypeModule = yes(TypeModule) ->
+ (
+ MaybeTypeModule = yes(TypeModule),
TypeModuleString = ml_module_name_string(TypeModule),
string__format("%s__%s__%s_%d",
- [s(PredName), s(TypeModuleString),
- s(TypeName), i(TypeArity)],
+ [s(PredName), s(TypeModuleString), s(TypeName), i(TypeArity)],
LabelName)
;
+ MaybeTypeModule = no,
string__format("%s__%s_%d",
- [s(PredName), s(TypeName), i(TypeArity)],
- LabelName)
+ [s(PredName), s(TypeName), i(TypeArity)], LabelName)
).
:- func ml_module_name_string(mercury_module_name) = string.
ml_module_name_string(ModuleName) = ModuleNameString :-
Separator = "__",
- mdbcomp__prim_data__sym_name_to_string(ModuleName, Separator,
- ModuleNameString).
+ sym_name_to_string(ModuleName, Separator, ModuleNameString).
%-----------------------------------------------------------------------------%
-%
% flatten_arguments:
% flatten_argument:
% flatten_function_body:
@@ -1417,7 +1320,6 @@
%
% Also, for Action = chain_gc_stack_frames, add code to save and
% restore the stack chain pointer at any `try_commit' statements.
-%
:- pred flatten_arguments(mlds__arguments::in, mlds__arguments::out,
elim_info::in, elim_info::out) is det.
@@ -1469,10 +1371,9 @@
flatten_stmt(Stmt0, Stmt, !Info) :-
(
Stmt0 = block(Defns0, Statements0),
- flatten_nested_defns(Defns0, Statements0, Defns,
- InitStatements, !Info),
- flatten_statements(InitStatements ++ Statements0, Statements,
+ flatten_nested_defns(Defns0, Statements0, Defns, InitStatements,
!Info),
+ flatten_statements(InitStatements ++ Statements0, Statements, !Info),
Stmt = block(Defns, Statements)
;
Stmt0 = while(Rval0, Statement0, Once),
@@ -1551,7 +1452,6 @@
%-----------------------------------------------------------------------------%
- %
% add code to save/restore the stack chain pointer:
% convert
% try {
@@ -1585,15 +1485,12 @@
Statement0 = mlds__statement(_, StatementContext),
Handler0 = mlds__statement(_, HandlerContext),
SavedVarDecl = gen_saved_stack_chain_var(Id, StatementContext),
- SaveStatement = gen_save_stack_chain_var(ModuleName, Id,
- StatementContext),
+ SaveStatement = gen_save_stack_chain_var(ModuleName, Id, StatementContext),
RestoreStatement = gen_restore_stack_chain_var(ModuleName, Id,
HandlerContext),
- Statement = mlds__statement(
- block([], [SaveStatement, Statement0]),
+ Statement = mlds__statement(block([], [SaveStatement, Statement0]),
HandlerContext),
- Handler = mlds__statement(
- block([], [RestoreStatement, Handler0]),
+ Handler = mlds__statement(block([], [RestoreStatement, Handler0]),
HandlerContext),
TryCommit = try_commit(Ref, Statement, Handler),
Stmt = block(
@@ -1603,7 +1500,6 @@
%-----------------------------------------------------------------------------%
-%
% flatten_nested_defns:
% flatten_nested_defn:
% Hoist out nested function definitions, and any local variables
@@ -1613,7 +1509,6 @@
% environment struct into assignment statements.
% Return the remaining (non-hoisted) definitions,
% the list of assignment statements, and the updated elim_info.
-%
:- pred flatten_nested_defns(mlds__defns::in, mlds__statements::in,
mlds__defns::out, mlds__statements::out,
@@ -1637,18 +1532,13 @@
Defns, InitStatements, !Info) :-
Defn0 = mlds__defn(Name, Context, Flags0, DefnBody0),
(
- DefnBody0 = mlds__function(PredProcId, Params, FuncBody0,
- Attributes),
- %
- % recursively flatten the nested function
- %
+ DefnBody0 = mlds__function(PredProcId, Params, FuncBody0, Attributes),
+ % Recursively flatten the nested function.
flatten_function_body(FuncBody0, FuncBody, !Info),
- %
- % mark the function as private / one_copy,
+ % Mark the function as private / one_copy,
% rather than as local / per_instance,
- % if we're about to hoist it out to the top level
- %
+ % if we're about to hoist it out to the top level.
Action = !.Info ^ action,
( Action = hoist_nested_funcs ->
Flags1 = set_access(Flags0, private),
@@ -1656,26 +1546,21 @@
;
Flags = Flags0
),
- DefnBody = mlds__function(PredProcId, Params,
- FuncBody, Attributes),
+ DefnBody = mlds__function(PredProcId, Params, FuncBody, Attributes),
Defn = mlds__defn(Name, Context, Flags, DefnBody),
( Action = hoist_nested_funcs ->
- % Note that we assume that we can safely hoist stuff
- % inside nested functions into the containing function.
- % If that wasn't the case, we'd need code something
- % like this:
+ % Note that we assume that we can safely hoist stuff inside nested
+ % functions into the containing function. If that wasn't the case,
+ % we'd need code something like this:
% LocalVars = elim_info_get_local_data(ElimInfo),
% OuterVars0 = elim_info_get_outer_vars(ElimInfo),
% OuterVars = [LocalVars | OuterVars0],
% FlattenedDefns = ml_elim_nested_defns(ModuleName,
% OuterVars, Defn0),
- % list__foldl(elim_info_add_nested_func,
- % FlattenedDefns),
+ % list__foldl(elim_info_add_nested_func, FlattenedDefns),
- %
- % strip out the now flattened nested function,
- % and store it in the elim_info
- %
+ % Strip out the now flattened nested function, and store it
+ % in the elim_info.
elim_info_add_nested_func(Defn, !Info),
Defns = []
;
@@ -1684,51 +1569,40 @@
InitStatements = []
;
DefnBody0 = mlds__data(Type, Init0, MaybeGCTraceCode0),
- %
- % for local variable definitions, if they are
- % referenced by any nested functions, then
- % strip them out and store them in the elim_info
- %
+ % For local variable definitions, if they are referenced by any nested
+ % functions, then strip them out and store them in the elim_info.
(
- % 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.
+ % 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)
->
elim_info_add_and_flatten_local_data(Defn0, !Info),
Defns = [],
InitStatements = []
;
- % Hoist ordinary local variables
+ % Hoist ordinary local variables.
Name = data(DataName),
DataName = var(VarName),
ml_should_add_local_data(!.Info,
DataName, MaybeGCTraceCode0,
FollowingDefns, FollowingStatements)
->
- % we need to strip out the initializer (if any)
- % and convert it into an assignment statement,
- % since this local variable is going to become
- % a field, and fields can't have initializers.
+ % We need to strip out the initializer (if any) and convert it
+ % into an assignment statement, since this local variable
+ % is going to become a field, and fields can't have initializers.
( Init0 = init_obj(Rval) ->
- % XXX Bug! Converting the initializer to an
- % assignment doesn't work, because it doesn't
- % handle the case when initializers in
+ % XXX Bug! Converting the initializer to an assignment doesn't
+ % work, because it doesn't handle the case when initializers in
% FollowingDefns reference this variable
Init1 = no_initializer,
- DefnBody1 = mlds__data(Type, Init1,
- MaybeGCTraceCode0),
- Defn1 = mlds__defn(Name, Context, Flags0,
- DefnBody1),
- VarLval = var(qual(!.Info ^ module_name,
- module_qual, VarName), Type),
+ DefnBody1 = mlds__data(Type, Init1, MaybeGCTraceCode0),
+ Defn1 = mlds__defn(Name, Context, Flags0, DefnBody1),
+ VarLval = var(qual(!.Info ^ module_name, module_qual, VarName),
+ Type),
InitStatements = [mlds__statement(
- atomic(assign(VarLval, Rval)),
- Context)]
+ atomic(assign(VarLval, Rval)), Context)]
;
Defn1 = Defn0,
InitStatements = []
@@ -1737,8 +1611,8 @@
Defns = []
;
fixup_initializer(Init0, Init, !Info),
- flatten_maybe_statement(MaybeGCTraceCode0,
- MaybeGCTraceCode, !Info),
+ flatten_maybe_statement(MaybeGCTraceCode0, MaybeGCTraceCode,
+ !Info),
DefnBody = mlds__data(Type, Init, MaybeGCTraceCode),
Defn = mlds__defn(Name, Context, Flags0, DefnBody),
Defns = [Defn],
@@ -1746,23 +1620,21 @@
)
;
DefnBody0 = mlds__class(_),
+ % Leave nested class declarations alone.
%
- % leave nested class declarations alone
- %
- % XXX that might not be the right thing to do,
- % but currently ml_code_gen.m doesn't generate
- % any of these, so it doesn't matter what we do
+ % XXX That might not be the right thing to do, but currently
+ % ml_code_gen.m doesn't generate any of these, so it doesn't matter
+ % what we do.
%
Defns = [Defn0],
InitStatements = []
).
+ % Succeed iff we should add the definition of this variable to the
+ % local_data field of the elim_info, meaning that it should be added
+ % to the environment struct (if it's a variable) or hoisted out to the
+ % top level (if it's a static const).
%
- % Succeed iff we should add the definition of this variable
- % to the local_data field of the elim_info, meaning that
- % it should be added to the environment struct
- % (if it's a variable) or hoisted out to the top level
- % (if it's a static const).
:- pred ml_should_add_local_data(elim_info::in, mlds__data_name::in,
mlds__maybe_gc_trace_code::in, mlds__defns::in, mlds__statements::in)
is semidet.
@@ -1779,19 +1651,15 @@
FollowingDefns, FollowingStatements)
).
- %
- % This checks for a nested function definition
- % or static initializer that references the variable.
- % 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, 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.
+ % This checks for a nested function definition or static initializer
+ % that references the variable. 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, 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.
%
% XXX Do we need to check for references from the GC_TraceCode
% fields here?
@@ -1805,31 +1673,24 @@
(
list__member(FollowingDefn, FollowingDefns)
;
- statements_contains_defn(FollowingStatements,
- FollowingDefn)
+ statements_contains_defn(FollowingStatements, FollowingDefn)
),
(
- FollowingDefn = mlds__defn(_, _, _,
- mlds__function(_, _, _, _)),
+ FollowingDefn = mlds__defn(_, _, _, mlds__function(_, _, _, _)),
defn_contains_var(FollowingDefn, QualDataName)
;
- FollowingDefn = mlds__defn(_, _, _,
- mlds__data(_, Initializer, _)),
+ FollowingDefn = mlds__defn(_, _, _, mlds__data(_, Initializer, _)),
ml_decl_is_static_const(FollowingDefn),
initializer_contains_var(Initializer, QualDataName)
).
- %
- % Add the variable definition to the
- % local_data field of the elim_info,
- % fix up any references inside the GC tracing code,
- % and then update the GC tracing code in the
- % local_data.
- %
- % Note that we need to add the variable definition
- % to the local_data *before* we fix up the GC tracing
- % code, otherwise references to the variable itself
- % in the GC tracing code won't get fixed.
+ % Add the variable definition to the local_data field of the elim_info,
+ % fix up any references inside the GC tracing code, and then update
+ % the GC tracing code in the local_data.
+ %
+ % Note that we need to add the variable definition to the local_data
+ % *before* we fix up the GC tracing code, otherwise references to the
+ % variable itself in the GC tracing code won't get fixed.
%
:- pred elim_info_add_and_flatten_local_data(mlds__defn::in,
elim_info::in, elim_info::out) is det.
@@ -1840,8 +1701,7 @@
DefnBody0 = mlds__data(Type, Init, MaybeGCTraceCode0)
->
elim_info_add_local_data(Defn0, !Info),
- flatten_maybe_statement(MaybeGCTraceCode0, MaybeGCTraceCode,
- !Info),
+ flatten_maybe_statement(MaybeGCTraceCode0, MaybeGCTraceCode, !Info),
DefnBody = mlds__data(Type, Init, MaybeGCTraceCode),
Defn = mlds__defn(Name, Context, Flags, DefnBody),
elim_info_remove_local_data(Defn0, !Info),
@@ -1852,7 +1712,6 @@
%-----------------------------------------------------------------------------%
-%
% fixup_initializer:
% fixup_atomic_stmt:
% fixup_case_cond:
@@ -1864,7 +1723,6 @@
% fixup_lval:
% Recursively process the specified construct, calling fixup_var on
% every variable inside it.
-%
:- pred fixup_initializer(mlds__initializer::in, mlds__initializer::out,
elim_info::in, elim_info::out) is det.
@@ -2000,12 +1858,9 @@
%-----------------------------------------------------------------------------%
-%
-% fixup_var:
-% change up any references to local vars in the
-% containing function to go via the environment pointer
-%
-
+ % Change up any references to local vars in the containing function
+ % to go via the environment pointer.
+ %
:- pred fixup_var(mlds__var::in, mlds__type::in, mlds__lval::out,
elim_info::in, elim_info::out) is det.
@@ -2018,11 +1873,8 @@
Action = !.Info ^ action,
Globals = !.Info ^ elim_info_globals,
(
- %
- % Check for references to local variables
- % that are used by nested functions,
- % and replace them with `env_ptr->foo'.
- %
+ % Check for references to local variables that are used by
+ % nested functions, and replace them with `env_ptr->foo'.
ThisVarModuleName = ModuleName,
IsLocalVar = (pred(VarType::out) is nondet :-
list__member(Var, Locals),
@@ -2044,18 +1896,15 @@
Lval = field(Tag, EnvPtr, FieldName, FieldType, EnvPtrVarType)
;
% Check for references to the env_ptr itself.
- % For those, the code generator will have left the
- % type as mlds__unknown_type, and we need to fill
- % it in here.
+ % For those, the code generator will have left the type as
+ % mlds__unknown_type, and we need to fill it in here.
Action = hoist_nested_funcs,
ThisVarName = mlds__var_name("env_ptr", no),
ThisVarType = mlds__unknown_type
->
Lval = var(ThisVar, EnvPtrVarType)
;
- %
- % leave everything else unchanged
- %
+ % Leave everything else unchanged.
Lval = var(ThisVar, ThisVarType)
).
@@ -2136,7 +1985,7 @@
EnvModuleName = mlds__append_class_qualifier(ClassModule,
QualKind, Globals, ClassName, Arity)
;
- error("ml_env_module_name: ClassType is not a class")
+ unexpected(this_file, "ml_env_module_name: ClassType is not a class")
).
%-----------------------------------------------------------------------------%
@@ -2150,7 +1999,6 @@
% statement_contains_defn:
% Nondeterministically return all the definitions contained
% in the specified construct.
-%
:- pred defns_contains_defn(mlds__defns::in, mlds__defn::out) is nondet.
@@ -2273,8 +2121,9 @@
%-----------------------------------------------------------------------------%
-% Add code to unlink the stack chain before any explicit returns or tail calls.
-
+ % Add code to unlink the stack chain before any explicit returns or
+ % tail calls.
+ %
:- pred add_unchain_stack_to_maybe_statement(maybe(mlds__statement)::in,
maybe(mlds__statement)::out,
elim_info::in, elim_info::out) is det.
@@ -2314,8 +2163,7 @@
;
Stmt0 = if_then_else(Cond, Then0, MaybeElse0),
add_unchain_stack_to_statement(Then0, Then, !Info),
- add_unchain_stack_to_maybe_statement(MaybeElse0, MaybeElse,
- !Info),
+ add_unchain_stack_to_maybe_statement(MaybeElse0, MaybeElse, !Info),
Stmt = if_then_else(Cond, Then, MaybeElse)
;
Stmt0 = switch(Type, Val, Range, Cases0, Default0),
@@ -2417,7 +2265,7 @@
ml_gen_unchain_frame(Context, ElimInfo) = UnchainFrame :-
EnvPtrTypeName = ElimInfo ^ env_ptr_type_name,
- %
+
% Generate code to remove this frame from the stack chain:
%
% stack_chain = stack_chain->prev;
@@ -2432,7 +2280,7 @@
% a field offset rather than a field name:
%
% stack_chain = MR_hl_field(stack_chain, 0);
- %
+
StackChain = ml_stack_chain_var,
Tag = yes(0),
PrevFieldId = offset(const(int_const(0))),
@@ -2442,9 +2290,11 @@
Assignment = assign(StackChain, PrevFieldRval),
UnchainFrame = mlds__statement(atomic(Assignment), Context).
- % Generate a local variable declaration
- % to hold the saved stack chain pointer:
+ % Generate a local variable declaration to hold the saved stack chain
+ % pointer:
+ %
% void *saved_stack_chain;
+ %
:- func gen_saved_stack_chain_var(int, mlds__context) = mlds__defn.
gen_saved_stack_chain_var(Id, Context) = Defn :-
@@ -2459,7 +2309,9 @@
Defn = mlds__defn(Name, Context, Flags, DefnBody).
% Generate a statement to save the stack chain pointer:
+ %
% saved_stack_chain = stack_chain;
+ %
:- func gen_save_stack_chain_var(mlds_module_name, int, mlds__context) =
mlds__statement.
@@ -2470,7 +2322,9 @@
SaveStatement = mlds__statement(atomic(Assignment), Context).
% Generate a statement to restore the stack chain pointer:
+ %
% stack_chain = saved_stack_chain;
+ %
:- func gen_restore_stack_chain_var(mlds_module_name, int, mlds__context) =
mlds__statement.
@@ -2493,43 +2347,35 @@
:- type elim_info
---> elim_info(
- % Specify whether we're eliminating nested
- % functions, or doing the transformation
- % needed for accurate GC.
+ % Specify whether we're eliminating nested functions, or doing
+ % the transformation needed for accurate GC.
action :: action,
% The name of the current module.
module_name :: mlds_module_name,
- % The lists of local variables for
- % each of the containing functions,
- % innermost first
+ % The lists of local variables for each of the containing
+ % functions, innermost first.
% XXX this is not used.
- % It would be needed if we want to
- % handle arbitrary nesting.
- % Currently we assume that any variables
- % can safely be hoisted to the outermost
- % function, so this field is not needed.
+ % It would be needed if we want to handle arbitrary nesting.
+ % Currently we assume that any variables can safely be hoisted
+ % to the outermost function, so this field is not needed.
outer_vars :: outervars,
- % The list of nested function definitions
- % that we must hoist out.
- % This list is stored in reverse order.
+ % The list of nested function definitions that we must hoist
+ % out. This list is stored in reverse order.
nested_funcs :: list(mlds__defn),
- % The list of local variables that we must
- % put in the environment structure
- % This list is stored in reverse order.
+ % The list of local variables that we must put in the
+ % environment structure This list is stored in reverse order.
local_data :: list(mlds__defn),
- % Type of the introduced environment struct
+ % Type of the introduced environment struct.
env_type_name :: mlds__type,
- % Type of the introduced environment struct
- % pointer. This might not just be just
- % a pointer to the env_type_name (in the
- % IL backend we don't necessarily use a
- % pointer).
+ % Type of the introduced environment struct pointer.
+ % This might not just be just a pointer to the env_type_name
+ % (in the IL backend we don't necessarily use a pointer).
env_ptr_type_name :: mlds__type,
% A counter used to number the local variables
@@ -2539,9 +2385,8 @@
elim_info_globals :: globals
).
- % The lists of local variables for
- % each of the containing functions,
- % innermost first
+ % The lists of local variables for each of the containing functions,
+ % innermost first.
:- type outervars == list(list(mlds__defn)).
:- func elim_info_init(action, mlds_module_name, outervars,
@@ -2583,7 +2428,7 @@
( list__delete_first(ElimInfo0 ^ local_data, LocalVar, LocalData) ->
ElimInfo = ElimInfo0 ^ local_data := LocalData
;
- error("elim_info_remove_local_data: not found")
+ unexpected(this_file, "elim_info_remove_local_data: not found")
).
:- pred elim_info_finish(elim_info::in,
@@ -2592,5 +2437,11 @@
elim_info_finish(ElimInfo, Funcs, Locals) :-
Funcs = list__reverse(ElimInfo ^ nested_funcs),
Locals = list__reverse(ElimInfo ^ local_data).
+
+%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+
+this_file = "ml_elim_nested.m".
%-----------------------------------------------------------------------------%
Index: compiler/ml_optimize.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/ml_optimize.m,v
retrieving revision 1.31
diff -u -b -r1.31 ml_optimize.m
--- compiler/ml_optimize.m 1 Sep 2005 09:06:33 -0000 1.31
+++ compiler/ml_optimize.m 12 Sep 2005 10:17:12 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 2000-2005 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -59,8 +61,8 @@
:- import_module std_util.
:- import_module string.
-:- type opt_info --->
- opt_info(
+:- type opt_info
+ ---> opt_info(
globals :: globals,
module_name :: mlds_module_name,
entity_name :: mlds__entity_name,
@@ -86,15 +88,13 @@
optimize_in_defn(ModuleName, Globals, Defn0) = Defn :-
Defn0 = mlds__defn(Name, Context, Flags, DefnBody0),
(
- DefnBody0 = mlds__function(PredProcId, Params, FuncBody0,
- Attributes),
+ DefnBody0 = mlds__function(PredProcId, Params, FuncBody0, Attributes),
OptInfo = opt_info(Globals, ModuleName, Name, Params, Context),
FuncBody1 = optimize_func(OptInfo, FuncBody0),
FuncBody = optimize_in_function_body(OptInfo, FuncBody1),
- DefnBody = mlds__function(PredProcId, Params, FuncBody,
- Attributes),
+ DefnBody = mlds__function(PredProcId, Params, FuncBody, Attributes),
Defn = mlds__defn(Name, Context, Flags, DefnBody)
;
DefnBody0 = mlds__data(_, _, _),
@@ -103,10 +103,8 @@
DefnBody0 = mlds__class(ClassDefn0),
ClassDefn0 = class_defn(Kind, Imports, BaseClasses, Implements,
CtorDefns0, MemberDefns0),
- MemberDefns = optimize_in_defns(MemberDefns0, Globals,
- ModuleName),
- CtorDefns = optimize_in_defns(CtorDefns0, Globals,
- ModuleName),
+ MemberDefns = optimize_in_defns(MemberDefns0, Globals, ModuleName),
+ CtorDefns = optimize_in_defns(CtorDefns0, Globals, ModuleName),
ClassDefn = class_defn(Kind, Imports, BaseClasses, Implements,
CtorDefns, MemberDefns),
DefnBody = mlds__class(ClassDefn),
@@ -137,8 +135,7 @@
mlds__statement.
optimize_in_statement(OptInfo, statement(Stmt, Context)) =
- statement(optimize_in_stmt(OptInfo ^ context := Context, Stmt),
- Context).
+ statement(optimize_in_stmt(OptInfo ^ context := Context, Stmt), Context).
:- func optimize_in_stmt(opt_info, mlds__stmt) = mlds__stmt.
@@ -157,8 +154,7 @@
Stmt = block(Defns, Statements)
;
Stmt0 = while(Rval, Statement0, Once),
- Stmt = while(Rval, optimize_in_statement(OptInfo,
- Statement0), Once)
+ Stmt = while(Rval, optimize_in_statement(OptInfo, Statement0), Once)
;
Stmt0 = if_then_else(Rval, Then, MaybeElse),
Stmt = if_then_else(Rval,
@@ -280,25 +276,25 @@
% This specifies how we should branch to the top of the loop
% introduced by tailcall opptimization.
+ %
:- func tailcall_loop_top(globals) = mlds__goto_target.
tailcall_loop_top(Globals) =
( target_supports_break_and_continue(Globals) ->
- % the function body has been wrapped inside
- % `while (true) { ... break; }', and so to
- % branch to the top of the function, we just do
- % a `continue' which will continue the next iteration
- % of the loop
+ % The function body has been wrapped inside
+ % `while (true) { ... break; }', and so to branch to the top of the
+ % function, we just do a `continue' which will continue the next
+ % iteration of the loop.
continue
;
- % a label has been inserted at the start of the function,
- % and so to branch to the top of the function, we just
- % branch to that label
+ % A label has been inserted at the start of the function, and so to
+ % branch to the top of the function, we just branch to that label.
label(tailcall_loop_label_name)
).
% The label name we use for the top of the loop introduced by
% tailcall optimization, when we're doing it with labels & gotos.
+ %
:- func tailcall_loop_label_name = string.
tailcall_loop_label_name = "loop_top".
@@ -307,7 +303,7 @@
% Assign the specified list of rvals to the arguments.
% This is used as part of tail recursion optimization (see above).
-
+ %
:- pred generate_assign_args(opt_info::in, mlds__arguments::in,
list(mlds__rval)::in, list(mlds__statement)::out,
list(mlds__defn)::out) is det.
@@ -321,61 +317,48 @@
Statements, TempDefns) :-
Arg = mlds__argument(Name, Type, _ArgGCTraceCode),
(
- %
- % extract the variable name
- %
+ % Extract the variable name.
Name = data(var(VarName))
->
- QualVarName = qual(OptInfo ^ module_name, module_qual,
- VarName),
+ QualVarName = qual(OptInfo ^ module_name, module_qual, VarName),
(
- %
- % don't bother assigning a variable to itself
- %
+ % Don't bother assigning a variable to itself.
ArgRval = lval(var(QualVarName, _VarType))
->
generate_assign_args(OptInfo, Args, ArgRvals,
Statements, TempDefns)
;
- % Declare a temporary variable, initialized it
- % to the arg, recursively process the remaining
- % args, and then assign the temporary to the
- % parameter:
+ % Declare a temporary variable, initialized it to the arg,
+ % recursively process the remaining args, and then assign the
+ % temporary to the parameter:
%
% SomeType argN__tmp_copy;
% argN__tmp_copy = new_argN_value;
% ...
% argN = argN_tmp_copy;
%
- % The temporaries are needed for the case where
- % we are e.g. assigning v1, v2 to v2, v1;
- % they ensure that we don't try to reference the old
- % value of a parameter after it has already been
- % clobbered by the new value.
+ % The temporaries are needed for the case where we are e.g.
+ % assigning v1, v2 to v2, v1; they ensure that we don't try
+ % to reference the old value of a parameter after it has already
+ % been clobbered by the new value.
%
- % Note that we have to use an assignment rather
- % than an initializer to initialize the temp,
- % because this pass comes before ml_elem_nested.m,
- % and ml_elim_nested.m doesn't handle code containing
- % initializers.
+ % Note that we have to use an assignment rather than an initializer
+ % to initialize the temp, because this pass comes before
+ % ml_elem_nested.m, and ml_elim_nested.m doesn't handle code
+ % containing initializers.
VarName = mlds__var_name(VarNameStr, MaybeNum),
- TempName = mlds__var_name(VarNameStr ++ "__tmp_copy",
- MaybeNum),
- QualTempName = qual(OptInfo ^ module_name, module_qual,
- TempName),
+ TempName = mlds__var_name(VarNameStr ++ "__tmp_copy", MaybeNum),
+ QualTempName = qual(OptInfo ^ module_name, module_qual, TempName),
Initializer = no_initializer,
- % We don't need to trace the temporary variables
- % for GC, since they are not live across a call
- % or a heap allocation
+ % We don't need to trace the temporary variables for GC, since they
+ % are not live across a call or a heap allocation.
GC_TraceCode = no,
- TempDefn = ml_gen_mlds_var_decl(var(TempName),
- Type, Initializer, GC_TraceCode,
- OptInfo ^ context),
+ TempDefn = ml_gen_mlds_var_decl(var(TempName), Type, Initializer,
+ GC_TraceCode, OptInfo ^ context),
TempInitStatement = statement(
- atomic(assign(var(QualTempName, Type),
- ArgRval)),
+ atomic(assign(var(QualTempName, Type), ArgRval)),
OptInfo ^ context),
AssignStatement = statement(
atomic(assign(
@@ -405,24 +388,23 @@
optimize_func_stmt(OptInfo, mlds__statement(Stmt0, Context)) =
mlds__statement(Stmt, Context) :-
- % Tailcall optimization -- if we do a self tailcall, we
- % can turn it into a loop.
+ % Tailcall optimization -- if we do a self tailcall, we can turn it
+ % into a loop.
(
globals__lookup_bool_option(OptInfo ^ globals,
optimize_tailcalls, yes),
stmt_contains_statement(Stmt0, Call),
Call = mlds__statement(CallStmt, _),
can_optimize_tailcall(
- qual(OptInfo ^ module_name, module_qual,
- OptInfo ^ entity_name),
+ qual(OptInfo ^ module_name, module_qual, OptInfo ^ entity_name),
CallStmt)
->
Comment = atomic(comment("tailcall optimized into a loop")),
CommentStmt = statement(Comment, Context),
- % The loop can be defined either using while, break, and
- % continue, or using a label and goto. We prefer to
- % use the former, if possible, since it is a higher-level
- % construct that may help the back-end compiler's optimizer.
+ % The loop can be defined either using while, break, and continue,
+ % or using a label and goto. We prefer to use the former, if possible,
+ % since it is a higher-level construct that may help the back-end
+ % compiler's optimizer.
( target_supports_break_and_continue(OptInfo ^ globals) ->
% Wrap a while loop around the function body:
% while (true) {
@@ -473,12 +455,11 @@
%-----------------------------------------------------------------------------%
-%
-% If the list of statements contains a block with no local variables,
-% then bring the block up one level. This optimization is needed to avoid
-% a compiler limit in the Microsoft C compiler (version 13.10.3077) for
-% too deeply nested blocks.
-%
+ % If the list of statements contains a block with no local variables,
+ % then bring the block up one level. This optimization is needed to avoid
+ % a compiler limit in the Microsoft C compiler (version 13.10.3077) for
+ % too deeply nested blocks.
+ %
:- pred maybe_flatten_block(mlds__statements::in, mlds__statements::out) is det.
maybe_flatten_block(!Stmts) :-
@@ -527,10 +508,9 @@
% ...
% }
%
-% Note that if there are multiple initializations of the same
-% variable, then we'll apply the optimization successively,
-% replacing the existing initializers as we go, and keeping
-% only the last, e.g.
+% Note that if there are multiple initializations of the same variable,
+% then we'll apply the optimization successively, replacing the existing
+% initializers as we go, and keeping only the last, e.g.
%
% int v = 1;
% v = 2;
@@ -589,8 +569,7 @@
globals__lookup_bool_option(OptInfo ^ globals,
optimize_initializations, yes)
->
- convert_assignments_into_initializers(OptInfo, !Defns,
- !Statements)
+ convert_assignments_into_initializers(OptInfo, !Defns, !Statements)
;
true
).
@@ -601,9 +580,8 @@
convert_assignments_into_initializers(OptInfo, !Defns, !Statements) :-
(
- % Check if the first statement in the block is
- % an assignment to one of the variables declared in
- % the block.
+ % Check if the first statement in the block is an assignment to one
+ % of the variables declared in the block.
!.Statements = [AssignStatement | !:Statements],
AssignStatement = statement(atomic(assign(LHS, RHS)), _),
LHS = var(ThisVar, _ThisType),
@@ -613,20 +591,19 @@
list__takewhile(isnt(var_defn(VarName)), !.Defns,
_PrecedingDefns, [_VarDefn | FollowingDefns]),
- % We must check that the value being assigned
- % doesn't refer to the variable itself, or to any
- % of the variables which are declared after this one.
- % We must also check that the initializers (if any)
- % of the variables that follow this one don't
- % refer to this variable.
+ % We must check that the value being assigned doesn't refer to the
+ % variable itself, or to any of the variables which are declared
+ % after this one. We must also check that the initializers (if any)
+ % of the variables that follow this one don't refer to this variable.
\+ rval_contains_var(RHS, ThisData),
\+ (
list__member(OtherDefn, FollowingDefns),
OtherDefn = mlds__defn(data(OtherVarName),
_, _, data(_Type, OtherInitializer, _GC)),
- ( rval_contains_var(RHS,
- qual(Qualifier, QualKind, OtherVarName))
- ; initializer_contains_var(OtherInitializer, ThisData)
+ (
+ rval_contains_var(RHS, qual(Qualifier, QualKind, OtherVarName))
+ ;
+ initializer_contains_var(OtherInitializer, ThisData)
)
)
->
@@ -634,9 +611,8 @@
% on the variable declaration.
set_initializer(!.Defns, VarName, RHS, !:Defns),
- % Now try to apply the same optimization again
- convert_assignments_into_initializers(OptInfo, !Defns,
- !Statements)
+ % Now try to apply the same optimization again.
+ convert_assignments_into_initializers(OptInfo, !Defns, !Statements)
;
% No optimization possible -- leave the block unchanged.
true
@@ -648,9 +624,9 @@
Defn = mlds__defn(data(var(VarName)), _, _, _).
% set_initializer(Defns0, VarName, Rval, Defns):
- % Finds the first definition of the specified variable
- % in Defns0, and replaces the initializer of that
- % definition with init_obj(Rval).
+ %
+ % Finds the first definition of the specified variable in Defns0,
+ % and replaces the initializer of that definition with init_obj(Rval).
%
:- pred set_initializer(mlds__defns::in, mlds__var_name::in, mlds__rval::in,
mlds__defns::out) is det.
@@ -672,18 +648,14 @@
).
%-----------------------------------------------------------------------------%
-
%
% This is a pass to eliminate initialized local variable definitions,
-% by substituting the value of the initializer for occurrences
-% of the variable.
+% by substituting the value of the initializer for occurrences of the variable.
%
-
-% XXX This is quadratic in the number of variable definitions,
-% since we done one pass over the block per variable definition.
-% A more efficient algorithm would be to do one pass to figure
-% out which variables could be eliminated, and then do another
-% pass to actually eliminate them.
+% XXX This is quadratic in the number of variable definitions, since we do
+% one pass over the block per variable definition. A more efficient algorithm
+% would be to do one pass to figure out which variables could be eliminated,
+% and then do another pass to actually eliminate them.
:- pred maybe_eliminate_locals(opt_info::in, mlds__defns::in, mlds__defns::out,
mlds__statements::in, mlds__statements::out) is det.
@@ -691,10 +663,11 @@
maybe_eliminate_locals(OptInfo, !Defns, !Statements) :-
globals__lookup_bool_option(OptInfo ^ globals, eliminate_local_vars,
EliminateLocalVars),
- ( EliminateLocalVars = yes ->
+ (
+ EliminateLocalVars = yes,
eliminate_locals(OptInfo, !Defns, !Statements)
;
- true
+ EliminateLocalVars = no
).
:- pred eliminate_locals(opt_info::in, mlds__defns::in, mlds__defns::out,
@@ -702,10 +675,7 @@
eliminate_locals(_OptInfo, [], [], Statements, Statements).
eliminate_locals(OptInfo, [Defn0 | Defns0], Defns, !Statements) :-
- (
- try_to_eliminate_defn(OptInfo, Defn0, Defns0, Defns1,
- !Statements)
- ->
+ ( try_to_eliminate_defn(OptInfo, Defn0, Defns0, Defns1, !Statements) ->
eliminate_locals(OptInfo, Defns1, Defns, !Statements)
;
eliminate_locals(OptInfo, Defns0, Defns2, !Statements),
@@ -716,23 +686,24 @@
% in this pass to eliminate initialized local variable definitions.
:- type var_elim_info
---> var_elim_info(
- %
- % these fields remain constant
- %
+ % These fields remain constant.
+
var_name :: mlds__var,
- % the name of the variable to eliminate
+ % The name of the variable to eliminate.
+
var_value :: mlds__rval,
- % the value to replace the
- % eliminated variable with
- %
- % these get updated as we go along
- %
+ % The value to replace the eliminated variable
+ % with.
+
+ % These get updated as we go along.
+
replace_count :: int,
- % the number of occurrences of the variable
+ % The number of occurrences of the variable.
+
invalidated :: bool
% `yes' if the optimization can't be applied,
% e.g. because the variable was assigned to,
- % or because its address was taken
+ % or because its address was taken.
).
% Check if this definition is a variable that we can eliminate.
@@ -740,6 +711,7 @@
% This will fail if the definition is not a variable definition,
% or if any of the statements or definitions take the address
% of the variable, or assign to it.
+ %
:- pred try_to_eliminate_defn(opt_info::in, mlds__defn::in, mlds__defns::in,
mlds__defns::out, mlds__statements::in, mlds__statements::out)
is semidet.
@@ -761,27 +733,23 @@
find_initial_val_in_statements(QualVarName, Rval, !Statements)
),
- % It's only safe to do this transformation if the
- % variable's value is constant, otherwise we might
- % end up moving the rvalue across a statement which
- % modifies it.
+ % It's only safe to do this transformation if the variable's value
+ % is constant, otherwise we might end up moving the rvalue across
+ % a statement which modifies it.
rval_will_not_change(Rval),
- % This transformation moves evaluation of the rvalue later in
- % the computation. If the rvalue is something which might
- % loop, throw an exception, or abort (e.g. for division by zero),
- % then this might change the behaviour of the program.
- % In such cases, we can only do the transformation
- % if reordering of both conjunctions and disjunctions
- % (we can't tell here whether this MLDS code came from a
- % conjunction or a disjunction) is allowed.
+ % This transformation moves evaluation of the rvalue later in the
+ % computation. If the rvalue is something which might loop, throw an
+ % exception, or abort (e.g. for division by zero), then this might change
+ % the behaviour of the program. In such cases, we can only do the
+ % transformation if reordering of both conjunctions and disjunctions
+ % (we can't tell here whether this MLDS code came from a conjunction
+ % or a disjunction) is allowed.
(
rval_cannot_throw(Rval)
;
- globals__lookup_bool_option(OptInfo ^ globals,
- reorder_conj, yes),
- globals__lookup_bool_option(OptInfo ^ globals,
- reorder_disj, yes)
+ globals__lookup_bool_option(OptInfo ^ globals, reorder_conj, yes),
+ globals__lookup_bool_option(OptInfo ^ globals, reorder_disj, yes)
),
% Replace uses of this variable with the variable's value,
@@ -791,10 +759,9 @@
Count, Invalidated),
Invalidated = no,
- % Make sure that we didn't duplicate the rval,
- % unless it is just a constant or a variable,
- % because duplicating any real operation would be
- % a pessimization
+ % Make sure that we didn't duplicate the rval, unless it is just a constant
+ % or a variable, because duplicating any real operation would be
+ % a pessimization.
( Count =< 1
; rval_is_cheap_enough_to_duplicate(Rval)
).
@@ -808,8 +775,8 @@
; Rval = self(_)
).
- % Succeed only if the specified rval definitely won't change
- % in value.
+ % Succeed only if the specified rval definitely won't change in value.
+ %
:- pred rval_will_not_change(mlds__rval::in) is semidet.
rval_will_not_change(const(_)).
@@ -829,6 +796,7 @@
% Succeed only if the given rval definitely can't loop,
% throw an exception, or abort.
% We use a pretty conservative approximation...
+ %
:- pred rval_cannot_throw(mlds__rval::in) is semidet.
rval_cannot_throw(const(_)).
@@ -837,20 +805,17 @@
rval_cannot_throw(mem_addr(_)).
rval_cannot_throw(self(_)).
-% Search through a list of statements,
-% trying to find the first assignment to the specified variable.
-% Return the initial value, and a modified list of statements
-% with the initial assignment deleted.
-% Fail if the first value can't be determined.
+ % Search through a list of statements, trying to find the first assignment
+ % to the specified variable. Return the initial value, and a modified list
+ % of statements with the initial assignment deleted. Fail if the first
+ % value can't be determined.
+ %
:- pred find_initial_val_in_statements(mlds__var::in, mlds__rval::out,
mlds__statements::in, mlds__statements::out) is semidet.
find_initial_val_in_statements(VarName, Rval, [Statement0 | Statements0],
Statements) :-
- (
- find_initial_val_in_statement(VarName, Rval1,
- Statement0, Statement1)
- ->
+ ( find_initial_val_in_statement(VarName, Rval1, Statement0, Statement1) ->
Rval = Rval1,
( Statement1 = mlds__statement(block([], []), _) ->
Statements = Statements0
@@ -858,11 +823,10 @@
Statements = [Statement1 | Statements0]
)
;
- % Check that Statement0 doesn't modify the value of the
- % variable -- this includes checking that there are no
- % labels via which code could branch into the middle of
- % Statement0. Only if we are sure that Statement0
- % can't modify the variable's value is it safe to go
+ % Check that Statement0 doesn't modify the value of the variable
+ % -- this includes checking that there are no labels via which code
+ % could branch into the middle of Statement0. Only if we are sure
+ % that Statement0 can't modify the variable's value is it safe to go
% on and look for the initial value in Statements0.
VarName = qual(Mod, QualKind, UnqualVarName),
DataName = qual(Mod, QualKind, var(UnqualVarName)),
@@ -884,7 +848,7 @@
Statement = mlds__statement(Stmt, Context),
( Stmt0 = atomic(assign(var(Var, _Type), Rval0)) ->
Rval = Rval0,
- % delete the assignment, by replacing it with an empty block
+ % Delete the assignment, by replacing it with an empty block.
Stmt = block([], [])
; Stmt0 = block(Defns0, SubStatements0) ->
Var = qual(Mod, QualKind, UnqualVarName),
@@ -897,14 +861,12 @@
fail
).
- % Replace uses of this variable with the variable's value
- % in the specified definitions and statements.
- % This will return a count of how many occurrences
- % of the variable there were.
- % It will also return Invalidated = yes if
- % any of the statements or definitions take the address
- % of the variable, or assign to it; in that case,
- % the transformation should not be performed.
+ % Replace uses of this variable with the variable's value in the specified
+ % definitions and statements. This will return a count of how many
+ % occurrences of the variable there were. It will also return
+ % Invalidated = yes if any of the statements or definitions take
+ % the address of the variable, or assign to it; in that case, the
+ % transformation should not be performed.
:- pred eliminate_var(mlds__var::in, mlds__rval::in,
mlds__defns::in, mlds__defns::out,
mlds__statements::in, mlds__statements::out,
@@ -913,18 +875,17 @@
eliminate_var(QualVarName, VarRval, !Defns, !Statements, Count, Invalidated) :-
Count0 = 0,
Invalidated0 = no,
- VarElimInfo0 = var_elim_info(QualVarName, VarRval, Count0,
- Invalidated0),
+ VarElimInfo0 = var_elim_info(QualVarName, VarRval, Count0, Invalidated0),
eliminate_var_in_block(!Defns, !Statements, VarElimInfo0, VarElimInfo),
Count = VarElimInfo ^ replace_count,
Invalidated = VarElimInfo ^ invalidated.
% eliminate_var_in_*:
-% process the specified construct, replacing all rvalue occurences
-% of the variable (^var_name) with its value (^var_value),
-% incrementing the ^replace_count field for each occurrence
-% as an rvalue, and setting ^invalidated to yes if the variable
-% occurs as an lvalue.
+%
+% Process the specified construct, replacing all rvalue occurences of the
+% variable (^var_name) with its value (^var_value), incrementing the
+% ^replace_count field for each occurrence as an rvalue, and setting
+% ^invalidated to yes if the variable occurs as an lvalue.
:- pred eliminate_var_in_block(mlds__defns::in, mlds__defns::out,
mlds__statements::in, mlds__statements::out,
@@ -946,15 +907,13 @@
eliminate_var_in_defn(Defn0, Defn, !VarElimInfo) :-
Defn0 = mlds__defn(Name, Context, Flags, DefnBody0),
(
- DefnBody0 = mlds__data(Type, Initializer0,
- MaybeGCTraceCode),
- eliminate_var_in_initializer(Initializer0, Initializer,
- !VarElimInfo),
+ DefnBody0 = mlds__data(Type, Initializer0, MaybeGCTraceCode),
+ eliminate_var_in_initializer(Initializer0, Initializer, !VarElimInfo),
DefnBody = mlds__data(Type, Initializer, MaybeGCTraceCode)
;
DefnBody0 = mlds__class(_),
% We assume that nested classes don't refer to local variables
- % in the containing scope
+ % in the containing scope.
DefnBody = DefnBody0
;
DefnBody0 = mlds__function(Id, Params, Body0, Attributes),
@@ -1010,14 +969,12 @@
Rval0 = lval(Lval0),
VarName = !.VarElimInfo ^ var_name,
( Lval0 = var(VarName, _) ->
- % we found an rvalue occurrence of the variable --
- % replace it with the rval for the variable's value,
- % and increment the counter for the number of
- % occurrences that we have replaced.
+ % We found an rvalue occurrence of the variable -- replace it
+ % with the rval for the variable's value, and increment the counter
+ % for the number of occurrences that we have replaced.
Rval = !.VarElimInfo ^ var_value,
Count0 = !.VarElimInfo ^ replace_count,
- !:VarElimInfo = !.VarElimInfo ^ replace_count
- := Count0 + 1
+ !:VarElimInfo = !.VarElimInfo ^ replace_count := Count0 + 1
;
eliminate_var_in_lval(Lval0, Lval, !VarElimInfo),
Rval = lval(Lval)
@@ -1068,10 +1025,9 @@
;
Lval0 = var(VarName, _Type),
( VarName = !.VarElimInfo ^ var_name ->
- % we found an lvalue occurrence of the variable --
- % if the variable that we are trying to eliminate
- % has its address is taken, or is assigned to,
- % or in general if it is used as an lvalue,
+ % We found an lvalue occurrence of the variable -- if the variable
+ % that we are trying to eliminate has its address is taken,
+ % or is assigned to, or in general if it is used as an lvalue,
% then it's not safe to eliminate it
!:VarElimInfo = !.VarElimInfo ^ invalidated := yes
;
@@ -1122,14 +1078,12 @@
Stmt0 = if_then_else(Cond0, Then0, MaybeElse0),
eliminate_var_in_rval(Cond0, Cond, !VarElimInfo),
eliminate_var_in_statement(Then0, Then, !VarElimInfo),
- eliminate_var_in_maybe_statement(MaybeElse0, MaybeElse,
- !VarElimInfo),
+ eliminate_var_in_maybe_statement(MaybeElse0, MaybeElse, !VarElimInfo),
Stmt = if_then_else(Cond, Then, MaybeElse)
;
Stmt0 = switch(Type, Val0, Range, Cases0, Default0),
eliminate_var_in_rval(Val0, Val, !VarElimInfo),
- list__map_foldl(eliminate_var_in_case, Cases0, Cases,
- !VarElimInfo),
+ list__map_foldl(eliminate_var_in_case, Cases0, Cases, !VarElimInfo),
eliminate_var_in_default(Default0, Default, !VarElimInfo),
Stmt = switch(Type, Val, Range, Cases, Default)
;
@@ -1174,8 +1128,7 @@
var_elim_info::in, var_elim_info::out) is det.
eliminate_var_in_case(Conds0 - Statement0, Conds - Statement, !VarElimInfo) :-
- list__map_foldl(eliminate_var_in_case_cond, Conds0, Conds,
- !VarElimInfo),
+ list__map_foldl(eliminate_var_in_case_cond, Conds0, Conds, !VarElimInfo),
eliminate_var_in_statement(Statement0, Statement, !VarElimInfo).
:- pred eliminate_var_in_default(
Index: compiler/ml_simplify_switch.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/ml_simplify_switch.m,v
retrieving revision 1.10
diff -u -b -r1.10 ml_simplify_switch.m
--- compiler/ml_simplify_switch.m 22 Mar 2005 06:40:10 -0000 1.10
+++ compiler/ml_simplify_switch.m 12 Sep 2005 10:56:44 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 2000-2001, 2003-2005 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -51,28 +53,24 @@
ml_simplify_switch(Stmt0, MLDS_Context, Statement, !Info) :-
ml_gen_info_get_globals(!.Info, Globals),
(
- %
% Convert dense int switches into computed gotos,
% unless the target prefers switches.
- %
- % is this an int switch?
+ % Is this an int switch?
Stmt0 = switch(Type, Rval, Range, Cases, Default),
is_integral_type(Type),
- % does the target want us to convert dense int
- % switches into computed gotos?
+ % Does the target want us to convert dense int switches
+ % into computed gotos?
target_supports_computed_goto(Globals),
\+ (
target_supports_int_switch(Globals),
- globals__lookup_bool_option(Globals, prefer_switch,
- yes)
+ globals__lookup_bool_option(Globals, prefer_switch, yes)
),
- % is the switch big enough?
+ % Is the switch big enough?
list__length(Cases, NumCases),
- globals__lookup_int_option(Globals, dense_switch_size,
- DenseSize),
+ globals__lookup_int_option(Globals, dense_switch_size, DenseSize),
NumCases >= DenseSize,
% ... and dense enough?
@@ -88,10 +86,8 @@
Stmt = block(Decls, Statements),
Statement = mlds__statement(Stmt, MLDS_Context)
;
- %
- % Convert the remaining (sparse) int switches into
- % if-then-else chains, unless the target prefers switches.
- %
+ % Convert the remaining (sparse) int switches into if-then-else chains,
+ % unless the target prefers switches.
Stmt0 = switch(Type, Rval, _Range, Cases, Default),
is_integral_type(Type),
@@ -103,11 +99,8 @@
Statement = ml_switch_to_if_else_chain(Cases, Default, Rval,
MLDS_Context)
;
- %
- % Optimize away trivial switches
- % (these can occur e.g. with --tags none, where the
- % primary tag test always has only one reachable case)
- %
+ % Optimize away trivial switches (these can occur e.g. with
+ % --tags none, where the tag test always has only one reachable case)
Stmt0 = switch(_Type, _Rval, _Range, Cases, Default),
Cases = [SingleCase],
@@ -135,7 +128,7 @@
NumCases = list__length(Cases),
NumCases > 2,
- % The switch needs to be dense enough
+ % The switch needs to be dense enough.
find_first_and_last_case(Cases, FirstCaseVal, LastCaseVal),
CasesRange = LastCaseVal - FirstCaseVal + 1,
Density = calc_density(NumCases, CasesRange),
@@ -146,6 +139,7 @@
% However, if the range of the type is sufficiently small,
% we can make the jump table large enough to hold all
% of the values for the type.
+ %
:- pred maybe_eliminate_default(mlds__switch_range::in,
list(mlds__switch_case)::in, mlds__switch_default::in, int::in,
int::out, int::out, bool::out) is det.
@@ -174,9 +168,8 @@
LastVal = LastCaseVal
).
- % Calculate the percentage density given the range
- % and the number of cases.
-
+ % Calculate the percentage density given the range and the number of cases.
+ %
:- func calc_density(int, int) = int.
calc_density(NumCases, Range) = Density :-
@@ -184,8 +177,8 @@
%-----------------------------------------------------------------------------%
-% Find the highest and lowest case values in a list of cases.
-
+ % Find the highest and lowest case values in a list of cases.
+ %
:- pred find_first_and_last_case(list(mlds__switch_case)::in,
int::out, int::out) is det.
@@ -195,31 +188,30 @@
:- pred find_first_and_last_case_2(mlds__switch_case::in,
int::in, int::out, int::in, int::out) is det.
-find_first_and_last_case_2(Case, Min0, Min, Max0, Max) :-
+find_first_and_last_case_2(Case, !Min, !Max) :-
Case = CaseConds - _CaseStatement,
- list__foldl2(find_first_and_last_case_3, CaseConds,
- Min0, Min, Max0, Max).
+ list__foldl2(find_first_and_last_case_3, CaseConds, !Min, !Max).
:- pred find_first_and_last_case_3(mlds__case_match_cond::in,
int::in, int::out, int::in, int::out) is det.
-find_first_and_last_case_3(match_value(Rval), Min0, Min, Max0, Max) :-
+find_first_and_last_case_3(match_value(Rval), !Min, !Max) :-
(
Rval = const(int_const(Val))
->
- int__min(Min0, Val, Min),
- int__max(Max0, Val, Max)
+ int__min(Val, !Min),
+ int__max(Val, !Max)
;
error("find_first_and_last_case_3: non-int case")
).
find_first_and_last_case_3(match_range(MinRval, MaxRval),
- Min0, Min, Max0, Max) :-
+ !Min, !Max) :-
(
- MinRval = const(int_const(Min1)),
- MaxRval = const(int_const(Max1))
+ MinRval = const(int_const(RvalMin)),
+ MaxRval = const(int_const(RvalMax))
->
- int__min(Min0, Min1, Min),
- int__max(Max0, Max1, Max)
+ int__min(RvalMin, !Min),
+ int__max(RvalMax, !Max)
;
error("find_first_and_last_case_3: non-int case")
).
@@ -227,7 +219,7 @@
%-----------------------------------------------------------------------------%
% Generate code for a switch using a dense jump table.
-
+ %
:- pred generate_dense_switch(list(mlds__switch_case)::in,
mlds__switch_default::in, int::in, int::in, bool::in,
mlds__type::in, mlds__rval::in, mlds__context::in,
@@ -236,19 +228,15 @@
generate_dense_switch(Cases, Default, FirstVal, LastVal, NeedRangeCheck,
_Type, Rval, MLDS_Context, Decls, Statements, !Info) :-
- %
% If the case values start at some number other than 0,
- % then subtract that number to give us a zero-based index
- %
+ % then subtract that number to give us a zero-based index.
( FirstVal = 0 ->
Index = Rval
;
Index = binop(-, Rval, const(int_const(FirstVal)))
),
- %
- % Now generate the jump table
- %
+ % Now generate the jump table.
ml_gen_new_label(EndLabel, !Info),
map__init(CaseLabelsMap0),
generate_cases(Cases, EndLabel, CaseLabelsMap0,
@@ -256,13 +244,11 @@
ml_gen_new_label(DefaultLabel, !Info),
CaseLabels = get_case_labels(FirstVal, LastVal,
CaseLabelsMap, DefaultLabel),
- DefaultLabelStatement = mlds__statement(label(DefaultLabel),
- MLDS_Context),
+ DefaultLabelStatement = mlds__statement(label(DefaultLabel), MLDS_Context),
(
Default = default_is_unreachable,
- % we still need the label, in case we inserted
- % references to it into (unreachable) slots in the
- % jump table
+ % We still need the label, in case we inserted references to it
+ % into (unreachable) slots in the jump table.
DefaultStatements = [DefaultLabelStatement]
;
Default = default_do_nothing,
@@ -275,39 +261,29 @@
StartComment = mlds__statement(
atomic(comment("switch (using dense jump table)")),
MLDS_Context),
- DoJump = mlds__statement(
- computed_goto(Index, CaseLabels),
- MLDS_Context),
- EndLabelStatement = mlds__statement(
- label(EndLabel),
- MLDS_Context),
- EndComment = mlds__statement(
- atomic(comment("End of dense switch")),
+ DoJump = mlds__statement(computed_goto(Index, CaseLabels), MLDS_Context),
+ EndLabelStatement = mlds__statement(label(EndLabel), MLDS_Context),
+ EndComment = mlds__statement(atomic(comment("End of dense switch")),
MLDS_Context),
% We may need to check that the value of the variable lies within the
- % appropriate range
+ % appropriate range.
(
- NeedRangeCheck = yes
- ->
+ NeedRangeCheck = yes,
Difference = LastVal - FirstVal,
- InRange = binop(unsigned_le, Index,
- const(int_const(Difference))),
- Else = yes(mlds__statement(
- block([], DefaultStatements),
+ InRange = binop(unsigned_le, Index, const(int_const(Difference))),
+ Else = yes(mlds__statement(block([], DefaultStatements),
MLDS_Context)),
- SwitchBody = mlds__statement(
- block([], [DoJump | CasesCode]),
+ SwitchBody = mlds__statement(block([], [DoJump | CasesCode]),
MLDS_Context),
- DoSwitch = mlds__statement(
- if_then_else(InRange, SwitchBody, Else),
+ DoSwitch = mlds__statement(if_then_else(InRange, SwitchBody, Else),
MLDS_Context),
Statements = [StartComment, DoSwitch] ++
[EndLabelStatement, EndComment]
;
+ NeedRangeCheck = no,
Statements = [StartComment, DoJump | CasesCode] ++
- DefaultStatements ++
- [EndLabelStatement, EndComment]
+ DefaultStatements ++ [EndLabelStatement, EndComment]
),
Decls = CasesDecls.
@@ -327,15 +303,15 @@
Decls = CaseDecls ++ Decls1,
Statements = CaseStatements ++ Statements1.
+ % This converts an MLDS switch case into code for a dense switch case,
+ % by adding a label at the front and a `goto <EndLabel>' at the end.
+ % It also inserts the label for this case into the CaseLabelsMap.
+ %
:- pred generate_case(mlds__switch_case::in, mlds__label::in,
case_labels_map::in, case_labels_map::out,
mlds__defns::out, mlds__statements::out,
ml_gen_info::in, ml_gen_info::out) is det.
-% This converts an MLDS switch case into code for a dense switch case,
-% by adding a label at the front and a `goto <EndLabel>' at the end.
-% It also inserts the label for this case into the CaseLabelsMap.
-
generate_case(Case, EndLabel, CaseLabelsMap0, CaseLabelsMap,
Decls, Statements, !Info) :-
Case = MatchCondition - CaseStatement,
@@ -343,28 +319,22 @@
insert_cases_into_map(MatchCondition, ThisLabel,
CaseLabelsMap0, CaseLabelsMap),
CaseStatement = mlds__statement(_, MLDS_Context),
- LabelComment = mlds__statement(
- atomic(comment("case of dense switch")),
- MLDS_Context),
- LabelCode = mlds__statement(
- label(ThisLabel),
+ LabelComment = mlds__statement(atomic(comment("case of dense switch")),
MLDS_Context),
+ LabelCode = mlds__statement(label(ThisLabel), MLDS_Context),
JumpComment = mlds__statement(
atomic(comment("branch to end of dense switch")),
MLDS_Context),
- JumpCode = mlds__statement(
- goto(label(EndLabel)),
- MLDS_Context),
+ JumpCode = mlds__statement(goto(label(EndLabel)), MLDS_Context),
Decls = [],
Statements = [LabelComment, LabelCode, CaseStatement,
JumpComment, JumpCode].
%-----------------------------------------------------------------------------%
-
%
% We build up a map which records which label should be used for
% each case value.
-%
+
:- type case_labels_map == map(int, mlds__label).
:- pred insert_cases_into_map(mlds__case_match_conds::in, mlds__label::in,
@@ -378,21 +348,19 @@
:- pred insert_case_into_map(mlds__case_match_cond::in, mlds__label::in,
case_labels_map::in, case_labels_map::out) is det.
-insert_case_into_map(match_value(Rval), ThisLabel,
- CaseLabelsMap0, CaseLabelsMap) :-
+insert_case_into_map(match_value(Rval), ThisLabel, !CaseLabelsMap) :-
( Rval = const(int_const(Val)) ->
- map__det_insert(CaseLabelsMap0, Val, ThisLabel, CaseLabelsMap)
+ map__det_insert(!.CaseLabelsMap, Val, ThisLabel, !:CaseLabelsMap)
;
error("insert_case_into_map: non-int case")
).
insert_case_into_map(match_range(MinRval, MaxRval), ThisLabel,
- CaseLabelsMap0, CaseLabelsMap) :-
+ !CaseLabelsMap) :-
(
MinRval = const(int_const(Min)),
MaxRval = const(int_const(Max))
->
- insert_range_into_map(Min, Max, ThisLabel,
- CaseLabelsMap0, CaseLabelsMap)
+ insert_range_into_map(Min, Max, ThisLabel, !CaseLabelsMap)
;
error("insert_case_into_map: non-int case")
).
@@ -400,23 +368,21 @@
:- pred insert_range_into_map(int::in, int::in, mlds__label::in,
case_labels_map::in, case_labels_map::out) is det.
-insert_range_into_map(Min, Max, ThisLabel, CaseLabelsMap0, CaseLabelsMap) :-
+insert_range_into_map(Min, Max, ThisLabel, !CaseLabelsMap) :-
( Min > Max ->
- CaseLabelsMap = CaseLabelsMap0
+ true
;
- map__det_insert(CaseLabelsMap0, Min, ThisLabel,
- CaseLabelsMap1),
- insert_range_into_map(Min + 1, Max, ThisLabel,
- CaseLabelsMap1, CaseLabelsMap)
+ map__det_insert(!.CaseLabelsMap, Min, ThisLabel, !:CaseLabelsMap),
+ insert_range_into_map(Min + 1, Max, ThisLabel, !CaseLabelsMap)
).
%-----------------------------------------------------------------------------%
-% Given the starting and ending case values, the mapping from case values
-% to labels, and the default label to use for case values which aren't in
-% the map, this function returns the list of labels to use for the case
-% values.
-
+ % Given the starting and ending case values, the mapping from case values
+ % to labels, and the default label to use for case values which aren't in
+ % the map, this function returns the list of labels to use for the case
+ % values.
+ %
:- func get_case_labels(int, int, map(int, mlds__label), mlds__label)
= list(mlds__label).
@@ -436,8 +402,8 @@
%-----------------------------------------------------------------------------%
- % Convert an int switch to a chain of if-then-elses
- % that test each case in turn.
+ % Convert an int switch to a chain of if-then-elses that test each case
+ % in turn.
%
:- func ml_switch_to_if_else_chain(mlds__switch_cases, mlds__switch_default,
mlds__rval, mlds__context) = mlds__statement.
@@ -456,22 +422,23 @@
Statement :-
Case = MatchConditions - CaseStatement,
(
- Cases = [], Default = default_is_unreachable
+ Cases = [],
+ Default = default_is_unreachable
->
Statement = CaseStatement
;
- CaseMatchedRval = ml_gen_case_match_conds(MatchConditions,
- SwitchRval),
- RestStatement = ml_switch_to_if_else_chain(Cases, Default,
- SwitchRval, MLDS_Context),
- IfStmt = if_then_else(CaseMatchedRval,
- CaseStatement, yes(RestStatement)),
+ CaseMatchedRval = ml_gen_case_match_conds(MatchConditions, SwitchRval),
+ RestStatement = ml_switch_to_if_else_chain(Cases, Default, SwitchRval,
+ MLDS_Context),
+ IfStmt = if_then_else(CaseMatchedRval, CaseStatement,
+ yes(RestStatement)),
Statement = mlds__statement(IfStmt, MLDS_Context)
).
- % Generate an rval which will be true iff any of the specified
- % list of case conditions matches the specified rval
- % (which must have integral type).
+ % Generate an rval which will be true iff any of the specified list of
+ % case conditions matches the specified rval (which must have integral
+ % type).
+ %
:- func ml_gen_case_match_conds(mlds__case_match_conds, rval) = rval.
ml_gen_case_match_conds([], _) = const(false).
@@ -482,15 +449,14 @@
ml_gen_case_match_cond(Cond1, SwitchRval),
ml_gen_case_match_conds([Cond2 | Conds], SwitchRval)).
- % Generate an rval which will be true iff the specified
- % case condition matches the specified rval
- % (which must have integral type).
+ % Generate an rval which will be true iff the specified case condition
+ % matches the specified rval (which must have integral type).
+ %
:- func ml_gen_case_match_cond(mlds__case_match_cond, rval) = rval.
ml_gen_case_match_cond(match_value(CaseRval), SwitchRval) =
binop(eq, CaseRval, SwitchRval).
ml_gen_case_match_cond(match_range(MinRval, MaxRval), SwitchRval) =
- binop(and, binop(>=, SwitchRval, MinRval),
- binop(<=, SwitchRval, MaxRval)).
+ binop(and, binop(>=, SwitchRval, MinRval), binop(<=, SwitchRval, MaxRval)).
%-----------------------------------------------------------------------------%
Index: compiler/ml_string_switch.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/ml_string_switch.m,v
retrieving revision 1.18
diff -u -b -r1.18 ml_string_switch.m
--- compiler/ml_string_switch.m 22 Mar 2005 06:40:10 -0000 1.18
+++ compiler/ml_string_switch.m 12 Sep 2005 11:04:00 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 1994-2005 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -26,9 +28,8 @@
:- import_module ml_backend__mlds.
:- import_module parse_tree__prog_data.
-:- pred ml_string_switch__generate(cases_list::in, prog_var::in,
- code_model::in, can_fail::in, prog_context::in,
- mlds__defns::out, mlds__statements::out,
+:- pred generate(cases_list::in, prog_var::in, code_model::in, can_fail::in,
+ prog_context::in, mlds__defns::out, mlds__statements::out,
ml_gen_info::in, ml_gen_info::out) is det.
%-----------------------------------------------------------------------------%
@@ -42,6 +43,7 @@
:- import_module ml_backend__ml_code_gen.
:- import_module ml_backend__ml_simplify_switch.
:- import_module ml_backend__ml_switch_gen.
+:- import_module parse_tree__error_util.
:- import_module assoc_list.
:- import_module bool.
@@ -52,20 +54,17 @@
:- import_module std_util.
:- import_module string.
-ml_string_switch__generate(Cases, Var, CodeModel, _CanFail, Context,
- Decls, Statements, !Info) :-
+generate(Cases, Var, CodeModel, _CanFail, Context, Decls, Statements, !Info) :-
MLDS_Context = mlds__make_context(Context),
- %
- % Compute the value we're going to switch on
- %
+ % Compute the value we're going to switch on.
+
ml_gen_var(!.Info, Var, VarLval),
VarRval = lval(VarLval),
- %
% Generate the following local variable declarations:
% int slot;
% MR_String str;
- %
+
ml_gen_info_new_cond_var(SlotVarSeq, !Info),
SlotVarName = mlds__var_name(
string__format("slot_%d", [i(SlotVarSeq)]), no),
@@ -87,17 +86,14 @@
StringVarType, StringVarGCTraceCode, MLDS_Context),
ml_gen_var_lval(!.Info, StringVarName, StringVarType, StringVarLval),
- %
- % Generate new labels
- %
+ % Generate new labels.
ml_gen_new_label(EndLabel, !Info),
GotoEndStatement = mlds__statement(goto(label(EndLabel)),
MLDS_Context),
- % Determine how big to make the hash table.
- % Currently we round the number of cases up to the nearest power
- % of two, and then double it. This should hopefully ensure that
- % we don't get too many hash collisions.
+ % Determine how big to make the hash table. Currently we round the number
+ % of cases up to the nearest power of two, and then double it. This should
+ % hopefully ensure that we don't get too many hash collisions.
%
list__length(Cases, NumCases),
int__log2(NumCases, LogNumCases),
@@ -105,26 +101,22 @@
TableSize = 2 * RoundedNumCases,
HashMask = TableSize - 1,
- % Compute the hash table
- %
+ % Compute the hash table.
switch_util__string_hash_cases(Cases, HashMask, HashValsMap),
map__to_assoc_list(HashValsMap, HashValsList),
switch_util__calc_hash_slots(HashValsList, HashValsMap, HashSlotsMap),
% Generate the code for when the hash lookup fails.
- %
ml_gen_failure(CodeModel, Context, FailStatements, !Info),
- % Generate the code etc. for the hash table
- %
- ml_string_switch__gen_hash_slots(0, TableSize, HashSlotsMap, CodeModel,
+ % Generate the code etc. for the hash table.
+ gen_hash_slots(0, TableSize, HashSlotsMap, CodeModel,
Context, Strings, NextSlots, SlotsCases, !Info),
- %
% Generate the following local constant declarations:
% static const int next_slots_table = { <NextSlots> };
% static const MR_String string_table[] = { <Strings> };
- %
+
ml_gen_info_new_const(NextSlotsSeq, !Info),
ml_format_static_const_name(!.Info, "next_slots_table", NextSlotsSeq,
NextSlotsName),
@@ -142,10 +134,7 @@
ml_gen_var_lval(!.Info, StringTableName, StringTableType,
StringTableLval),
- %
% Generate code which does the hash table lookup.
- %
-
SwitchStmt0 = switch(SlotVarType, lval(SlotVarLval),
range(0, TableSize - 1), SlotsCases, default_is_unreachable),
ml_simplify_switch(SwitchStmt0, MLDS_Context, SwitchStatement, !Info),
@@ -161,36 +150,27 @@
),
FoundMatchCode = mlds__statement(
block([], [
+ mlds__statement(atomic(comment("we found a match")), MLDS_Context),
mlds__statement(atomic(comment(
- "we found a match")),
- MLDS_Context),
- mlds__statement(atomic(comment(
- "dispatch to the corresponding code")),
- MLDS_Context),
+ "dispatch to the corresponding code")), MLDS_Context),
SwitchStatement,
GotoEndStatement
]),
MLDS_Context),
LoopBody = ml_gen_block([], [
mlds__statement(atomic(comment(
- "lookup the string for this hash slot")),
- MLDS_Context),
+ "lookup the string for this hash slot")), MLDS_Context),
mlds__statement(
atomic(assign(StringVarLval,
binop(array_index(elem_type_string),
lval(StringTableLval),
lval(SlotVarLval)))),
MLDS_Context),
- mlds__statement(atomic(comment(
- "did we find a match?")),
- MLDS_Context),
+ mlds__statement(atomic(comment("did we find a match?")), MLDS_Context),
mlds__statement(
- if_then_else(FoundMatchCond, FoundMatchCode,
- no),
- MLDS_Context),
+ if_then_else(FoundMatchCond, FoundMatchCode, no), MLDS_Context),
mlds__statement(atomic(comment(
- "no match yet, so get next slot in hash chain")),
- MLDS_Context),
+ "no match yet, so get next slot in hash chain")), MLDS_Context),
mlds__statement(
atomic(assign(SlotVarLval,
binop(array_index(elem_type_int),
@@ -200,109 +180,95 @@
],
Context),
HashLookupStatements = [
- mlds__statement(
- atomic(comment("hashed string switch")),
+ mlds__statement(atomic(comment("hashed string switch")),
MLDS_Context),
mlds__statement(atomic(comment(
- "compute the hash value of the input string")),
- MLDS_Context),
+ "compute the hash value of the input string")), MLDS_Context),
mlds__statement(
atomic(assign(SlotVarLval, binop(&,
unop(std_unop(hash_string), VarRval),
const(int_const(HashMask))))),
MLDS_Context),
- mlds__statement(atomic(comment(
- "hash chain loop")),
- MLDS_Context),
+ mlds__statement(atomic(comment("hash chain loop")), MLDS_Context),
mlds__statement(
- while(binop(>=, lval(SlotVarLval),
- const(int_const(0))),
+ while(binop(>=, lval(SlotVarLval), const(int_const(0))),
LoopBody,
yes), % this is a do...while loop
MLDS_Context)
],
FailComment =
- mlds__statement(
- atomic(comment("no match, so fail")),
- MLDS_Context),
- EndLabelStatement =
- mlds__statement(
- label(EndLabel),
+ mlds__statement(atomic(comment("no match, so fail")),
MLDS_Context),
+ EndLabelStatement = mlds__statement(label(EndLabel), MLDS_Context),
EndComment =
- mlds__statement(
- atomic(comment("end of hashed string switch")),
+ mlds__statement(atomic(comment("end of hashed string switch")),
MLDS_Context),
- %
% Collect all the generated variable/constant declarations
% and code fragments together.
- %
- Decls = [NextSlotsDefn, StringTableDefn,
- SlotVarDefn, StringVarDefn],
- Statements = HashLookupStatements ++
- [FailComment | FailStatements] ++
+ Decls = [NextSlotsDefn, StringTableDefn, SlotVarDefn, StringVarDefn],
+ Statements = HashLookupStatements ++ [FailComment | FailStatements] ++
[EndLabelStatement, EndComment].
%-----------------------------------------------------------------------------%
-:- pred ml_string_switch__gen_hash_slots(int::in, int::in,
+:- pred gen_hash_slots(int::in, int::in,
map(int, hash_slot)::in, code_model::in, prog_context::in,
list(mlds__initializer)::out, list(mlds__initializer)::out,
list(mlds__switch_case)::out,
ml_gen_info::in, ml_gen_info::out) is det.
-ml_string_switch__gen_hash_slots(Slot, TableSize, HashSlotMap, CodeModel,
- Context, Strings, NextSlots, MLDS_Cases, !Info) :-
+gen_hash_slots(Slot, TableSize, HashSlotMap, CodeModel, Context, Strings,
+ NextSlots, MLDS_Cases, !Info) :-
( Slot = TableSize ->
Strings = [],
NextSlots = [],
MLDS_Cases = []
;
MLDS_Context = mlds__make_context(Context),
- ml_string_switch__gen_hash_slot(Slot, HashSlotMap,
- CodeModel, MLDS_Context, String, NextSlot, SlotCases,
- !Info),
- ml_string_switch__gen_hash_slots(Slot + 1, TableSize,
- HashSlotMap, CodeModel, Context,
+ gen_hash_slot(Slot, HashSlotMap, CodeModel, MLDS_Context, String,
+ NextSlot, SlotCases, !Info),
+ gen_hash_slots(Slot + 1, TableSize, HashSlotMap, CodeModel, Context,
Strings0, NextSlots0, MLDS_Cases0, !Info),
Strings = [String | Strings0],
NextSlots = [NextSlot | NextSlots0],
MLDS_Cases = SlotCases ++ MLDS_Cases0
).
-:- pred ml_string_switch__gen_hash_slot(int::in, map(int, hash_slot)::in,
+:- pred gen_hash_slot(int::in, map(int, hash_slot)::in,
code_model::in, mlds__context::in, mlds__initializer::out,
mlds__initializer::out, list(mlds__switch_case)::out,
ml_gen_info::in, ml_gen_info::out) is det.
-ml_string_switch__gen_hash_slot(Slot, HashSlotMap, CodeModel, MLDS_Context,
- init_obj(StringRval), init_obj(NextSlotRval), MLDS_Cases,
- !Info) :-
+gen_hash_slot(Slot, HashSlotMap, CodeModel, MLDS_Context,
+ init_obj(StringRval), init_obj(NextSlotRval), MLDS_Cases, !Info) :-
( map__search(HashSlotMap, Slot, hash_slot(Case, Next)) ->
NextSlotRval = const(int_const(Next)),
Case = case(_, ConsTag, _, Goal),
( ConsTag = string_constant(String0) ->
String = String0
;
- error("ml_string_switch__gen_hash_slots: " ++
- "string expected")
+ error("gen_hash_slots: string expected")
),
StringRval = const(string_const(String)),
ml_gen_goal(CodeModel, Goal, GoalStatement, !Info),
- string__append_list(["case """, String, """"],
- CommentString),
- Comment = mlds__statement(
- atomic(comment(CommentString)),
+ string__append_list(["case """, String, """"], CommentString),
+ Comment = mlds__statement(atomic(comment(CommentString)),
MLDS_Context),
- CaseStatement = mlds__statement(
- block([], [Comment, GoalStatement]),
+ CaseStatement = mlds__statement(block([], [Comment, GoalStatement]),
MLDS_Context),
- MLDS_Cases = [[match_value(const(int_const(Slot)))] -
- CaseStatement]
+ MLDS_Cases = [[match_value(const(int_const(Slot)))] - CaseStatement]
;
StringRval = const(null(ml_string_type)),
NextSlotRval = const(int_const(-2)),
MLDS_Cases = []
).
+
+%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+
+this_file = "ml_string_switch.m".
+
+%-----------------------------------------------------------------------------%
Index: compiler/ml_switch_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/ml_switch_gen.m,v
retrieving revision 1.17
diff -u -b -r1.17 ml_switch_gen.m
--- compiler/ml_switch_gen.m 22 Mar 2005 06:40:10 -0000 1.17
+++ compiler/ml_switch_gen.m 12 Sep 2005 13:55:46 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 1994-2005 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -18,8 +20,9 @@
% Note that currently most of these are not implemented!
% The ones that are not are marked NYI (for "not yet implemented").
%
-% 1. For switches on atomic data types (int, char, enums), there are
+% 1 For switches on atomic data types (int, char, enums), there are
% several possibilities.
+%
% a) If all the alternative goals for a switch on an atomic data type
% contain only construction unifications of constants, then we
% should generate a dense lookup table (an array) for each output
@@ -32,24 +35,25 @@
% c) If the target supports switch statements,
% we generate an MLDS switch statement.
%
-% 2. For switches on strings, there are several possibilities.
-% a) If the target supports indirect gotos, we should look up the
-% address to jump to in a hash table (e.g. using open addressing to
-% resolve hash collisions), and then jump to it using an indirect
-% goto, unless the target supports string switch statements and
-% the `--prefer-switch' option is set. (NYI)
-% c) If the target supports string switches,
+% 2 For switches on strings, there are several possibilities.
+%
+% a) If the target supports indirect gotos, we should look up the address
+% to jump to in a hash table (e.g. using open addressing to resolve
+% hash collisions), and then jump to it using an indirect goto,
+% unless the target supports string switch statements and the
+% `--prefer-switch' option is set. (NYI)
+% b) If the target supports string switches,
% we generate an MLDS switch statement.
%
-% 3. For switches on discriminated union types, we generate code that does
+% 3 For switches on discriminated union types, we generate code that does
% indexing first on the primary tag, and then on the secondary tag (if
% the primary tag is shared between several function symbols). The
% indexing code for switches on both primary and secondary tags can be
% in the form of a try-me-else chain, a try chain, a dense jump table
% or a binary search. (NYI)
%
-% For all other cases (or if the --smart-indexing option was
-% disabled), we just generate a chain of if-then-elses.
+% For all other cases (or if the --smart-indexing option was disabled),
+% we just generate a chain of if-then-elses.
%
% TODO:
% - implement the things marked NYI above
@@ -79,9 +83,6 @@
mlds__defns::out, mlds__statements::out,
ml_gen_info::in, ml_gen_info::out) is det.
-% The following types are exported to the modules that implement
-% specialized kinds of switches.
-
% Generate an appropriate default for a switch.
%
:- pred ml_switch_generate_default(can_fail::in, code_model::in,
@@ -89,6 +90,7 @@
ml_gen_info::in, ml_gen_info::out) is det.
% Succeed iff the target supports the specified construct.
+ %
:- pred target_supports_int_switch(globals::in) is semidet.
:- pred target_supports_string_switch(globals::in) is semidet.
:- pred target_supports_goto(globals::in) is semidet.
@@ -108,6 +110,7 @@
:- import_module ml_backend__ml_string_switch.
:- import_module ml_backend__ml_tag_switch.
:- import_module ml_backend__ml_unify_gen.
+:- import_module parse_tree__error_util.
:- import_module bool.
:- import_module int.
@@ -119,24 +122,16 @@
%-----------------------------------------------------------------------------%
- % Choose which method to use to generate the switch.
- % CanFail says whether the switch covers all cases.
-
ml_gen_switch(CaseVar, CanFail, Cases, CodeModel, Context,
Decls, Statements, !Info) :-
- %
% Lookup the representation of the constructors for the tag tests
% and their corresponding priorities.
- %
ml_switch_lookup_tags(!.Info, Cases, CaseVar, TaggedCases0),
- %
+
% Sort the cases according to the priority of their tag tests.
- %
list__sort_and_remove_dups(TaggedCases0, TaggedCases),
- %
% Figure out what kind of switch this is.
- %
ml_switch_gen__determine_category(!.Info, CaseVar, SwitchCategory),
ml_gen_info_get_globals(!.Info, Globals),
globals__lookup_bool_option(Globals, smart_indexing, Indexing),
@@ -152,9 +147,8 @@
)
->
% XXX This may be inefficient in some cases.
- ml_switch_generate_if_else_chain(TaggedCases, CaseVar,
- CodeModel, CanFail, Context,
- Decls, Statements, !Info)
+ ml_switch_generate_if_else_chain(TaggedCases, CaseVar, CodeModel,
+ CanFail, Context, Decls, Statements, !Info)
;
% XXX Lookup switches are NYI
% When we do get around to implementing them,
@@ -180,14 +174,11 @@
% FirstVal, LastVal, NeedRangeCheck, NeedBitVecCheck,
% Decls, Statements, !Info)
% ;
- %
% Try using a string hash switch.
- %
Indexing = yes,
SwitchCategory = string_switch,
list__length(TaggedCases, NumCases),
- globals__lookup_int_option(Globals, string_switch_size,
- StringSize),
+ globals__lookup_int_option(Globals, string_switch_size, StringSize),
NumCases >= StringSize,
% We can implement string hash switches using either
% computed gotos or int switches.
@@ -205,16 +196,13 @@
% We may prefer to do a direct-mapped string switch.
\+ (
target_supports_string_switch(Globals),
- globals__lookup_bool_option(Globals, prefer_switch,
- yes)
+ globals__lookup_bool_option(Globals, prefer_switch, yes)
)
->
ml_string_switch__generate(TaggedCases, CaseVar, CodeModel,
CanFail, Context, Decls, Statements, !Info)
;
- %
% Try using a tag switch.
- %
Indexing = yes,
SwitchCategory = tag_switch,
list__length(TaggedCases, NumCases),
@@ -225,11 +213,9 @@
ml_tag_switch__generate(TaggedCases, CaseVar, CodeModel,
CanFail, Context, Decls, Statements, !Info)
;
- %
- % Try using a "direct-mapped" switch.
- % This also handles dense (computed goto) switches --
- % for those, we first generate a direct-mapped switch,
- % and then convert it into a computed goto switch
+ % Try using a "direct-mapped" switch. This also handles dense
+ % (computed goto) switches -- for those, we first generate a
+ % direct-mapped switch, and then convert it into a computed goto switch
% in ml_simplify_switch.
%
Indexing = yes,
@@ -240,17 +226,13 @@
target_supports_computed_goto(Globals)
)
->
- ml_switch_generate_mlds_switch(TaggedCases, CaseVar,
- CodeModel, CanFail, Context,
- Decls, Statements, !Info)
+ ml_switch_generate_mlds_switch(TaggedCases, CaseVar, CodeModel,
+ CanFail, Context, Decls, Statements, !Info)
;
- %
- % The fallback method: if all else fails, generate an
- % if-then-else chain which tests each of the cases in turn.
- %
- ml_switch_generate_if_else_chain(TaggedCases, CaseVar,
- CodeModel, CanFail, Context,
- Decls, Statements, !Info)
+ % The fallback method: if all else fails, generate an if-then-else
+ % chain which tests each of the cases in turn.
+ ml_switch_generate_if_else_chain(TaggedCases, CaseVar, CodeModel,
+ CanFail, Context, Decls, Statements, !Info)
).
%-----------------------------------------------------------------------------%
@@ -316,10 +298,9 @@
%-----------------------------------------------------------------------------%
- % We categorize switches according to whether the value
- % being switched on is an atomic type, a string, or
- % something more complicated.
-
+ % We categorize switches according to whether the value being switched on
+ % is an atomic type, a string, or something more complicated.
+ %
:- pred ml_switch_gen__determine_category(ml_gen_info::in, prog_var::in,
switch_category::out) is det.
@@ -357,10 +338,12 @@
ml_switch_generate_if_else_chain([], _Var, CodeModel, CanFail, Context,
[], Statements, !Info) :-
- ( CanFail = can_fail ->
+ (
+ CanFail = can_fail,
ml_gen_failure(CodeModel, Context, Statements, !Info)
;
- error("switch failure")
+ CanFail = cannot_fail,
+ unexpected(this_file, "switch failure")
).
ml_switch_generate_if_else_chain([Case | Cases], Var, CodeModel, CanFail,
Context, Decls, Statements, !Info) :-
@@ -377,20 +360,17 @@
ml_switch_generate_if_else_chain(Cases, Var, CodeModel,
CanFail, Context, RestDecls, RestStatements, !Info),
Rest = ml_gen_block(RestDecls, RestStatements, Context),
- IfStmt = if_then_else(TagTestExpression,
- GoalStatement, yes(Rest)),
- IfStatement = mlds__statement(IfStmt,
- mlds__make_context(Context)),
+ IfStmt = if_then_else(TagTestExpression, GoalStatement, yes(Rest)),
+ IfStatement = mlds__statement(IfStmt, mlds__make_context(Context)),
Decls = TagTestDecls,
- Statements = list__append(TagTestStatements,
- [IfStatement])
+ Statements = TagTestStatements ++ [IfStatement]
).
%-----------------------------------------------------------------------------%
- % Generate an MLDS switch.
- % This is used for "direct-mapped" switches, where we map a
- % Mercury switch directly to a switch in the target language.
+ % Generate an MLDS switch. This is used for "direct-mapped" switches,
+ % where we map a Mercury switch directly to a switch in the target
+ % language.
%
:- pred ml_switch_generate_mlds_switch(list(extended_case)::in, prog_var::in,
code_model::in, can_fail::in, prog_context::in,
@@ -405,8 +385,7 @@
Rval = mlds__lval(Lval),
ml_switch_gen_range(!.Info, MLDS_Type, Range),
ml_switch_generate_mlds_cases(Cases, CodeModel, MLDS_Cases, !Info),
- ml_switch_generate_default(CanFail, CodeModel, Context, Default,
- !Info),
+ ml_switch_generate_default(CanFail, CodeModel, Context, Default, !Info),
SwitchStmt0 = switch(MLDS_Type, Rval, Range, MLDS_Cases, Default),
MLDS_Context = mlds__make_context(Context),
ml_simplify_switch(SwitchStmt0, MLDS_Context, SwitchStatement, !Info),
@@ -450,7 +429,7 @@
; Tag = string_constant(String) ->
Rval = const(string_const(String))
;
- error("ml_switch_gen.m: invalid tag type")
+ unexpected(this_file, "ml_switch_gen.m: invalid tag type")
),
ml_gen_goal(CodeModel, Goal, Statement, !Info),
MLDS_Case = [match_value(Rval)] - Statement.
@@ -461,9 +440,11 @@
(
CanFail = can_fail,
ml_gen_failure(CodeModel, Context, FailStatements, !Info),
- ( FailStatements = [] ->
+ (
+ FailStatements = [],
Default = default_do_nothing
;
+ FailStatements = [_ | _],
Fail = ml_gen_block([], FailStatements, Context),
Default = default_case(Fail)
)
@@ -473,4 +454,9 @@
).
%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+
+this_file = "ml_switch_gen.m".
+
%-----------------------------------------------------------------------------%
Index: compiler/ml_tag_switch.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/ml_tag_switch.m,v
retrieving revision 1.11
diff -u -b -r1.11 ml_tag_switch.m
--- compiler/ml_tag_switch.m 25 Aug 2005 03:19:47 -0000 1.11
+++ compiler/ml_tag_switch.m 12 Sep 2005 13:16:55 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 2000, 2003-2005 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -25,10 +27,9 @@
:- import_module list.
% Generate efficient indexing code for tag based switches.
-
-:- pred ml_tag_switch__generate(list(extended_case)::in, prog_var::in,
- code_model::in, can_fail::in, prog_context::in,
- mlds__defns::out, mlds__statements::out,
+ %
+:- pred generate(list(extended_case)::in, prog_var::in, code_model::in,
+ can_fail::in, prog_context::in, mlds__defns::out, mlds__statements::out,
ml_gen_info::in, ml_gen_info::out) is det.
:- implementation.
@@ -41,6 +42,7 @@
:- import_module ml_backend__ml_simplify_switch.
:- import_module ml_backend__ml_switch_gen.
:- import_module ml_backend__ml_unify_gen.
+:- import_module parse_tree__error_util.
:- import_module assoc_list.
:- import_module int.
@@ -51,64 +53,59 @@
%-----------------------------------------------------------------------------%
-ml_tag_switch__generate(Cases, Var, CodeModel, CanFail, Context,
- Decls, Statements, !Info) :-
- % generate the rval for the primary tag
+generate(Cases, Var, CodeModel, CanFail, Context, Decls, Statements, !Info) :-
+ % Generate the rval for the primary tag.
ml_gen_var(!.Info, Var, VarLval),
VarRval = lval(VarLval),
PTagRval = unop(std_unop(tag), VarRval),
- % group the cases based on primary tag value,
- % find out how many constructors share each primary tag value,
- % and sort the cases so that the most frequently occurring
- % primary tag values come first.
+ % Group the cases based on primary tag value, find out how many
+ % constructors share each primary tag value, and sort the cases so that
+ % the most frequently occurring primary tag values come first.
ml_gen_info_get_module_info(!.Info, ModuleInfo),
ml_variable_type(!.Info, Var, Type),
- switch_util__get_ptag_counts(Type, ModuleInfo,
- MaxPrimary, PtagCountMap),
+ switch_util__get_ptag_counts(Type, ModuleInfo, MaxPrimary, PtagCountMap),
map__to_assoc_list(PtagCountMap, PtagCountList),
map__init(PtagCaseMap0),
switch_util__group_cases_by_ptag(Cases, PtagCaseMap0, PtagCaseMap),
switch_util__order_ptags_by_count(PtagCountList, PtagCaseMap,
PtagCaseList),
- % generate the switch on the primary tag
-
- ml_tag_switch__gen_ptag_cases(PtagCaseList, Var, CanFail, CodeModel,
+ % Generate the switch on the primary tag.
+ gen_ptag_cases(PtagCaseList, Var, CanFail, CodeModel,
PtagCountMap, Context, MLDS_Cases, !Info),
ml_switch_generate_default(CanFail, CodeModel, Context, Default, !Info),
- % package up the results into a switch statement
-
+ % Package up the results into a switch statement.
Range = range(0, MaxPrimary),
- SwitchStmt0 = switch(mlds__native_int_type, PTagRval, Range,
- MLDS_Cases, Default),
+ SwitchStmt0 = switch(mlds__native_int_type, PTagRval, Range, MLDS_Cases,
+ Default),
MLDS_Context = mlds__make_context(Context),
ml_simplify_switch(SwitchStmt0, MLDS_Context, SwitchStatement, !Info),
Decls = [],
Statements = [SwitchStatement].
-:- pred ml_tag_switch__gen_ptag_cases(ptag_case_list::in, prog_var::in,
+:- pred gen_ptag_cases(ptag_case_list::in, prog_var::in,
can_fail::in, code_model::in, ptag_count_map::in,
prog_context::in, list(mlds__switch_case)::out,
ml_gen_info::in, ml_gen_info::out) is det.
-ml_tag_switch__gen_ptag_cases([], _, _, _, _, _, [], !Info).
-ml_tag_switch__gen_ptag_cases([Case | Cases], Var, CanFail, CodeModel,
+gen_ptag_cases([], _, _, _, _, _, [], !Info).
+gen_ptag_cases([Case | Cases], Var, CanFail, CodeModel,
PtagCountMap, Context, [MLDS_Case | MLDS_Cases], !Info) :-
- ml_tag_switch__gen_ptag_case(Case, Var, CanFail, CodeModel,
+ gen_ptag_case(Case, Var, CanFail, CodeModel,
PtagCountMap, Context, MLDS_Case, !Info),
- ml_tag_switch__gen_ptag_cases(Cases, Var, CanFail, CodeModel,
+ gen_ptag_cases(Cases, Var, CanFail, CodeModel,
PtagCountMap, Context, MLDS_Cases, !Info).
-:- pred ml_tag_switch__gen_ptag_case(pair(tag_bits, ptag_case)::in,
+:- pred gen_ptag_case(pair(tag_bits, ptag_case)::in,
prog_var::in, can_fail::in, code_model::in, ptag_count_map::in,
prog_context::in, mlds__switch_case::out,
ml_gen_info::in, ml_gen_info::out) is det.
-ml_tag_switch__gen_ptag_case(Case, Var, CanFail, CodeModel, PtagCountMap,
- Context, MLDS_Case, !Info) :-
+gen_ptag_case(Case, Var, CanFail, CodeModel, PtagCountMap, Context, MLDS_Case,
+ !Info) :-
Case = PrimaryTag - ptag_case(SecTagLocn, GoalMap),
map__lookup(PtagCountMap, PrimaryTag, CountInfo),
CountInfo = SecTagLocn1 - MaxSecondary,
@@ -116,16 +113,16 @@
"ml_tag_switch.m: secondary tag locations differ"),
map__to_assoc_list(GoalMap, GoalList),
( SecTagLocn = none ->
- % There is no secondary tag, so there is no switch on it
+ % There is no secondary tag, so there is no switch on it.
(
GoalList = [],
- error("no goal for non-shared tag")
+ unexpected(this_file, "no goal for non-shared tag")
;
GoalList = [_Stag - stag_goal(_ConsId, Goal)],
ml_gen_goal(CodeModel, Goal, Statement, !Info)
;
GoalList = [_, _ | _],
- error("more than one goal for non-shared tag")
+ unexpected(this_file, "more than one goal for non-shared tag")
)
;
(
@@ -146,26 +143,24 @@
CaseCanFail = cannot_fail
->
% There is only one possible matching goal,
- % so we don't need to switch on it
+ % so we don't need to switch on it.
ml_gen_goal(CodeModel, Goal, Statement, !Info)
;
- ml_tag_switch__gen_stag_switch(GoalList, PrimaryTag,
- SecTagLocn, Var, CodeModel, CaseCanFail,
- Context, Statement, !Info)
+ gen_stag_switch(GoalList, PrimaryTag, SecTagLocn,
+ Var, CodeModel, CaseCanFail, Context, Statement, !Info)
)
),
PrimaryTagRval = const(int_const(PrimaryTag)),
MLDS_Case = [match_value(PrimaryTagRval)] - Statement.
-:- pred ml_tag_switch__gen_stag_switch(stag_goal_list::in, int::in,
+:- pred gen_stag_switch(stag_goal_list::in, int::in,
stag_loc::in, prog_var::in, code_model::in, can_fail::in,
prog_context::in, mlds__statement::out,
ml_gen_info::in, ml_gen_info::out) is det.
-ml_tag_switch__gen_stag_switch(Cases, PrimaryTag, StagLocn, Var,
- CodeModel, CanFail, Context, Statement, !Info) :-
- % generate the rval for the secondary tag
-
+gen_stag_switch(Cases, PrimaryTag, StagLocn, Var, CodeModel, CanFail, Context,
+ Statement, !Info) :-
+ % Generate the rval for the secondary tag.
ml_gen_info_get_module_info(!.Info, ModuleInfo),
ml_variable_type(!.Info, Var, VarType),
ml_gen_var(!.Info, Var, VarLval),
@@ -179,41 +174,42 @@
VarType, ModuleInfo, VarRval)
;
StagLocn = none,
- error("ml_tag_switch__gen_stag_switch: no stag")
+ unexpected(this_file, "gen_stag_switch: no stag")
),
- % generate the switch on the secondary tag
-
- ml_tag_switch__gen_stag_cases(Cases, CodeModel, MLDS_Cases, !Info),
- ml_switch_generate_default(CanFail, CodeModel, Context, Default,
- !Info),
-
- % package up the results into a switch statement
+ % Generate the switch on the secondary tag.
+ gen_stag_cases(Cases, CodeModel, MLDS_Cases, !Info),
+ ml_switch_generate_default(CanFail, CodeModel, Context, Default, !Info),
+ % Package up the results into a switch statement.
Range = range_unknown, % XXX could do better
- SwitchStmt = switch(mlds__native_int_type, STagRval, Range,
- MLDS_Cases, Default),
+ SwitchStmt = switch(mlds__native_int_type, STagRval, Range, MLDS_Cases,
+ Default),
MLDS_Context = mlds__make_context(Context),
ml_simplify_switch(SwitchStmt, MLDS_Context, Statement, !Info).
-:- pred ml_tag_switch__gen_stag_cases(stag_goal_list::in, code_model::in,
- list(mlds__switch_case)::out, ml_gen_info::in, ml_gen_info::out)
- is det.
-
-ml_tag_switch__gen_stag_cases([], _, [], !Info).
-ml_tag_switch__gen_stag_cases([Case | Cases], CodeModel,
- [MLDS_Case | MLDS_Cases], !Info) :-
- ml_tag_switch__gen_stag_case(Case, CodeModel, MLDS_Case, !Info),
- ml_tag_switch__gen_stag_cases(Cases, CodeModel, MLDS_Cases, !Info).
+:- pred gen_stag_cases(stag_goal_list::in, code_model::in,
+ list(mlds__switch_case)::out, ml_gen_info::in, ml_gen_info::out) is det.
+
+gen_stag_cases([], _, [], !Info).
+gen_stag_cases([Case | Cases], CodeModel, [MLDS_Case | MLDS_Cases], !Info) :-
+ gen_stag_case(Case, CodeModel, MLDS_Case, !Info),
+ gen_stag_cases(Cases, CodeModel, MLDS_Cases, !Info).
-:- pred ml_tag_switch__gen_stag_case(pair(tag_bits, stag_goal)::in,
+:- pred gen_stag_case(pair(tag_bits, stag_goal)::in,
code_model::in, mlds__switch_case::out,
ml_gen_info::in, ml_gen_info::out) is det.
-ml_tag_switch__gen_stag_case(Case, CodeModel, MLDS_Case, !Info) :-
+gen_stag_case(Case, CodeModel, MLDS_Case, !Info) :-
Case = Stag - stag_goal(_ConsId, Goal),
StagRval = const(int_const(Stag)),
ml_gen_goal(CodeModel, Goal, Statement, !Info),
MLDS_Case = [match_value(StagRval)] - Statement.
+
+%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+
+this_file = "ml_tag_switch.m".
%-----------------------------------------------------------------------------%
Index: compiler/ml_tailcall.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/ml_tailcall.m,v
retrieving revision 1.27
diff -u -b -r1.27 ml_tailcall.m
--- compiler/ml_tailcall.m 1 Sep 2005 09:06:33 -0000 1.27
+++ compiler/ml_tailcall.m 12 Sep 2005 14:12:20 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 1999-2005 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -7,46 +9,43 @@
% File: ml_tailcall.m
% Main author: fjh
-% This module is an MLDS-to-MLDS transformation
-% that marks function calls as tail calls whenever
-% it is safe to do so, based on the assumptions described below.
+% This module is an MLDS-to-MLDS transformation that marks function calls
+% as tail calls whenever it is safe to do so, based on the assumptions
+% described below.
% This module also contains a pass over the MLDS that detects functions
-% which are directly recursive, but not tail-recursive,
-% and warns about them.
+% which are directly recursive, but not tail-recursive, and warns about them.
-% A function call can safely be marked as a tail call if
-% (1) it occurs in a position which would fall through into the
-% end of the function body or to a `return' statement,
-% and
-% (2) the lvalues in which the return value(s) from the `call'
-% will be placed are the same as the value(s) returned
-% by the `return', and these lvalues are all local variables.
-% and
-% (3) the function's local variables do not need to be live
-% for that call.
+% A function call can safely be marked as a tail call if all three of the
+% following conditions are satisfied:
%
-% For (2), we just assume (rather than checking) that
-% any variables returned by the `return' statement are
-% local variables. This assumption is true for the MLDS code
-% generated by ml_code_gen.m.
+% 1 it occurs in a position which would fall through into the end of the
+% function body or to a `return' statement,
%
-% For (3), we assume that the addresses of local variables
-% and nested functions are only ever passed down to other functions
-% (and used to assign to the local variable or to call the nested
-% function), so that here we only need to check if the potential
-% tail call uses such addresses, not whether such addresses were
-% taken in earlier calls. That is, if the addresses
-% of locals were taken in earlier calls from the same function,
-% we assume that these addresses will not be saved (on the heap,
-% or in global variables, etc.) and used after those earlier calls
-% have returned. This assumption is true for the MLDS code generated
-% by ml_code_gen.m.
+% 2 the lvalues in which the return value(s) from the `call' will be placed
+% are the same as the value(s) returned by the `return', and these lvalues
+% are all local variables,
+%
+% 3 the function's local variables do not need to be live for that call.
+%
+% For (2), we just assume (rather than checking) that any variables returned
+% by the `return' statement are local variables. This assumption is true
+% for the MLDS code generated by ml_code_gen.m.
+%
+% For (3), we assume that the addresses of local variables and nested functions
+% are only ever passed down to other functions (and used to assign to the local
+% variable or to call the nested function), so that here we only need to check
+% if the potential tail call uses such addresses, not whether such addresses
+% were taken in earlier calls. That is, if the addresses of locals were taken
+% in earlier calls from the same function, we assume that these addresses
+% will not be saved (on the heap, or in global variables, etc.) and used after
+% those earlier calls have returned. This assumption is true for the MLDS code
+% generated by ml_code_gen.m.
%
-% We just mark tailcalls in this module here. The actual tailcall
-% optimization (turn self-tailcalls into loops) is done in ml_optimize.
-% Individual backends may wish to treat tailcalls separately if there is
-% any backend support for them.
+% We just mark tailcalls in this module here. The actual tailcall optimization
+% (turn self-tailcalls into loops) is done in ml_optimize. Individual backends
+% may wish to treat tailcalls separately if there is any backend support
+% for them.
%
% Note that ml_call_gen.m will also mark calls to procedures with determinism
% `erroneous' as `no_return_call's (a special case of tail calls)
@@ -55,6 +54,7 @@
%-----------------------------------------------------------------------------%
:- module ml_backend__ml_tailcall.
+
:- interface.
:- import_module ml_backend__mlds.
@@ -96,10 +96,10 @@
%-----------------------------------------------------------------------------%
- % The `at_tail' type indicates whether or not a subgoal
- % is at a tail position, i.e. is followed by a return
- % statement or the end of the function, and if so,
- % specifies the return values (if any) in the return statement.
+ % The `at_tail' type indicates whether or not a subgoal is at a tail
+ % position, i.e. is followed by a return statement or the end of the
+ % function, and if so, specifies the return values (if any) in the return
+ % statement.
:- type at_tail == maybe(list(mlds__rval)).
% The `locals' type contains a list of local definitions
@@ -111,7 +111,6 @@
%-----------------------------------------------------------------------------%
-%
% mark_tailcalls_in_defns:
% mark_tailcalls_in_defn:
% Recursively process the definition(s),
@@ -129,7 +128,6 @@
% construct is in a tail call position.
% The `Locals' argument contains a list of the
% local definitions which are in scope at this point.
-%
:- func mark_tailcalls_in_defns(mlds__defns) = mlds__defns.
@@ -140,23 +138,19 @@
mark_tailcalls_in_defn(Defn0) = Defn :-
Defn0 = mlds__defn(Name, Context, Flags, DefnBody0),
(
- DefnBody0 = mlds__function(PredProcId, Params, FuncBody0,
- Attributes),
- %
- % Compute the initial value of the `Locals' and
- % `AtTail' arguments.
- %
+ DefnBody0 = mlds__function(PredProcId, Params, FuncBody0, Attributes),
+ % Compute the initial value of the `Locals' and `AtTail' arguments.
Params = mlds__func_params(Args, RetTypes),
Locals = [params(Args)],
- ( RetTypes = [] ->
+ (
+ RetTypes = [],
AtTail = yes([])
;
+ RetTypes = [_ | _],
AtTail = no
),
- FuncBody = mark_tailcalls_in_function_body(FuncBody0,
- AtTail, Locals),
- DefnBody = mlds__function(PredProcId, Params, FuncBody,
- Attributes),
+ FuncBody = mark_tailcalls_in_function_body(FuncBody0, AtTail, Locals),
+ DefnBody = mlds__function(PredProcId, Params, FuncBody, Attributes),
Defn = mlds__defn(Name, Context, Flags, DefnBody)
;
DefnBody0 = mlds__data(_, _, _),
@@ -195,23 +189,16 @@
mark_tailcalls_in_statements([], _, _) = [].
mark_tailcalls_in_statements([First0 | Rest0], AtTail, Locals) =
[First | Rest] :-
- %
- % If the First statement is followed by a `return'
- % statement, then it is in a tailcall position.
- % If there are no statements after the first, then
- % the first statement is in a tail call position
- % iff the statement list is in a tail call position.
- % Otherwise, i.e. if the first statement is followed
- % by anything other than a `return' statement, then
+ % If the First statement is followed by a `return' statement, then it is
+ % in a tailcall position. If there are no statements after the first, then
+ % the first statement is in a tail call position iff the statement list
+ % is in a tail call position. Otherwise, i.e. if the first statement
+ % is followed by anything other than a `return' statement, then
% the first statement is not in a tail call position.
%
- (
- Rest = [mlds__statement(return(ReturnVals), _) | _]
- ->
+ ( Rest = [mlds__statement(return(ReturnVals), _) | _] ->
FirstAtTail = yes(ReturnVals)
- ;
- Rest = []
- ->
+ ; Rest = [] ->
FirstAtTail = AtTail
;
FirstAtTail = no
@@ -231,16 +218,12 @@
mark_tailcalls_in_stmt(Stmt0, AtTail, Locals) = Stmt :-
(
- %
- % Whenever we encounter a block statement,
- % we recursively mark tailcalls in any nested
- % functions defined in that block.
- % We also need to add any local definitions in that
- % block to the list of currently visible local
- % declarations before processing the statements
- % in that block. The statement list will be in a
- % tail position iff the block is in a tail position.
- %
+ % Whenever we encounter a block statement, we recursively mark
+ % tailcalls in any nested functions defined in that block.
+ % We also need to add any local definitions in that block to the list
+ % of currently visible local declarations before processing the
+ % statements in that block. The statement list will be in a tail
+ % position iff the block is in a tail position.
Stmt0 = block(Defns0, Statements0),
Defns = mark_tailcalls_in_defns(Defns0),
NewLocals = [defns(Defns) | Locals],
@@ -248,30 +231,22 @@
AtTail, NewLocals),
Stmt = block(Defns, Statements)
;
- %
- % The statement in the body of a while loop is never
- % in a tail position.
- %
+ % The statement in the body of a while loop is never in a tail
+ % position.
Stmt0 = while(Rval, Statement0, Once),
Statement = mark_tailcalls_in_statement(Statement0, no, Locals),
Stmt = while(Rval, Statement, Once)
;
- %
- % Both the `then' and the `else' parts of an if-then-else
- % are in a tail position iff the if-then-else is in a
- % tail position.
- %
+ % Both the `then' and the `else' parts of an if-then-else are in a
+ % tail position iff the if-then-else is in a tail position.
Stmt0 = if_then_else(Cond, Then0, MaybeElse0),
Then = mark_tailcalls_in_statement(Then0, AtTail, Locals),
MaybeElse = mark_tailcalls_in_maybe_statement(MaybeElse0,
AtTail, Locals),
Stmt = if_then_else(Cond, Then, MaybeElse)
;
- %
- % All of the cases of a switch (including the default)
- % are in a tail position iff the switch is in a
- % tail position.
- %
+ % All of the cases of a switch (including the default) are in a
+ % tail position iff the switch is in a tail position.
Stmt0 = switch(Type, Val, Range, Cases0, Default0),
Cases = mark_tailcalls_in_cases(Cases0, AtTail, Locals),
Default = mark_tailcalls_in_default(Default0, AtTail, Locals),
@@ -292,34 +267,27 @@
%
(
CallKind0 = ordinary_call,
- %
- % we must be in a tail position
- %
+
+ % We must be in a tail position.
AtTail = yes(ReturnRvals),
- %
- % the values returned in this call must match
- % those returned by the `return' statement that
- % follows
- %
+
+ % The values returned in this call must match those returned
+ % by the `return' statement that follows.
match_return_vals(ReturnRvals, ReturnLvals),
- %
- % the call must not take the address of any
- % local variables or nested functions
- %
+
+ % The call must not take the address of any local variables
+ % or nested functions.
check_maybe_rval(Obj, Locals),
check_rvals(Args, Locals),
- %
- % the call must not be to a function nested within
- % this function
- %
+
+ % The call must not be to a function nested within this function.
check_rval(Func, Locals)
->
- % mark this call as a tail call
+ % Mark this call as a tail call.
CallKind = tail_call,
- Stmt = call(Sig, Func, Obj, Args, ReturnLvals,
- CallKind)
+ Stmt = call(Sig, Func, Obj, Args, ReturnLvals, CallKind)
;
- % leave this call unchanged
+ % Leave this call unchanged.
Stmt = Stmt0
)
;
@@ -330,13 +298,10 @@
Stmt = Stmt0
;
Stmt0 = try_commit(Ref, Statement0, Handler0),
- %
- % Both the statement inside a `try_commit' and the
- % handler are in tail call position iff the
- % `try_commit' statement is in a tail call position.
- %
- Statement = mark_tailcalls_in_statement(Statement0, AtTail,
- Locals),
+ % Both the statement inside a `try_commit' and the handler are in
+ % tail call position iff the `try_commit' statement is in a tail call
+ % position.
+ Statement = mark_tailcalls_in_statement(Statement0, AtTail, Locals),
Handler = mark_tailcalls_in_statement(Handler0, AtTail, Locals),
Stmt = try_commit(Ref, Statement, Handler)
;
@@ -372,7 +337,6 @@
%-----------------------------------------------------------------------------%
-%
% match_return_vals(Rvals, Lvals):
% match_return_val(Rval, Lval):
% Check that the Lval(s) returned by a call match
@@ -380,7 +344,6 @@
% and those Lvals are local variables
% (so that assignments to them won't have any side effects),
% so that we can optimize the call into a tailcall.
-%
:- pred match_return_vals(list(mlds__rval)::in, list(mlds__lval)::in)
is semidet.
@@ -398,8 +361,8 @@
:- pred lval_is_local(mlds__lval::in) is semidet.
lval_is_local(var(_, _)) :-
- % We just assume it is local. (This assumption is
- % true for the code generated by ml_code_gen.m.)
+ % We just assume it is local. (This assumption is true for the code
+ % generated by ml_code_gen.m.)
true.
lval_is_local(field(_Tag, Rval, _Field, _, _)) :-
% a field of a local variable is local
@@ -413,13 +376,11 @@
%-----------------------------------------------------------------------------%
-%
% check_rvals:
% check_maybe_rval:
% check_rval:
% Fail if the specified rval(s) might evaluate to the addresses of
% local variables (or fields of local variables) or nested functions.
-%
:- pred check_rvals(list(mlds__rval)::in, locals::in) is semidet.
@@ -453,12 +414,9 @@
% if that lval names a local variable.
check_lval(Lval, Locals).
-%
-% check_lval:
-% Fail if the specified lval might be a local variable
-% (or a field of a local variable).
-%
-
+ % Fail if the specified lval might be a local variable
+ % (or a field of a local variable).
+ %
:- pred check_lval(mlds__lval::in, locals::in) is semidet.
check_lval(field(_MaybeTag, Rval, _FieldId, _, _), Locals) :-
@@ -471,18 +429,14 @@
check_lval(var(Var0, _), Locals) :-
\+ var_is_local(Var0, Locals).
-%
-% check_const:
-% Fail if the specified const might be the address of a
-% local variable or nested function.
-%
-% The addresses of local variables are probably
-% not consts, at least not unless those variables are
-% declared as static (i.e. `one_copy'),
-% so it might be safe to allow all data_addr_consts here,
-% but currently we just take a conservative approach.
-%
-
+ % Fail if the specified const might be the address of a local variable
+ % or nested function.
+ %
+ % The addresses of local variables are probably not consts, at least
+ % not unless those variables are declared as static (i.e. `one_copy'),
+ % so it might be safe to allow all data_addr_consts here, but currently
+ % we just take a conservative approach.
+ %
:- pred check_const(mlds__rval_const::in, locals::in) is semidet.
check_const(Const, Locals) :-
@@ -491,8 +445,7 @@
; Const = data_addr_const(DataAddr) ->
DataAddr = data_addr(ModuleName, DataName),
( DataName = var(VarName) ->
- \+ var_is_local(qual(ModuleName, module_qual,
- VarName), Locals)
+ \+ var_is_local(qual(ModuleName, module_qual, VarName), Locals)
;
true
)
@@ -500,33 +453,25 @@
true
).
-%
-% var_is_local:
-% Check whether the specified variable is defined locally,
-% i.e. in storage that might no longer exist when the function
-% returns or does a tail call.
-%
-% It would be safe to fail for variables declared static
-% (i.e. `one_copy'), but currently we just take a conservative
-% approach.
-%
-
+ % Check whether the specified variable is defined locally, i.e. in storage
+ % that might no longer exist when the function returns or does a tail call.
+ %
+ % It would be safe to fail for variables declared static (i.e. `one_copy'),
+ % but currently we just take a conservative approach.
+ %
:- pred var_is_local(mlds__var::in, locals::in) is semidet.
var_is_local(Var, Locals) :-
- % XXX we ignore the ModuleName --
- % that is safe, but overly conservative
+ % XXX we ignore the ModuleName -- that is safe, but overly conservative.
Var = qual(_ModuleName, _QualKind, VarName),
some [Local] (
locals_member(Local, Locals),
Local = data(var(VarName))
).
-%
-% function_is_local:
-% Check whether the specified function is defined locally
-% (i.e. as a nested function).
-%
+ % Check whether the specified function is defined locally (i.e. as a
+ % nested function).
+ %
:- pred function_is_local(mlds__code_addr::in, locals::in) is semidet.
function_is_local(CodeAddr, Locals) :-
@@ -537,8 +482,8 @@
CodeAddr = internal(QualifiedProcLabel, SeqNum, _Sig),
MaybeSeqNum = yes(SeqNum)
),
- % XXX we ignore the ModuleName --
- % that is safe, but might be overly conservative
+ % XXX we ignore the ModuleName -- that is safe, but might be
+ % overly conservative.
QualifiedProcLabel = qual(_ModuleName, _QualKind, ProcLabel),
ProcLabel = PredLabel - ProcId,
some [Local] (
@@ -546,12 +491,10 @@
Local = function(PredLabel, ProcId, MaybeSeqNum, _PredId)
).
-%
-% locals_member(Name, Locals):
-% Nondeterministically enumerates the names of all the entities
-% in Locals.
-%
-
+ % locals_member(Name, Locals):
+ %
+ % Nondeterministically enumerates the names of all the entities in Locals.
+ %
:- pred locals_member(mlds__entity_name::out, locals::in) is nondet.
locals_member(Name, LocalsList) :-
@@ -572,7 +515,8 @@
solutions(nontailcall_in_mlds(MLDS), Warnings),
list__foldl(report_nontailcall_warning, Warnings, !IO).
-:- type tailcall_warning ---> tailcall_warning(
+:- type tailcall_warning
+ ---> tailcall_warning(
mlds__pred_label,
proc_id,
mlds__context
@@ -615,12 +559,12 @@
mlds__statement::in, tailcall_warning::out) is nondet.
nontailcall_in_statement(CallerModule, CallerFuncName, Statement, Warning) :-
- % nondeterministically find a non-tail call
+ % Nondeterministically find a non-tail call.
statement_contains_statement(Statement, SubStatement),
SubStatement = mlds__statement(SubStmt, Context),
SubStmt = call(_CallSig, Func, _This, _Args, _RetVals, CallKind),
CallKind = ordinary_call,
- % check if this call is a directly recursive call
+ % Check if this call is a directly recursive call.
Func = const(code_addr_const(CodeAddr)),
(
CodeAddr = proc(QualProcLabel, _Sig),
@@ -631,7 +575,7 @@
),
QualProcLabel = qual(CallerModule, module_qual, PredLabel - ProcId),
CallerFuncName = function(PredLabel, ProcId, MaybeSeqNum, _PredId),
- % if so, construct an appropriate warning
+ % If so, construct an appropriate warning.
Warning = tailcall_warning(PredLabel, ProcId, Context).
:- pred report_nontailcall_warning(tailcall_warning::in,
@@ -654,7 +598,7 @@
], !IO)
;
PredLabel = special_pred(_, _, _, _)
- % don't warn about these
+ % Don't warn about these.
).
%-----------------------------------------------------------------------------%
Index: compiler/ml_type_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/ml_type_gen.m,v
retrieving revision 1.43
diff -u -b -r1.43 ml_type_gen.m
--- compiler/ml_type_gen.m 12 Sep 2005 05:24:14 -0000 1.43
+++ compiler/ml_type_gen.m 12 Sep 2005 14:11:59 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 1999-2005 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -13,13 +15,11 @@
% to classes with a single int member, plus a bunch of static (one_copy)
% const members for the different enumerations consts.
%
-% For discriminated unions, we create an MLDS base class type
-% corresponding to the HLDS type, and we also create MLDS
-% derived class types corresponding to each of the constructors
-% which are defined from the base class type.
-% For constructors which are represented as the addresses of
-% specially reserved objects, we generate the static (one_copy)
-% members for those objects.
+% For discriminated unions, we create an MLDS base class type corresponding
+% to the HLDS type, and we also create MLDS derived class types corresponding
+% to each of the constructors which are defined from the base class type.
+% For constructors which are represented as the addresses of specially reserved
+% objects, we generate the static (one_copy) members for those objects.
%-----------------------------------------------------------------------------%
@@ -68,9 +68,10 @@
:- pred ml_uses_secondary_tag(cons_tag_values::in, constructor::in, int::out)
is semidet.
-% A constructor is represented using the base class rather than a derived
-% class if there is only a single functor, or if there is a single
-% functor and some constants represented using reserved addresses.
+ % A constructor is represented using the base class rather than a derived
+ % class if there is only a single functor, or if there is a single
+ % functor and some constants represented using reserved addresses.
+ %
:- pred ml_tag_uses_base_class(cons_tag::in) is semidet.
%-----------------------------------------------------------------------------%
@@ -102,16 +103,17 @@
ml_gen_types(ModuleInfo, MLDS_TypeDefns, !IO) :-
globals__io_lookup_bool_option(highlevel_data, HighLevelData, !IO),
globals__io_get_target(Target, !IO),
- ( HighLevelData = yes ->
+ (
+ HighLevelData = yes,
module_info_types(ModuleInfo, TypeTable),
map__keys(TypeTable, TypeCtors0),
list__filter((pred(TypeCtor::in) is semidet :-
- \+ type_ctor_needs_lowlevel_rep(Target,
- TypeCtor)
+ \+ type_ctor_needs_lowlevel_rep(Target, TypeCtor)
), TypeCtors0, TypeCtors),
- list__foldl(ml_gen_type_defn(ModuleInfo, TypeTable),
- TypeCtors, [], MLDS_TypeDefns)
+ list__foldl(ml_gen_type_defn(ModuleInfo, TypeTable), TypeCtors,
+ [], MLDS_TypeDefns)
;
+ HighLevelData = no,
MLDS_TypeDefns = []
).
@@ -141,10 +143,12 @@
_ReservedTag, _), ModuleInfo, TypeCtor, TypeDefn, !Defns) :-
% XXX we probably shouldn't ignore _ReservedTag
ml_gen_equality_members(MaybeUserEqComp, MaybeEqualityMembers),
- ( IsEnum = yes ->
+ (
+ IsEnum = yes,
ml_gen_enum_type(TypeCtor, TypeDefn, Ctors, TagValues,
MaybeEqualityMembers, !Defns)
;
+ IsEnum = no,
ml_gen_du_parent_type(ModuleInfo, TypeCtor, TypeDefn,
Ctors, TagValues, MaybeEqualityMembers, !Defns)
).
@@ -180,23 +184,23 @@
hlds_data__get_type_defn_context(TypeDefn, Context),
MLDS_Context = mlds__make_context(Context),
- % generate the class name
+ % Generate the class name.
ml_gen_type_name(TypeCtor, QualifiedClassName, MLDS_ClassArity),
QualifiedClassName = qual(_, _, MLDS_ClassName),
- % generate the class members
+ % Generate the class members.
ValueMember = ml_gen_enum_value_member(Context),
EnumConstMembers = list__map(ml_gen_enum_constant(Context, TagValues),
Ctors),
Members = list__append(MaybeEqualityMembers,
[ValueMember|EnumConstMembers]),
- % enums don't import or inherit anything
+ % Enums don't import or inherit anything.
Imports = [],
Inherits = [],
Implements = [],
- % put it all together
+ % Put it all together.
MLDS_TypeName = type(MLDS_ClassName, MLDS_ClassArity),
MLDS_TypeFlags = ml_gen_type_decl_flags,
MLDS_TypeDefnBody = mlds__class(mlds__class_defn(mlds__enum,
@@ -218,9 +222,7 @@
= mlds__defn.
ml_gen_enum_constant(Context, ConsTagValues, Ctor) = MLDS_Defn :-
- %
- % figure out the value of this enumeration constant
- %
+ % Figure out the value of this enumeration constant.
Ctor = ctor(_ExistQTVars, _Constraints, Name, Args),
list__length(Args, Arity),
map__lookup(ConsTagValues, cons(Name, Arity), TagVal),
@@ -229,12 +231,10 @@
;
error("ml_gen_enum_constant: enum constant needs int tag")
),
- % sanity check
+ % Sanity check.
require(unify(Arity, 0), "ml_gen_enum_constant: arity != []"),
- %
- % generate an MLDS definition for this enumeration constant.
- %
+ % Generate an MLDS definition for this enumeration constant.
unqualify_name(Name, UnqualifiedName),
MLDS_Defn = mlds__defn(data(var(mlds__var_name(UnqualifiedName, no))),
mlds__make_context(Context),
@@ -246,7 +246,6 @@
% Discriminated union types.
%
- %
% For each discriminated union type, we generate an MLDS type of the
% following form:
%
@@ -350,10 +349,8 @@
BaseClassName, BaseClassArity),
(
- %
- % If none of the constructors for this type need
- % a secondary tag, then we don't need the
- % members for the secondary tag.
+ % If none of the constructors for this type need a secondary tag,
+ % then we don't need the members for the secondary tag.
%
\+ (some [Ctor] (
list__member(Ctor, Ctors),
@@ -363,9 +360,7 @@
TagMembers = [],
TagClassId = BaseClassId
;
- %
% Generate the members for the secondary tag.
- %
TagDataMember = ml_gen_tag_member("data_tag", Context),
TagConstMembers = [],
% XXX we don't yet bother with these;
@@ -374,11 +369,9 @@
% ml_gen_tag_constant(Context, TagValues), Ctors)),
TagMembers0 = [TagDataMember | TagConstMembers],
- %
- % If all the constructors for this type need a
- % secondary tag, then we put the secondary tag members
- % directly in the base class, otherwise we put it in
- % a separate nested derived class.
+ % If all the constructors for this type need a secondary tag, then
+ % we put the secondary tag members directly in the base class,
+ % otherwise we put it in a separate nested derived class.
%
(
(all [Ctor] (
@@ -391,29 +384,27 @@
TagClassId = BaseClassId
;
globals__get_target(Globals, Target),
- ml_gen_secondary_tag_class(MLDS_Context,
- BaseClassQualifier, BaseClassId, TagMembers0,
- Target, TagTypeDefn, TagClassId),
+ ml_gen_secondary_tag_class(MLDS_Context, BaseClassQualifier,
+ BaseClassId, TagMembers0, Target, TagTypeDefn, TagClassId),
TagMembers = [TagTypeDefn]
)
),
- % generate the nested derived classes for the constructors,
+ % Generate the nested derived classes for the constructors,
% or static (one_copy) member objects for constructors with
- % reserved_object representations,
- % or fields and a constructor method for the single_functor case.
+ % reserved_object representations, or fields and a constructor method
+ % for the single_functor case.
list__foldl2(ml_gen_du_ctor_member(ModuleInfo, BaseClassId,
BaseClassQualifier, TagClassId, TypeDefn, TagValues),
Ctors, [], CtorMembers, [], BaseClassCtorMethods),
- % the base class doesn't import or inherit anything
+ % The base class doesn't import or inherit anything.
Imports = [],
Inherits = [],
Implements = [],
- % put it all together
- Members = list__condense([MaybeEqualityMembers, TagMembers,
- CtorMembers]),
+ % Put it all together.
+ Members = list__condense([MaybeEqualityMembers, TagMembers, CtorMembers]),
MLDS_TypeName = type(BaseClassName, BaseClassArity),
MLDS_TypeFlags = ml_gen_type_decl_flags,
MLDS_TypeDefnBody = mlds__class(mlds__class_defn(mlds__class,
@@ -423,7 +414,6 @@
MLDS_Defns = [MLDS_TypeDefn | MLDS_Defns0].
- %
% Generate the declaration for the field that holds the secondary tag.
%
:- func ml_gen_tag_member(string, prog_context) = mlds__defn.
@@ -438,33 +428,25 @@
= mlds__defns.
ml_gen_tag_constant(Context, ConsTagValues, Ctor) = MLDS_Defns :-
- %
% Check if this constructor uses a secondary tag.
- %
( ml_uses_secondary_tag(ConsTagValues, Ctor, SecondaryTag) ->
- %
- % Generate an MLDS definition for this secondary
- % tag constant. We do this mainly for readability
- % and interoperability. Note that we don't do the
- % same thing for primary tags, so this is most
- % useful in the `--tags none' case, where there
- % will be no primary tags.
- %
+ % Generate an MLDS definition for this secondary tag constant.
+ % We do this mainly for readability and interoperability. Note that
+ % we don't do the same thing for primary tags, so this is most useful
+ % in the `--tags none' case, where there will be no primary tags.
+
Ctor = ctor(_ExistQTVars, _Constraints, Name, _Args),
unqualify_name(Name, UnqualifiedName),
ConstValue = const(int_const(SecondaryTag)),
- MLDS_Defn = mlds__defn(data(var(mlds__var_name(
- UnqualifiedName, no))),
+ MLDS_Defn = mlds__defn(data(var(mlds__var_name(UnqualifiedName, no))),
mlds__make_context(Context),
ml_gen_enum_constant_decl_flags,
- mlds__data(mlds__native_int_type,
- init_obj(ConstValue), no)),
+ mlds__data(mlds__native_int_type, init_obj(ConstValue), no)),
MLDS_Defns = [MLDS_Defn]
;
MLDS_Defns = []
).
- %
% Check if this constructor's representation uses a secondary tag,
% and if so, return the secondary tag value.
% BEWARE that this is not the same as ml_needs_secondary_tag, below.
@@ -473,16 +455,12 @@
TagVal = get_tagval(ConsTagValues, Ctor),
get_secondary_tag(TagVal) = yes(SecondaryTag).
- %
- % Check if this constructor needs a secondary tag.
- % This is true if its representation uses a secondary
- % tag, obviously. But it is also true if its
- % representation is the address of a reserved object;
- % in that case, for some back-ends (e.g. C)
- % we need a field of some kind to ensure
- % that the reserved object had non-zero size,
- % which in turn is needed to ensure that its
- % address is distinct from any other reserved objects
+ % Check if this constructor needs a secondary tag. This is true if its
+ % representation uses a secondary tag, obviously. But it is also true
+ % if its representation is the address of a reserved object; in that case,
+ % for some back-ends (e.g. C) we need a field of some kind to ensure
+ % that the reserved object had non-zero size, which in turn is needed
+ % to ensure that its address is distinct from any other reserved objects
% for the same type.
%
:- pred ml_needs_secondary_tag(cons_tag_values::in, constructor::in)
@@ -494,9 +472,8 @@
; tagval_is_reserved_addr(TagVal, reserved_object(_, _, _))
).
- %
- % Check if this constructor is a constant whose
- % value is represented as a reserved address.
+ % Check if this constructor is a constant whose value is represented
+ % as a reserved address.
%
:- pred ml_uses_reserved_addr(cons_tag_values::in, constructor::in,
reserved_address::out) is semidet.
@@ -519,10 +496,9 @@
list__length(Args, Arity),
map__lookup(ConsTagValues, cons(Name, Arity), TagVal).
- %
- % Generate a definition for the class used for the secondary tag
- % type. This is needed for discriminated unions for which some
- % but not all constructors use secondary tags.
+ % Generate a definition for the class used for the secondary tag type.
+ % This is needed for discriminated unions for which some but not all
+ % constructors use secondary tags.
%
:- pred ml_gen_secondary_tag_class(mlds__context::in, mlds_module_name::in,
mlds__class_id::in, mlds__defns::in, compilation_target::in,
@@ -536,10 +512,9 @@
UnqualClassName = "tag_type",
ClassName = qual(BaseClassQualifier, type_qual, UnqualClassName),
ClassArity = 0,
- SecondaryTagClassId = mlds__class_type(ClassName, ClassArity,
- mlds__class),
+ SecondaryTagClassId = mlds__class_type(ClassName, ClassArity, mlds__class),
- % the secondary tag class inherits the base class for this type,
+ % The secondary tag class inherits the base class for this type,
% unless we're compiling to C -- in that case, we omit it,
% since it is empty, and we don't want to include empty base
% classes when compiling to C.
@@ -552,7 +527,7 @@
Implements = [],
Ctors = [],
- % put it all together
+ % Put it all together.
MLDS_TypeName = type(UnqualClassName, ClassArity),
MLDS_TypeFlags = ml_gen_type_decl_flags,
MLDS_TypeDefnBody = mlds__class(mlds__class_defn(mlds__class,
@@ -560,10 +535,9 @@
MLDS_TypeDefn = mlds__defn(MLDS_TypeName, MLDS_Context, MLDS_TypeFlags,
MLDS_TypeDefnBody).
+ % Generate definitions corresponding to a constructor of a discriminated
+ % union type. This will be one of the following:
%
- % Generate definitions corresponding to
- % a constructor of a discriminated union type.
- % This will be one of the following:
% - (in the usual case) a nested derived class definition
% - (for reserved_object) a one_copy (static) member object
% - (for the single_functor case) a bunch of fields and
@@ -576,31 +550,27 @@
ml_gen_du_ctor_member(ModuleInfo, BaseClassId, BaseClassQualifier,
SecondaryTagClassId, TypeDefn, ConsTagValues, Ctor,
- MLDS_Members0, MLDS_Members,
- MLDS_CtorMethods0, MLDS_CtorMethods) :-
+ MLDS_Members0, MLDS_Members, MLDS_CtorMethods0, MLDS_CtorMethods) :-
Ctor = ctor(ExistQTVars, Constraints, CtorName, Args),
- % XXX we should keep a context for the constructor,
+ % XXX We should keep a context for the constructor,
% but we don't, so we just use the context from the type.
hlds_data__get_type_defn_context(TypeDefn, Context),
MLDS_Context = mlds__make_context(Context),
- % generate the class name for this constructor
+ % Generate the class name for this constructor.
unqualify_name(CtorName, UnqualCtorName),
list__length(Args, CtorArity),
TagVal = get_tagval(ConsTagValues, Ctor),
( tagval_is_reserved_addr(TagVal, ReservedAddr) ->
( ReservedAddr = reserved_object(_, _, _) ->
- %
% Generate a reserved object for this constructor.
- % Note that we use the SecondaryTagClassId for the
- % type of this reserved object; we can't use the
- % BaseClassId because for some back-ends,
- % we need to ensure that the type used for the
- % reserved object has at least one data member,
- % to make sure that each reserved object gets a
- % distinct address.
+ % Note that we use the SecondaryTagClassId for the type of this
+ % reserved object; we can't use the BaseClassId because for some
+ % back-ends, we need to ensure that the type used for the reserved
+ % object has at least one data member, to make sure that each
+ % reserved object gets a distinct address.
%
MLDS_ReservedObjName = ml_format_reserved_object_name(
UnqualCtorName, CtorArity),
@@ -609,56 +579,50 @@
public, no_initializer, Context),
MLDS_Members = [MLDS_ReservedObjDefn | MLDS_Members0]
;
- % for reserved numeric addresses, we don't need
- % to generate any objects or types
+ % For reserved numeric addresses, we don't need to generate
+ % any objects or types.
MLDS_Members = MLDS_Members0
),
MLDS_CtorMethods = MLDS_CtorMethods0
;
- %
- % Generate the members for this constructor
- %
+ % Generate the members for this constructor.
- % number any unnamed fields starting from 1
+ % Number any unnamed fields starting from 1.
ArgNum0 = 1,
- % generate class members for the type_infos and typeclass_infos
+ % Generate class members for the type_infos and typeclass_infos
% that hold information about existentially quantified
% type variables and type class constraints.
% Note that the order of fields is as follows:
% - first typeinfos (for unconstrained type variables)
% - then typeclassinfos (for class constraints)
% - finally the ordinary members
- ( ExistQTVars = [] ->
+ (
+ ExistQTVars = [],
% optimize common case
ExtraMembers = [],
ArgNum2 = ArgNum0
;
- constraint_list_get_tvars(Constraints,
- ConstrainedTVars),
+ ExistQTVars = [_ | _],
+ constraint_list_get_tvars(Constraints, ConstrainedTVars),
list__delete_elems(ExistQTVars, ConstrainedTVars,
UnconstrainedTVars),
- list__map_foldl(
- ml_gen_type_info_member(ModuleInfo, Context),
- UnconstrainedTVars, TypeInfoMembers,
- ArgNum0, ArgNum1),
- list__map_foldl(ml_gen_typeclass_info_member(ModuleInfo,
- Context), Constraints, TypeClassInfoMembers,
- ArgNum1, ArgNum2),
- list__append(TypeInfoMembers, TypeClassInfoMembers,
- ExtraMembers)
+ list__map_foldl(ml_gen_type_info_member(ModuleInfo, Context),
+ UnconstrainedTVars, TypeInfoMembers, ArgNum0, ArgNum1),
+ list__map_foldl(ml_gen_typeclass_info_member(ModuleInfo, Context),
+ Constraints, TypeClassInfoMembers, ArgNum1, ArgNum2),
+ ExtraMembers = TypeInfoMembers ++ TypeClassInfoMembers
),
- % generate the class members for the ordinary fields
- % of this constructor
+ % Generate the class members for the ordinary fields
+ % of this constructor.
list__map_foldl(ml_gen_du_ctor_field(ModuleInfo, Context),
Args, OrdinaryMembers, ArgNum2, _ArgNum3),
list__append(ExtraMembers, OrdinaryMembers, Members),
- % generate a constructor function to initialize the
- % fields, if needed (not all back-ends use constructor
- % functions)
+ % Generate a constructor function to initialize the fields, if needed
+ % (not all back-ends use constructor functions).
MaybeSecTagVal = get_secondary_tag(TagVal),
module_info_globals(ModuleInfo, Globals),
globals__get_target(Globals, Target),
@@ -668,36 +632,30 @@
CtorClassQualifier = BaseClassQualifier
;
CtorClassType = mlds__class_type(
- qual(BaseClassQualifier, type_qual,
- UnqualCtorName),
+ qual(BaseClassQualifier, type_qual, UnqualCtorName),
CtorArity, mlds__class),
- CtorClassQualifier =
- mlds__append_class_qualifier(
+ CtorClassQualifier = mlds__append_class_qualifier(
BaseClassQualifier, type_qual,
Globals, UnqualCtorName, CtorArity)
),
CtorFunction = gen_constructor_function(Globals,
BaseClassId, CtorClassType, CtorClassQualifier,
- SecondaryTagClassId, MaybeSecTagVal, Members,
- MLDS_Context),
- % If this constructor is going to go in the base class,
- % then we may also need to generate an additional
- % zero-argument constructor, which is used to
- % construct the class that is used for reserved_objects
+ SecondaryTagClassId, MaybeSecTagVal, Members, MLDS_Context),
+ % If this constructor is going to go in the base class, then we may
+ % also need to generate an additional zero-argument constructor,
+ % which is used to construct the class that is used for
+ % reserved_objects.
(
- TagVal = shared_with_reserved_addresses(RAs,
- single_functor),
+ TagVal = shared_with_reserved_addresses(RAs, single_functor),
some [RA] (
list__member(RA, RAs),
RA = reserved_object(_, _, _)
),
Members \= []
->
- ZeroArgCtor = gen_constructor_function(Globals,
- BaseClassId, CtorClassType,
- CtorClassQualifier,
- SecondaryTagClassId, no, [],
- MLDS_Context),
+ ZeroArgCtor = gen_constructor_function(Globals, BaseClassId,
+ CtorClassType, CtorClassQualifier, SecondaryTagClassId,
+ no, [], MLDS_Context),
Ctors = [ZeroArgCtor, CtorFunction]
;
Ctors = [CtorFunction]
@@ -707,23 +665,18 @@
),
( ml_tag_uses_base_class(TagVal) ->
- % put the members for this constructor directly
- % in the base class
+ % Put the members for this constructor directly in the base class.
MLDS_Members = Members ++ MLDS_Members0,
MLDS_CtorMethods = Ctors ++ MLDS_CtorMethods0
;
- %
% Generate a nested derived class for this constructor,
- % and put the members for this constructor in that
- % class
- %
+ % and put the members for this constructor in that class.
- % we inherit either the base class for this type,
- % or the secondary tag class, depending on whether
- % we need a secondary tag. But when targetting C,
- % we want to omit empty base classes. So if
- % targetting C, don't include any base class if
- % there is no secondary tag.
+ % We inherit either the base class for this type, or the secondary
+ % tag class, depending on whether we need a secondary tag.
+ % But when targetting C, we want to omit empty base classes.
+ % So if targetting C, don't include any base class if there is
+ % no secondary tag.
( MaybeSecTagVal = yes(_) ->
Inherits = [SecondaryTagClassId]
; target_uses_empty_base_classes(Target) = yes ->
@@ -734,12 +687,11 @@
Imports = [],
Implements = [],
- % put it all together
+ % Put it all together.
MLDS_TypeName = type(UnqualCtorName, CtorArity),
MLDS_TypeFlags = ml_gen_type_decl_flags,
MLDS_TypeDefnBody = mlds__class(mlds__class_defn(
- mlds__class, Imports, Inherits, Implements,
- Ctors, Members)),
+ mlds__class, Imports, Inherits, Implements, Ctors, Members)),
MLDS_TypeDefn = mlds__defn(MLDS_TypeName, MLDS_Context,
MLDS_TypeFlags, MLDS_TypeDefnBody),
MLDS_Members = [MLDS_TypeDefn | MLDS_Members0],
@@ -775,6 +727,7 @@
% are qualified with the module name get unqualified when output
% as Java, and parameter names must all be unqualified.
% XXX perhaps we should do the same for all back-ends?
+ %
:- func target_requires_module_qualified_params(compilation_target) = bool.
target_requires_module_qualified_params(c) = no.
@@ -795,12 +748,12 @@
InitMembers0 = list__map(gen_init_field(Target, BaseClassId,
ClassType, ClassQualifier), Members),
(
- MaybeTag = yes(TagVal)
- ->
+ MaybeTag = yes(TagVal),
InitTag = gen_init_tag(ClassType, SecondaryTagClassId, TagVal,
Context, Globals),
InitMembers = [InitTag | InitMembers0]
;
+ MaybeTag = no,
InitMembers = InitMembers0
),
@@ -812,13 +765,13 @@
CtorFlags = init_decl_flags(public, per_instance, non_virtual,
overridable, modifiable, concrete),
- % Note that the name of constructor is
- % determined by the backend convention.
- CtorDefn = mlds__defn(export("<constructor>"), Context, CtorFlags,
- Ctor).
+ % Note that the name of constructor is determined by the backend
+ % convention.
+ CtorDefn = mlds__defn(export("<constructor>"), Context, CtorFlags, Ctor).
- % Get the name and type from the field definition,
- % for use as a constructor argument name and type.
+ % Get the name and type from the field definition, for use as a
+ % constructor argument name and type.
+ %
:- func make_arg(mlds__defn) = mlds__argument is det.
make_arg(mlds__defn(Name, _Context, _Flags, Defn)) = Arg :-
@@ -829,6 +782,7 @@
).
% Generate "this-><fieldname> = <fieldname>;".
+ %
:- func gen_init_field(compilation_target, mlds__class_id, mlds__type,
mlds_module_name, mlds__defn) = mlds__statement is det.
@@ -865,14 +819,14 @@
Field = mlds__field(yes(0), self(ClassType),
named_field(qual(ClassQualifier, type_qual, Name),
mlds__ptr_type(ClassType)),
- % XXX we should use ClassType rather than
- % BaseClassId here. But doing so breaks the
- % IL back-end, because then the hack in
+ % XXX we should use ClassType rather than BaseClassId here.
+ % But doing so breaks the IL back-end, because then the hack in
% fixup_class_qualifiers doesn't work.
Type, BaseClassId),
Statement = mlds__statement(atomic(assign(Field, Param)), Context).
% Generate "this->data_tag = <TagVal>;".
+ %
:- func gen_init_tag(mlds__type, mlds__class_id, int, mlds__context, globals)
= mlds__statement.
@@ -880,12 +834,10 @@
= Statement :-
( SecondaryTagClassId = mlds__class_type(TagClass, TagArity, _) ->
TagClass = qual(BaseClassQualifier, QualKind, TagClassName),
- TagClassQualifier = mlds__append_class_qualifier(
- BaseClassQualifier, QualKind, Globals,
- TagClassName, TagArity)
+ TagClassQualifier = mlds__append_class_qualifier(BaseClassQualifier,
+ QualKind, Globals, TagClassName, TagArity)
;
- unexpected(this_file,
- "gen_init_tag: class_id should be a class")
+ unexpected(this_file, "gen_init_tag: class_id should be a class")
),
Name = "data_tag",
Type = mlds__native_int_type,
@@ -909,9 +861,9 @@
ml_gen_type_info_member(ModuleInfo, Context, TypeVar, MLDS_Defn,
ArgNum0, ArgNum) :-
- % We don't have access to the correct kind here. This won't
- % matter though, since the type will only be checked to see that it
- % is a variable, and won't be used in any other way.
+ % We don't have access to the correct kind here. This won't matter though,
+ % since the type will only be checked to see that it is a variable,
+ % and won't be used in any other way.
Kind = star,
polymorphism__build_type_info_type(variable(TypeVar, Kind), Type),
ml_gen_field(ModuleInfo, Context, no, Type, MLDS_Defn, ArgNum0, ArgNum).
@@ -960,17 +912,17 @@
(
Name = qualified(ModuleName, TypeName)
;
- % builtin types like `int' may be still unqualified
- % at this point
+ % Builtin types like `int' may be still unqualified at this point.
Name = unqualified(TypeName),
mercury_public_builtin_module(ModuleName)
),
MLDS_Module = mercury_module_name_to_mlds(ModuleName),
QualifiedTypeName = qual(MLDS_Module, module_qual, TypeName).
- % For interoperability, we ought to generate an `==' member
- % for types which have a user-defined equality, if the target
- % language supports it (as do e.g. C++, Java).
+ % For interoperability, we ought to generate an `==' member for types
+ % which have a user-defined equality, if the target language supports it
+ % (as do e.g. C++, Java).
+ %
:- pred ml_gen_equality_members(maybe(unify_compare)::in,
list(mlds__defn)::out) is det.
Index: compiler/ml_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/ml_util.m,v
retrieving revision 1.35
diff -u -b -r1.35 ml_util.m
--- compiler/ml_util.m 22 Mar 2005 06:40:10 -0000 1.35
+++ compiler/ml_util.m 12 Sep 2005 13:51:11 -0000
@@ -1,4 +1,6 @@
%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
% Copyright (C) 1999-2005 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
@@ -22,24 +24,27 @@
:- import_module std_util.
%-----------------------------------------------------------------------------%
- % succeeds iff the definitions contain the entry point to
+
+ % Succeeds iff the definitions contain the entry point to
% the a main predicate.
%
:- pred defns_contain_main(mlds__defns::in) is semidet.
%-----------------------------------------------------------------------------%
- % return `true' if the statement is a tail call which
- % can be optimized into a jump back to the start of the
- % function
+
+ % Return `true' if the statement is a tail call which can be optimized
+ % into a jump back to the start of the function.
+ %
:- pred can_optimize_tailcall(mlds__qualified_entity_name::in, mlds__stmt::in)
is semidet.
%-----------------------------------------------------------------------------%
%
-% routines that deal with statements
+% Routines that deal with statements.
%
- % nondeterministically generates sub-statements from statements.
+ % Nondeterministically generates sub-statements from statements.
+ %
:- pred statements_contains_statement(mlds__statements::in,
mlds__statement::out) is nondet.
@@ -49,8 +54,9 @@
:- pred stmt_contains_statement(mlds__stmt::in, mlds__statement::out)
is nondet.
- % succeeds iff this statement contains a reference to the
- % specified variable
+ % Succeeds iff this statement contains a reference to the
+ % specified variable.
+ %
:- pred statement_contains_var(mlds__statement::in, mlds__data::in) is semidet.
:- pred has_foreign_languages(mlds__statement::in, list(foreign_language)::out)
@@ -58,66 +64,75 @@
%-----------------------------------------------------------------------------%
%
-% routines that deal with definitions
+% Routines that deal with definitions.
%
% defn_contains_foreign_code(NativeTargetLang, Defn):
- % Succeeds iff this definition contains outline_foreign_proc
- % statements, or inline_target_code statements in a target
- % language other than the specified native target language.
- % XXX perhaps we should eliminate the need to check for
- % inline_target_code, because it shouldn't be generated
- % with target language different to the native target
- % language in the long run.
+ %
+ % Succeeds iff this definition contains outline_foreign_proc statements,
+ % or inline_target_code statements in a target language other than the
+ % specified native target language.
+ %
+ % XXX perhaps we should eliminate the need to check for inline_target_code,
+ % because it shouldn't be generated with target language different to the
+ % native target language in the long run.
+ %
:- pred defn_contains_foreign_code(target_lang::in, mlds__defn::in) is semidet.
% defn_contains_foreign_code(ForeignLang, Defn):
- % Succeeds iff this definition contains outline_foreign_proc
- % statements for the given foreign language.
+ %
+ % Succeeds iff this definition contains outline_foreign_proc statements
+ % for the given foreign language.
+ %
:- pred defn_contains_outline_foreign_proc(foreign_language::in,
mlds__defn::in) is semidet.
% Succeeds iff this definition is a type definition.
+ %
:- pred defn_is_type(mlds__defn::in) is semidet.
% Succeeds iff this definition is a function definition.
+ %
:- pred defn_is_function(mlds__defn::in) is semidet.
% Succeeds iff this definition is a data definition which
% defines a type_ctor_info constant.
+ %
:- pred defn_is_type_ctor_info(mlds__defn::in) is semidet.
% Succeeds iff this definition is a data definition which
% defines a variable whose type is mlds__commit_type.
+ %
:- pred defn_is_commit_type_var(mlds__defn::in) is semidet.
% Succeeds iff this definition has `public' in the access
% field in its decl_flags.
+ %
:- pred defn_is_public(mlds__defn::in) is semidet.
% Succeeds iff these definitions contains a reference to
% the specified variable.
+ %
:- pred defns_contains_var(mlds__defns::in, mlds__data::in) is semidet.
% Succeeds iff this definition contains a reference to
% the specified variable.
+ %
:- pred defn_contains_var(mlds__defn::in, mlds__data::in) is semidet.
%-----------------------------------------------------------------------------%
%
-% routines that deal with lvals/rvals
+% Routines that deal with lvals/rvals.
%
- %
- % initializer_contains_var:
- % rvals_contains_var:
- % maybe_rval_contains_var:
- % rval_contains_var:
- % lvals_contains_var:
- % lval_contains_var:
- % Succeeds iff the specified construct contains a reference to
- % the specified variable.
- %
+% initializer_contains_var:
+% rvals_contains_var:
+% maybe_rval_contains_var:
+% rval_contains_var:
+% lvals_contains_var:
+% lval_contains_var:
+% Succeeds iff the specified construct contains a reference to
+% the specified variable.
:- pred initializer_contains_var(mlds__initializer::in, mlds__data::in)
is semidet.
@@ -137,6 +152,7 @@
% Does the type require the lowlevel representation on the indicated
% backend?
+ %
:- pred type_needs_lowlevel_rep(compilation_target::in,
prog_data__type::in) is semidet.
@@ -170,15 +186,10 @@
can_optimize_tailcall(Name, Call) :-
Call = call(_Signature, FuncRval, MaybeObject, _CallArgs,
_Results, CallKind),
- %
- % check if this call can be optimized as a tail call
- %
+ % Check if this call can be optimized as a tail call.
( CallKind = tail_call ; CallKind = no_return_call ),
- %
- % check if the callee adddress is the same as
- % the caller
- %
+ % Check if the callee address is the same as the caller.
FuncRval = const(code_addr_const(CodeAddr)),
(
CodeAddr = proc(QualifiedProcLabel, _Sig),
@@ -188,22 +199,21 @@
MaybeSeqNum = yes(SeqNum)
),
QualifiedProcLabel = qual(ModuleName, module_qual, PredLabel - ProcId),
- % check that the module name matches
+
+ % Check that the module name matches.
Name = qual(ModuleName, module_qual, FuncName),
- % check that the PredLabel, ProcId, and MaybeSeqNum match
+
+ % Check that the PredLabel, ProcId, and MaybeSeqNum match.
FuncName = function(PredLabel, ProcId, MaybeSeqNum, _),
- %
- % In C++, `this' is a constant, so our usual technique
- % of assigning the arguments won't work if it is a
- % member function. Thus we don't do this optimization
- % if we're optimizing a member function call
- %
+ % In C++, `this' is a constant, so our usual technique of assigning
+ % the arguments won't work if it is a member function. Thus we don't do
+ % this optimization if we're optimizing a member function call.
MaybeObject = no.
%-----------------------------------------------------------------------------%
%
-% routines that deal with statements
+% Routines that deal with statements.
%
% statement_contains_statement:
@@ -439,7 +449,7 @@
target_code_component_contains_var(name(EntityName), DataName) :-
EntityName = qual(ModuleName, QualKind, data(UnqualDataName)),
DataName = qual(ModuleName, QualKind, UnqualDataName),
- % this is a place where we can succeed
+ % This is a place where we can succeed.
true.
has_foreign_languages(Statement, Langs) :-
@@ -452,7 +462,7 @@
%-----------------------------------------------------------------------------%
%
-% routines that deal with definitions
+% Routines that deal with definitions.
%
defn_contains_foreign_code(NativeTargetLang, Defn) :-
@@ -537,10 +547,9 @@
%-----------------------------------------------------------------------------%
%
-% routines that deal with lvals/rvals
+% Routines that deal with lvals/rvals.
%
-%
% initializer_contains_var:
% rvals_contains_var:
% maybe_rval_contains_var:
@@ -549,7 +558,6 @@
% lval_contains_var:
% Succeeds iff the specified construct contains a reference to
% the specified variable.
-%
% initializer_contains_var(no_initializer, _) :- fail.
initializer_contains_var(init_obj(Rval), Name) :-
@@ -598,7 +606,7 @@
rval_contains_var(Rval, Name).
lval_contains_var(var(qual(ModuleName, QualKind, Name), _Type),
qual(ModuleName, QualKind, var(Name))) :-
- % this is another place where we can succeed
+ % This is another place where we can succeed.
true.
%-----------------------------------------------------------------------------%
cvs diff: Diffing compiler/notes
cvs diff: Diffing debian
cvs diff: Diffing debian/patches
cvs diff: Diffing deep_profiler
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/aditi
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/concurrency
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/error
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/easyx
cvs diff: Diffing extras/graphics/easyx/samples
cvs diff: Diffing extras/graphics/mercury_glut
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/gears
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/lex/tests
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/moose/tests
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/quickcheck
cvs diff: Diffing extras/quickcheck/tutes
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/solver_types
cvs diff: Diffing extras/solver_types/library
cvs diff: Diffing extras/stream
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing extras/xml_stylesheets
cvs diff: Diffing java
cvs diff: Diffing java/runtime
cvs diff: Diffing library
cvs diff: Diffing mdbcomp
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing slice
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/debugger/declarative
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/general/string_format
cvs diff: Diffing tests/general/structure_reuse
cvs diff: Diffing tests/grade_subdirs
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/mmc_make
cvs diff: Diffing tests/mmc_make/lib
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing util
cvs diff: Diffing vim
cvs diff: Diffing vim/after
cvs diff: Diffing vim/ftplugin
cvs diff: Diffing vim/syntax
--------------------------------------------------------------------------
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