summaryrefslogtreecommitdiffhomepage
path: root/ir/be/betranshlp.h
blob: 9b509610331cefc66cb436828bf69bb1a76c3632 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*
 * This file is part of libFirm.
 * Copyright (C) 2012 University of Karlsruhe.
 */

/**
 * @file
 * @brief    Helper functions for code selection.
 * @author   Matthias Braun, Michael Beck
 * @date     14.06.2007
 */
#ifndef FIRM_BE_BETRANSHLP_H
#define FIRM_BE_BETRANSHLP_H

#include <stdbool.h>
#include <stdint.h>

#include "be_types.h"
#include "firm_types.h"
#include "irmode_t.h"

/**
 * A callback to pre-transform some nodes before the transformation starts.
 */
typedef void (arch_pretrans_nodes)(ir_graph*);

/**
 * The type of a transform function.
 */
typedef ir_node *(be_transform_func)(ir_node *node);

/**
 * Calls transformation function for given node and marks it visited.
 */
ir_node *be_transform_node(ir_node *node);

/**
 * Transform the node's block.
 */
ir_node *be_transform_nodes_block(ir_node const *node);

/**
 * Creates a new phi (needs some special handling since we can't transform
 * all predecessors yet).
 */
ir_node *be_transform_phi(ir_node *node, const arch_register_req_t *req);

/**
 * Duplicate a node during transformation.
 */
ir_node *be_duplicate_node(ir_node *node);

ir_node *be_gen_Proj_default(ir_node *node);

/** clear transform functions and sets some virtual nodes like
 * Start, Sync, Pin to the duplication transformer */
void be_start_transform_setup(void);

/** register a transform function for a specific node type */
void be_set_transform_function(ir_op *op, be_transform_func func);

/** register a transform function for a Proj attached to a specific node */
void be_set_transform_proj_function(ir_op *pred_op, be_transform_func func);

/**
 * Associate an old node with a transformed node. Uses link field.
 */
void be_set_transformed_node(ir_node *old_node, ir_node *new_node);

/**
 * returns true if the node is already transformed
 */
bool be_is_transformed(const ir_node *node);

/**
 * enqueue all inputs into the transform queue.
 */
void be_enqueue_operands(ir_node *node);

/**
 * Transform a graph. Transformers must be registered first.
 */
void be_transform_graph(ir_graph *irg, arch_pretrans_nodes *func);

typedef bool (*upper_bits_clean_func)(const ir_node *node, ir_mode *mode);

/**
 * register a test function for be_upper_bits_clean for a specific node
 * type.
 */
void be_set_upper_bits_clean_function(ir_op *op, upper_bits_clean_func func);

/**
 * returns true if it is assured, that the upper bits of a node are "clean"
 * which means for a 16 or 8 bit value, that the upper bits in the register
 * are 0 for unsigned and a copy of the last significant bit for signed
 * numbers.
 */
bool be_upper_bits_clean(const ir_node *node, ir_mode *mode);

/**
 * returns true if node is the root pattern of a (left) rotation.
 * The root @p node must be an Add or Or node.
 */
bool be_pattern_is_rotl(const ir_node *node, ir_node **left, ir_node **right);

/**
 * maps an operation which potentially produces exceptions (like Div,Mod) to a
 * runtime call.
 */
void be_map_exc_node_to_runtime_call(ir_node *node, ir_mode *res_mode,
                                     ir_entity *runtime_entity,
                                     long pn_M, long pn_X_regular,
                                     long pn_X_except, long pn_res);

typedef struct be_stack_change_t be_stack_change_t;

typedef struct be_stack_env_t {
	be_stack_change_t *changes;
} be_stack_env_t;

/**
 * Initialize a stack change environment.
 *
 * Usually architectures use a machine stack to store local information, e.g.
 * arguments of function calls.  This concept is not present in the middleend,
 * appears during code selection and causes chains of stack changes, which may
 * not be interleaved.  To prevent interleaving, the instruction scheduler has
 * to be aware of these chains or a total order has to be established for them
 * beforehand.  This interface performs the latter.
 * The change chains are recorded during code selection and wired afterwards.
 *
 * @param env  The stack environment to initialize.
 */
void be_stack_init(be_stack_env_t *env);

/**
 * Record one stack change chain.
 *
 * @param before  The first node of the stack change chain.
 * @param pos     The operand number of the stack of @p before.
 * @param after   The stack value produced by this change, or NULL for the last
 *                change, e.g. return.
 */
void be_stack_record_chain(be_stack_env_t *env, ir_node *before, unsigned pos, ir_node *after);

/**
 * Wire all recorded stack change chains within each block and free all recorded
 * information.
 *
 * @param env  The stack environment.
 */
void be_stack_finish(be_stack_env_t *env);

ir_entity **be_collect_parameter_entities(ir_graph *irg);

/**
 * In case where a parameter is transmitted via register but someone takes its
 * address a store to the frame which can be references is necessary.
 * This function can be used as a preprocessing phase before transformation to
 * do this. The assumption is that all parameter_entities on the stackframe
 * without an offset need such stores.
 */
void be_add_parameter_entity_stores(ir_graph *irg);

void be_add_parameter_entity_stores_list(ir_graph *irg, unsigned n_entities,
                                         ir_entity **entities);

uint32_t be_get_tv_bits32(ir_tarval *tv, unsigned offset);

/**
 * Skip integer truncations.
 *
 * @param node         the node
 * @param single_user  only skip, if a down-conv has a single user
 * @return the node after skipping down-convs
 */
ir_node *be_skip_downconv(ir_node *node, bool single_user);

/** Skip all signedness convs */
ir_node *be_skip_sameconv(ir_node *node);

bool be_match_immediate(ir_node const *node, ir_tarval **tarval_out,
                        ir_entity **entity_out, unsigned *reloc_kind_out);

ir_node *be_make_Sync(ir_node *block, int arity, ir_node **ins);

/**
 * Returns true if mode should be stored in a general purpose register
 */
static inline bool be_mode_needs_gp_reg(ir_mode *const mode)
{
	return get_mode_arithmetic(mode) == irma_twos_complement;
}

/**
 * Finds number of output value of a node which is constrained to a single
 * specific register.
 */
unsigned be_get_out_for_reg(ir_node const *node, arch_register_t const *reg);

#endif