3 * File name: ir/ana/analyze_irg_agrs.c
4 * Purpose: read/write analyze of graph argument, which have mode reference.
5 * Author: Beyhan Veliev
8 * Copyright: (c) 1998-2005 Universität Karlsruhe
9 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
13 * @file analyze_irg_agrs.c
37 #include "analyze_irg_args.h"
40 static void *VISITED = &v;
43 * Walk recursive the successors of a graph argument
44 * with mode reference and mark in the "irg_args" if it will be read,
47 * @param arg The graph argument with mode reference,
48 * that must be checked.
50 static unsigned analyze_arg(ir_node *arg, unsigned bits)
55 /* We must visit a node once to avoid endless recursion.*/
56 set_irn_link(arg, VISITED);
58 for (i = get_irn_n_outs(arg) - 1; i >= 0; --i) {
59 succ = get_irn_out(arg, i);
62 if (get_irn_link(succ) == VISITED)
65 /* We should not walk over the memory edge.*/
66 if (get_irn_mode(succ) == mode_M)
69 /* If we reach with the recursion a Call node and our reference
70 isn't the address of this Call we accept that the reference will
71 be read and written if the graph of the method represented by
72 "Call" isn't computed else we analyze that graph. If our
73 reference is the address of this
74 Call node that mean the reference will be read.*/
75 if (get_irn_op(succ) == op_Call) {
76 ir_node *Call_ptr = get_Call_ptr(succ);
78 if (Call_ptr == arg) {
79 /* Hmm: not sure what this is, most likely a read */
80 bits |= ptr_access_read;
82 else if (op_SymConst == get_irn_op(Call_ptr) &&
83 get_SymConst_kind(Call_ptr) == symconst_addr_ent) {
84 entity *meth_ent = get_SymConst_entity(Call_ptr);
86 for (p = get_Call_n_params(succ) - 1; p >= 0; --p){
87 if (get_Call_param(succ, p) == arg) {
88 /* an arg can be used more than once ! */
89 bits |= get_method_param_access(meth_ent, p);
92 } else /* can do anything */
93 bits |= ptr_access_all;
95 /* search stops here anyway */
98 else if (get_irn_op(succ) == op_Store) {
99 /* We have reached a Store node => the reference is written or stored. */
100 if (get_Store_ptr(succ) == arg) {
102 bits |= ptr_access_write;
106 bits |= ptr_access_store;
109 /* search stops here anyway */
112 else if (get_irn_op(succ) == op_Load) {
113 /* We have reached a Load node => the reference is read. */
114 bits |= ptr_access_read;
116 /* search stops here anyway */
119 else if (get_irn_op(succ) == op_Conv) {
120 /* our address is casted into something unknown. Break our search. */
121 return ptr_access_all;
124 /* If we know that, the argument will be read, write and stored, we
125 can break the recursion.*/
126 if (bits == ptr_access_all)
127 return ptr_access_all;
130 * A calculation that do not lead to a reference mode ends our search.
131 * This is dangerous: It would allow to cast into integer and that cast back ...
132 * so, when we detect a Conv we go mad, see the Conv case above.
134 if (!mode_is_reference(get_irn_mode(succ)))
137 /* follow further the address calculation */
138 bits = analyze_arg(succ, bits);
140 set_irn_link(arg, NULL);
146 * Check if a argument of the ir graph with mode
147 * reference is read, write or both.
149 * @param irg The ir graph to analyze.
151 static void analyze_ent_args(entity *ent)
154 ir_node *irg_args, *arg;
159 ptr_access_kind *rw_info;
161 mtp = get_entity_type(ent);
162 nparams = get_method_n_params(mtp);
164 ent->param_access = NEW_ARR_F(ptr_access_kind, nparams);
166 /* If the method haven't parameters we have
172 irg = get_entity_irg(ent);
174 /* we have not yet analysed the graph, set ALL access for pointer args */
175 for (i = nparams - 1; i >= 0; --i)
176 ent->param_access[i] =
177 is_Pointer_type(get_method_param_type(mtp, i)) ? ptr_access_all : ptr_access_none;
180 /* no graph, no better info */
184 /* Call algorithm that computes the out edges */
185 if (get_irg_outs_state(irg) != outs_consistent)
188 irg_args = get_irg_args(irg);
190 /* A array to save the information for each argument with
192 NEW_ARR_A(ptr_access_kind, rw_info, nparams);
194 /* We initialize the element with none state. */
195 for (i = nparams - 1; i >= 0; --i)
196 rw_info[i] = ptr_access_none;
198 /* search for arguments with mode reference
200 for (i = get_irn_n_outs(irg_args) - 1; i >= 0; --i) {
201 arg = get_irn_out(irg_args, i);
202 arg_mode = get_irn_mode(arg);
203 proj_nr = get_Proj_proj(arg);
205 if (mode_is_reference(arg_mode))
206 rw_info[proj_nr] |= analyze_arg(arg, rw_info[proj_nr]);
209 /* copy the temporary info */
210 memcpy(ent->param_access, rw_info, nparams * sizeof(ent->param_access[0]));
212 printf("\n%s:\n", get_entity_name(ent));
213 for (i = 0; i < nparams; ++i) {
214 if (is_Pointer_type(get_method_param_type(mtp, i)))
215 if (ent->param_access[i] != ptr_access_none) {
216 printf(" Pointer Arg %d access: ", i);
217 if (ent->param_access[i] & ptr_access_read)
219 if (ent->param_access[i] & ptr_access_write)
221 if (ent->param_access[i] & ptr_access_store)
229 * Compute for a method with pointer parameter(s)
230 * if they will be read or written.
232 ptr_access_kind get_method_param_access(entity *ent, int pos)
234 type *mtp = get_entity_type(ent);
235 int is_variadic = get_method_variadicity(mtp) == variadicity_variadic;
237 assert(0 <= pos && (is_variadic || pos < get_method_n_params(mtp)));
239 if (ent->param_access) {
240 if (pos < ARR_LEN(ent->param_access))
241 return ent->param_access[pos];
243 return ptr_access_all;
246 analyze_ent_args(ent);
248 if (pos < ARR_LEN(ent->param_access))
249 return ent->param_access[pos];
251 return ptr_access_all;
255 * Analyze how pointer arguments of a given
256 * ir graph are accessed.
258 * @param irg The ir graph to analyze.
260 void analyze_irg_args(ir_graph *irg)
264 if (irg == get_const_code_irg())
267 ent = get_irg_entity(irg);
271 if (! ent->param_access)
272 analyze_ent_args(ent);