File: arg_info.m

package info (click to toggle)
mercury 0.9-1
  • links: PTS
  • area: main
  • in suites: potato
  • size: 18,488 kB
  • ctags: 9,800
  • sloc: objc: 146,680; ansic: 51,418; sh: 6,436; lisp: 1,567; cpp: 1,040; perl: 854; makefile: 450; asm: 232; awk: 203; exp: 32; fortran: 3; csh: 1
file content (188 lines) | stat: -rw-r--r-- 7,018 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
%-----------------------------------------------------------------------------%
% Copyright (C) 1994-1999 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.

%-----------------------------------------------------------------------------%

:- module arg_info.
:- interface. 
:- import_module hlds_module, hlds_pred, llds, prog_data.
:- import_module 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(code_model, list(arg_info)).
:- mode arg_info__unify_arg_info(in, out) is det.

:- pred make_arg_infos(list(type), list(mode), code_model, module_info,
	list(arg_info)).
:- mode make_arg_infos(in, in, in, 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_interface_code_model(ProcInfo0, CodeModel),
	make_arg_infos(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.

	% We assume all input arguments always go in sequentially numbered
	% registers starting at register number 1. We also assume that
	% all output arguments go in sequentially numbered registers
	% starting at register number 1, except for model_semi procedures,
	% where the first register is reserved for the result and hence
	% the output arguments start at register number 2.

make_arg_infos(ArgTypes, ArgModes, CodeModel, ModuleInfo, ArgInfo) :-
	( CodeModel = model_semi ->
		StartReg = 2
	;
		StartReg = 1
	),
	make_arg_infos_list(ArgModes, ArgTypes, 1, StartReg,
		ModuleInfo, ArgInfo).

:- pred make_arg_infos_list(list(mode), list(type), int, int,
	module_info, list(arg_info)).
:- mode make_arg_infos_list(in, in, in, in, in, out) is det.

make_arg_infos_list([], [], _, _, _, []).
make_arg_infos_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 args 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_list(Modes, Types, InReg1, OutReg1,
		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").

%---------------------------------------------------------------------------%

arg_info__unify_arg_info(model_det,
	[arg_info(1, top_in), arg_info(2, top_in)]).
arg_info__unify_arg_info(model_semi,
	[arg_info(1, top_in), arg_info(2, top_in)]).
arg_info__unify_arg_info(model_non, _) :-
	error("arg_info: nondet unify!").

%---------------------------------------------------------------------------%

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).

%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%