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
35 #include "analyze_irg_args.h"
38 static void *VISITED = &v;
41 * Walk recursive the successors of a graph argument
42 * with mode reference and mark in the "irg_args" if it will be read,
45 * @param arg The graph argument with mode reference,
46 * that must be checked.
48 static unsigned analyze_arg(ir_node *arg, unsigned bits)
53 /* We must visit a node once to avoid endless recursion.*/
54 set_irn_link(arg, VISITED);
56 for (i = get_irn_n_outs(arg) - 1; i >= 0; --i) {
57 succ = get_irn_out(arg, i);
60 if (get_irn_link(succ) == VISITED)
63 /* We should not walk over the memory edge.*/
64 if (get_irn_mode(succ) == mode_M)
67 /* If we reach with the recursion a Call node and our reference
68 isn't the address of this Call we accept that the reference will
69 be read and written if the graph of the method represented by
70 "Call" isn't computed else we analyze that graph. If our
71 reference is the address of this
72 Call node that mean the reference will be read.*/
73 if (get_irn_op(succ) == op_Call) {
74 ir_node *Call_ptr = get_Call_ptr(succ);
76 if (Call_ptr == arg) {
77 /* Hmm: not sure what this is, most likely a read */
78 bits |= ptr_access_read;
80 else if (op_SymConst == get_irn_op(Call_ptr) &&
81 get_SymConst_kind(Call_ptr) == symconst_addr_ent) {
82 entity *meth_ent = get_SymConst_entity(Call_ptr);
84 for (p = get_Call_n_params(succ) - 1; p >= 0; --p){
85 if (get_Call_param(succ, p) == arg) {
86 /* an arg can be used more than once ! */
87 bits |= get_method_param_access(meth_ent, p);
90 } else /* can do anything */
91 bits |= ptr_access_all;
93 /* search stops here anyway */
96 else if (get_irn_op(succ) == op_Store) {
97 /* We have reached a Store node => the reference is written or stored. */
98 if (get_Store_ptr(succ) == arg) {
100 bits |= ptr_access_write;
104 bits |= ptr_access_store;
107 /* search stops here anyway */
110 else if (get_irn_op(succ) == op_Load) {
111 /* We have reached a Load node => the reference is read. */
112 bits |= ptr_access_read;
114 /* search stops here anyway */
117 else if (get_irn_op(succ) == op_Conv) {
118 /* our address is casted into something unknown. Break our search. */
119 return ptr_access_all;
122 /* If we know that, the argument will be read, write and stored, we
123 can break the recursion.*/
124 if (bits == ptr_access_all)
125 return ptr_access_all;
128 * A calculation that do not lead to a reference mode ends our search.
129 * This is dangerous: It would allow to cast into integer and that cast back ...
130 * so, when we detect a Conv we go mad, see the Conv case above.
132 if (!mode_is_reference(get_irn_mode(succ)))
135 /* follow further the address calculation */
136 bits = analyze_arg(succ, bits);
138 set_irn_link(arg, NULL);
144 * Check if a argument of the ir graph with mode
145 * reference is read, write or both.
147 * @param irg The ir graph to analyze.
149 static void analyze_ent_args(entity *ent)
152 ir_node *irg_args, *arg;
157 ptr_access_kind *rw_info;
159 mtp = get_entity_type(ent);
160 nparams = get_method_n_params(mtp);
162 ent->param_access = NEW_ARR_F(ptr_access_kind, nparams);
164 /* If the method haven't parameters we have
170 irg = get_entity_irg(ent);
172 /* we have not yet analysed the graph, set ALL access for pointer args */
173 for (i = nparams - 1; i >= 0; --i)
174 ent->param_access[i] =
175 is_Pointer_type(get_method_param_type(mtp, i)) ? ptr_access_all : ptr_access_none;
178 /* no graph, no better info */
182 /* Call algorithm that computes the out edges */
183 if (get_irg_outs_state(irg) != outs_consistent)
186 irg_args = get_irg_args(irg);
188 /* A array to save the information for each argument with
190 NEW_ARR_A(ptr_access_kind, rw_info, nparams);
192 /* We initialize the element with none state. */
193 for (i = nparams - 1; i >= 0; --i)
194 rw_info[i] = ptr_access_none;
196 /* search for arguments with mode reference
198 for (i = get_irn_n_outs(irg_args) - 1; i >= 0; --i) {
199 arg = get_irn_out(irg_args, i);
200 arg_mode = get_irn_mode(arg);
201 proj_nr = get_Proj_proj(arg);
203 if (mode_is_reference(arg_mode))
204 rw_info[proj_nr] |= analyze_arg(arg, rw_info[proj_nr]);
207 /* copy the temporary info */
208 memcpy(ent->param_access, rw_info, nparams * sizeof(ent->param_access[0]));
210 printf("\n%s:\n", get_entity_name(ent));
211 for (i = 0; i < nparams; ++i) {
212 if (is_Pointer_type(get_method_param_type(mtp, i)))
213 if (ent->param_access[i] != ptr_access_none) {
214 printf(" Pointer Arg %d access: ", i);
215 if (ent->param_access[i] & ptr_access_read)
217 if (ent->param_access[i] & ptr_access_write)
219 if (ent->param_access[i] & ptr_access_store)
227 * Compute for a method with pointer parameter(s)
228 * if they will be read or written.
230 ptr_access_kind get_method_param_access(entity *ent, int pos)
232 type *mtp = get_entity_type(ent);
233 int is_variadic = get_method_variadicity(mtp) == variadicity_variadic;
235 assert(0 <= pos && (is_variadic || pos < get_method_n_params(mtp)));
237 if (ent->param_access) {
238 if (pos < ARR_LEN(ent->param_access))
239 return ent->param_access[pos];
241 return ptr_access_all;
244 analyze_ent_args(ent);
246 if (pos < ARR_LEN(ent->param_access))
247 return ent->param_access[pos];
249 return ptr_access_all;
253 * Analyze how pointer arguments of a given
254 * ir graph are accessed.
256 * @param irg The ir graph to analyze.
258 void analyze_irg_args(ir_graph *irg)
262 if (irg == get_const_code_irg())
265 ent = get_irg_entity(irg);
269 if (! ent->param_access)
270 analyze_ent_args(ent);