lower_alloc.c 2.29 KB
Newer Older
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 */

/**
 * @file
 * @brief   Lower (stack-) Alloc nodes to allocate an aligned number of bytes
 * @author  Matthias Braun
 */
#include "lower_alloc.h"
#include "irgwalk.h"
#include "irnode_t.h"
#include "ircons.h"
#include "irgmod.h"
#include "irnodeset.h"

18
static unsigned po2_stack_alignment;
19
20
21
22
23
24
25
26
27
28
29

/**
 * Adjust the size of a node representing a stack alloc to a certain
 * stack_alignment.
 *
 * @param size       the node containing the non-aligned size
 * @param block      the block where new nodes are allocated on
 * @return a node representing the aligned size
 */
static ir_node *adjust_alloc_size(dbg_info *dbgi, ir_node *size, ir_node *block)
{
30
31
32
33
34
35
36
37
38
	/* Example: po2_alignment 4 (align to 16 bytes):
	 *   size = (size+15) & 0xfff...f8 */
	ir_mode   *mode    = get_irn_mode(size);
	ir_graph  *irg     = get_irn_irg(block);
	ir_tarval *allone  = get_mode_all_one(mode);
	ir_tarval *shr     = tarval_shr_unsigned(allone, po2_stack_alignment);
	ir_tarval *mask    = tarval_shl_unsigned(shr, po2_stack_alignment);
	ir_tarval *invmask = tarval_not(mask);
	ir_node   *addv    = new_r_Const(irg, invmask);
39
	ir_node   *add     = new_rd_Add(dbgi, block, size, addv);
40
	ir_node   *maskc   = new_r_Const(irg, mask);
41
	ir_node   *and     = new_rd_And(dbgi, block, add, maskc);
42
	return and;
43
44
45
46
47
}

/**
 * lower Alloca nodes to allocate "bytes" instead of a certain type
 */
48
static void lower_node(ir_node *node, void *data)
49
{
50
	bool *changed = (bool*)data;
51
	if (!is_Alloc(node))
52
53
		return;

54
55
56
57
58
59
60
	ir_node  *const size     = get_Alloc_size(node);
	ir_node  *const mem      = get_Alloc_mem(node);
	ir_node  *const block    = get_nodes_block(node);
	dbg_info *const dbgi     = get_irn_dbg_info(node);
	ir_node  *const new_size = adjust_alloc_size(dbgi, size, block);
	ir_node  *const new_node
		= new_rd_Alloc(dbgi, block, mem, new_size, 1);
61
62
63

	if (new_node != node)
		exchange(node, new_node);
64
	*changed = true;
65
66
}

67
void lower_alloc(ir_graph *irg, unsigned new_po2_stack_alignment)
68
{
69
70
71
72
	if (new_po2_stack_alignment == 0)
		return;

	po2_stack_alignment = new_po2_stack_alignment;
73
	bool changed = false;
74
	irg_walk_graph(irg, NULL, lower_node, &changed);
75
76
77

	confirm_irg_properties(irg, changed ? IR_GRAPH_PROPERTIES_CONTROL_FLOW
	                                    : IR_GRAPH_PROPERTIES_ALL);
78
}