Files
mercury/compiler/arg_info.m
Simon Taylor 18430aaef1 Aditi compilation.
Estimated hours taken: 1200

Aditi compilation.

compiler/options.m:
	The documentation for these is commented out because the Aditi
	system is not currently useful to the general public.
	--aditi: enable Aditi compilation.
	--dump-rl: write the intermediate RL to `<module>.rl_dump'.
	--dump-rl-bytecode: write a text version of the bytecodes
		to `<module>.rla'
	--aditi-only: don't produce a `.c' file.
	--filenames-from-stdin: accept a list of filenames to compile
		from stdin. This is used by the query shell.
	--optimize-rl, --optimize-rl-cse, --optimize-rl-invariants,
	--optimize-rl-index, --detect-rl-streams:
		Options to control RL optimization passes.
	--aditi-user:
		Default owner of any Aditi procedures,
		defaults to $USER or "guest".
	--generate-schemas:
		write schemas for base relations to `<module>'.base_schema
		and schemas for derived relations to `<module>'.derived_schema.
		This is used by the query shell.

compiler/handle_options.m:
	Handle the default for --aditi-user.

compiler/hlds_pred.m:
compiler/prog_data.m:
compiler/prog_io_pragma.m:
compiler/make_hlds.m:
	Add some Aditi pragma declarations - `aditi', `supp_magic', `context',
	`naive', `psn' (predicate semi-naive), `aditi_memo', `aditi_no_memo',
	`base_relation', `owner' and `index'.
	Separate out code to parse a predicate name and arity.

compiler/hlds_pred.m:
	Add predicates to identify Aditi procedures.
	Added markers `generate_inline' and `aditi_interface', which
	are used internally for Aditi code generation.
	Add an `owner' field to pred_infos, which is used for database
	security checks.
	Add a field to pred_infos to hold the list of indexes for a base
	relation.

compiler/make_hlds.m:
	Some pragmas must be exported if the corresponding predicates
	are exported, check this.
	Make sure stratification of Aditi procedures is checked.
	Predicates with a mode declaration but no type declaration
	are no longer assumed to be local.
	Set the `do_aditi_compilation' field of the module_info if there
	are any local Aditi procedures or base relations.
	Check that `--aditi' is set if Aditi compilation is required.

compiler/post_typecheck.m:
	Check that every Aditi predicate has an `aditi__state' argument,
	which is used to ensure sequencing of updates and that Aditi
	procedures are only called within transactions.

compiler/dnf.m:
	Changed the definition of disjunctive normal form slightly
	so that a call followed by some atomic goals not including
	any database calls is considered atomic. magic.m can handle
	this kind of goal, and it results in more efficient RL code.

compiler/hlds_module.m:
compiler/dependency_graph.m:
	Added dependency_graph__get_scc_entry_points which finds
	the procedures in an SCC which could be called from outside.
	Added a new field to the dependency_info, the
	aditi_dependency_ordering. This contains all Aditi SCCs of
	the original program, with multiple SCCs merged where
	possible to improve the effectiveness of differential evaluation
	and the low level RL optimizations.

compiler/hlds_module.m:
	Add a field to record whether there are any local Aditi procedures
	in the current module.
	Added versions of module_info_pred_proc_info and
	module_info_set_pred_proc_info which take a pred_proc_id,
	not a separate pred_id and proc_id.

compiler/polymorphism.m:
compiler/lambda.m:
	Make sure that predicates created for closures in Aditi procedures
	have the correct markers.

compiler/goal_util.m:
	Added goal_util__switch_to_disjunction,
	goal_util__case_to_disjunct (factored out from simplify.m)
	and goal_util__if_then_else_to_disjunction. These are
	require because supplementary magic sets can't handle
	if-then-elses or switches.

compiler/type_util.m:
	Added type_is_aditi_state/1.

compiler/mode_util.m:
	Added partition_args/5 which partitions a list of arguments
	into inputs and others.

compiler/inlining.m:
	Don't inline memoed procedures.
	Don't inline Aditi procedures into non-Aditi procedures.

compiler/intermod.m:
	Handle Aditi markers.
	Clean up handling of markers which should not appear in `.opt' files.

compiler/simplify.m:
	Export a slightly different interface for use by magic.m.
	Remove explicit quantifications where possible.
	Merge multiple nested quantifications.
	Don't report infinite recursion warnings for Aditi procedures.

compiler/prog_out.m:
	Generalised the code to output a module list to write any list.

compiler/code_gen.m:
compiler/arg_info.m:
	Don't process Aditi procedures.

compiler/mercury_compile.m:
	Call magic.m and rl_gen.m.
	Don't perform the low-level annotation passes on Aditi procedures.
	Remove calls to constraint.m - sometime soon a rewritten version
	will be called directly from deforestation.

compiler/passes_aux.m:
	Add predicates to process only non-Aditi procedures.

compiler/llds.m:
compiler/llds_out.m:
	Added new `code_addr' enum members, do_{det,semidet,nondet}_aditi_call,
	which are defined in extras/aditi/aditi.m.

compiler/call_gen.m:
	Handle generation of do_*_aditi_call.

compiler/llds_out.m:
	Write the RL code for the module as a constant char array
	in the `.c' file.

compiler/term_errors.m:
compiler/error_util.m:
	Move code to describe predicates into error_util.m
	Allow the caller to explicitly add line breaks.
	Added error_util:list_to_pieces to format a list of
	strings.
	Reordered some arguments for currying.

compiler/hlds_out.m:
	Don't try to print clauses if there are none.

runtime/mercury_init.h:
util/mkinit.c:
scripts/c2init.in:
	Added a function `mercury__load_aditi_rl_code()' to the generated
	`<module>_init.c' file which throws all the RL code for the program
	at the database. This should be called at connection time by
	`aditi__connect'.
	Added an option `--aditi' which controls the output
	`mercury__load_aditi_rl_code()'.

compiler/notes/compiler_design.html:
	Document the new files.

Mmakefile:
bindist/Mmakefile:
	Don't distribute extras/aditi yet.

New files:

compiler/magic.m:
compiler/magic_util.m:
	Supplementary magic sets transformation. Report errors
	for constructs that Aditi can't handle.

compiler/context.m:
	Supplementary context transformation.

compiler/rl_gen.m:
compiler/rl_relops.m:
	Aditi code generation.

compiler/rl_info.m:
	Code generator state.

compiler/rl.m:
	Intermediate RL representation.

compiler/rl_util:
	Predicates to collect information about RL instructions.

compiler/rl_dump.m:
	Print out the representation in rl.m.

compiler/rl_opt.m:
	Control low-level RL optimizations.

compiler/rl_block.m:
	Break a procedure into basic blocks.

compiler/rl_analyse.m:
	Generic dataflow analysis for RL procedures.

compiler/rl_liveness.m:
	Make sure all relations are initialised before used, clear
	references to relations that are no longer required.

compiler/rl_loop.m:
	Loop invariant removal.

compiler/rl_block_opt.m:
	CSE and instruction merging on basic blocks.

compiler/rl_key.m:
	Detect upper/lower bounds for which a goal could succeed.

compiler/rl_sort.m:
	Use indexing for joins and projections.
	Optimize away unnecessary sorting and indexing.

compiler/rl_stream.m:
	Detect relations which don't need to be materialised.

compiler/rl_code.m:
	RL bytecode definitions. Automatically generated from the Aditi
	header files.

compiler/rl_out.m:
compiler/rl_file.m:
	Output the RL bytecodes in binary to <module>.rlo (for use by Aditi)
	and in text to <module>.rla (for use by the RL interpreter).
	Also output the schema information if --generate-schemas is set.

compiler/rl_exprn.m:
	Generate bytecodes for join conditions.

extras/aditi/Mmakefile:
extras/aditi/aditi.m:
	Definitions of some Aditi library predicates and the
	interfacing and transaction processing code.
1998-12-06 23:49:14 +00:00

255 lines
9.5 KiB
Mathematica

%-----------------------------------------------------------------------------%
% Copyright (C) 1994-1998 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: arg_info.m
% main author: fjh
% This module is one of the pre-passes of the code generator.
% It initializes the arg_info field of the proc_info structure in the HLDS,
% which records for each argument of each procedure, whether the
% argument is input/output/unused, and which register it is supposed to
% go into.
% Possible optimization: at the moment, each argument is assigned a
% different register. We could try putting both an input and an output
% argument into a single register, which should improve performance
% a bit.
%-----------------------------------------------------------------------------%
:- module arg_info.
:- interface.
:- import_module hlds_module, hlds_pred, llds, globals, prog_data.
:- import_module bool, list, assoc_list.
:- pred generate_arg_info(module_info, module_info).
:- mode generate_arg_info(in, out) is det.
:- pred arg_info__unify_arg_info(args_method, code_model, list(arg_info)).
:- mode arg_info__unify_arg_info(in, in, out) is det.
:- pred make_arg_infos(args_method, list(type), list(mode), code_model,
module_info, list(arg_info)).
:- mode make_arg_infos(in, in, in, in, in, out) is det.
% Return yes if a procedure using the given args_method
% can by called by do_call_*_closure.
:- pred arg_info__args_method_is_ho_callable(globals, args_method, bool).
:- mode arg_info__args_method_is_ho_callable(in, in, out) is det.
% Return an args_method which can be used for procedures
% which may be called by do_call_*_closure.
:- pred arg_info__ho_call_args_method(globals, args_method).
:- mode arg_info__ho_call_args_method(in, out) is det.
% Given a list of the head variables and their argument information,
% return a list giving the input variables and their initial locations.
:- pred arg_info__build_input_arg_list(assoc_list(prog_var, arg_info),
assoc_list(prog_var, rval)).
:- mode arg_info__build_input_arg_list(in, out) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module code_util, mode_util.
:- import_module std_util, map, int, require.
%-----------------------------------------------------------------------------%
% This whole section just traverses the module structure.
generate_arg_info(ModuleInfo0, ModuleInfo) :-
module_info_preds(ModuleInfo0, Preds),
map__keys(Preds, PredIds),
generate_pred_arg_info(PredIds, ModuleInfo0, ModuleInfo).
:- pred generate_pred_arg_info(list(pred_id), module_info, module_info).
:- mode generate_pred_arg_info(in, in, out) is det.
generate_pred_arg_info([], ModuleInfo, ModuleInfo).
generate_pred_arg_info([PredId | PredIds], ModuleInfo0, ModuleInfo) :-
module_info_preds(ModuleInfo0, PredTable),
map__lookup(PredTable, PredId, PredInfo),
pred_info_procids(PredInfo, ProcIds),
generate_proc_list_arg_info(PredId, ProcIds, ModuleInfo0, ModuleInfo1),
generate_pred_arg_info(PredIds, ModuleInfo1, ModuleInfo).
:- pred generate_proc_list_arg_info(pred_id, list(proc_id),
module_info, module_info).
:- mode generate_proc_list_arg_info(in, in, in, out) is det.
generate_proc_list_arg_info(_PredId, [], ModuleInfo, ModuleInfo).
generate_proc_list_arg_info(PredId, [ProcId | ProcIds],
ModuleInfo0, ModuleInfo) :-
module_info_preds(ModuleInfo0, PredTable0),
map__lookup(PredTable0, PredId, PredInfo0),
( hlds_pred__pred_info_is_aditi_relation(PredInfo0) ->
ModuleInfo1 = ModuleInfo0
;
pred_info_procedures(PredInfo0, ProcTable0),
pred_info_arg_types(PredInfo0, ArgTypes),
map__lookup(ProcTable0, ProcId, ProcInfo0),
generate_proc_arg_info(ProcInfo0, ArgTypes,
ModuleInfo0, ProcInfo),
map__det_update(ProcTable0, ProcId, ProcInfo, ProcTable),
pred_info_set_procedures(PredInfo0, ProcTable, PredInfo),
map__det_update(PredTable0, PredId, PredInfo, PredTable),
module_info_set_preds(ModuleInfo0, PredTable, ModuleInfo1)
),
generate_proc_list_arg_info(PredId, ProcIds, ModuleInfo1, ModuleInfo).
:- pred generate_proc_arg_info(proc_info, list(type), module_info, proc_info).
:- mode generate_proc_arg_info(in, in, in, out) is det.
generate_proc_arg_info(ProcInfo0, ArgTypes, ModuleInfo, ProcInfo) :-
proc_info_argmodes(ProcInfo0, ArgModes),
proc_info_args_method(ProcInfo0, Method),
proc_info_interface_code_model(ProcInfo0, CodeModel),
make_arg_infos(Method, ArgTypes, ArgModes, CodeModel, ModuleInfo,
ArgInfo),
proc_info_set_arg_info(ProcInfo0, ArgInfo, ProcInfo).
%---------------------------------------------------------------------------%
% This is the useful part of the code ;-).
% This code is one of the places where we make assumptions
% about the calling convention. This is the only place in
% the compiler that makes such assumptions, but there are
% other places scattered around the runtime and the library
% which also rely on it.
% For the `simple' argument convention, we assume all arguments
% go in sequentially numbered registers starting at register
% number 1, except for semi-deterministic procs, where the
% first register is reserved for the result and hence the arguments
% start at register number 2. Each register is used either for
% input or output but not both.
% For the `compact' argument convention, we assume all input arguments
% go in sequentially numbered registers starting at register
% number 1, and all output arguments go in sequentially numbered
% registers starting at register number 1,
% except for semi-deterministic procs, where the
% first register is reserved for the result and hence the output
% arguments start at register number 2.
% In the `compact' argument convention, we may use a single
% register for both an input arg and an output arg.
%
% lambda.m ensures that all procedures which are called directly
% from do_call_*_closure use the `compact' argument convention,
% so that mercury_ho_call.c can place the input arguments without
% knowing anything about the called procedure.
make_arg_infos(Method, ArgTypes, ArgModes, CodeModel, ModuleInfo, ArgInfo) :-
( CodeModel = model_semi ->
StartReg = 2
;
StartReg = 1
),
(
Method = simple,
make_arg_infos_list(ArgModes, ArgTypes, StartReg, ModuleInfo,
ArgInfo)
;
Method = compact,
make_arg_infos_compact_list(ArgModes, ArgTypes, 1, StartReg,
ModuleInfo, ArgInfo)
).
:- pred make_arg_infos_list(list(mode), list(type), int, module_info,
list(arg_info)).
:- mode make_arg_infos_list(in, in, in, in, out) is det.
make_arg_infos_list([], [], _, _, []).
make_arg_infos_list([Mode | Modes], [Type | Types], Reg0, ModuleInfo,
[ArgInfo | ArgInfos]) :-
mode_to_arg_mode(ModuleInfo, Mode, Type, ArgMode),
ArgInfo = arg_info(Reg0, ArgMode),
Reg1 is Reg0 + 1,
make_arg_infos_list(Modes, Types, Reg1, ModuleInfo, ArgInfos).
make_arg_infos_list([], [_|_], _, _, _) :-
error("make_arg_infos_list: length mis-match").
make_arg_infos_list([_|_], [], _, _, _) :-
error("make_arg_infos_list: length mis-match").
:- pred make_arg_infos_compact_list(list(mode), list(type), int, int,
module_info, list(arg_info)).
:- mode make_arg_infos_compact_list(in, in, in, in, in, out) is det.
make_arg_infos_compact_list([], [], _, _, _, []).
make_arg_infos_compact_list([Mode | Modes], [Type | Types], InReg0, OutReg0,
ModuleInfo, [ArgInfo | ArgInfos]) :-
mode_to_arg_mode(ModuleInfo, Mode, Type, ArgMode),
(
ArgMode = top_in,
ArgReg = InReg0,
InReg1 is InReg0 + 1,
OutReg1 = OutReg0
;
ArgMode = top_out,
ArgReg = OutReg0,
InReg1 = InReg0,
OutReg1 is OutReg0 + 1
;
% Allocate unused regs as if they were outputs.
% We must allocate them a register, and the choice
% should not matter since unused args should be rare.
ArgMode = top_unused,
ArgReg = OutReg0,
InReg1 = InReg0,
OutReg1 is OutReg0 + 1
),
ArgInfo = arg_info(ArgReg, ArgMode),
make_arg_infos_compact_list(Modes, Types, InReg1, OutReg1,
ModuleInfo, ArgInfos).
make_arg_infos_compact_list([], [_|_], _, _, _, _) :-
error("make_arg_infos_list: length mis-match").
make_arg_infos_compact_list([_|_], [], _, _, _, _) :-
error("make_arg_infos_list: length mis-match").
%---------------------------------------------------------------------------%
arg_info__unify_arg_info(_ArgsMethod, model_det,
[arg_info(1, top_in), arg_info(2, top_in)]).
arg_info__unify_arg_info(simple, model_semi,
[arg_info(2, top_in), arg_info(3, top_in)]).
arg_info__unify_arg_info(compact, model_semi,
[arg_info(1, top_in), arg_info(2, top_in)]).
arg_info__unify_arg_info(_ArgsMethod, model_non, _) :-
error("arg_info: nondet unify!").
%---------------------------------------------------------------------------%
arg_info__args_method_is_ho_callable(_, compact, yes).
arg_info__args_method_is_ho_callable(_, simple, no).
arg_info__ho_call_args_method(_, compact).
%---------------------------------------------------------------------------%
arg_info__build_input_arg_list([], []).
arg_info__build_input_arg_list([V - Arg | Rest0], VarArgs) :-
Arg = arg_info(Loc, Mode),
(
Mode = top_in
->
code_util__arg_loc_to_register(Loc, Reg),
VarArgs = [V - lval(Reg) | VarArgs0]
;
VarArgs = VarArgs0
),
arg_info__build_input_arg_list(Rest0, VarArgs0).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%