2 * Copyright (C) 2011 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
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.
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.
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
22 * @brief Lower (stack-) Alloc nodes to allocate an aligned number of bytes
23 * @author Matthias Braun
27 #include "lower_alloc.h"
33 #include "irnodeset.h"
35 static bool lower_constant_sizes;
36 static unsigned stack_alignment;
37 static long addr_delta;
38 static ir_nodeset_t transformed;
41 * Adjust the size of a node representing a stack alloc to a certain
44 * @param size the node containing the non-aligned size
45 * @param block the block where new nodes are allocated on
46 * @return a node representing the aligned size
48 static ir_node *adjust_alloc_size(dbg_info *dbgi, ir_node *size, ir_node *block)
55 if (stack_alignment <= 1)
57 if (is_Const(size) && !lower_constant_sizes)
60 mode = get_irn_mode(size);
61 tv = new_tarval_from_long(stack_alignment-1, mode);
62 irg = get_Block_irg(block);
63 mask = new_r_Const(irg, tv);
64 size = new_rd_Add(dbgi, block, size, mask, mode);
66 tv = new_tarval_from_long(-(long)stack_alignment, mode);
67 mask = new_r_Const(irg, tv);
68 size = new_rd_And(dbgi, block, size, mask, mode);
72 static void transform_Proj_Alloc(ir_node *node)
83 /* we might need a result adjustment */
86 if (get_Proj_proj(node) != pn_Alloc_res)
88 if (ir_nodeset_contains(&transformed, node))
91 alloc = get_Proj_pred(node);
92 dbgi = get_irn_dbg_info(alloc);
93 irg = get_irn_irg(node);
94 block = get_nodes_block(node);
95 delta = new_r_Const_long(irg, mode_P, addr_delta);
96 dummy = new_r_Dummy(irg, mode_P);
97 add = new_rd_Add(dbgi, block, dummy, delta, mode_P);
100 new_proj = new_r_Proj(alloc, mode_P, pn_Alloc_res);
101 set_Add_left(add, new_proj);
102 ir_nodeset_insert(&transformed, new_proj);
106 * lower Alloca nodes to allocate "bytes" instead of a certain type
108 static void lower_alloca_free(ir_node *node, void *data)
123 ir_where_alloc where;
125 if (is_Alloc(node)) {
126 type = get_Alloc_type(node);
127 } else if (is_Free(node)) {
128 type = get_Free_type(node);
129 } else if (is_Proj(node)) {
130 ir_node *proj_pred = get_Proj_pred(node);
131 if (is_Alloc(proj_pred)) {
132 transform_Proj_Alloc(node);
138 if (ir_nodeset_contains(&transformed, node))
141 ir_nodeset_insert(&transformed, node);
142 size = get_type_size_bytes(type);
143 if (type == get_unknown_type())
145 if (size == 1 && stack_alignment <= 1)
148 if (is_Alloc(node)) {
149 count = get_Alloc_count(node);
150 mem = get_Alloc_mem(node);
151 where = get_Alloc_where(node);
153 count = get_Free_count(node);
154 mem = get_Free_mem(node);
155 where = get_Free_where(node);
157 mode = get_irn_mode(count);
158 block = get_nodes_block(node);
159 irg = get_irn_irg(node);
160 szconst = new_r_Const_long(irg, mode, (long)size);
161 mul = new_r_Mul(block, count, szconst, mode);
162 dbgi = get_irn_dbg_info(node);
163 new_size = adjust_alloc_size(dbgi, mul, block);
164 new_type = get_unknown_type();
165 if (is_Alloc(node)) {
166 new_node = new_rd_Alloc(dbgi, block, mem, new_size, new_type, where);
168 ir_node *ptr = get_Free_ptr(node);
170 = new_rd_Free(dbgi, block, mem, ptr, new_size, new_type, where);
172 ir_nodeset_insert(&transformed, new_node);
174 if (new_node != node)
175 exchange(node, new_node);
178 void lower_alloc(ir_graph *irg, unsigned new_stack_alignment, bool lower_consts,
181 if (!is_po2(stack_alignment))
182 panic("lower_alloc only supports stack alignments that are a power of 2");
183 addr_delta = new_addr_delta;
184 stack_alignment = new_stack_alignment;
185 lower_constant_sizes = lower_consts;
186 ir_nodeset_init(&transformed);
187 irg_walk_graph(irg, lower_alloca_free, NULL, NULL);
188 ir_nodeset_destroy(&transformed);