[m-rev.] diff: ml_unify_gen.m -> ml_unify_gen + ml_closure_gen.m
Fergus Henderson
fjh at cs.mu.OZ.AU
Mon Mar 4 18:31:20 AEDT 2002
Estimated hours taken: 1
Branches: main
Move the code for constructing closures from ml_unify_gen.m
into a new module ml_closure_gen.m.
compiler/ml_unify_gen.m:
compiler/ml_code_util.m:
Move ml_make_boxed_types and fixup_builtin_module from
ml_unify_gen.m to ml_code_util.m, for use by ml_closure_gen.m.
compiler/ml_unify_gen.m:
Export ml_gen_new_object, for use by ml_closure_gen.m.
compiler/rtti_to_mlds.m:
Import ml_closure_gen.m, for ml_gen_closure_wrapper.
compiler/ml_unify_gen.m:
compiler/ml_closure_gen.m:
Move the code for constructing closures from ml_unify_gen.m
into a new module ml_closure_gen.m.
compiler/notes/compiler_design.html:
Mention the new module.
Workspace: /home/ceres/fjh/mercury
Index: compiler/ml_closure_gen.m
===================================================================
RCS file: compiler/ml_closure_gen.m
diff -N compiler/ml_closure_gen.m
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ compiler/ml_closure_gen.m 4 Mar 2002 07:04:56 -0000
@@ -0,0 +1,836 @@
+%-----------------------------------------------------------------------------%
+% Copyright (C) 1999-2002 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.
+%-----------------------------------------------------------------------------%
+
+% File: ml_closure_gen.m
+% Main author: fjh
+
+% This module is part of the MLDS code generator.
+% It handles generation of MLDS code to construct closures.
+
+%-----------------------------------------------------------------------------%
+
+:- module ml_closure_gen.
+:- interface.
+
+:- import_module prog_data.
+:- import_module hlds_pred, hlds_goal.
+:- import_module mlds, ml_code_util.
+
+:- import_module list.
+
+ %
+ % ml_gen_closure(PredId, ProcId, EvalMethod, Var, ArgVars, ArgModes,
+ % HowToConstruct, Context, MLDS_Decls, MLDS_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.
+:- pred ml_gen_closure(pred_id, proc_id, lambda_eval_method, prog_var,
+ prog_vars, list(uni_mode), how_to_construct, prog_context,
+ mlds__defns, mlds__statements, ml_gen_info, ml_gen_info).
+:- mode ml_gen_closure(in, in, in, in, in, in, in, in, out, out, in, out)
+ is det.
+
+ %
+ % ml_gen_closure_wrapper(PredId, ProcId, Offset, NumClosureArgs,
+ % Context, WrapperFuncRval, WrapperFuncType):
+ %
+ % Generates a wrapper function which unboxes the input arguments,
+ % calls the specified procedure, passing it some extra arguments
+ % from the closure, and then boxes the output arguments.
+ % It adds the definition of this wrapper function to the extra_defns
+ % field in the ml_gen_info, and return the wrapper function's
+ % rval and type.
+ %
+ % The NumClosuresArgs parameter specifies how many arguments
+ % to extract from the closure. The Offset parameter 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.)
+ %
+:- pred ml_gen_closure_wrapper(pred_id, proc_id, int, int, prog_context,
+ mlds__rval, mlds__type, ml_gen_info, ml_gen_info).
+:- mode ml_gen_closure_wrapper(in, in, in, in, in, out, out,
+ in, out) is det.
+
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module hlds_module.
+:- import_module code_model, pseudo_type_info, rtti.
+:- import_module ml_unify_gen, ml_call_gen, rtti_to_mlds.
+:- import_module type_util, mode_util, error_util.
+:- import_module options, globals.
+
+% XXX The following modules depend on the LLDS,
+% so ideally they should not be used here.
+:- import_module continuation_info. % needed for `generate_closure_layout'
+:- import_module stack_layout. % needed for `represent_locn_as_int'
+:- import_module llds. % needed for `layout_locn'
+
+:- import_module assoc_list, bool, int, map, set, std_util, string, term.
+
+ml_gen_closure(PredId, ProcId, EvalMethod, Var, ArgVars, ArgModes,
+ HowToConstruct, Context, MLDS_Decls, MLDS_Statements) -->
+ % This constructs a closure.
+ % The representation of closures for the LLDS backend is defined in
+ % runtime/mercury_ho_call.h.
+ % XXX should we use a different representation for closures
+ % in the MLDS backend?
+
+ (
+ { EvalMethod = normal }
+ ;
+ { EvalMethod = (aditi_bottom_up) },
+ % XXX not yet implemented
+ { sorry(this_file, "`aditi_bottom_up' closures") }
+ ;
+ { EvalMethod = (aditi_top_down) },
+ % XXX not yet implemented
+ { sorry(this_file, "`aditi_top_down' closures") }
+ ),
+
+ %
+ % 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,
+ ClosureLayoutRval, ClosureLayoutType,
+ ClosureLayoutDecls),
+
+ %
+ % 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.
+ %
+ { Offset = ml_closure_arg_offset },
+ { list__length(ArgVars, NumArgs) },
+ ml_gen_closure_wrapper(PredId, ProcId, Offset, NumArgs,
+ Context, WrapperFuncRval0, WrapperFuncType0),
+
+ %
+ % 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
+ % Note that we need to box these arguments, except for
+ % the closure layout, which is already a reference type.
+ %
+ { NumArgsRval = unop(box(NumArgsType0), NumArgsRval0) },
+ { NumArgsType = mlds__generic_type },
+ { WrapperFuncRval = unop(box(WrapperFuncType0), WrapperFuncRval0) },
+ { WrapperFuncType = mlds__generic_type },
+ { ExtraArgRvals = [ClosureLayoutRval, WrapperFuncRval, NumArgsRval] },
+ { ExtraArgTypes = [ClosureLayoutType, WrapperFuncType, NumArgsType] },
+
+ %
+ % 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
+ %
+ ml_gen_new_object(MaybeConsId, PrimaryTag, MaybeSecondaryTag,
+ MaybeConsName, Var, ExtraArgRvals, ExtraArgTypes, ArgVars,
+ ArgModes, HowToConstruct, Context,
+ MLDS_Decls0, MLDS_Statements),
+ { MLDS_Decls = ClosureLayoutDecls ++ MLDS_Decls0 }.
+
+ %
+ % Generate a value for the closure layout struct.
+ % See MR_Closure_Layout in ../runtime/mercury_ho_call.h.
+ %
+ % Note that the code here is similar to code in stack_layout.m;
+ % any changes here may need to be reflected there, and vice versa.
+ %
+:- pred ml_gen_closure_layout(pred_id::in, proc_id::in, prog_context::in,
+ mlds__rval::out, mlds__type::out, mlds__defns::out,
+ ml_gen_info::in, ml_gen_info::out) is det.
+ml_gen_closure_layout(PredId, ProcId, Context,
+ ClosureLayoutRval, ClosureLayoutType,
+ ClosureLayoutDefns) -->
+ =(Info),
+ { ml_gen_info_get_module_info(Info, ModuleInfo) },
+ { continuation_info__generate_closure_layout(
+ ModuleInfo, PredId, ProcId, ClosureLayoutInfo) },
+
+ { ml_gen_closure_proc_id(ModuleInfo, Context,
+ InitProcId, ProcIdType, ClosureProcIdDefns) },
+
+ { ClosureLayoutInfo = closure_layout_info(ClosureArgs, TVarLocnMap) },
+ { ml_stack_layout_construct_closure_args(ModuleInfo, ClosureArgs,
+ InitClosureArgs, ClosureArgTypes, ClosureArgDefns) },
+ ml_gen_info_new_const(TvarVectorSeqNum),
+ ml_format_static_const_name("typevar_vector", TvarVectorSeqNum,
+ TvarVectorName),
+ { ml_stack_layout_construct_tvar_vector(ModuleInfo, TvarVectorName,
+ 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),
+ ml_format_static_const_name("closure_layout", LayoutSeqNum, Name),
+ { Access = local },
+ { Initializer = init_array(Inits) },
+ % 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) },
+ { ClosureLayoutDefn = ml_gen_static_const_defn(Name, ClosureLayoutType,
+ Access, Initializer, Context) },
+ { ClosureLayoutDefns = ClosureProcIdDefns ++ TVarDefns ++
+ ClosureArgDefns ++ [ClosureLayoutDefn] },
+ { module_info_name(ModuleInfo, ModuleName) },
+ { MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName) },
+ { ClosureLayoutRval = lval(var(qual(MLDS_ModuleName, Name),
+ ClosureLayoutType)) }.
+
+:- pred ml_gen_closure_proc_id(module_info::in, prog_context::in,
+ mlds__initializer::out, mlds__type::out,
+ mlds__defns::out) is det.
+ml_gen_closure_proc_id(_ModuleInfo, _Context, InitProcId, ProcIdType,
+ ClosureProcIdDefns) :-
+ % XXX currently we don't fill in the ProcId field!
+ InitProcId = init_obj(const(null(ProcIdType))),
+ ProcIdType = mlds__generic_type,
+ ClosureProcIdDefns = [].
+/*
+ { module_info_name(ModuleInfo, ModuleName) },
+ { term__context_file(Context, FileName) },
+ { term__context_line(Context, LineNumber) },
+ % XXX We don't have the GoalInfo here,
+ % so we can't compute the goal path correctly
+ % { goal_info_get_goal_path(GoalInfo, GoalPath) },
+ % { trace__path_to_string(GoalPath, GoalPathStr) },
+ { GoalPathStr = "" },
+ % DataAddr = layout_addr(
+ % closure_proc_id(CallerProcLabel, SeqNo, ClosureProcLabel)),
+ % Data = layout_data(closure_proc_id_data(CallerProcLabel, SeqNo,
+ % ClosureProcLabel, ModuleName, FileName, LineNumber, GoalPath)),
+ % InitProcId = init_obj(const(data_addr_const(DataAddr))),
+ % ProcIdType = ...
+*/
+
+:- pred ml_stack_layout_construct_closure_args(module_info::in,
+ list(closure_arg_info)::in, list(mlds__initializer)::out,
+ list(mlds__type)::out, mlds__defns::out) is det.
+
+ml_stack_layout_construct_closure_args(ModuleInfo, ClosureArgs,
+ ClosureArgInits, ClosureArgTypes, MLDS_Defns) :-
+ list__map_foldl(ml_stack_layout_construct_closure_arg_rval(ModuleInfo),
+ ClosureArgs, ArgInitsAndTypes, [], MLDS_Defns),
+ assoc_list__keys(ArgInitsAndTypes, ArgInits),
+ assoc_list__values(ArgInitsAndTypes, ArgTypes),
+ Length = list__length(ArgInits),
+ LengthRval = const(int_const(Length)),
+ LengthType = mlds__native_int_type,
+ CastLengthRval = unop(box(LengthType), LengthRval),
+ ClosureArgInits = [init_obj(CastLengthRval) | ArgInits],
+ ClosureArgTypes = [LengthType | ArgTypes].
+
+:- pred ml_stack_layout_construct_closure_arg_rval(module_info::in,
+ closure_arg_info::in, pair(mlds__initializer, mlds__type)::out,
+ mlds__defns::in, mlds__defns::out) is det.
+
+ml_stack_layout_construct_closure_arg_rval(ModuleInfo, ClosureArg,
+ ArgInit - ArgType, MLDS_Defns0, MLDS_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.
+ ExistQTvars = [],
+ NumUnivQTvars = -1,
+
+ pseudo_type_info__construct_pseudo_type_info(Type, NumUnivQTvars,
+ ExistQTvars, PseudoTypeInfo),
+ ml_gen_pseudo_type_info(ModuleInfo, PseudoTypeInfo, ArgRval, ArgType,
+ MLDS_Defns0, MLDS_Defns),
+ CastArgRval = unop(box(ArgType), ArgRval),
+ ArgInit = init_obj(CastArgRval).
+
+:- pred ml_gen_pseudo_type_info_defn(module_info::in, pseudo_type_info::in,
+ mlds__defns::in, mlds__defns::out) is det.
+
+ml_gen_pseudo_type_info_defn(ModuleInfo, Pseudo, Defns0, Defns) :-
+ ml_gen_pseudo_type_info(ModuleInfo, Pseudo, _Rval, _Type,
+ Defns0, Defns).
+
+:- pred ml_gen_pseudo_type_info(module_info::in, pseudo_type_info::in,
+ mlds__rval::out, mlds__type::out,
+ mlds__defns::in, mlds__defns::out) is det.
+
+ml_gen_pseudo_type_info(ModuleInfo, Pseudo, Rval, Type,
+ MLDS_Defns0, MLDS_Defns) :-
+ ( Pseudo = type_var(N) ->
+ % type variables are represented just as integers
+ Rval = const(int_const(N)),
+ Type = mlds__native_int_type,
+ MLDS_Defns = MLDS_Defns0
+ ;
+ ( Pseudo = type_ctor_info(RttiTypeId0) ->
+ % for zero-arity types, we just generate a
+ % reference to the already-existing type_ctor_info
+ RttiName = type_ctor_info,
+ RttiTypeId0 = rtti_type_id(ModuleName0, _, _),
+ ModuleName = fixup_builtin_module(ModuleName0),
+ RttiTypeId = RttiTypeId0,
+ MLDS_Defns = MLDS_Defns0
+ ;
+ % 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(Pseudo),
+ rtti_data_to_name(RttiData, RttiTypeId, RttiName),
+ 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),
+ MLDS_Defns1 = RttiDefns ++ MLDS_Defns0,
+ % Generate definitions of any pseudo_type_infos
+ % referenced by this pseudotypeinfo.
+ list__foldl(ml_gen_pseudo_type_info_defn(ModuleInfo),
+ arg_pseudo_type_infos(Pseudo),
+ MLDS_Defns1, MLDS_Defns)
+ ),
+ MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName),
+ Rval = const(data_addr_const(data_addr(MLDS_ModuleName,
+ rtti(RttiTypeId, RttiName)))),
+ Type = mlds__rtti_type(RttiName)
+ ).
+
+:- func arg_pseudo_type_infos(pseudo_type_info) = list(pseudo_type_info).
+arg_pseudo_type_infos(type_var(_)) = [].
+arg_pseudo_type_infos(type_ctor_info(_)) = [].
+arg_pseudo_type_infos(type_info(_TypeId, ArgPTIs)) = ArgPTIs.
+arg_pseudo_type_infos(higher_order_type_info(_TypeId, _Arity, ArgPTIs)) =
+ ArgPTIs.
+
+:- func convert_to_local(mlds__defn) = mlds__defn.
+convert_to_local(mlds__defn(Name, Context, Flags0, Body)) =
+ mlds__defn(Name, Context, Flags, Body) :-
+ Flags = set_access(Flags0, local).
+
+:- pred ml_stack_layout_construct_tvar_vector(module_info::in,
+ mlds__var_name::in, prog_context::in, map(tvar, set(layout_locn))::in,
+ mlds__rval::out, mlds__type::out, mlds__defns::out) is det.
+
+ml_stack_layout_construct_tvar_vector(ModuleInfo, TvarVectorName, Context,
+ TVarLocnMap, MLDS_Rval, PtrType, MLDS_Defns) :-
+ PtrType = mlds__ptr_type(mlds__native_int_type),
+ ArrayType = mlds__array_type(mlds__native_int_type),
+ ( map__is_empty(TVarLocnMap) ->
+ MLDS_Rval = const(null(PtrType)),
+ MLDS_Defns = []
+ ;
+ Access = local,
+ ml_stack_layout_construct_tvar_rvals(TVarLocnMap,
+ Vector, _VectorTypes),
+ Initializer = init_array(Vector),
+ MLDS_Defn = ml_gen_static_const_defn(TvarVectorName, ArrayType,
+ Access, Initializer, Context),
+ MLDS_Defns = [MLDS_Defn],
+ module_info_name(ModuleInfo, ModuleName),
+ MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName),
+ MLDS_Rval = lval(var(qual(MLDS_ModuleName, TvarVectorName),
+ PtrType))
+ ).
+
+:- pred ml_stack_layout_construct_tvar_rvals(map(tvar, set(layout_locn))::in,
+ list(mlds__initializer)::out, list(mlds__type)::out) is det.
+
+ml_stack_layout_construct_tvar_rvals(TVarLocnMap, Vector, VectorTypes) :-
+ map__to_assoc_list(TVarLocnMap, TVarLocns),
+ ml_stack_layout_construct_type_param_locn_vector(TVarLocns, 1,
+ TypeParamLocs),
+ 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.
+
+:- pred ml_stack_layout_construct_type_param_locn_vector(
+ assoc_list(tvar, set(layout_locn))::in,
+ int::in, list(mlds__initializer)::out) is det.
+
+ml_stack_layout_construct_type_param_locn_vector([], _, []).
+ml_stack_layout_construct_type_param_locn_vector([TVar - Locns | TVarLocns],
+ CurSlot, Vector) :-
+ term__var_to_int(TVar, TVarNum),
+ NextSlot is CurSlot + 1,
+ ( TVarNum = CurSlot ->
+ ( set__remove_least(Locns, LeastLocn, _) ->
+ Locn = LeastLocn
+ ;
+ unexpected(this_file,
+ "tvar has empty set of locations")
+ ),
+ stack_layout__represent_locn_as_int(Locn, LocnAsInt),
+ Rval = const(int_const(LocnAsInt)),
+ ml_stack_layout_construct_type_param_locn_vector(TVarLocns,
+ NextSlot, VectorTail),
+ Vector = [init_obj(Rval) | VectorTail]
+ ; TVarNum > CurSlot ->
+ % This slot will never be referred to.
+ ml_stack_layout_construct_type_param_locn_vector(
+ [TVar - Locns | TVarLocns], NextSlot, VectorTail),
+ Vector = [init_obj(const(int_const(0))) | VectorTail]
+ ;
+ unexpected(this_file,
+ "unsorted tvars in construct_type_param_locn_vector")
+ ).
+
+ %
+ % ml_gen_closure_wrapper:
+ % see comment in interface section for details.
+ %
+ % This is used to create wrappers both for ordinary closures and
+ % also for type class methods.
+ %
+ % The generated function will be of the following form:
+ %
+ % foo_wrapper(void *closure_arg,
+ % MR_Box wrapper_arg1, MR_Box *wrapper_arg2,
+ % ..., MR_Box wrapper_argn)
+ % {
+ % FooClosure *closure;
+ % ...
+ % /* declarations needed for converting output args */
+ % Arg2Type conv_arg2;
+ % ...
+ % #if MODEL_SEMI
+ % MR_bool succeeded;
+ % #endif
+ %
+ % closure = closure_arg; /* XXX should add cast */
+ %
+ % CONJ(code_model,
+ % /* call function, boxing/unboxing inputs if needed */
+ % foo(closure->f1, unbox(closure->f2), ...,
+ % unbox(wrapper_arg1), &conv_arg2,
+ % wrapper_arg3, ...);
+ % ,
+ % /* box output arguments */
+ % *wrapper_arg2 = box(conv_arg2);
+ % ...
+ % )
+ % }
+ %
+ % where the stuff in CONJ() expands to the appropriate code
+ % for a conjunction, which depends on the code model:
+ %
+ % #if MODEL_DET
+ % /* call function, boxing/unboxing inputs if needed */
+ % foo(closure->f1, unbox(closure->f2), ...,
+ % unbox(wrapper_arg1), &conv_arg2,
+ % wrapper_arg3, ...);
+ %
+ % /* box output arguments */
+ % *wrapper_arg2 = box(conv_arg2);
+ % ...
+ % #elif MODEL_SEMI
+ % /* call function, boxing/unboxing inputs if needed */
+ % succeeded = foo(closure->f1, unbox(closure->f2), ...,
+ % unbox(wrapper_arg1), &conv_arg2,
+ % wrapper_arg3, ...);
+ %
+ % if (succeeded) {
+ % /* box output arguments */
+ % *wrapper_arg2 = box(conv_arg2);
+ % ...
+ % }
+ %
+ % return succeeded;
+ % }
+ % #else /* MODEL_NON */
+ % foo_1() {
+ % /* box output arguments */
+ % *wrapper_arg2 = box(conv_arg2);
+ % ...
+ % (*succ_cont)();
+ % }
+ %
+ % /* call function, boxing/unboxing inputs if needed */
+ % foo(closure->f1, unbox(closure->f2), ...,
+ % unbox(wrapper_arg1), &conv_arg2,
+ % wrapper_arg3, ...,
+ % foo_1);
+ % #endif
+ %
+ml_gen_closure_wrapper(PredId, ProcId, Offset, NumClosureArgs,
+ Context, WrapperFuncRval, WrapperFuncType) -->
+ %
+ % grab the relevant information about the called procedure
+ %
+ =(Info),
+ { ml_gen_info_get_module_info(Info, ModuleInfo) },
+ { module_info_pred_proc_info(ModuleInfo, PredId, ProcId,
+ PredInfo, ProcInfo) },
+ { pred_info_get_is_pred_or_func(PredInfo, PredOrFunc) },
+ { proc_info_headvars(ProcInfo, ProcHeadVars) },
+ { proc_info_argmodes(ProcInfo, ProcArgModes) },
+ { proc_info_interface_code_model(ProcInfo, CodeModel) },
+ { proc_info_varset(ProcInfo, ProcVarSet) },
+ { 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
+ % XXX The accurate GC handling for closures arguments is wrong
+ %
+ { ProcBoxedArgTypes = ml_make_boxed_types(ProcArity) },
+
+ %
+ % 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
+ {
+ list__drop(NumClosureArgs, ProcHeadVars, WrapperHeadVars0),
+ list__drop(NumClosureArgs, ProcArgModes, WrapperArgModes0),
+ list__drop(NumClosureArgs, ProcBoxedArgTypes,
+ WrapperBoxedArgTypes0)
+ ->
+ WrapperHeadVars = WrapperHeadVars0,
+ WrapperArgModes = WrapperArgModes0,
+ WrapperBoxedArgTypes = WrapperBoxedArgTypes0
+ ;
+ 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),
+
+ % then insert the `closure_arg' parameter
+ { ClosureArgType = mlds__generic_type },
+ % XXX FIXME The GC handling for closures is wrong
+ { GC_TraceCode = no },
+ { ClosureArg = mlds__argument(
+ data(var(var_name("closure_arg", no))),
+ ClosureArgType,
+ GC_TraceCode) },
+ { WrapperParams0 = mlds__func_params(WrapperArgs0, WrapperRetType) },
+ { WrapperParams = mlds__func_params([ClosureArg | WrapperArgs0],
+ WrapperRetType) },
+
+ % also compute the lvals for the parameters,
+ % and local declarations for any --copy-out output parameters
+ ml_gen_wrapper_arg_lvals(WrapperHeadVarNames, WrapperBoxedArgTypes,
+ WrapperArgModes, PredOrFunc, CodeModel, Context,
+ WrapperHeadVarDecls, WrapperHeadVarLvals, WrapperCopyOutLvals),
+
+ %
+ % generate code to declare and initialize the closure pointer.
+ % XXX we should use a struct type for the closure, but
+ % currently we're using a low-level data representation
+ % in the closure
+ %
+ % #if HIGH_LEVEL_DATA
+ % FooClosure *closure;
+ % #else
+ % void *closure;
+ % #endif
+ % closure = closure_arg;
+ %
+ { ClosureName = mlds__var_name("closure", no) },
+ { ClosureArgName = mlds__var_name("closure_arg", no) },
+ { MLDS_Context = mlds__make_context(Context) },
+ { ClosureType = mlds__generic_type },
+ % XXX FIXME The GC handling for closures is wrong
+ { GC_TraceCode = no },
+ { ClosureDecl = ml_gen_mlds_var_decl(var(ClosureName),
+ ClosureType, GC_TraceCode, MLDS_Context) },
+ ml_gen_var_lval(ClosureName, ClosureType, ClosureLval),
+ ml_gen_var_lval(ClosureArgName, ClosureArgType, ClosureArgLval),
+ { InitClosure = ml_gen_assign(ClosureLval, lval(ClosureArgLval),
+ Context) },
+
+ %
+ % 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 } ->
+ { module_info_globals(ModuleInfo, Globals) },
+ { 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) },
+ ml_initial_cont(WrapperOutputLvals, WrapperOutputTypes,
+ InitialCont)
+ ;
+ ml_initial_cont([], [], InitialCont)
+ ),
+ ml_gen_info_push_success_cont(InitialCont)
+ ;
+ []
+ ),
+
+ % prepare to generate code to call the function:
+ % XXX currently we're using a low-level data representation
+ % in the closure
+ %
+ % foo(
+ % #if HIGH_LEVEL_DATA
+ % closure->arg1, closure->arg2, ...,
+ % #else
+ % MR_field(MR_mktag(0), closure, 3),
+ % MR_field(MR_mktag(0), closure, 4),
+ % ...
+ % #endif
+ % unbox(wrapper_arg1), &conv_arg2, wrapper_arg3, ...
+ % );
+ %
+ ml_gen_closure_field_lvals(ClosureLval, Offset, 1, NumClosureArgs,
+ ClosureArgLvals),
+ { CallLvals = list__append(ClosureArgLvals, WrapperHeadVarLvals) },
+ ml_gen_call(PredId, ProcId, ProcHeadVarNames, CallLvals,
+ ProcBoxedArgTypes, CodeModel, Context, Decls0, Statements0),
+
+ % insert the stuff to declare and initialize the closure
+ { Decls1 = [ClosureDecl | Decls0] },
+ { Statements1 = [InitClosure | Statements0] },
+
+ %
+ % For semidet code, add the declaration `MR_bool succeeded;'
+ %
+ ( { CodeModel = model_semi } ->
+ { SucceededVarDecl = ml_gen_succeeded_var_decl(MLDS_Context) },
+ { Decls2 = [SucceededVarDecl | Decls1] }
+ ;
+ { Decls2 = Decls1 }
+ ),
+
+ % Add an appropriate `return' statement
+ ml_append_return_statement(CodeModel, WrapperCopyOutLvals, Context,
+ Statements1, Statements),
+
+ %
+ % Insert the local declarations of the wrapper's output arguments,
+ % if any (this is needed for `--nondet-copy-out')
+ %
+ { Decls = list__append(WrapperHeadVarDecls, Decls2) },
+
+ %
+ % if the wrapper function was model_non, then
+ % pop the success continuation that we pushed
+ %
+ ( { CodeModel = model_non } ->
+ ml_gen_info_pop_success_cont
+ ;
+ []
+ ),
+
+ %
+ % Put it all together
+ %
+ { WrapperFuncBody = ml_gen_block(Decls, Statements, Context) },
+ ml_gen_new_func_label(yes(WrapperParams), WrapperFuncName,
+ WrapperFuncRval),
+ ml_gen_wrapper_func(WrapperFuncName, WrapperParams, Context,
+ WrapperFuncBody, WrapperFunc),
+ { WrapperFuncType = mlds__func_type(WrapperParams) },
+ ml_gen_info_add_extra_defn(WrapperFunc).
+
+:- pred ml_gen_wrapper_func(ml_label_func, mlds__func_params, prog_context,
+ mlds__statement, mlds__defn, ml_gen_info, ml_gen_info).
+:- mode ml_gen_wrapper_func(in, in, in, in, out, in, out) is det.
+
+ml_gen_wrapper_func(FuncLabel, FuncParams, Context, Statement, Func) -->
+ ml_gen_label_func(FuncLabel, FuncParams, Context, Statement, Func0),
+ { Func0 = mlds__defn(Name, Ctxt, DeclFlags0, Defn) },
+ { DeclFlags1 = set_per_instance(DeclFlags0, one_copy) },
+ { DeclFlags = set_access(DeclFlags1, private) },
+ { Func = mlds__defn(Name, Ctxt, DeclFlags, Defn) }.
+
+:- func ml_gen_wrapper_head_var_names(int, int) = list(mlds__var_name).
+ml_gen_wrapper_head_var_names(Num, Max) = Names :-
+ ( Num > Max ->
+ Names = []
+ ;
+ Name = string__format("wrapper_arg_%d", [i(Num)]),
+ Names1 = ml_gen_wrapper_head_var_names(Num + 1, Max),
+ Names = [mlds__var_name(Name, no) | Names1]
+ ).
+
+ % ml_gen_wrapper_arg_lvals(HeadVarNames, Types, ArgModes,
+ % PredOrFunc, CodeModel, LocalVarDefns, HeadVarLvals):
+ % 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), list(prog_type), list(mode),
+ pred_or_func, code_model, prog_context,
+ list(mlds__defn), list(mlds__lval), list(mlds__lval),
+ ml_gen_info, ml_gen_info).
+:- mode ml_gen_wrapper_arg_lvals(in, in, in, in, in, in, out, out, out, in, out)
+ is det.
+
+ml_gen_wrapper_arg_lvals(Names, Types, Modes, PredOrFunc, CodeModel, Context,
+ Defns, Lvals, CopyOutLvals) -->
+ (
+ { Names = [], Types = [], Modes = [] }
+ ->
+ { Lvals = [] },
+ { CopyOutLvals = [] },
+ { Defns = [] }
+ ;
+ { Names = [Name | Names1] },
+ { Types = [Type | Types1] },
+ { Modes = [Mode | Modes1] }
+ ->
+ ml_gen_wrapper_arg_lvals(Names1, Types1, Modes1,
+ PredOrFunc, CodeModel, Context,
+ Defns1, Lvals1, CopyOutLvals1),
+ ml_gen_type(Type, MLDS_Type),
+ ml_gen_var_lval(Name, MLDS_Type, VarLval),
+ =(Info),
+ { ml_gen_info_get_module_info(Info, ModuleInfo) },
+ { mode_to_arg_mode(ModuleInfo, Mode, Type, ArgMode) },
+ ( { ArgMode = top_in } ->
+ { Lval = VarLval },
+ { CopyOutLvals = CopyOutLvals1 },
+ { Defns = Defns1 }
+ ;
+ %
+ % handle output variables
+ %
+ ml_gen_info_get_globals(Globals),
+ { CopyOut = get_copy_out_option(Globals, CodeModel) },
+ (
+ {
+ CopyOut = yes
+ ;
+ % 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)
+ }
+ ->
+ %
+ % 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 },
+ { Defns = Defns1 }
+ ;
+ { CopyOutLvals = [Lval |
+ CopyOutLvals1] },
+ ml_gen_local_for_output_arg(Name, Type,
+ Context, Defn),
+ { Defns = [Defn | Defns1] }
+ )
+ ;
+ %
+ % output arguments are passed by reference,
+ % so we need to dereference them
+ %
+ { Lval = mem_ref(lval(VarLval), MLDS_Type) },
+ { CopyOutLvals = CopyOutLvals1 },
+ { Defns = Defns1 }
+ )
+ ),
+ { Lvals = [Lval | Lvals1] }
+ ;
+ { sorry(this_file,
+ "ml_gen_wrapper_arg_lvals: length mismatch") }
+ ).
+
+:- pred ml_gen_local_for_output_arg(var_name, prog_type, prog_context,
+ mlds__defn, ml_gen_info, ml_gen_info).
+:- mode ml_gen_local_for_output_arg(in, in, in, out, in, out) is det.
+
+ml_gen_local_for_output_arg(VarName, Type, Context, LocalVarDefn) -->
+ %
+ % Generate a declaration for a corresponding local variable.
+ %
+ ml_gen_var_decl(VarName, Type, Context, LocalVarDefn).
+
+:- pred ml_gen_closure_field_lvals(mlds__lval, int, int, int,
+ list(mlds__lval),
+ ml_gen_info, ml_gen_info).
+:- mode ml_gen_closure_field_lvals(in, in, in, in, out, in, out) is det.
+
+ml_gen_closure_field_lvals(ClosureLval, Offset, ArgNum, NumClosureArgs,
+ ClosureArgLvals) -->
+ ( { ArgNum > NumClosureArgs } ->
+ { ClosureArgLvals = [] }
+ ;
+ %
+ % generate `MR_field(MR_mktag(0), closure, <N>)'
+ %
+ { FieldId = offset(const(int_const(ArgNum + Offset))) },
+ % 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
+ %
+ ml_gen_closure_field_lvals(ClosureLval, Offset, ArgNum + 1,
+ NumClosureArgs, ClosureArgLvals0),
+ { ClosureArgLvals = [FieldLval | ClosureArgLvals0] }
+ ).
+
+%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+this_file = "ml_closure_gen.m".
+
+:- end_module ml_closure_gen.
+
+%-----------------------------------------------------------------------------%
Index: compiler/ml_code_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_code_util.m,v
retrieving revision 1.56
diff -u -d -r1.56 ml_code_util.m
--- compiler/ml_code_util.m 3 Mar 2002 13:43:47 -0000 1.56
+++ compiler/ml_code_util.m 4 Mar 2002 07:14:22 -0000
@@ -138,6 +138,12 @@
%
:- func ml_string_type = mlds__type.
+ % Allocate some fresh type variables to use as the Mercury types
+ % of boxed objects (e.g. to get the argument types for tuple
+ % constructors or closure constructors). Note that this should
+ % only be used in cases where the tvarset doesn't matter.
+:- func ml_make_boxed_types(arity) = list(prog_type).
+
%-----------------------------------------------------------------------------%
%
% Routines for generating function declarations (i.e. mlds__func_params).
@@ -548,6 +554,13 @@
% option, depending on the code model.
:- func get_copy_out_option(globals, code_model) = bool.
+ % Add the qualifier `builtin' to any unqualified name.
+ % Although the builtin types `int', `float', etc. are treated as part
+ % 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.
+
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
%
@@ -1053,6 +1066,11 @@
ml_string_type = mercury_type(string_type, str_type,
non_foreign_type(string_type)).
+ml_make_boxed_types(Arity) = BoxedTypes :-
+ varset__init(TypeVarSet0),
+ varset__new_vars(TypeVarSet0, Arity, BoxedTypeVars, _TypeVarSet),
+ term__var_list_to_term_list(BoxedTypeVars, BoxedTypes).
+
%-----------------------------------------------------------------------------%
%
% Code for generating function declarations (i.e. mlds__func_params).
@@ -2748,6 +2766,14 @@
;
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)
+ ;
+ ModuleName = ModuleName0
).
%-----------------------------------------------------------------------------%
Index: compiler/ml_unify_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_unify_gen.m,v
retrieving revision 1.53
diff -u -d -r1.53 ml_unify_gen.m
--- compiler/ml_unify_gen.m 3 Mar 2002 13:43:49 -0000 1.53
+++ compiler/ml_unify_gen.m 4 Mar 2002 07:07:20 -0000
@@ -16,10 +16,12 @@
:- interface.
:- import_module prog_data.
-:- import_module hlds_module, hlds_pred, hlds_data, hlds_goal.
+:- import_module hlds_module, hlds_data, hlds_goal.
:- import_module code_model.
:- import_module mlds, ml_code_util.
+:- import_module bool, list, std_util.
+
%-----------------------------------------------------------------------------%
% Generate MLDS code for a unification.
@@ -53,52 +55,45 @@
:- func ml_gen_secondary_tag_rval(tag_bits, prog_type, module_info, mlds__rval)
= mlds__rval.
- %
- % ml_gen_closure_wrapper(PredId, ProcId, Offset, NumClosureArgs,
- % Context, WrapperFuncRval, WrapperFuncType):
- %
- % Generates a wrapper function which unboxes the input arguments,
- % calls the specified procedure, passing it some extra arguments
- % from the closure, and then boxes the output arguments.
- % It adds the definition of this wrapper function to the extra_defns
- % field in the ml_gen_info, and return the wrapper function's
- % rval and type.
- %
- % The NumClosuresArgs parameter specifies how many arguments
- % to extract from the closure. The Offset parameter 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.)
- %
-:- pred ml_gen_closure_wrapper(pred_id, proc_id, int, int, prog_context,
- mlds__rval, mlds__type, ml_gen_info, ml_gen_info).
-:- mode ml_gen_closure_wrapper(in, in, in, in, in, out, out,
- in, out) is det.
-
% Generate an MLDS rval for a given reserved address,
% cast to the appropriate type.
:- func ml_gen_reserved_address(module_info, reserved_address, mlds__type) =
mlds__rval.
+ %
+ % ml_gen_new_object(MaybeConsId, Tag, HasSecTag, MaybeCtorName, Var,
+ % ExtraRvals, ExtraTypes, ArgVars, ArgModes, HowToConstruct,
+ % Context, MLDS_Decls, MLDS_Statements):
+ % Generate a `new_object' statement, or a static constant,
+ % depending on the value of the how_to_construct argument.
+ % The `ExtraRvals' and `ExtraTypes' arguments specify
+ % additional constants to insert at the start of the
+ % argument list.
+ %
+:- pred ml_gen_new_object(maybe(cons_id), mlds__tag, bool, maybe(ctor_name),
+ prog_var, list(mlds__rval), list(mlds__type), prog_vars,
+ list(uni_mode), how_to_construct,
+ prog_context, mlds__defns, mlds__statements,
+ ml_gen_info, ml_gen_info).
+:- mode ml_gen_new_object(in, in, in, in, in, in, in, in, in, in, in, out, out,
+ in, out) is det.
+
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
-:- import_module hlds_out, builtin_ops.
-:- import_module ml_code_gen, ml_call_gen, ml_type_gen.
+:- import_module hlds_pred, hlds_out, builtin_ops.
+:- import_module ml_code_gen, ml_call_gen, ml_type_gen, ml_closure_gen.
:- import_module prog_util, type_util, mode_util.
-:- import_module pseudo_type_info, rtti, rtti_to_mlds, error_util.
+:- import_module rtti, error_util.
:- import_module globals, options.
% XXX The following modules depend on the LLDS,
% so ideally they should not be used here.
:- import_module code_util. % needed for `cons_id_to_tag'.
-:- import_module continuation_info. % needed for `generate_closure_layout'
-:- import_module stack_layout. % needed for `represent_locn_as_int'
-:- import_module llds. % needed for `layout_locn'
-:- import_module bool, int, string, list, map, require, std_util, term, varset.
+:- import_module int, string, map, require, term, varset.
:- import_module assoc_list, set.
%-----------------------------------------------------------------------------%
@@ -474,20 +469,6 @@
ml_gen_constant(pred_closure_tag(_, _, _), _, _) -->
{ error("ml_gen_constant: pred_closure_tag") }.
- %
- % Although the builtin types `int', `float', etc. are treated as part
- % of the `builtin' module, for historical reasons they don't have
- % any qualifiers at this point, so we need to add the `builtin'
- % qualifier now.
- %
-:- func fixup_builtin_module(module_name) = module_name.
-fixup_builtin_module(ModuleName0) = ModuleName :-
- ( ModuleName0 = unqualified("") ->
- mercury_public_builtin_module(ModuleName)
- ;
- ModuleName = ModuleName0
- ).
-
%-----------------------------------------------------------------------------%
% Generate an MLDS rval for a given reserved address,
@@ -541,761 +522,6 @@
target_supports_inheritence(asm) = no.
%-----------------------------------------------------------------------------%
-
-:- pred ml_gen_closure(pred_id, proc_id, lambda_eval_method, prog_var,
- prog_vars, list(uni_mode), how_to_construct, prog_context,
- mlds__defns, mlds__statements, ml_gen_info, ml_gen_info).
-:- mode ml_gen_closure(in, in, in, in, in, in, in, in, out, out, in, out)
- is det.
-
-ml_gen_closure(PredId, ProcId, EvalMethod, Var, ArgVars, ArgModes,
- HowToConstruct, Context, MLDS_Decls, MLDS_Statements) -->
- % This constructs a closure.
- % The representation of closures for the LLDS backend is defined in
- % runtime/mercury_ho_call.h.
- % XXX should we use a different representation for closures
- % in the MLDS backend?
-
- (
- { EvalMethod = normal }
- ;
- { EvalMethod = (aditi_bottom_up) },
- % XXX not yet implemented
- { sorry(this_file, "`aditi_bottom_up' closures") }
- ;
- { EvalMethod = (aditi_top_down) },
- % XXX not yet implemented
- { sorry(this_file, "`aditi_top_down' closures") }
- ),
-
- %
- % 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,
- ClosureLayoutRval, ClosureLayoutType,
- ClosureLayoutDecls),
-
- %
- % 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.
- %
- { Offset = ml_closure_arg_offset },
- { list__length(ArgVars, NumArgs) },
- ml_gen_closure_wrapper(PredId, ProcId, Offset, NumArgs,
- Context, WrapperFuncRval0, WrapperFuncType0),
-
- %
- % 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
- % Note that we need to box these arguments, except for
- % the closure layout, which is already a reference type.
- %
- { NumArgsRval = unop(box(NumArgsType0), NumArgsRval0) },
- { NumArgsType = mlds__generic_type },
- { WrapperFuncRval = unop(box(WrapperFuncType0), WrapperFuncRval0) },
- { WrapperFuncType = mlds__generic_type },
- { ExtraArgRvals = [ClosureLayoutRval, WrapperFuncRval, NumArgsRval] },
- { ExtraArgTypes = [ClosureLayoutType, WrapperFuncType, NumArgsType] },
-
- %
- % 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
- %
- ml_gen_new_object(MaybeConsId, PrimaryTag, MaybeSecondaryTag,
- MaybeConsName, Var, ExtraArgRvals, ExtraArgTypes, ArgVars,
- ArgModes, HowToConstruct, Context,
- MLDS_Decls0, MLDS_Statements),
- { MLDS_Decls = ClosureLayoutDecls ++ MLDS_Decls0 }.
-
- %
- % Generate a value for the closure layout struct.
- % See MR_Closure_Layout in ../runtime/mercury_ho_call.h.
- %
- % Note that the code here is similar to code in stack_layout.m;
- % any changes here may need to be reflected there, and vice versa.
- %
-:- pred ml_gen_closure_layout(pred_id::in, proc_id::in, prog_context::in,
- mlds__rval::out, mlds__type::out, mlds__defns::out,
- ml_gen_info::in, ml_gen_info::out) is det.
-ml_gen_closure_layout(PredId, ProcId, Context,
- ClosureLayoutRval, ClosureLayoutType,
- ClosureLayoutDefns) -->
- =(Info),
- { ml_gen_info_get_module_info(Info, ModuleInfo) },
- { continuation_info__generate_closure_layout(
- ModuleInfo, PredId, ProcId, ClosureLayoutInfo) },
-
- { ml_gen_closure_proc_id(ModuleInfo, Context,
- InitProcId, ProcIdType, ClosureProcIdDefns) },
-
- { ClosureLayoutInfo = closure_layout_info(ClosureArgs, TVarLocnMap) },
- { ml_stack_layout_construct_closure_args(ModuleInfo, ClosureArgs,
- InitClosureArgs, ClosureArgTypes, ClosureArgDefns) },
- ml_gen_info_new_const(TvarVectorSeqNum),
- ml_format_static_const_name("typevar_vector", TvarVectorSeqNum,
- TvarVectorName),
- { ml_stack_layout_construct_tvar_vector(ModuleInfo, TvarVectorName,
- 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),
- ml_format_static_const_name("closure_layout", LayoutSeqNum, Name),
- { Access = local },
- { Initializer = init_array(Inits) },
- % 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) },
- { ClosureLayoutDefn = ml_gen_static_const_defn(Name, ClosureLayoutType,
- Access, Initializer, Context) },
- { ClosureLayoutDefns = ClosureProcIdDefns ++ TVarDefns ++
- ClosureArgDefns ++ [ClosureLayoutDefn] },
- { module_info_name(ModuleInfo, ModuleName) },
- { MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName) },
- { ClosureLayoutRval = lval(var(qual(MLDS_ModuleName, Name),
- ClosureLayoutType)) }.
-
-:- pred ml_gen_closure_proc_id(module_info::in, prog_context::in,
- mlds__initializer::out, mlds__type::out,
- mlds__defns::out) is det.
-ml_gen_closure_proc_id(_ModuleInfo, _Context, InitProcId, ProcIdType,
- ClosureProcIdDefns) :-
- % XXX currently we don't fill in the ProcId field!
- InitProcId = init_obj(const(null(ProcIdType))),
- ProcIdType = mlds__generic_type,
- ClosureProcIdDefns = [].
-/*
- { module_info_name(ModuleInfo, ModuleName) },
- { term__context_file(Context, FileName) },
- { term__context_line(Context, LineNumber) },
- % XXX We don't have the GoalInfo here,
- % so we can't compute the goal path correctly
- % { goal_info_get_goal_path(GoalInfo, GoalPath) },
- % { trace__path_to_string(GoalPath, GoalPathStr) },
- { GoalPathStr = "" },
- % DataAddr = layout_addr(
- % closure_proc_id(CallerProcLabel, SeqNo, ClosureProcLabel)),
- % Data = layout_data(closure_proc_id_data(CallerProcLabel, SeqNo,
- % ClosureProcLabel, ModuleName, FileName, LineNumber, GoalPath)),
- % InitProcId = init_obj(const(data_addr_const(DataAddr))),
- % ProcIdType = ...
-*/
-
-:- pred ml_stack_layout_construct_closure_args(module_info::in,
- list(closure_arg_info)::in, list(mlds__initializer)::out,
- list(mlds__type)::out, mlds__defns::out) is det.
-
-ml_stack_layout_construct_closure_args(ModuleInfo, ClosureArgs,
- ClosureArgInits, ClosureArgTypes, MLDS_Defns) :-
- list__map_foldl(ml_stack_layout_construct_closure_arg_rval(ModuleInfo),
- ClosureArgs, ArgInitsAndTypes, [], MLDS_Defns),
- assoc_list__keys(ArgInitsAndTypes, ArgInits),
- assoc_list__values(ArgInitsAndTypes, ArgTypes),
- Length = list__length(ArgInits),
- LengthRval = const(int_const(Length)),
- LengthType = mlds__native_int_type,
- CastLengthRval = unop(box(LengthType), LengthRval),
- ClosureArgInits = [init_obj(CastLengthRval) | ArgInits],
- ClosureArgTypes = [LengthType | ArgTypes].
-
-:- pred ml_stack_layout_construct_closure_arg_rval(module_info::in,
- closure_arg_info::in, pair(mlds__initializer, mlds__type)::out,
- mlds__defns::in, mlds__defns::out) is det.
-
-ml_stack_layout_construct_closure_arg_rval(ModuleInfo, ClosureArg,
- ArgInit - ArgType, MLDS_Defns0, MLDS_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.
- ExistQTvars = [],
- NumUnivQTvars = -1,
-
- pseudo_type_info__construct_pseudo_type_info(Type, NumUnivQTvars,
- ExistQTvars, PseudoTypeInfo),
- ml_gen_pseudo_type_info(ModuleInfo, PseudoTypeInfo, ArgRval, ArgType,
- MLDS_Defns0, MLDS_Defns),
- CastArgRval = unop(box(ArgType), ArgRval),
- ArgInit = init_obj(CastArgRval).
-
-:- pred ml_gen_pseudo_type_info_defn(module_info::in, pseudo_type_info::in,
- mlds__defns::in, mlds__defns::out) is det.
-
-ml_gen_pseudo_type_info_defn(ModuleInfo, Pseudo, Defns0, Defns) :-
- ml_gen_pseudo_type_info(ModuleInfo, Pseudo, _Rval, _Type,
- Defns0, Defns).
-
-:- pred ml_gen_pseudo_type_info(module_info::in, pseudo_type_info::in,
- mlds__rval::out, mlds__type::out,
- mlds__defns::in, mlds__defns::out) is det.
-
-ml_gen_pseudo_type_info(ModuleInfo, Pseudo, Rval, Type,
- MLDS_Defns0, MLDS_Defns) :-
- ( Pseudo = type_var(N) ->
- % type variables are represented just as integers
- Rval = const(int_const(N)),
- Type = mlds__native_int_type,
- MLDS_Defns = MLDS_Defns0
- ;
- ( Pseudo = type_ctor_info(RttiTypeId0) ->
- % for zero-arity types, we just generate a
- % reference to the already-existing type_ctor_info
- RttiName = type_ctor_info,
- RttiTypeId0 = rtti_type_id(ModuleName0, _, _),
- ModuleName = fixup_builtin_module(ModuleName0),
- RttiTypeId = RttiTypeId0,
- MLDS_Defns = MLDS_Defns0
- ;
- % 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(Pseudo),
- rtti_data_to_name(RttiData, RttiTypeId, RttiName),
- 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),
- MLDS_Defns1 = RttiDefns ++ MLDS_Defns0,
- % Generate definitions of any pseudo_type_infos
- % referenced by this pseudotypeinfo.
- list__foldl(ml_gen_pseudo_type_info_defn(ModuleInfo),
- arg_pseudo_type_infos(Pseudo),
- MLDS_Defns1, MLDS_Defns)
- ),
- MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName),
- Rval = const(data_addr_const(data_addr(MLDS_ModuleName,
- rtti(RttiTypeId, RttiName)))),
- Type = mlds__rtti_type(RttiName)
- ).
-
-:- func arg_pseudo_type_infos(pseudo_type_info) = list(pseudo_type_info).
-arg_pseudo_type_infos(type_var(_)) = [].
-arg_pseudo_type_infos(type_ctor_info(_)) = [].
-arg_pseudo_type_infos(type_info(_TypeId, ArgPTIs)) = ArgPTIs.
-arg_pseudo_type_infos(higher_order_type_info(_TypeId, _Arity, ArgPTIs)) =
- ArgPTIs.
-
-:- func convert_to_local(mlds__defn) = mlds__defn.
-convert_to_local(mlds__defn(Name, Context, Flags0, Body)) =
- mlds__defn(Name, Context, Flags, Body) :-
- Flags = set_access(Flags0, local).
-
-:- pred ml_stack_layout_construct_tvar_vector(module_info::in,
- mlds__var_name::in, prog_context::in, map(tvar, set(layout_locn))::in,
- mlds__rval::out, mlds__type::out, mlds__defns::out) is det.
-
-ml_stack_layout_construct_tvar_vector(ModuleInfo, TvarVectorName, Context,
- TVarLocnMap, MLDS_Rval, PtrType, MLDS_Defns) :-
- PtrType = mlds__ptr_type(mlds__native_int_type),
- ArrayType = mlds__array_type(mlds__native_int_type),
- ( map__is_empty(TVarLocnMap) ->
- MLDS_Rval = const(null(PtrType)),
- MLDS_Defns = []
- ;
- Access = local,
- ml_stack_layout_construct_tvar_rvals(TVarLocnMap,
- Vector, _VectorTypes),
- Initializer = init_array(Vector),
- MLDS_Defn = ml_gen_static_const_defn(TvarVectorName, ArrayType,
- Access, Initializer, Context),
- MLDS_Defns = [MLDS_Defn],
- module_info_name(ModuleInfo, ModuleName),
- MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName),
- MLDS_Rval = lval(var(qual(MLDS_ModuleName, TvarVectorName),
- PtrType))
- ).
-
-:- pred ml_stack_layout_construct_tvar_rvals(map(tvar, set(layout_locn))::in,
- list(mlds__initializer)::out, list(mlds__type)::out) is det.
-
-ml_stack_layout_construct_tvar_rvals(TVarLocnMap, Vector, VectorTypes) :-
- map__to_assoc_list(TVarLocnMap, TVarLocns),
- ml_stack_layout_construct_type_param_locn_vector(TVarLocns, 1,
- TypeParamLocs),
- 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.
-
-:- pred ml_stack_layout_construct_type_param_locn_vector(
- assoc_list(tvar, set(layout_locn))::in,
- int::in, list(mlds__initializer)::out) is det.
-
-ml_stack_layout_construct_type_param_locn_vector([], _, []).
-ml_stack_layout_construct_type_param_locn_vector([TVar - Locns | TVarLocns],
- CurSlot, Vector) :-
- term__var_to_int(TVar, TVarNum),
- NextSlot is CurSlot + 1,
- ( TVarNum = CurSlot ->
- ( set__remove_least(Locns, LeastLocn, _) ->
- Locn = LeastLocn
- ;
- error("tvar has empty set of locations")
- ),
- stack_layout__represent_locn_as_int(Locn, LocnAsInt),
- Rval = const(int_const(LocnAsInt)),
- ml_stack_layout_construct_type_param_locn_vector(TVarLocns,
- NextSlot, VectorTail),
- Vector = [init_obj(Rval) | VectorTail]
- ; TVarNum > CurSlot ->
- % This slot will never be referred to.
- ml_stack_layout_construct_type_param_locn_vector(
- [TVar - Locns | TVarLocns], NextSlot, VectorTail),
- Vector = [init_obj(const(int_const(0))) | VectorTail]
- ;
- error("unsorted tvars in construct_type_param_locn_vector")
- ).
-
- %
- % ml_gen_closure_wrapper:
- % see comment in interface section for details.
- %
- % This is used to create wrappers both for ordinary closures and
- % also for type class methods.
- %
- % The generated function will be of the following form:
- %
- % foo_wrapper(void *closure_arg,
- % MR_Box wrapper_arg1, MR_Box *wrapper_arg2,
- % ..., MR_Box wrapper_argn)
- % {
- % FooClosure *closure;
- % ...
- % /* declarations needed for converting output args */
- % Arg2Type conv_arg2;
- % ...
- % #if MODEL_SEMI
- % MR_bool succeeded;
- % #endif
- %
- % closure = closure_arg; /* XXX should add cast */
- %
- % CONJ(code_model,
- % /* call function, boxing/unboxing inputs if needed */
- % foo(closure->f1, unbox(closure->f2), ...,
- % unbox(wrapper_arg1), &conv_arg2,
- % wrapper_arg3, ...);
- % ,
- % /* box output arguments */
- % *wrapper_arg2 = box(conv_arg2);
- % ...
- % )
- % }
- %
- % where the stuff in CONJ() expands to the appropriate code
- % for a conjunction, which depends on the code model:
- %
- % #if MODEL_DET
- % /* call function, boxing/unboxing inputs if needed */
- % foo(closure->f1, unbox(closure->f2), ...,
- % unbox(wrapper_arg1), &conv_arg2,
- % wrapper_arg3, ...);
- %
- % /* box output arguments */
- % *wrapper_arg2 = box(conv_arg2);
- % ...
- % #elif MODEL_SEMI
- % /* call function, boxing/unboxing inputs if needed */
- % succeeded = foo(closure->f1, unbox(closure->f2), ...,
- % unbox(wrapper_arg1), &conv_arg2,
- % wrapper_arg3, ...);
- %
- % if (succeeded) {
- % /* box output arguments */
- % *wrapper_arg2 = box(conv_arg2);
- % ...
- % }
- %
- % return succeeded;
- % }
- % #else /* MODEL_NON */
- % foo_1() {
- % /* box output arguments */
- % *wrapper_arg2 = box(conv_arg2);
- % ...
- % (*succ_cont)();
- % }
- %
- % /* call function, boxing/unboxing inputs if needed */
- % foo(closure->f1, unbox(closure->f2), ...,
- % unbox(wrapper_arg1), &conv_arg2,
- % wrapper_arg3, ...,
- % foo_1);
- % #endif
- %
-ml_gen_closure_wrapper(PredId, ProcId, Offset, NumClosureArgs,
- Context, WrapperFuncRval, WrapperFuncType) -->
- %
- % grab the relevant information about the called procedure
- %
- =(Info),
- { ml_gen_info_get_module_info(Info, ModuleInfo) },
- { module_info_pred_proc_info(ModuleInfo, PredId, ProcId,
- PredInfo, ProcInfo) },
- { pred_info_get_is_pred_or_func(PredInfo, PredOrFunc) },
- { proc_info_headvars(ProcInfo, ProcHeadVars) },
- { proc_info_argmodes(ProcInfo, ProcArgModes) },
- { proc_info_interface_code_model(ProcInfo, CodeModel) },
- { proc_info_varset(ProcInfo, ProcVarSet) },
- { 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
- % XXX The accurate GC handling for closures arguments is wrong
- %
- { ProcBoxedArgTypes = ml_make_boxed_types(ProcArity) },
-
- %
- % 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
- {
- list__drop(NumClosureArgs, ProcHeadVars, WrapperHeadVars0),
- list__drop(NumClosureArgs, ProcArgModes, WrapperArgModes0),
- list__drop(NumClosureArgs, ProcBoxedArgTypes,
- WrapperBoxedArgTypes0)
- ->
- WrapperHeadVars = WrapperHeadVars0,
- WrapperArgModes = WrapperArgModes0,
- WrapperBoxedArgTypes = WrapperBoxedArgTypes0
- ;
- error("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),
-
- % then insert the `closure_arg' parameter
- { ClosureArgType = mlds__generic_type },
- % XXX FIXME The GC handling for closures is wrong
- { GC_TraceCode = no },
- { ClosureArg = mlds__argument(
- data(var(var_name("closure_arg", no))),
- ClosureArgType,
- GC_TraceCode) },
- { WrapperParams0 = mlds__func_params(WrapperArgs0, WrapperRetType) },
- { WrapperParams = mlds__func_params([ClosureArg | WrapperArgs0],
- WrapperRetType) },
-
- % also compute the lvals for the parameters,
- % and local declarations for any --copy-out output parameters
- ml_gen_wrapper_arg_lvals(WrapperHeadVarNames, WrapperBoxedArgTypes,
- WrapperArgModes, PredOrFunc, CodeModel, Context,
- WrapperHeadVarDecls, WrapperHeadVarLvals, WrapperCopyOutLvals),
-
- %
- % generate code to declare and initialize the closure pointer.
- % XXX we should use a struct type for the closure, but
- % currently we're using a low-level data representation
- % in the closure
- %
- % #if HIGH_LEVEL_DATA
- % FooClosure *closure;
- % #else
- % void *closure;
- % #endif
- % closure = closure_arg;
- %
- { ClosureName = mlds__var_name("closure", no) },
- { ClosureArgName = mlds__var_name("closure_arg", no) },
- { MLDS_Context = mlds__make_context(Context) },
- { ClosureType = mlds__generic_type },
- % XXX FIXME The GC handling for closures is wrong
- { GC_TraceCode = no },
- { ClosureDecl = ml_gen_mlds_var_decl(var(ClosureName),
- ClosureType, GC_TraceCode, MLDS_Context) },
- ml_gen_var_lval(ClosureName, ClosureType, ClosureLval),
- ml_gen_var_lval(ClosureArgName, ClosureArgType, ClosureArgLval),
- { InitClosure = ml_gen_assign(ClosureLval, lval(ClosureArgLval),
- Context) },
-
- %
- % 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 } ->
- { module_info_globals(ModuleInfo, Globals) },
- { 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) },
- ml_initial_cont(WrapperOutputLvals, WrapperOutputTypes,
- InitialCont)
- ;
- ml_initial_cont([], [], InitialCont)
- ),
- ml_gen_info_push_success_cont(InitialCont)
- ;
- []
- ),
-
- % prepare to generate code to call the function:
- % XXX currently we're using a low-level data representation
- % in the closure
- %
- % foo(
- % #if HIGH_LEVEL_DATA
- % closure->arg1, closure->arg2, ...,
- % #else
- % MR_field(MR_mktag(0), closure, 3),
- % MR_field(MR_mktag(0), closure, 4),
- % ...
- % #endif
- % unbox(wrapper_arg1), &conv_arg2, wrapper_arg3, ...
- % );
- %
- ml_gen_closure_field_lvals(ClosureLval, Offset, 1, NumClosureArgs,
- ClosureArgLvals),
- { CallLvals = list__append(ClosureArgLvals, WrapperHeadVarLvals) },
- ml_gen_call(PredId, ProcId, ProcHeadVarNames, CallLvals,
- ProcBoxedArgTypes, CodeModel, Context, Decls0, Statements0),
-
- % insert the stuff to declare and initialize the closure
- { Decls1 = [ClosureDecl | Decls0] },
- { Statements1 = [InitClosure | Statements0] },
-
- %
- % For semidet code, add the declaration `MR_bool succeeded;'
- %
- ( { CodeModel = model_semi } ->
- { SucceededVarDecl = ml_gen_succeeded_var_decl(MLDS_Context) },
- { Decls2 = [SucceededVarDecl | Decls1] }
- ;
- { Decls2 = Decls1 }
- ),
-
- % Add an appropriate `return' statement
- ml_append_return_statement(CodeModel, WrapperCopyOutLvals, Context,
- Statements1, Statements),
-
- %
- % Insert the local declarations of the wrapper's output arguments,
- % if any (this is needed for `--nondet-copy-out')
- %
- { Decls = list__append(WrapperHeadVarDecls, Decls2) },
-
- %
- % if the wrapper function was model_non, then
- % pop the success continuation that we pushed
- %
- ( { CodeModel = model_non } ->
- ml_gen_info_pop_success_cont
- ;
- []
- ),
-
- %
- % Put it all together
- %
- { WrapperFuncBody = ml_gen_block(Decls, Statements, Context) },
- ml_gen_new_func_label(yes(WrapperParams), WrapperFuncName,
- WrapperFuncRval),
- ml_gen_wrapper_func(WrapperFuncName, WrapperParams, Context,
- WrapperFuncBody, WrapperFunc),
- { WrapperFuncType = mlds__func_type(WrapperParams) },
- ml_gen_info_add_extra_defn(WrapperFunc).
-
-:- pred ml_gen_wrapper_func(ml_label_func, mlds__func_params, prog_context,
- mlds__statement, mlds__defn, ml_gen_info, ml_gen_info).
-:- mode ml_gen_wrapper_func(in, in, in, in, out, in, out) is det.
-
-ml_gen_wrapper_func(FuncLabel, FuncParams, Context, Statement, Func) -->
- ml_gen_label_func(FuncLabel, FuncParams, Context, Statement, Func0),
- { Func0 = mlds__defn(Name, Ctxt, DeclFlags0, Defn) },
- { DeclFlags1 = set_per_instance(DeclFlags0, one_copy) },
- { DeclFlags = set_access(DeclFlags1, private) },
- { Func = mlds__defn(Name, Ctxt, DeclFlags, Defn) }.
-
-:- func ml_gen_wrapper_head_var_names(int, int) = list(mlds__var_name).
-ml_gen_wrapper_head_var_names(Num, Max) = Names :-
- ( Num > Max ->
- Names = []
- ;
- Name = string__format("wrapper_arg_%d", [i(Num)]),
- Names1 = ml_gen_wrapper_head_var_names(Num + 1, Max),
- Names = [mlds__var_name(Name, no) | Names1]
- ).
-
- % ml_gen_wrapper_arg_lvals(HeadVarNames, Types, ArgModes,
- % PredOrFunc, CodeModel, LocalVarDefns, HeadVarLvals):
- % 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), list(prog_type), list(mode),
- pred_or_func, code_model, prog_context,
- list(mlds__defn), list(mlds__lval), list(mlds__lval),
- ml_gen_info, ml_gen_info).
-:- mode ml_gen_wrapper_arg_lvals(in, in, in, in, in, in, out, out, out, in, out)
- is det.
-
-ml_gen_wrapper_arg_lvals(Names, Types, Modes, PredOrFunc, CodeModel, Context,
- Defns, Lvals, CopyOutLvals) -->
- (
- { Names = [], Types = [], Modes = [] }
- ->
- { Lvals = [] },
- { CopyOutLvals = [] },
- { Defns = [] }
- ;
- { Names = [Name | Names1] },
- { Types = [Type | Types1] },
- { Modes = [Mode | Modes1] }
- ->
- ml_gen_wrapper_arg_lvals(Names1, Types1, Modes1,
- PredOrFunc, CodeModel, Context,
- Defns1, Lvals1, CopyOutLvals1),
- ml_gen_type(Type, MLDS_Type),
- ml_gen_var_lval(Name, MLDS_Type, VarLval),
- =(Info),
- { ml_gen_info_get_module_info(Info, ModuleInfo) },
- { mode_to_arg_mode(ModuleInfo, Mode, Type, ArgMode) },
- ( { ArgMode = top_in } ->
- { Lval = VarLval },
- { CopyOutLvals = CopyOutLvals1 },
- { Defns = Defns1 }
- ;
- %
- % handle output variables
- %
- ml_gen_info_get_globals(Globals),
- { CopyOut = get_copy_out_option(Globals, CodeModel) },
- (
- {
- CopyOut = yes
- ;
- % 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)
- }
- ->
- %
- % 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 },
- { Defns = Defns1 }
- ;
- { CopyOutLvals = [Lval |
- CopyOutLvals1] },
- ml_gen_local_for_output_arg(Name, Type,
- Context, Defn),
- { Defns = [Defn | Defns1] }
- )
- ;
- %
- % output arguments are passed by reference,
- % so we need to dereference them
- %
- { Lval = mem_ref(lval(VarLval), MLDS_Type) },
- { CopyOutLvals = CopyOutLvals1 },
- { Defns = Defns1 }
- )
- ),
- { Lvals = [Lval | Lvals1] }
- ;
- { error("ml_gen_wrapper_arg_lvals: length mismatch") }
- ).
-
-:- pred ml_gen_closure_field_lvals(mlds__lval, int, int, int,
- list(mlds__lval),
- ml_gen_info, ml_gen_info).
-:- mode ml_gen_closure_field_lvals(in, in, in, in, out, in, out) is det.
-
-ml_gen_closure_field_lvals(ClosureLval, Offset, ArgNum, NumClosureArgs,
- ClosureArgLvals) -->
- ( { ArgNum > NumClosureArgs } ->
- { ClosureArgLvals = [] }
- ;
- %
- % generate `MR_field(MR_mktag(0), closure, <N>)'
- %
- { FieldId = offset(const(int_const(ArgNum + Offset))) },
- % 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
- %
- ml_gen_closure_field_lvals(ClosureLval, Offset, ArgNum + 1,
- NumClosureArgs, ClosureArgLvals0),
- { ClosureArgLvals = [FieldLval | ClosureArgLvals0] }
- ).
-
-:- pred ml_gen_local_for_output_arg(var_name, prog_type, prog_context,
- mlds__defn, ml_gen_info, ml_gen_info).
-:- mode ml_gen_local_for_output_arg(in, in, in, out, in, out) is det.
-
-ml_gen_local_for_output_arg(VarName, Type, Context, LocalVarDefn) -->
- %
- % Generate a declaration for a corresponding local variable.
- %
- ml_gen_var_decl(VarName, Type, Context, LocalVarDefn).
-
-%-----------------------------------------------------------------------------%
% convert a cons_id for a given type to a cons_tag
ml_cons_id_to_tag(ConsId, Type, Tag) -->
@@ -1376,14 +602,6 @@
% additional constants to insert at the start of the
% argument list.
%
-:- pred ml_gen_new_object(maybe(cons_id), mlds__tag, bool, maybe(ctor_name),
- prog_var, list(mlds__rval), list(mlds__type), prog_vars,
- list(uni_mode), how_to_construct,
- prog_context, mlds__defns, mlds__statements,
- ml_gen_info, ml_gen_info).
-:- mode ml_gen_new_object(in, in, in, in, in, in, in, in, in, in, in, out, out,
- in, out) is det.
-
ml_gen_new_object(MaybeConsId, Tag, HasSecTag, MaybeCtorName, Var,
ExtraRvals, ExtraTypes, ArgVars, ArgModes, HowToConstruct,
Context, MLDS_Decls, MLDS_Statements) -->
@@ -2717,18 +1935,6 @@
;
error("ml_gen_field_id: invalid type")
).
-
-%-----------------------------------------------------------------------------%
-
- %
- % allocate some fresh type variables to use as the Mercury types
- % of boxed objects
- %
-:- func ml_make_boxed_types(arity) = list(prog_type).
-ml_make_boxed_types(Arity) = BoxedTypes :-
- varset__init(TypeVarSet0),
- varset__new_vars(TypeVarSet0, Arity, BoxedTypeVars, _TypeVarSet),
- term__var_list_to_term_list(BoxedTypeVars, BoxedTypes).
%-----------------------------------------------------------------------------%
Index: compiler/rtti_to_mlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/rtti_to_mlds.m,v
retrieving revision 1.25
diff -u -d -r1.25 rtti_to_mlds.m
--- compiler/rtti_to_mlds.m 3 Mar 2002 13:43:49 -0000 1.25
+++ compiler/rtti_to_mlds.m 4 Mar 2002 07:21:49 -0000
@@ -32,7 +32,7 @@
:- implementation.
:- import_module foreign, prog_data, hlds_data.
:- import_module pseudo_type_info, prog_util, prog_out, type_util.
-:- import_module ml_code_util, ml_unify_gen.
+:- import_module ml_code_util, ml_unify_gen, ml_closure_gen.
:- import_module bool, list, std_util, string, term, require.
rtti_data_list_to_mlds(ModuleInfo, RttiDatas) =
Index: compiler/notes/compiler_design.html
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/notes/compiler_design.html,v
retrieving revision 1.70
diff -u -d -r1.70 compiler_design.html
--- compiler/notes/compiler_design.html 12 Feb 2002 16:38:16 -0000 1.70
+++ compiler/notes/compiler_design.html 4 Mar 2002 06:49:02 -0000
@@ -914,6 +914,7 @@
The following sub-modules are used to handle different constructs:
<dl>
<dt> ml_unify_gen.m
+ <dt> ml_closure_gen.m
<dt> ml_call_gen.m
<dt> ml_switch_gen.m, which in turn has sub-modules
<ul>
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
The University of Melbourne | of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list