]>
Commit | Line | Data |
---|---|---|
cf2d1b38 | 1 | /* Header file for tree data flow functions. |
23a5b65a | 2 | Copyright (C) 2013-2014 Free Software Foundation, Inc. |
cf2d1b38 AM |
3 | |
4 | This file is part of GCC. | |
5 | ||
6 | GCC is free software; you can redistribute it and/or modify it under | |
7 | the terms of the GNU General Public License as published by the Free | |
8 | Software Foundation; either version 3, or (at your option) any later | |
9 | version. | |
10 | ||
11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 | for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GCC; see the file COPYING3. If not see | |
18 | <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #ifndef GCC_TREE_DFA_H | |
21 | #define GCC_TREE_DFA_H | |
22 | ||
23 | extern void renumber_gimple_stmt_uids (void); | |
24 | extern void renumber_gimple_stmt_uids_in_blocks (basic_block *, int); | |
25 | extern void dump_variable (FILE *, tree); | |
26 | extern void debug_variable (tree); | |
27 | extern void dump_dfa_stats (FILE *); | |
28 | extern void debug_dfa_stats (void); | |
29 | extern tree ssa_default_def (struct function *, tree); | |
30 | extern void set_ssa_default_def (struct function *, tree, tree); | |
31 | extern tree get_or_create_ssa_default_def (struct function *, tree); | |
32 | extern tree get_ref_base_and_extent (tree, HOST_WIDE_INT *, | |
33 | HOST_WIDE_INT *, HOST_WIDE_INT *); | |
34 | extern tree get_addr_base_and_unit_offset (tree, HOST_WIDE_INT *); | |
35 | extern bool stmt_references_abnormal_ssa_name (gimple); | |
36 | extern void dump_enumerated_decls (FILE *, int); | |
37 | ||
38 | /* Returns the base object and a constant BITS_PER_UNIT offset in *POFFSET that | |
39 | denotes the starting address of the memory access EXP. | |
40 | Returns NULL_TREE if the offset is not constant or any component | |
41 | is not BITS_PER_UNIT-aligned. | |
42 | VALUEIZE if non-NULL is used to valueize SSA names. It should return | |
43 | its argument or a constant if the argument is known to be constant. */ | |
44 | /* ??? This is a static inline here to avoid the overhead of the indirect calls | |
45 | to VALUEIZE. But is this overhead really that significant? And should we | |
46 | perhaps just rely on WHOPR to specialize the function? */ | |
47 | ||
48 | static inline tree | |
49 | get_addr_base_and_unit_offset_1 (tree exp, HOST_WIDE_INT *poffset, | |
50 | tree (*valueize) (tree)) | |
51 | { | |
52 | HOST_WIDE_INT byte_offset = 0; | |
53 | ||
54 | /* Compute cumulative byte-offset for nested component-refs and array-refs, | |
55 | and find the ultimate containing object. */ | |
56 | while (1) | |
57 | { | |
58 | switch (TREE_CODE (exp)) | |
59 | { | |
60 | case BIT_FIELD_REF: | |
61 | { | |
62 | HOST_WIDE_INT this_off = TREE_INT_CST_LOW (TREE_OPERAND (exp, 2)); | |
63 | if (this_off % BITS_PER_UNIT) | |
64 | return NULL_TREE; | |
65 | byte_offset += this_off / BITS_PER_UNIT; | |
66 | } | |
67 | break; | |
68 | ||
69 | case COMPONENT_REF: | |
70 | { | |
71 | tree field = TREE_OPERAND (exp, 1); | |
72 | tree this_offset = component_ref_field_offset (exp); | |
73 | HOST_WIDE_INT hthis_offset; | |
74 | ||
75 | if (!this_offset | |
76 | || TREE_CODE (this_offset) != INTEGER_CST | |
77 | || (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)) | |
78 | % BITS_PER_UNIT)) | |
79 | return NULL_TREE; | |
80 | ||
81 | hthis_offset = TREE_INT_CST_LOW (this_offset); | |
82 | hthis_offset += (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)) | |
83 | / BITS_PER_UNIT); | |
84 | byte_offset += hthis_offset; | |
85 | } | |
86 | break; | |
87 | ||
88 | case ARRAY_REF: | |
89 | case ARRAY_RANGE_REF: | |
90 | { | |
91 | tree index = TREE_OPERAND (exp, 1); | |
92 | tree low_bound, unit_size; | |
93 | ||
94 | if (valueize | |
95 | && TREE_CODE (index) == SSA_NAME) | |
96 | index = (*valueize) (index); | |
97 | ||
98 | /* If the resulting bit-offset is constant, track it. */ | |
99 | if (TREE_CODE (index) == INTEGER_CST | |
100 | && (low_bound = array_ref_low_bound (exp), | |
101 | TREE_CODE (low_bound) == INTEGER_CST) | |
102 | && (unit_size = array_ref_element_size (exp), | |
103 | TREE_CODE (unit_size) == INTEGER_CST)) | |
104 | { | |
807e902e | 105 | offset_int woffset |
460d1e22 RS |
106 | = wi::sext (wi::to_offset (index) - wi::to_offset (low_bound), |
107 | TYPE_PRECISION (TREE_TYPE (index))); | |
807e902e KZ |
108 | woffset *= wi::to_offset (unit_size); |
109 | byte_offset += woffset.to_shwi (); | |
cf2d1b38 AM |
110 | } |
111 | else | |
112 | return NULL_TREE; | |
113 | } | |
114 | break; | |
115 | ||
116 | case REALPART_EXPR: | |
117 | break; | |
118 | ||
119 | case IMAGPART_EXPR: | |
120 | byte_offset += TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (exp))); | |
121 | break; | |
122 | ||
123 | case VIEW_CONVERT_EXPR: | |
124 | break; | |
125 | ||
126 | case MEM_REF: | |
127 | { | |
128 | tree base = TREE_OPERAND (exp, 0); | |
129 | if (valueize | |
130 | && TREE_CODE (base) == SSA_NAME) | |
131 | base = (*valueize) (base); | |
132 | ||
133 | /* Hand back the decl for MEM[&decl, off]. */ | |
134 | if (TREE_CODE (base) == ADDR_EXPR) | |
135 | { | |
136 | if (!integer_zerop (TREE_OPERAND (exp, 1))) | |
137 | { | |
807e902e KZ |
138 | offset_int off = mem_ref_offset (exp); |
139 | byte_offset += off.to_short_addr (); | |
cf2d1b38 AM |
140 | } |
141 | exp = TREE_OPERAND (base, 0); | |
142 | } | |
143 | goto done; | |
144 | } | |
145 | ||
146 | case TARGET_MEM_REF: | |
147 | { | |
148 | tree base = TREE_OPERAND (exp, 0); | |
149 | if (valueize | |
150 | && TREE_CODE (base) == SSA_NAME) | |
151 | base = (*valueize) (base); | |
152 | ||
153 | /* Hand back the decl for MEM[&decl, off]. */ | |
154 | if (TREE_CODE (base) == ADDR_EXPR) | |
155 | { | |
156 | if (TMR_INDEX (exp) || TMR_INDEX2 (exp)) | |
157 | return NULL_TREE; | |
158 | if (!integer_zerop (TMR_OFFSET (exp))) | |
159 | { | |
807e902e KZ |
160 | offset_int off = mem_ref_offset (exp); |
161 | byte_offset += off.to_short_addr (); | |
cf2d1b38 AM |
162 | } |
163 | exp = TREE_OPERAND (base, 0); | |
164 | } | |
165 | goto done; | |
166 | } | |
167 | ||
168 | default: | |
169 | goto done; | |
170 | } | |
171 | ||
172 | exp = TREE_OPERAND (exp, 0); | |
173 | } | |
174 | done: | |
175 | ||
176 | *poffset = byte_offset; | |
177 | return exp; | |
178 | } | |
179 | ||
180 | ||
181 | ||
182 | #endif /* GCC_TREE_DFA_H */ |