2 * Copyright (C) 1995-2008 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 The codegenerator (transform FIRM Conv nodes into ppc FIRM)
23 * @author Moritz Kroll, Jens Mueller
31 #include "irgraph_t.h"
35 #include "iredges_t.h"
41 #include "../benode_t.h"
42 #include "bearch_ppc32_t.h"
44 #include "ppc32_nodes_attr.h"
45 //#include "../arch/archop.h" /* we need this for Min and Max nodes */
46 #include "ppc32_transform_conv.h"
47 #include "ppc32_new_nodes.h"
48 #include "ppc32_map_regs.h"
50 #include "gen_ppc32_regalloc_if.h"
60 ir_node *current_block;
66 * Conv walker initialization
68 void ppc32_init_conv_walk(void)
75 static ir_node *own_gen_convert_call(ppc32_transform_env_t *env, ir_node *op, const char *funcname,
76 ir_mode *from_mode, ir_mode *to_mode)
79 ir_entity *method_ent;
81 ir_node *call, *callee, *call_results;
85 method_type = new_type_method(new_id_from_str("convert_call_type"), 1, 1);
86 set_method_param_type(method_type, 0, new_type_primitive(new_id_from_str("conv_param"), from_mode));
87 set_method_res_type(method_type, 0, new_type_primitive(new_id_from_str("conv_result"), to_mode));
89 method_ent = new_entity(get_glob_type(), new_id_from_str(funcname), method_type);
90 callee = new_rd_SymConst_addr_ent(env->dbg, env->irg, mode_P_code, method_ent, method_type);
91 call = new_rd_Call(env->dbg, env->irg, env->block, memory, callee, 1, in, method_type);
92 call_results = new_rd_Proj(env->dbg, env->irg, env->block, call, mode_T, pn_Call_T_result);
93 memory = new_rd_Proj(env->dbg, env->irg, env->block, call, mode_M, pn_Call_M_regular);
95 return new_rd_Proj(env->dbg, env->irg, env->block, call_results, to_mode, 0);
99 * Transforms a Conv node.
101 * @param mod the debug module
102 * @param block the block the new node should belong to
103 * @param node the ir Conv node
105 * @param mode node mode
106 * @return the created ppc Conv node
108 static ir_node *gen_Conv(ppc32_transform_env_t *env, ir_node *op) {
109 ir_mode *from_mode = get_irn_mode(get_irn_n(env->irn,0));
110 ir_mode *to_mode = env->mode;
111 ir_modecode from_modecode=get_mode_modecode(from_mode);
112 ir_modecode to_modecode=get_mode_modecode(to_mode);
114 switch(from_modecode){
116 op = new_rd_Conv(env->dbg, env->irg, env->block, op, mode_D);
121 if (mode_is_signed(to_mode)) // Float to integer
123 ir_node *fctiw = new_rd_ppc32_fCtiw(env->dbg, env->irg, env->block, op, from_mode);
124 ir_node *stfd = new_rd_ppc32_Stfd(env->dbg, env->irg, env->block, get_irg_frame(env->irg),
126 ir_node *storememproj = new_rd_Proj(env->dbg, env->irg, env->block, stfd, mode_M, pn_Store_M);
127 ir_node *lwz = new_rd_ppc32_Lwz(env->dbg, env->irg, env->block, get_irg_frame(env->irg),
129 set_ppc32_frame_entity(stfd, memslot);
130 set_ppc32_offset_mode(stfd, ppc32_ao_Lo16); // TODO: only allows a 16-bit offset on stack
131 set_ppc32_frame_entity(lwz, memslot);
132 set_ppc32_offset_mode(stfd, ppc32_ao_Lo16); // TODO: only allows a 16-bit offset on stack
133 memory = new_rd_Proj(env->dbg, env->irg, env->block, lwz, mode_M, pn_Store_M);
134 res = new_rd_Proj(env->dbg, env->irg, env->block, lwz, to_mode, pn_Load_res);
139 res = own_gen_convert_call(env, op, "conv_double_to_unsigned_int", mode_D, mode_Iu);
148 return new_rd_Conv(env->dbg, env->irg, env->block, res, to_mode);
159 op = new_rd_Conv(env->dbg, env->irg, env->block, op, mode_Is);
161 return own_gen_convert_call(env, op, (to_mode == mode_D) ? "conv_int_to_double" : "conv_int_to_single", mode_Is, to_mode);
166 op = new_rd_Conv(env->dbg, env->irg, env->block, op, mode_Iu);
168 return own_gen_convert_call(env, op, (to_mode == mode_D) ? "conv_unsigned_int_to_double": "conv_unsigned_int_to_single", mode_Iu, to_mode);
176 fprintf(stderr, "Mode for Conv not supported: %s -> %s\n", get_mode_name(from_mode), get_mode_name(to_mode));
183 int search_from_node_in_block(ir_node *from, ir_node *to)
185 int n = get_irn_arity(from), i;
188 ir_node *pred = get_irn_n(from, i);
189 if(pred==to) return 1;
190 if(get_irn_n(pred, -1)==current_block)
192 if(search_from_node_in_block(pred, to)) return 1;
198 int nodes_dependency_order(ir_node **a, ir_node **b)
200 if(search_from_node_in_block(*a,*b)) return 1;
201 if(search_from_node_in_block(*b,*a)) return -1;
205 void finalize_block(ppc32_code_gen_t *cgenv)
208 ir_node *current_conv;
209 cw_block_attr *attr = current_block->link;
210 ppc32_transform_env_t tenv;
212 if(!attr->conv_count) return;
216 ir_type *frame_type = get_irg_frame_type(cgenv->irg);
217 memslot = frame_alloc_area(frame_type, get_mode_size_bytes(mode_D), 4, 0);
220 attr->convs = xmalloc(attr->conv_count * sizeof(ir_node *));
222 for (i = 0, current_conv = attr->first_conv; i < attr->conv_count; i++, current_conv = current_conv->link)
224 attr->convs[i] = current_conv;
227 qsort(attr->convs, attr->conv_count, sizeof(ir_node *),
228 (int (*)(const void *, const void *)) nodes_dependency_order);
230 tenv.block = current_block;
231 tenv.irg = current_ir_graph;
232 DEBUG_ONLY(tenv.mod = cgenv->mod;)
234 memory = get_irg_no_mem(current_ir_graph);
235 for(i = 0; i < attr->conv_count; i++)
237 tenv.dbg = get_irn_dbg_info(attr->convs[i]);
238 tenv.irn = attr->convs[i];
239 tenv.mode = get_irn_mode(attr->convs[i]);
241 exchange(attr->convs[i], gen_Conv(&tenv, get_Conv_op(attr->convs[i])));
245 void init_block(void)
247 cw_block_attr *attr = xmalloc(sizeof(cw_block_attr));
248 attr->first_conv = NULL;
249 attr->convs = NULL; /* attr->convs is set in finalize_block() */
250 attr->conv_count = 0;
251 current_block->link = attr;
255 * Constant generating code
264 /* Compares two (entity, tarval) combinations */
265 static int cmp_tv_ent(const void *a, const void *b, size_t len) {
266 const struct tv_ent *e1 = a;
267 const struct tv_ent *e2 = b;
269 return !(e1->tv == e2->tv);
272 /* Generates a SymConst node for a known FP const */
273 static ir_node *gen_fp_known_symconst(ppc32_transform_env_t *env, tarval *known_const) {
274 static set *const_set = NULL;
275 static ir_type *tp = NULL;
277 struct tv_ent *entry;
283 const_set = new_set(cmp_tv_ent, 10);
285 tp = new_type_primitive(new_id_from_str("const_double_t"), env->mode);
288 key.tv = known_const;
291 entry = set_insert(const_set, &key, sizeof(key), HASH_PTR(key.tv));
295 sprintf(buf, "const_%ld", get_irn_node_nr(env->irn));
296 ent = new_entity(get_glob_type(), new_id_from_str(buf), tp);
298 set_entity_ld_ident(ent, get_entity_ident(ent));
299 set_entity_visibility(ent, visibility_local);
300 set_entity_variability(ent, variability_constant);
301 set_entity_allocation(ent, allocation_static);
303 /* we create a new entity here: It's initialization must resist on the
305 rem = current_ir_graph;
306 current_ir_graph = get_const_code_irg();
307 cnst = new_Const(env->mode, key.tv);
308 current_ir_graph = rem;
310 set_atomic_ent_value(ent, cnst);
312 /* set the entry for hashmap */
316 return new_rd_SymConst_addr_ent(env->dbg, env->irg, ent, tp);
323 * @param env transformation environment
324 * @return the created ppc Const node
326 static ir_node *gen_Const(ppc32_transform_env_t *env) {
327 tarval *tv_const = get_Const_tarval(env->irn);
330 if (mode_is_float(env->mode))
331 constant = new_rd_ppc32_fConst(env->dbg, env->irg, env->block, env->mode);
333 constant = new_rd_ppc32_Const(env->dbg, env->irg, env->block, env->mode);
334 set_ppc32_constant_tarval(constant, tv_const);
339 * Transforms a SymConst.
341 * @param env transformation environment
342 * @return the created ppc SymConst node
344 static ir_node *gen_SymConst(ppc32_transform_env_t *env) {
346 symconst = new_rd_ppc32_SymConst(env->dbg, env->irg, env->block, env->mode);
347 set_ppc32_frame_entity(symconst, get_SymConst_entity(env->irn));
351 /*********************************************************
354 * _ __ ___ __ _ _ _ __ __| |_ __ ___ _____ _ __
355 * | '_ ` _ \ / _` | | '_ \ / _` | '__| \ \ / / _ \ '__|
356 * | | | | | | (_| | | | | | | (_| | | | |\ V / __/ |
357 * |_| |_| |_|\__,_|_|_| |_| \__,_|_| |_| \_/ \___|_|
359 *********************************************************/
364 * Transforms all conv nodes into ppc convs before abi
366 * @param node the firm node
367 * @param env the debug module
369 void ppc32_conv_walk(ir_node *node, void *env) {
370 ppc32_code_gen_t *cgenv = (ppc32_code_gen_t *)env;
371 ir_opcode code = get_irn_opcode(node);
372 ppc32_transform_env_t tenv;
376 if(current_block != NULL)
377 finalize_block(cgenv);
379 current_block = node;
385 tenv.irg = current_ir_graph;
386 DEBUG_ONLY(tenv.mod = cgenv->mod;)
388 if (code == iro_Conv)
390 ir_modecode from_mode=get_mode_modecode(get_irn_mode(get_irn_n(node,0)));
391 ir_modecode to_mode=get_mode_modecode(get_irn_mode(node));
394 if(from_mode == to_mode) return;
395 if(from_mode == irm_F || from_mode == irm_D)
411 else if(to_mode == irm_F || to_mode == irm_D)
428 /* in Liste eintragen */
429 attr = get_irn_link(current_block);
430 set_irn_link(node, attr->first_conv);
431 attr->first_conv = node;
435 else if (code == iro_Call) {
437 ir_type *tp = get_Call_type(node);
439 int stack_alignment = 4;
441 for (i = get_Call_n_params(node) - 1; i >= 0; --i) {
442 ir_mode *mode = get_irn_mode(get_Call_param(node, i));
445 if (mode_is_reference(mode)) {
446 /* might be a compound parameter */
447 ptp = get_method_param_type(tp, i);
449 if (is_compound_type(ptp)) {
450 s = (get_type_size_bytes(ptp) + stack_alignment - 1) & -stack_alignment;
456 s = (get_mode_size_bytes(mode) + stack_alignment - 1) & -stack_alignment;
459 if ((unsigned) size > cgenv->area_size)
460 cgenv->area_size = size;
465 * Transforms all const nodes into ppc const nodes inside the using block
467 * @param node the firm node
468 * @param env the debug module
470 void ppc32_pretransform_walk(ir_node *node, void *env) {
471 ppc32_code_gen_t *cgenv = (ppc32_code_gen_t *)env;
472 ir_opcode code = get_irn_opcode(node);
473 ppc32_transform_env_t tenv;
477 current_block = node;
481 tenv.irg = current_ir_graph;
482 DEBUG_ONLY(tenv.mod = cgenv->mod;)
484 if(code == iro_Const || code == iro_SymConst)
488 tenv.block = cgenv->start_succ_block;
490 tenv.mode = get_irn_mode(node);
491 tenv.dbg = get_irn_dbg_info(node);
493 if(code == iro_Const)
494 newconst = gen_Const(&tenv);
496 newconst = gen_SymConst(&tenv);
498 exchange(node, newconst);