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 * A struct to save if a graph argument with mode reference is
52 #define ACCESS(a) if ((a) == ACC_UNKNOWN) (a) = ACC_ACCESSED
53 #define NOT_ACCESS(a) if ((a) == ACC_UNKNOWN) (a) = ACC_NOT_ACCESSED
56 static void *VISITED = &v;
59 * Walk recursive the successors of a graph argument
60 * with mode reference and mark in the "irg_args" if it will be read,
63 * @param arg The graph argument with mode reference,
64 * that must be checked.
66 static unsigned analyze_arg(ir_node *arg, unsigned bits)
71 /* We must visit a node once to avoid endless recursion.*/
72 set_irn_link(arg, VISITED);
74 for (i = get_irn_n_outs(arg) - 1; i >= 0; --i) {
75 succ = get_irn_out(arg, i);
78 if (get_irn_link(succ) == VISITED)
81 /* We should not walk over the memory edge.*/
82 if (get_irn_mode(succ) == mode_M)
85 /* A addition or subtraction of the argument with output, that
86 isn't with mode reference must not be checked.*/
87 if ((get_irn_op(succ) == op_Add || get_irn_op(succ) == op_Sub) &&
88 !mode_is_reference(get_irn_mode(succ)))
91 /* A Block as successor isn't interesting.*/
92 if (get_irn_op(succ) == op_Block)
95 /* If we reach with the recursion a Call node and our reference
96 isn't the address of this Call we accept that the reference will
97 be read and written if the graph of the method represented by
98 "Call" isn't computed else we analyze that graph. If our
99 reference is the address of this
100 Call node that mean the reference will be read.*/
101 if (get_irn_op(succ) == op_Call) {
102 ir_node *Call_ptr = get_Call_ptr(succ);
105 return bits | ptr_access_read;
106 else if (op_SymConst == get_irn_op(Call_ptr) &&
107 get_SymConst_kind(Call_ptr) == symconst_addr_ent) {
108 entity *meth_ent = get_SymConst_entity(Call_ptr);
110 for (p = get_Call_n_params(succ) - 1; p >= 0; --p){
111 if (get_Call_param(succ, p) == arg) {
112 /* an arg can be used more than once ! */
113 bits |= get_method_param_access(meth_ent, p);
117 bits |= ptr_access_rw;
119 else if (get_irn_op(succ) == op_Store) {
120 /* We have reached a Store node => the reference is written. */
121 bits |= ptr_access_write;
123 else if (get_irn_op(succ) == op_Load) {
124 /* We have reached a Load node => the reference is read. */
125 bits |= ptr_access_read;
128 /* If we know that, the argument will be read and written, we
129 can break the recursion.*/
130 if (bits == ptr_access_rw)
131 return ptr_access_rw;
133 bits = analyze_arg(succ, bits);
135 set_irn_link(arg, NULL);
141 * Check if a argument of the ir graph with mode
142 * reference is read, write or both.
144 * @param irg The ir graph to analyze.
146 static void analyze_ent_args(entity *ent)
149 ir_node *irg_args, *arg;
157 mtp = get_entity_type(ent);
158 nparams = get_method_n_params(mtp);
160 ent->param_access = NEW_ARR_F(ptr_access_kind, nparams);
162 /* If the method haven't parameters we have
167 irg = get_entity_irg(ent);
170 /* if we could not determine the graph, set RW access */
171 for (i = nparams - 1; i >= 0; --i)
172 ent->param_access[i] =
173 is_Pointer_type(get_method_param_type(mtp, i)) ? ptr_access_rw : ptr_access_none;
178 /* Call algorithm that computes the out edges */
179 if (get_irg_outs_state(irg) != outs_consistent)
182 irg_args = get_irg_args(irg);
184 /* A array to save the information for each argument with
186 NEW_ARR_A(rw_info_t, rw_info, nparams);
188 /* We initialize the element with UNKNOWN state. */
189 for (i = nparams - 1; i >= 0; --i) {
190 rw_info[i].read = ACC_UNKNOWN;
191 rw_info[i].write = ACC_UNKNOWN;
194 /* search for arguments with mode reference
196 for (i = get_irn_n_outs(irg_args) - 1; i >= 0; --i) {
197 arg = get_irn_out(irg_args, i);
198 arg_mode = get_irn_mode(arg);
199 proj_nr = get_Proj_proj(arg);
201 if (mode_is_reference(arg_mode)) {
202 bits = analyze_arg(arg, ptr_access_none);
204 if (bits & ptr_access_read)
205 ACCESS(rw_info[proj_nr].read);
206 if (bits & ptr_access_write)
207 ACCESS(rw_info[proj_nr].write);
211 /* set all unknown values to NOT_ACCESSED */
212 for (i = nparams - 1; i >= 0; --i) {
213 NOT_ACCESS(rw_info[i].read);
214 NOT_ACCESS(rw_info[i].write);
216 ent->param_access[i] = (rw_info[i].read == ACC_ACCESSED ? ptr_access_read : ptr_access_none) |
217 (rw_info[i].write == ACC_ACCESSED ? ptr_access_write : ptr_access_none);
220 printf("%s:\n", get_entity_name(ent));
221 for (i = 0; i < nparams; ++i) {
222 if (is_Pointer_type(get_method_param_type(mtp, i)))
223 printf("Pointer Arg %i wird %s %s\n", i,
224 ent->param_access[i] & ptr_access_read ? "gelesen" : "",
225 ent->param_access[i] & ptr_access_write ? "geschrieben" : "");
230 * Compute for a method with pointer parameter(s)
231 * if they will be read or written.
233 ptr_access_kind get_method_param_access(entity *ent, int pos)
235 type *mtp = get_entity_type(ent);
236 int is_variadic = get_method_variadicity(mtp) == variadicity_variadic;
238 assert(0 <= pos && (is_variadic || pos < get_method_n_params(mtp)));
240 if (ent->param_access) {
241 if (pos < ARR_LEN(ent->param_access))
242 return ent->param_access[pos];
244 return ptr_access_rw;
247 analyze_ent_args(ent);
249 if (pos < ARR_LEN(ent->param_access))
250 return ent->param_access[pos];
252 return ptr_access_rw;
256 * Analyze how pointer arguments of a given
257 * ir graph are accessed.
259 * @param irg The ir graph to analyze.
261 void analyze_irg_args(ir_graph *irg)
265 if (irg == get_const_code_irg())
268 ent = get_irg_entity(irg);
272 if (! ent->param_access)
273 analyze_ent_args(ent);