2 * This file is part of libFirm.
3 * Copyright (C) 2012 University of Karlsruhe.
8 * @brief Lower (stack-) Alloc nodes to allocate an aligned number of bytes
9 * @author Matthias Braun
13 #include "lower_alloc.h"
19 #include "irnodeset.h"
21 static bool lower_constant_sizes;
22 static unsigned stack_alignment;
23 static long addr_delta;
24 static ir_nodeset_t transformed;
27 * Adjust the size of a node representing a stack alloc to a certain
30 * @param size the node containing the non-aligned size
31 * @param block the block where new nodes are allocated on
32 * @return a node representing the aligned size
34 static ir_node *adjust_alloc_size(dbg_info *dbgi, ir_node *size, ir_node *block)
41 if (stack_alignment <= 1)
43 if (is_Const(size) && !lower_constant_sizes)
46 mode = get_irn_mode(size);
47 tv = new_tarval_from_long(stack_alignment-1, mode);
48 irg = get_Block_irg(block);
49 mask = new_r_Const(irg, tv);
50 size = new_rd_Add(dbgi, block, size, mask, mode);
52 tv = new_tarval_from_long(-(long)stack_alignment, mode);
53 mask = new_r_Const(irg, tv);
54 size = new_rd_And(dbgi, block, size, mask, mode);
58 static void transform_Proj_Alloc(ir_node *node)
69 /* we might need a result adjustment */
72 if (get_Proj_proj(node) != pn_Alloc_res)
74 if (ir_nodeset_contains(&transformed, node))
77 alloc = get_Proj_pred(node);
78 dbgi = get_irn_dbg_info(alloc);
79 irg = get_irn_irg(node);
80 block = get_nodes_block(node);
81 delta = new_r_Const_long(irg, mode_P, addr_delta);
82 dummy = new_r_Dummy(irg, mode_P);
83 add = new_rd_Add(dbgi, block, dummy, delta, mode_P);
86 new_proj = new_r_Proj(alloc, mode_P, pn_Alloc_res);
87 set_Add_left(add, new_proj);
88 ir_nodeset_insert(&transformed, new_proj);
92 * lower Alloca nodes to allocate "bytes" instead of a certain type
94 static void lower_alloca_free(ir_node *node, void *data)
109 ir_where_alloc where;
111 if (is_Alloc(node)) {
112 type = get_Alloc_type(node);
113 } else if (is_Free(node)) {
114 type = get_Free_type(node);
115 } else if (is_Proj(node)) {
116 ir_node *proj_pred = get_Proj_pred(node);
117 if (is_Alloc(proj_pred)) {
118 transform_Proj_Alloc(node);
124 if (ir_nodeset_contains(&transformed, node))
127 ir_nodeset_insert(&transformed, node);
128 size = get_type_size_bytes(type);
129 if (is_unknown_type(type))
131 if (size == 1 && stack_alignment <= 1)
134 if (is_Alloc(node)) {
135 count = get_Alloc_count(node);
136 mem = get_Alloc_mem(node);
137 where = get_Alloc_where(node);
139 count = get_Free_count(node);
140 mem = get_Free_mem(node);
141 where = get_Free_where(node);
143 mode = get_irn_mode(count);
144 block = get_nodes_block(node);
145 irg = get_irn_irg(node);
146 szconst = new_r_Const_long(irg, mode, (long)size);
147 mul = new_r_Mul(block, count, szconst, mode);
148 dbgi = get_irn_dbg_info(node);
149 new_size = adjust_alloc_size(dbgi, mul, block);
150 new_type = get_unknown_type();
151 if (is_Alloc(node)) {
152 new_node = new_rd_Alloc(dbgi, block, mem, new_size, new_type, where);
154 ir_node *ptr = get_Free_ptr(node);
156 = new_rd_Free(dbgi, block, mem, ptr, new_size, new_type, where);
158 ir_nodeset_insert(&transformed, new_node);
160 if (new_node != node)
161 exchange(node, new_node);
164 void lower_alloc(ir_graph *irg, unsigned new_stack_alignment, bool lower_consts,
167 if (!is_po2(stack_alignment))
168 panic("stack alignment not a power of 2");
169 addr_delta = new_addr_delta;
170 stack_alignment = new_stack_alignment;
171 lower_constant_sizes = lower_consts;
172 ir_nodeset_init(&transformed);
173 irg_walk_graph(irg, lower_alloca_free, NULL, NULL);
174 ir_nodeset_destroy(&transformed);