fix some warnings, represent mode size as unsigned value
[libfirm] / ir / ana / irmemory.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief    Memory disambiguator
23  * @author   Michael Beck
24  * @date     27.12.2006
25  * @version  $Id$
26  */
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <stdlib.h>
32
33 #include "irnode_t.h"
34 #include "irgraph_t.h"
35 #include "irprog_t.h"
36 #include "irmemory.h"
37 #include "irflag.h"
38 #include "hashptr.h"
39 #include "irflag.h"
40 #include "irouts.h"
41 #include "irgwalk.h"
42 #include "irprintf.h"
43 #include "debug.h"
44
45 /** The debug handle. */
46 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
47
48 /** The source language specific language disambiguator function. */
49 static DISAMBIGUATOR_FUNC language_disambuigator = NULL;
50
51 /** The global memory disambiguator options. */
52 static unsigned global_mem_disamgig_opt = aa_opt_no_opt;
53
54 /* Returns a human readable name for an alias relation. */
55 const char *get_ir_alias_relation_name(ir_alias_relation rel) {
56 #define X(a) case a: return #a
57         switch (rel) {
58         X(no_alias);
59         X(may_alias);
60         X(sure_alias);
61         default: assert(0); return "UNKNOWN";
62         }
63 #undef X
64 }
65
66 /* Get the memory disambiguator options for a graph. */
67 unsigned get_irg_memory_disambiguator_options(ir_graph *irg) {
68         unsigned opt = irg->mem_disambig_opt;
69         if (opt & aa_opt_inherited)
70                 return global_mem_disamgig_opt;
71         return opt;
72 }  /* get_irg_memory_disambiguator_options */
73
74 /*  Set the memory disambiguator options for a graph. */
75 void set_irg_memory_disambiguator_options(ir_graph *irg, unsigned options) {
76         irg->mem_disambig_opt = options & ~aa_opt_inherited;
77 }  /* set_irg_memory_disambiguator_options */
78
79 /* Set the global disambiguator options for all graphs not having local options. */
80 void set_irp_memory_disambiguator_options(unsigned options) {
81         global_mem_disamgig_opt = options;
82 }  /* set_irp_memory_disambiguator_options */
83
84 /**
85  * Find the base address and entity of an Sel node.
86  *
87  * @param sel  the node
88  * @param pEnt after return points to the base entity.
89  *
90  * @return the base address.
91  */
92 static ir_node *find_base_adr(ir_node *sel, ir_entity **pEnt) {
93         ir_node *ptr = get_Sel_ptr(sel);
94
95         while (is_Sel(ptr)) {
96                 sel = ptr;
97                 ptr = get_Sel_ptr(sel);
98         }
99         *pEnt = get_Sel_entity(sel);
100         return ptr;
101 }  /* find_base_adr */
102
103 /**
104  * Check if a given Const node is greater or equal a given size.
105  *
106  * @return no_alias if the Const is greater, may_alias else
107  */
108 static ir_alias_relation check_const(ir_node *cns, int size) {
109         tarval *tv = get_Const_tarval(cns);
110         tarval *tv_size;
111
112         if (size == 0)
113                 return tarval_is_null(tv) ? may_alias : no_alias;
114         tv_size = new_tarval_from_long(size, get_tarval_mode(tv));
115         return tarval_cmp(tv_size, tv) & (pn_Cmp_Eq|pn_Cmp_Lt) ? no_alias : may_alias;
116 }  /* check_const */
117
118 /**
119  * Treat idx1 and idx2 as integer indexes and check if they differ always more than size.
120  *
121  * @return sure_alias iff idx1 == idx2
122  *         no_alias iff they ALWAYS differ more than size
123  *         may_alias else
124  */
125 static ir_alias_relation different_index(ir_node *idx1, ir_node *idx2, int size) {
126         if (idx1 == idx2)
127                 return sure_alias;
128         if (is_Const(idx1) && is_Const(idx2)) {
129                 /* both are const, we can compare them */
130                 tarval *tv1 = get_Const_tarval(idx1);
131                 tarval *tv2 = get_Const_tarval(idx2);
132                 tarval *tv, *tv_size;
133                 ir_mode *m1, *m2;
134
135                 if (size == 0)
136                         return tv1 == tv2 ? sure_alias : no_alias;
137
138                 /* arg, modes may be different */
139                 m1 = get_tarval_mode(tv1);
140                 m2 = get_tarval_mode(tv2);
141                 if (m1 != m2) {
142                         int size = get_mode_size_bits(m1) - get_mode_size_bits(m2);
143
144                         if (size < 0) {
145                                 /* m1 is a small mode, cast up */
146                                 m1 = mode_is_signed(m1) ? find_signed_mode(m2) : find_unsigned_mode(m2);
147                                 if (m1 == NULL) {
148                                         /* should NOT happen, but if it does we give up here */
149                                         return may_alias;
150                                 }
151                                 tv1 = tarval_convert_to(tv1, m1);
152                         } else if (size > 0) {
153                                 /* m2 is a small mode, cast up */
154                                 m2 = mode_is_signed(m2) ? find_signed_mode(m1) : find_unsigned_mode(m1);
155                                 if (m2 == NULL) {
156                                         /* should NOT happen, but if it does we give up here */
157                                         return may_alias;
158                                 }
159                                 tv2 = tarval_convert_to(tv2, m2);
160                         }
161                         /* here the size should be identical, check for signed */
162                         if (get_mode_sign(m1) != get_mode_sign(m2)) {
163                                 /* find the signed */
164                                 if (mode_is_signed(m2)) {
165                                         tarval *t = tv1;
166                                         ir_mode *tm = m1;
167                                         tv1 = tv2; m1 = m2;
168                                         tv2 = t;   m2 = tm;
169                                 }
170
171                                 /* m1 is now the signed one */
172                                 if (tarval_cmp(tv1, get_tarval_null(m1)) & (pn_Cmp_Eq|pn_Cmp_Gt)) {
173                                         /* tv1 is signed, but >= 0, simply cast into unsigned */
174                                         tv1 = tarval_convert_to(tv1, m2);
175                                 } else {
176                                         tv_size = new_tarval_from_long(size, m2);
177
178                                         if (tarval_cmp(tv2, tv_size) & (pn_Cmp_Eq|pn_Cmp_Gt)) {
179                                                 /* tv1 is negative and tv2 >= tv_size, so the difference is bigger than size */
180                                                 return no_alias;
181                                         }
182                                         /* tv_size > tv2, so we can subtract without overflow */
183                                         tv2 = tarval_sub(tv_size, tv2);
184
185                                         /* tv1 is < 0, so we can negate it */
186                                         tv1 = tarval_neg(tv1);
187
188                                         /* cast it into unsigned. for two-complement it does the right thing for MIN_INT */
189                                         tv1 = tarval_convert_to(tv1, m2);
190
191                                         /* now we can compare without overflow */
192                                         return tarval_cmp(tv1, tv2) & (pn_Cmp_Eq|pn_Cmp_Gt) ? no_alias : may_alias;
193                                 }
194                         }
195                 }
196                 if (tarval_cmp(tv1, tv2) == pn_Cmp_Gt) {
197                         tarval *t = tv1;
198                         tv1 = tv2;
199                         tv2 = t;
200                 }
201                 /* tv1 is now the "smaller" one */
202                 tv      = tarval_sub(tv2, tv1);
203                 tv_size = new_tarval_from_long(size, get_tarval_mode(tv));
204                 return tarval_cmp(tv_size, tv) & (pn_Cmp_Eq|pn_Cmp_Lt) ? no_alias : may_alias;
205         }
206
207         /* Note: we rely here on the fact that normalization puts constants on the RIGHT side */
208         if (is_Add(idx1)) {
209                 ir_node *l1 = get_Add_left(idx1);
210                 ir_node *r1 = get_Add_right(idx1);
211
212                 if (l1 == idx2) {
213                         /* x + c == y */
214                         if (is_Const(r1))
215                                 return check_const(r1, size);
216                 }
217                 if (is_Add(idx2)) {
218                         /* both are Adds, check if they are of x + a == x + b kind */
219                         ir_node *l2 = get_Add_left(idx2);
220                         ir_node *r2 = get_Add_right(idx2);
221
222                         if (l1 == l2)
223                                 return different_index(r1, r2, size);
224                         else if (l1 == r2)
225                                 return different_index(r1, l2, size);
226                         else if (r1 == r2)
227                                 return different_index(l1, l2, size);
228                         else if (r1 == l2)
229                                 return different_index(l1, r2, size);
230                 }
231         }
232         if (is_Add(idx2)) {
233                 ir_node *l2 = get_Add_left(idx2);
234                 ir_node *r2 = get_Add_right(idx2);
235
236                 if (l2 == idx1) {
237                         /* x + c == y */
238                         if (is_Const(r2))
239                                 return check_const(r2, size);
240                 }
241         }
242
243         if (is_Sub(idx1)) {
244                 ir_node *l1 = get_Sub_left(idx1);
245                 ir_node *r1 = get_Sub_right(idx1);
246
247                 if (l1 == idx2) {
248                         /* x - c == y */
249                         if (is_Const(r1))
250                                 return check_const(r1, size);
251                 }
252
253                 if (is_Sub(idx2)) {
254                         /* both are Subs, check if they are of x - a == x - b kind */
255                         ir_node *l2 = get_Sub_left(idx2);
256
257                         if (l1 == l2) {
258                                 ir_node *r2 = get_Sub_right(idx2);
259                                 return different_index(r1, r2, size);
260                         }
261                 }
262         }
263         if (is_Sub(idx2)) {
264                 ir_node *l2 = get_Sub_left(idx2);
265                 ir_node *r2 = get_Sub_right(idx2);
266
267                 if (l2 == idx1) {
268                         /* x - c == y */
269                         if (is_Const(r2))
270                                 return check_const(r2, size);
271                 }
272
273         }
274         return may_alias;
275 }  /* different_index */
276
277 /**
278  * Two Sel addresses have the same base address, check if there offsets are different.
279  *
280  * @param adr1  The first address.
281  * @param adr2  The second address.
282  */
283 static ir_alias_relation different_sel_offsets(ir_node *sel1, ir_node *sel2) {
284         /* seems to be broken */
285         (void) sel1;
286         (void) sel2;
287 #if 0
288         ir_entity *ent1 = get_Sel_entity(sel1);
289         ir_entity *ent2 = get_Sel_entity(sel2);
290         int i, check_arr = 0;
291
292         if (ent1 == ent2)
293                 check_arr = 1;
294         else {
295                 ir_type *tp1 = get_entity_type(ent1);
296                 ir_type *tp2 = get_entity_type(ent2);
297
298                 if (tp1 == tp2)
299                         check_arr = 1;
300                 else if (get_type_state(tp1) == layout_fixed && get_type_state(tp2) == layout_fixed &&
301                          get_type_size_bits(tp1) == get_type_size_bits(tp2))
302                         check_arr = 1;
303         }
304         if (check_arr) {
305                 /* we select an entity of same size, check for indexes */
306                 int n = get_Sel_n_indexs(sel1);
307                 int have_no = 0;
308
309                 if (n > 0 && n == get_Sel_n_indexs(sel2)) {
310                         /* same non-zero number of indexes, an array access, check */
311                         for (i = 0; i < n; ++i) {
312                                 ir_node *idx1 = get_Sel_index(sel1, i);
313                                 ir_node *idx2 = get_Sel_index(sel2, i);
314                                 ir_alias_relation res = different_index(idx1, idx2, 0); /* we can safely IGNORE the size here if it's at least >0 */
315
316                                 if (res == may_alias)
317                                         return may_alias;
318                                 else if (res == no_alias)
319                                         have_no = 1;
320                         }
321                         /* if we have at least one no_alias, there is no alias relation, else we have sure */
322                         return have_no > 0 ? no_alias : sure_alias;
323                 }
324         }
325 #endif
326         return may_alias;
327 }  /* different_sel_offsets */
328
329 /**
330  * Determine the alias relation by checking if adr1 and adr2 are pointer
331  * to different type.
332  *
333  * @param adr1    The first address.
334  * @param adr2    The second address.
335  */
336 static ir_alias_relation different_types(ir_node *adr1, ir_node *adr2)
337 {
338         ir_entity *ent1 = NULL, *ent2 = NULL;
339
340         if (is_SymConst_addr_ent(adr1))
341                 ent1 = get_SymConst_entity(adr1);
342         else if (is_Sel(adr1))
343                 ent1 = get_Sel_entity(adr1);
344
345         if (is_SymConst_addr_ent(adr2))
346                 ent2 = get_SymConst_entity(adr2);
347         else if (is_Sel(adr2))
348                 ent2 = get_Sel_entity(adr2);
349
350         if (ent1 != NULL && ent2 != NULL) {
351                 ir_type *tp1 = get_entity_type(ent1);
352                 ir_type *tp2 = get_entity_type(ent2);
353
354                 if (tp1 != tp2) {
355                         if (is_Pointer_type(tp1) && is_Pointer_type(tp2)) {
356                                 /* do deref until no pointer types are found */
357                                 do {
358                                         tp1 = get_pointer_points_to_type(tp1);
359                                         tp2 = get_pointer_points_to_type(tp2);
360                                 } while (is_Pointer_type(tp1) && is_Pointer_type(tp2));
361                         }
362
363                         if (get_type_tpop(tp1) != get_type_tpop(tp2)) {
364                                 /* different type structure */
365                                 return no_alias;
366                         }
367                         if (is_Class_type(tp1)) {
368                                 /* check class hierarchy */
369                                 if (! is_SubClass_of(tp1, tp2) &&
370                                         ! is_SubClass_of(tp2, tp1))
371                                         return no_alias;
372                         } else {
373                                 /* different types */
374                                 return no_alias;
375                         }
376                 }
377         }
378         return may_alias;
379 }  /* different_types */
380
381 /**
382  * Check if an offset is a constant and these constant is bigger or equal
383  * than a given size.
384  */
385 static int check_const_offset(ir_node *offset, int size) {
386         ir_mode *mode = get_irn_mode(offset);
387
388         /* ok, we found an offset, check for constant */
389         if (is_Const(offset) && mode_is_int(mode)) {
390                 tarval *tv = new_tarval_from_long(size, mode);
391
392                 /* size <= offset ? */
393                 if (tarval_cmp(tv, get_Const_tarval(offset)) & (pn_Cmp_Eq|pn_Cmp_Lt))
394                         return 1;
395         }
396         return 0;
397 }  /* check_const_offset */
398
399 /**
400  * Check if we can determine that the two pointers always have an offset bigger then size
401  */
402 static ir_alias_relation _different_pointer(ir_node *adr1, ir_node *adr2, int size) {
403         int found = 0;
404
405         if (is_Add(adr1)) {
406                 /* first address is the result of a pointer addition */
407                 ir_node *l1 = get_Add_left(adr1);
408                 ir_node *r1 = get_Add_right(adr1);
409
410                 if (l1 == adr2) {
411                         found = check_const_offset(r1, size);
412                 } else if (r1 == adr2) {
413                         found = check_const_offset(l1, size);
414                 } else if (is_Add(adr2)) {
415                         /* second address is the result of a pointer addition */
416                         ir_node *l2 = get_Add_left(adr2);
417                         ir_node *r2 = get_Add_right(adr2);
418
419                         if (l1 == l2) {
420                                 return _different_pointer(r1, r2, size);
421                         } else if (l1 == r2) {
422                                 return _different_pointer(r1, l2, size);
423                         } else if (r1 == l2) {
424                                 return _different_pointer(l1, r2, size);
425                         } else if (r1 == r2) {
426                                 return _different_pointer(l1, l2, size);
427                         }
428                 }
429         } else if (is_Add(adr2)) {
430                 /* second address is the result of a pointer addition */
431                 ir_node *l2 = get_Add_left(adr2);
432                 ir_node *r2  = get_Add_right(adr2);
433
434                 if (l2 == adr1) {
435                         found = check_const_offset(r2, size);
436                 } else if (r2 == adr1) {
437                         found = check_const_offset(l2, size);
438                 }
439         } else {
440                 return different_index(adr1, adr2, size);
441         }
442         return found ? no_alias : may_alias;
443 }  /* _different_pointer */
444
445 /**
446  * Check if we can determine that the two pointers always have an offset bigger then the maximum size of mode1, mode2
447  */
448 static ir_alias_relation different_pointer(ir_node *adr1, ir_mode *mode1, ir_node *adr2, ir_mode *mode2) {
449         int size = get_mode_size_bytes(mode1);
450         int n    = get_mode_size_bytes(mode2);
451
452         if (n > size)
453                 size = n;
454         return _different_pointer(adr1, adr2, size);
455 }  /* different_pointer */
456
457 /**
458  * Returns non-zero if a node is a routine parameter.
459  *
460  * @param node  the node to test
461  */
462 static int is_arg_Proj(ir_node *node) {
463         if (! is_Proj(node))
464                 return 0;
465         node = get_Proj_pred(node);
466         if (! is_Proj(node))
467                 return 0;
468         return pn_Start_T_args == get_Proj_proj(node) && is_Start(get_Proj_pred(node));
469 }  /* is_arg_Proj */
470
471 /**
472  * Returns true if an address represents a global variable.
473  *
474  * @param irn  the node representing the address
475  */
476 static INLINE int is_global_var(ir_node *irn) {
477         return is_SymConst_addr_ent(irn);
478 }  /* is_global_var */
479
480 /**
481  * Determine the alias relation between two addresses.
482  */
483 static ir_alias_relation _get_alias_relation(
484         ir_graph *irg,
485         ir_node *adr1, ir_mode *mode1,
486         ir_node *adr2, ir_mode *mode2)
487 {
488         ir_opcode op1, op2;
489         ir_entity *ent1, *ent2;
490         unsigned options;
491
492         if (! get_opt_alias_analysis())
493                 return may_alias;
494
495         if (adr1 == adr2)
496                 return sure_alias;
497
498         options = get_irg_memory_disambiguator_options(irg);
499
500         /* The Armageddon switch */
501         if (options & aa_opt_no_alias)
502                 return no_alias;
503
504         /* Two save some code, sort the addresses by its id's. Beware, this
505            might break some things, so better check here. */
506         assert(iro_SymConst < iro_Sel && iro_Sel < iro_Proj && "Code dependence broken");
507         op1 = get_irn_opcode(adr1);
508         op2 = get_irn_opcode(adr2);
509
510         if (op1 > op2) {
511                 ir_node *t = adr1;
512                 ir_mode *m = mode1;
513                 adr1  = adr2;
514                 mode1 = mode2;
515                 adr2  = t;
516                 mode2 = m;
517         }
518
519         if (is_global_var(adr1)) {
520                 /* first address is a global variable */
521
522                 if (is_global_var(adr2)) {
523                         /* both addresses are global variables and we know
524                            they are different (R1 a) */
525                         if (get_SymConst_entity(adr1) != get_SymConst_entity(adr2))
526                                 return no_alias;
527                         else {
528                                 /* equal entity addresses */
529                                 return sure_alias;
530                         }
531                 }
532                 if (is_Sel(adr2)) {
533                         ir_node *base2 = find_base_adr(adr2, &ent2);
534
535                         if (is_global_var(base2)) {
536                                 /* base2 address is a global var (R1 a) */
537                                 if (adr1 != base2)
538                                         return no_alias;
539                         } else if (base2 == get_irg_frame(irg)) {
540                                 /* the second one is a local variable so they are always
541                                    different (R1 b) */
542                                 return no_alias;
543                         } else if (base2 == get_irg_tls(irg)) {
544                                 /* the second one is a TLS variable so they are always
545                                    different (R1 c) */
546                                 return no_alias;
547                         }
548                 }
549
550                 /* Here we are: the first is a global var, the second some pointer. */
551                 ent1 = get_SymConst_entity(adr1);
552                 if (get_entity_address_taken(ent1) == ir_address_not_taken) {
553                         /* The address of the global variable was never taken, so
554                            the pointer cannot match (R2). */
555                         return no_alias;
556                 }
557         } else if (is_Sel(adr1)) {
558                 /* the first address is a Sel */
559                 ir_node *base1 = find_base_adr(adr1, &ent1);
560
561                 if (base1 == get_irg_frame(irg)) {
562                         /* first is a local variable ent1 */
563                         if (is_Sel(adr2)) {
564                                 /* the second address is a Sel */
565                                 ir_node *base2 = find_base_adr(adr2, &ent2);
566
567                                 if (base1 == base2) {
568                                         /* identical bases: both are local variables */
569                                         if (ent1 != ent2) {
570                                                 /* both addresses are local variables and we know
571                                                they are different (R1 a) */
572                                                 return no_alias;
573                                         } else {
574                                                 /* same local var */
575                                                 return different_sel_offsets(adr1, adr2);
576                                         }
577                                 } else if (base2 == get_irg_tls(irg)) {
578                                         /* the second one is a TLS variable so they are always
579                                        different (R1 d) */
580                                         return no_alias;
581                                 } else if (is_arg_Proj(base2)) {
582                                         /* the second one is an offset from a parameter so they are
583                                            always different (R1 e) */
584                                         return no_alias;
585                                 }
586                         } else if (is_arg_Proj(adr2)) {
587                                 /* a local variable and a parameter are always different (R1 e) */
588                                 return no_alias;
589                         }
590                 } else if (base1 == get_irg_tls(irg)) {
591                         /* the first is a TLS variable */
592                         if (is_Sel(adr2)) {
593                                 /* the second address is a Sel */
594                                 ir_node *base2 = find_base_adr(adr2, &ent2);
595
596                                 if (base1 == base2)
597                                         if (ent1 != ent2) {
598                                                 /* both addresses are tls variables and we know
599                                                they are different (R1 a) */
600                                         } else {
601                                                 /* same tls var */
602                                                 return different_sel_offsets(adr1, adr2);
603                                         }
604                                 else if (base2 == get_irg_frame(irg)) {
605                                         /* the first one is a tls variable, the second a local one,
606                                            they are different (R1 d) */
607                                         return no_alias;
608                                 }
609                         }
610                 } else if (is_arg_Proj(base1)) {
611                         /* the first one is an offset from a parameter */
612                         if (is_Sel(adr2)) {
613                                 /* the second address is a Sel */
614                                 ir_node *base2 = find_base_adr(adr2, &ent2);
615
616                                 if (base2 == get_irg_frame(irg)) {
617                                         /* the second one is a local variable so they are always
618                                        different (R1 e) */
619                                         return no_alias;
620                                 }
621                         }
622                 } else if (is_global_var(base1)) {
623                         /* the first one is a global variable */
624                         ent1 = get_SymConst_entity(base1);
625                         if (is_Sel(adr2)) {
626                                 /* the second address is a Sel */
627                                 ir_node *base2 = find_base_adr(adr2, &ent2);
628
629                                 if (base1 == base2) {
630                                         /* same global var */
631                                         return different_sel_offsets(adr1, adr2);
632                                 }
633                                 else if (base2 == get_irg_frame(irg)) {
634                                         /* the second one is a local variable so they are always
635                                        different (R1 a) */
636                                         return no_alias;
637                                 } else if (base2 == get_irg_tls(irg)) {
638                                         /* the second one is a TLS variable so they are always
639                                        different (R1 a) */
640                                         return no_alias;
641                                 } else if (is_arg_Proj(base2)) {
642                                         if (get_entity_address_taken(ent1) == ir_address_not_taken) {
643                                                 /* The address of the global variable was never taken, so
644                                                    the pointer cannot match (R2). */
645                                                 return no_alias;
646                                         }
647                                 } else if (is_global_var(base2)) {
648                                         ent2 = get_SymConst_entity(base2);
649                                         /* both addresses are global variables and we know
650                                            they are different (R1 a) */
651                                         if (ent1 != ent2)
652                                                 return no_alias;
653                                 }
654                         }
655                 }
656         } else {
657                 /* some pointers, check if they have the same base buf constant offset */
658                 ir_alias_relation rel = different_pointer(adr1, mode1, adr2, mode2);
659                 if (rel != may_alias)
660                         return rel;
661         }
662
663
664         if (options & aa_opt_type_based) { /* Type based alias analysis */
665                 ir_alias_relation rel;
666
667                 if (options & aa_opt_byte_type_may_alias) {
668                         if (get_mode_size_bits(mode1) == 8 || get_mode_size_bits(mode2) == 8) {
669                                 /* One of the modes address a byte. Assume a may_alias and leave
670                                    the type based check. */
671                                 goto leave_type_based_alias;
672                         }
673                 }
674                 /* cheap check: If the mode sizes did not match, the types MUST be different */
675                 if (get_mode_size_bits(mode1) != get_mode_size_bits(mode2))
676                         return no_alias;
677
678                 /* cheap test: if only one is a reference mode, no alias */
679                 if (mode_is_reference(mode1) != mode_is_reference(mode2))
680                         return no_alias;
681
682                 /* try rule R5 */
683                 rel = different_types(adr1, adr2);
684                 if (rel != may_alias)
685                         return rel;
686 leave_type_based_alias:;
687         }
688
689         /* do we have a language specific memory disambiguator? */
690         if (language_disambuigator) {
691                 ir_alias_relation rel = (*language_disambuigator)(irg, adr1, mode1, adr2, mode2);
692                 if (rel != may_alias)
693                         return rel;
694         }
695
696         /* access points-to information here */
697         return may_alias;
698 }  /* _get_alias_relation */
699
700 /*
701  * Determine the alias relation between two addresses.
702  */
703 ir_alias_relation get_alias_relation(
704         ir_graph *irg,
705         ir_node *adr1, ir_mode *mode1,
706         ir_node *adr2, ir_mode *mode2)
707 {
708         ir_alias_relation rel = _get_alias_relation(irg, adr1, mode1, adr2, mode2);
709         DB((dbg, LEVEL_1, "alias(%+F, %+f) = %s\n", adr1, adr2, get_ir_alias_relation_name(rel)));
710         return rel;
711 }  /* get_alias_relation */
712
713 /* Set a source language specific memory disambiguator function. */
714 void set_language_memory_disambiguator(DISAMBIGUATOR_FUNC func) {
715         language_disambuigator = func;
716 }  /* set_language_memory_disambiguator */
717
718 /** The result cache for the memory disambiguator. */
719 static set *result_cache = NULL;
720
721 /** An entry in the relation cache. */
722 typedef struct mem_disambig_entry {
723         ir_node           *adr1;    /**< The first address. */
724         ir_node           *adr2;    /**< The second address. */
725         ir_alias_relation result;   /**< The alias relation result. */
726 } mem_disambig_entry;
727
728 #define HASH_ENTRY(adr1, adr2)  (HASH_PTR(adr1) ^ HASH_PTR(adr2))
729
730 /**
731  * Compare two relation cache entries.
732  */
733 static int cmp_mem_disambig_entry(const void *elt, const void *key, size_t size) {
734         const mem_disambig_entry *p1 = elt;
735         const mem_disambig_entry *p2 = key;
736         (void) size;
737
738         return p1->adr1 == p2->adr1 && p1->adr2 == p2->adr2;
739 }  /* cmp_mem_disambig_entry */
740
741 /**
742  * Initialize the relation cache.
743  */
744 void mem_disambig_init(void) {
745         result_cache = new_set(cmp_mem_disambig_entry, 8);
746 }  /* mem_disambig_init */
747
748 /*
749  * Determine the alias relation between two addresses.
750  */
751 ir_alias_relation get_alias_relation_ex(
752         ir_graph *irg,
753         ir_node *adr1, ir_mode *mode1,
754         ir_node *adr2, ir_mode *mode2)
755 {
756         mem_disambig_entry key, *entry;
757
758         if (! get_opt_alias_analysis())
759                 return may_alias;
760
761         if (get_irn_opcode(adr1) > get_irn_opcode(adr2)) {
762                 ir_node *t = adr1;
763                 adr1 = adr2;
764                 adr2 = t;
765         }
766
767         key.adr1 = adr1;
768         key.adr2 = adr2;
769         entry = set_find(result_cache, &key, sizeof(key), HASH_ENTRY(adr1, adr2));
770         if (entry)
771                 return entry->result;
772
773         key.result = get_alias_relation(irg, adr1, mode1, adr2, mode2);
774
775         set_insert(result_cache, &key, sizeof(key), HASH_ENTRY(adr1, adr2));
776         return key.result;
777 }  /* get_alias_relation_ex */
778
779 /* Free the relation cache. */
780 void mem_disambig_term(void) {
781         if (result_cache) {
782                 del_set(result_cache);
783                 result_cache = NULL;
784         }
785 }  /* mem_disambig_term */
786
787 /**
788  * Check the mode of a Load/Store with the mode of the entity
789  * that is accessed.
790  * If the mode of the entity and the Load/Store mode do not match, we
791  * have the bad reinterpret case:
792  *
793  * int i;
794  * char b = *(char *)&i;
795  *
796  * We do NOT count this as one value and return address_taken
797  * in that case.
798  * However, we support an often used case. If the mode is two-complement
799  * we allow casts between signed/unsigned.
800  *
801  * @param mode     the mode of the Load/Store
802  * @param ent_mode the mode of the accessed entity
803  *
804  * @return non-zero if the Load/Store is a hidden cast, zero else
805  */
806 static int is_hidden_cast(ir_mode *mode, ir_mode *ent_mode) {
807         if (ent_mode != mode) {
808                 if (ent_mode == NULL ||
809                         get_mode_size_bits(ent_mode) != get_mode_size_bits(mode) ||
810                         get_mode_sort(ent_mode) != get_mode_sort(mode) ||
811                         get_mode_arithmetic(ent_mode) != irma_twos_complement ||
812                         get_mode_arithmetic(mode) != irma_twos_complement)
813                         return 1;
814         }
815         return 0;
816 }  /* is_hidden_cast */
817
818 /**
819  * Determine the address_taken state of a node (or it's successor Sels).
820  *
821  * @param irn  the node
822  */
823 static ir_address_taken_state find_address_taken_state(ir_node *irn) {
824         int     i, j;
825         ir_mode *emode, *mode;
826         ir_node *value;
827         ir_entity *ent;
828
829         for (i = get_irn_n_outs(irn) - 1; i >= 0; --i) {
830                 ir_node *succ = get_irn_out(irn, i);
831
832                 switch (get_irn_opcode(succ)) {
833                 case iro_Load:
834                         /* check if this load is not a hidden conversion */
835                         mode = get_Load_mode(succ);
836                         ent = is_SymConst(irn) ? get_SymConst_entity(irn) : get_Sel_entity(irn);
837                         emode = get_type_mode(get_entity_type(ent));
838                         if (is_hidden_cast(mode, emode))
839                                 return ir_address_taken;
840                         break;
841
842                 case iro_Store:
843                         /* check that the node is not the Store's value */
844                         value = get_Store_value(succ);
845                         if (value == irn)
846                                 return ir_address_taken;
847                         /* check if this Store is not a hidden conversion */
848                         mode = get_irn_mode(value);
849                         ent = is_SymConst(irn) ? get_SymConst_entity(irn) : get_Sel_entity(irn);
850                         emode = get_type_mode(get_entity_type(ent));
851                         if (is_hidden_cast(mode, emode))
852                                 return ir_address_taken;
853                         break;
854
855                 case iro_Sel: {
856                         /* Check the successor of irn. */
857                         ir_address_taken_state res = find_address_taken_state(succ);
858                         if (res != ir_address_not_taken)
859                                 return res;
860                         break;
861                 }
862
863                 case iro_Call:
864                         /* Only the call address is not an address taker but
865                            this is an uninteresting case, so we ignore it here. */
866                         for (j = get_Call_n_params(succ) - 1; j >= 0; --j) {
867                                 ir_node *param = get_Call_param(succ, j);
868                                 if (param == irn)
869                                         return ir_address_taken;
870                         }
871                         break;
872
873                 default:
874                         /* another op, the address may be taken */
875                         return ir_address_taken_unknown;
876                 }
877         }
878         /* All successors finished, the address is not taken. */
879         return ir_address_not_taken;
880 }  /* find_address_taken_state */
881
882 /**
883  * Update the "address taken" flag of all frame entities.
884  */
885 static void analyse_irg_address_taken(ir_graph *irg) {
886         ir_type *ft = get_irg_frame_type(irg);
887         ir_node *irg_frame;
888         int i;
889
890         /* set initial state to not_taken, as this is the "smallest" state */
891         for (i = get_class_n_members(ft) - 1; i >= 0; --i) {
892                 ir_entity *ent = get_class_member(ft, i);
893
894                 set_entity_address_taken(ent, ir_address_not_taken);
895         }
896
897         assure_irg_outs(irg);
898
899         irg_frame = get_irg_frame(irg);
900
901         for (i = get_irn_n_outs(irg_frame) - 1; i >= 0; --i) {
902                 ir_node *succ = get_irn_out(irg_frame, i);
903                 ir_address_taken_state state;
904
905             if (is_Sel(succ)) {
906                         ir_entity *ent = get_Sel_entity(succ);
907
908                         if (get_entity_address_taken(ent) == ir_address_taken)
909                                 continue;
910
911                         state = find_address_taken_state(succ);
912                         if (state > get_entity_address_taken(ent))
913                                 set_entity_address_taken(ent, state);
914                 }
915         }
916         /* now computed */
917         irg->adr_taken_state = ir_address_taken_computed;
918 }  /* analyse_address_taken */
919
920 /* Returns the current address taken state of the graph. */
921 ir_address_taken_computed_state get_irg_address_taken_state(const ir_graph *irg) {
922         return irg->adr_taken_state;
923 }  /* get_irg_address_taken_state */
924
925 /* Sets the current address taken state of the graph. */
926 void set_irg_address_taken_state(ir_graph *irg, ir_address_taken_computed_state state) {
927         irg->adr_taken_state = state;
928 }  /* set_irg_address_taken_state */
929
930 /* Assure that the address taken flag is computed for the given graph. */
931 void assure_irg_address_taken_computed(ir_graph *irg) {
932         if (irg->adr_taken_state == ir_address_taken_not_computed)
933                 analyse_irg_address_taken(irg);
934 }  /* assure_irg_address_taken_computed */
935
936
937 /**
938  * Initialize the address_taken flag for a global type like type.
939  */
940 static void init_taken_flag(ir_type * tp) {
941         int i;
942
943         /* All external visible entities are at least
944            ir_address_taken_unknown. This is very conservative. */
945         for (i = get_compound_n_members(tp) - 1; i >= 0; --i) {
946                 ir_entity *ent = get_compound_member(tp, i);
947                 ir_address_taken_state state;
948
949                 state = get_entity_visibility(ent) == visibility_external_visible ?
950                                 ir_address_taken_unknown : ir_address_not_taken ;
951                 set_entity_address_taken(ent, state);
952         }
953 }  /* init_taken_flag */
954
955 /**
956  * Mark all entities used in the initializer for the given entity as address taken
957  */
958 static void check_initializer(ir_entity *ent) {
959         ir_node *n;
960         int i;
961
962         /* do not check uninitialized values */
963         if (get_entity_variability(ent) == variability_uninitialized)
964                 return;
965
966         /* Beware: Methods initialized with "themself". This does not count as a taken
967            address. */
968         if (is_Method_type(get_entity_type(ent)))
969                 return;
970
971         if (is_atomic_entity(ent)) {
972                 /* let's check if it's an address */
973                 n = get_atomic_ent_value(ent);
974                 if (is_SymConst_addr_ent(n)) {
975                         ir_entity *ent = get_SymConst_entity(n);
976                         set_entity_address_taken(ent, ir_address_taken);
977                 }
978         } else {
979                 for (i = get_compound_ent_n_values(ent) - 1; i >= 0; --i) {
980                         n = get_compound_ent_value(ent, i);
981
982                         /* let's check if it's an address */
983                         if (is_SymConst_addr_ent(n)) {
984                                 ir_entity *ent = get_SymConst_entity(n);
985                                 set_entity_address_taken(ent, ir_address_taken);
986                         }
987                 }
988         }
989 }  /* check_initializer */
990
991
992 /**
993  * Mark all entities used in initializers as address taken
994  */
995 static void check_initializers(ir_type *tp) {
996         int i;
997
998         for (i = get_compound_n_members(tp) - 1; i >= 0; --i) {
999                 ir_entity *ent = get_compound_member(tp, i);
1000
1001                 check_initializer(ent);
1002         }
1003 }  /* check_initializers */
1004
1005 #ifdef DEBUG_libfirm
1006 /**
1007  * Print the address taken state of all entities of a given type for debugging.
1008  */
1009 static void print_address_taken_state(ir_type *tp) {
1010         int i;
1011         for (i = get_compound_n_members(tp) - 1; i >= 0; --i) {
1012                 ir_entity *ent = get_compound_member(tp, i);
1013                 ir_address_taken_state state = get_entity_address_taken(ent);
1014
1015                 if (state != ir_address_not_taken) {
1016                         assert(ir_address_not_taken <= (int) state && state <= ir_address_taken);
1017                         ir_printf("%+F: %s\n", ent, get_address_taken_state_name(state));
1018                 }
1019         }
1020 }  /* print_address_taken_state */
1021 #endif /* DEBUG_libfirm */
1022
1023 /**
1024  * Post-walker: check for global entity address
1025  */
1026 static void check_global_address(ir_node *irn, void *env) {
1027         ir_node *tls = env;
1028         ir_entity *ent;
1029         ir_address_taken_state state;
1030
1031         if (is_SymConst_addr_ent(irn)) {
1032                 /* A global. */
1033                 ent = get_SymConst_entity(irn);
1034         } else if (is_Sel(irn) && get_Sel_ptr(irn) == tls) {
1035                 /* A TLS variable. */
1036                 ent = get_Sel_entity(irn);
1037         } else
1038                 return;
1039
1040         if (get_entity_address_taken(ent) >= ir_address_taken) {
1041                 /* Already at the maximum. */
1042                 return;
1043         }
1044         state = find_address_taken_state(irn);
1045         if (state > get_entity_address_taken(ent))
1046                 set_entity_address_taken(ent, state);
1047 }  /* check_global_address */
1048
1049 /**
1050  * Update the "address taken" flag of all global entities.
1051  */
1052 static void analyse_irp_globals_address_taken(void) {
1053         int i;
1054
1055         FIRM_DBG_REGISTER(dbg, "firm.ana.irmemory");
1056
1057         init_taken_flag(get_glob_type());
1058         init_taken_flag(get_tls_type());
1059
1060         check_initializers(get_glob_type());
1061         check_initializers(get_tls_type());
1062
1063         for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
1064                 ir_graph *irg = get_irp_irg(i);
1065
1066                 assure_irg_outs(irg);
1067                 irg_walk_graph(irg, NULL, check_global_address, get_irg_tls(irg));
1068         }
1069
1070 #ifdef DEBUG_libfirm
1071         if (firm_dbg_get_mask(dbg) & LEVEL_1) {
1072                 print_address_taken_state(get_glob_type());
1073                 print_address_taken_state(get_tls_type());
1074         }
1075 #endif /* DEBUG_libfirm */
1076
1077         /* now computed */
1078         irp->globals_adr_taken_state = ir_address_taken_computed;
1079 }  /* analyse_irp_globals_address_taken */
1080
1081 /* Returns the current address taken state of the globals. */
1082 ir_address_taken_computed_state get_irp_globals_address_taken_state(void) {
1083         return irp->globals_adr_taken_state;
1084 }  /* get_irp_globals_address_taken_state */
1085
1086 /* Sets the current address taken state of the graph. */
1087 void set_irp_globals_address_taken_state(ir_address_taken_computed_state state) {
1088         irp->globals_adr_taken_state = state;
1089 }  /* set_irg_address_taken_state */
1090
1091 /* Assure that the address taken flag is computed for the globals. */
1092 void assure_irp_globals_address_taken_computed(void) {
1093         if (irp->globals_adr_taken_state == ir_address_taken_not_computed)
1094                 analyse_irp_globals_address_taken();
1095 }  /* assure_irp_globals_address_taken_computed */
1096
1097
1098 #include <adt/pmap.h>
1099 #include "typerep.h"
1100
1101 DEBUG_ONLY(static firm_dbg_module_t *dbgcall = NULL;)
1102
1103 /** Maps method types to cloned method types. */
1104 static pmap *mtp_map;
1105
1106 /**
1107  * Clone a method type if not already cloned.
1108  */
1109 static ir_type *clone_type_and_cache(ir_type *tp) {
1110         static ident *prefix = NULL;
1111         ir_type *res;
1112         pmap_entry *e = pmap_find(mtp_map, tp);
1113
1114         if (e)
1115                 return e->value;
1116
1117         if (prefix == NULL)
1118                 prefix = new_id_from_chars("C", 1);
1119
1120         res = clone_type_method(tp, prefix);
1121         pmap_insert(mtp_map, tp, res);
1122         DB((dbgcall, LEVEL_2, "cloned type %+F into %+F\n", tp, res));
1123
1124         return res;
1125 }  /* clone_type_and_cache */
1126
1127 /**
1128  * Copy the calling conventions from the entities to the call type.
1129  */
1130 static void update_calls_to_private(ir_node *call, void *env) {
1131         (void) env;
1132         if (is_Call(call)) {
1133                 ir_node *ptr = get_Call_ptr(call);
1134
1135                 if (is_SymConst(ptr)) {
1136                         ir_entity *ent = get_SymConst_entity(ptr);
1137                         ir_type *ctp = get_Call_type(call);
1138
1139                         if (get_entity_additional_properties(ent) & mtp_property_private) {
1140                                 if ((get_method_additional_properties(ctp) & mtp_property_private) == 0) {
1141                                         ctp = clone_type_and_cache(ctp);
1142                                         set_method_additional_property(ctp, mtp_property_private);
1143                                         set_Call_type(call, ctp);
1144                                         DB((dbgcall, LEVEL_1, "changed call to private method %+F\n", ent));
1145                                 }
1146                         }
1147                 }
1148         }
1149 }  /* update_calls_to_private */
1150
1151 /* Mark all private methods, i.e. those of which all call sites are known. */
1152 void mark_private_methods(void) {
1153         int i;
1154         int changed = 0;
1155
1156         FIRM_DBG_REGISTER(dbgcall, "firm.opt.cc");
1157
1158         assure_irp_globals_address_taken_computed();
1159
1160         mtp_map = pmap_create();
1161
1162         /* first step: change the calling conventions of the local non-escaped entities */
1163         for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
1164                 ir_graph               *irg = get_irp_irg(i);
1165                 ir_entity              *ent = get_irg_entity(irg);
1166                 ir_address_taken_state state = get_entity_address_taken(ent);
1167
1168                 if (get_entity_visibility(ent) == visibility_local &&
1169                     state == ir_address_not_taken) {
1170                         ir_type *mtp = get_entity_type(ent);
1171
1172                         set_entity_additional_property(ent, mtp_property_private);
1173                         DB((dbgcall, LEVEL_1, "found private method %+F\n", ent));
1174                         if ((get_method_additional_properties(mtp) & mtp_property_private) == 0) {
1175                                 /* need a new type */
1176                                 mtp = clone_type_and_cache(mtp);
1177                                 set_entity_type(ent, mtp);
1178                                 set_method_additional_property(mtp, mtp_property_private);
1179                                 changed = 1;
1180                         }
1181                 }
1182         }
1183
1184         if (changed)
1185                 all_irg_walk(NULL, update_calls_to_private, NULL);
1186
1187         pmap_destroy(mtp_map);
1188 }  /* mark_private_methods */