lower_hl.c 4.57 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
 */

/**
 * @file
 * @brief   Lower some High-level constructs, moved from the firmlower.
 * @author  Boris Boesler, Goetz Lindenmaier, Michael Beck
 */
11
#include "lowering.h"
12
13
14
#include "irmode_t.h"
#include "irnode_t.h"
#include "entity_t.h"
15
#include "typerep.h"
16
17
18
19
20
21
22
#include "irprog_t.h"
#include "ircons.h"
#include "irhooks.h"
#include "irgmod.h"
#include "irgwalk.h"

/**
23
 * Lower a Sel node. Do not touch Sels accessing entities on the frame type.
24
 */
25
26
static void lower_sel(ir_node *sel)
{
27
28
29
	ir_node *const ptr          = get_Sel_ptr(sel);
	ir_type *const type         = get_Sel_type(sel);
	ir_type *const element_type = get_array_element_type(type);
30
	unsigned const element_size = get_type_size(element_type);
31
32
33
34

	ir_node *newn;
	if (element_size == 0) {
		newn = ptr;
Matthias Braun's avatar
Matthias Braun committed
35
	} else {
36
37
38
39
40
41
		dbg_info *const dbg         = get_irn_dbg_info(sel);
		ir_node  *const index       = get_Sel_index(sel);
		ir_node  *const bl          = get_nodes_block(sel);
		ir_mode  *const mode        = get_irn_mode(sel);
		ir_mode  *const offset_mode = get_reference_offset_mode(mode);
		ir_node  *const idx_conv    = new_rd_Conv(dbg, bl, index, offset_mode);
42
43
44
45
46
47

		ir_node  *scaled_index;
		if (element_size == 1) {
			scaled_index = idx_conv;
		} else {
			ir_graph *const irg      = get_irn_irg(sel);
48
			ir_node  *const el_size  = new_rd_Const_long(dbg, irg, offset_mode,
49
			                                             element_size);
50
			scaled_index = new_rd_Mul(dbg, bl, idx_conv, el_size);
51
		}
52
		newn = new_rd_Add(dbg, bl, ptr, scaled_index);
53
	}
54

55
56
	hook_lower(sel);
	exchange(sel, newn);
Matthias Braun's avatar
Matthias Braun committed
57
}
58

59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/**
 * Lower a Member node. Do not touch Members accessing entities on the frame
 * type.
 */
static void lower_member(ir_node *member)
{
	ir_graph  *const irg   = get_irn_irg(member);
	ir_entity *const ent   = get_Member_entity(member);
	ir_type   *const owner = get_entity_owner(ent);
	/* we can only replace Members when the owner type layout is decided. */
	if (get_type_state(owner) != layout_fixed)
		return;

	int       const offset = get_entity_offset(ent);
	ir_node  *const ptr   = get_Member_ptr(member);

	/* replace Member by add(ptr, const(ent.offset)) */
	ir_node *newn;
	if (offset != 0) {
78
79
80
81
82
83
		dbg_info *const dbg         = get_irn_dbg_info(member);
		ir_mode  *const mode        = get_irn_mode(member);
		ir_node  *const bl          = get_nodes_block(member);
		ir_mode  *const mode_offset = get_reference_offset_mode(mode);
		ir_node  *const cnst
			= new_r_Const_long(irg, mode_offset, offset);
84
		newn = new_rd_Add(dbg, bl, ptr, cnst);
85
86
87
88
89
90
91
92
	} else {
		newn = ptr;
	}

	hook_lower(member);
	exchange(member, newn);
}

93
94
95
96
97
98
99
100
101
102
static void replace_by_Const(ir_node *const node, long const value)
{
	ir_graph *const irg  = get_irn_irg(node);
	ir_mode  *const mode = get_irn_mode(node);
	ir_node  *const newn = new_r_Const_long(irg, mode, value);
	/* run the hooks */
	hook_lower(node);
	exchange(node, newn);
}

103
/**
104
 * Lower an Offset node.
105
 */
106
static void lower_offset(ir_node *const offset)
107
{
108
	/* rewrite the Offset node by a Const node */
109
	ir_entity *const ent = get_Offset_entity(offset);
110
	assert(get_type_state(get_entity_type(ent)) == layout_fixed);
111
	replace_by_Const(offset, get_entity_offset(ent));
112
}
113

114
/**
115
 * Lower an Align node.
116
 */
117
static void lower_align(ir_node *const align)
118
{
119
	ir_type *const tp = get_Align_type(align);
120
	assert(get_type_state(tp) == layout_fixed);
121
	/* rewrite the Align node by a Const node */
122
	replace_by_Const(align, get_type_alignment(tp));
123
}
124

125
126
127
128
129
130
131
132
/**
 * Lower a Size node.
 */
static void lower_size(ir_node *const size)
{
	ir_type *const tp = get_Size_type(size);
	assert(get_type_state(tp) == layout_fixed);
	/* rewrite the Size node by a Const node */
133
	replace_by_Const(size, get_type_size(tp));
134
}
135
136
137
138

/**
 * lowers IR-nodes, called from walker
 */
139
140
static void lower_irnode(ir_node *irn, void *env)
{
Matthias Braun's avatar
Matthias Braun committed
141
	(void) env;
142
	switch (get_irn_opcode(irn)) {
143
	case iro_Align:  lower_align(irn);  break;
144
	case iro_Member: lower_member(irn); break;
145
146
147
148
	case iro_Offset: lower_offset(irn); break;
	case iro_Sel:    lower_sel(irn);    break;
	case iro_Size:   lower_size(irn);   break;
	default:         break;
149
	}
150
}
151

152
void lower_highlevel_graph(ir_graph *irg)
153
{
154
	/* Finally: lower Offset/TypeConst-size and Sel nodes, unaligned Load/Stores. */
Michael Beck's avatar
Michael Beck committed
155
	irg_walk_graph(irg, NULL, lower_irnode, NULL);
156
157

	confirm_irg_properties(irg, IR_GRAPH_PROPERTIES_CONTROL_FLOW);
158
}
Michael Beck's avatar
Michael Beck committed
159

Michael Beck's avatar
Michael Beck committed
160
161
162
/*
 * does the same as lower_highlevel() for all nodes on the const code irg
 */
163
164
void lower_const_code(void)
{
165
	walk_const_code(NULL, lower_irnode, NULL);
166
}
167
168
169
170
171
172
173
174

void lower_highlevel()
{
	foreach_irp_irg(i, irg) {
		lower_highlevel_graph(irg);
	}
	lower_const_code();
}