#include "lc_opts.h"
#include "lc_opts_enum.h"
-#include "pseudo_irg.h"
#include "irgwalk.h"
#include "irprog.h"
#include "irprintf.h"
/* fill register allocator interface */
static const arch_irn_ops_t arm_irn_ops = {
- get_arm_in_req,
arm_classify,
arm_get_frame_entity,
arm_set_stack_bias,
* Transforms the standard Firm graph into
* a ARM firm graph.
*/
-static void arm_prepare_graph(void *self)
+static void arm_prepare_graph(ir_graph *irg)
{
- arm_code_gen_t *cg = self;
-
/* transform nodes into assembler instructions */
- arm_transform_graph(cg);
+ arm_transform_graph(irg);
/* do local optimizations (mainly CSE) */
- local_optimize_graph(cg->irg);
-
- if (cg->dump)
- dump_ir_graph(cg->irg, "transformed");
+ local_optimize_graph(irg);
/* do code placement, to optimize the position of constants */
- place_code(cg->irg);
-
- if (cg->dump)
- dump_ir_graph(cg->irg, "place");
+ place_code(irg);
}
/**
* Called immediately before emit phase.
*/
-static void arm_finish_irg(void *self)
+static void arm_finish_irg(ir_graph *irg)
{
- arm_code_gen_t *cg = self;
-
/* do peephole optimizations and fix stack offsets */
- arm_peephole_optimization(cg);
+ arm_peephole_optimization(irg);
}
-static ir_node *arm_flags_remat(ir_node *node, ir_node *after)
+static void arm_before_ra(ir_graph *irg)
{
- ir_node *block;
- ir_node *copy;
-
- if (is_Block(after)) {
- block = after;
- } else {
- block = get_nodes_block(after);
- }
- copy = exact_copy(node);
- set_nodes_block(copy, block);
- sched_add_after(after, copy);
- return copy;
-}
-
-static void arm_before_ra(void *self)
-{
- arm_code_gen_t *cg = self;
-
- be_sched_fix_flags(cg->irg, &arm_reg_classes[CLASS_arm_flags],
- &arm_flags_remat);
+ be_sched_fix_flags(irg, &arm_reg_classes[CLASS_arm_flags], NULL, NULL);
}
static void transform_Reload(ir_node *node)
}
}
-static void arm_after_ra(void *self)
+static void arm_collect_frame_entity_nodes(ir_node *node, void *data)
{
- arm_code_gen_t *cg = self;
- be_coalesce_spillslots(cg->irg);
+ be_fec_env_t *env = data;
+ const ir_mode *mode;
+ int align;
+ ir_entity *entity;
+ const arm_load_store_attr_t *attr;
- irg_block_walk_graph(cg->irg, NULL, arm_after_ra_walker, NULL);
-}
+ if (be_is_Reload(node) && be_get_frame_entity(node) == NULL) {
+ mode = get_irn_mode(node);
+ align = get_mode_size_bytes(mode);
+ be_node_needs_frame_entity(env, node, mode, align);
+ return;
+ }
-/**
- * Emits the code, closes the output file and frees
- * the code generator interface.
- */
-static void arm_emit_and_done(void *self)
-{
- arm_code_gen_t *cg = self;
- ir_graph *irg = cg->irg;
+ switch (get_arm_irn_opcode(node)) {
+ case iro_arm_Ldf:
+ case iro_arm_Ldr:
+ break;
+ default:
+ return;
+ }
- arm_gen_routine(cg, irg);
+ attr = get_arm_load_store_attr_const(node);
+ entity = attr->entity;
+ mode = attr->load_store_mode;
+ align = get_mode_size_bytes(mode);
+ if (entity != NULL)
+ return;
+ if (!attr->is_frame_entity)
+ return;
+ be_node_needs_frame_entity(env, node, mode, align);
+}
- /* de-allocate code generator */
- del_set(cg->reg_set);
- free(self);
+static void arm_set_frame_entity(ir_node *node, ir_entity *entity)
+{
+ if (is_be_node(node)) {
+ be_node_set_frame_entity(node, entity);
+ } else {
+ arm_load_store_attr_t *attr = get_arm_load_store_attr(node);
+ attr->entity = entity;
+ }
}
-/* forward */
-static void *arm_cg_init(ir_graph *irg);
+static void arm_after_ra(ir_graph *irg)
+{
+ be_fec_env_t *fec_env = be_new_frame_entity_coalescer(irg);
-static const arch_code_generator_if_t arm_code_gen_if = {
- arm_cg_init,
- NULL, /* get_pic_base */
- NULL, /* before abi introduce */
- arm_prepare_graph,
- NULL, /* spill */
- arm_before_ra, /* before register allocation hook */
- arm_after_ra,
- arm_finish_irg,
- arm_emit_and_done,
-};
+ irg_walk_graph(irg, NULL, arm_collect_frame_entity_nodes, fec_env);
+ be_assign_entities(fec_env, arm_set_frame_entity);
+ be_free_frame_entity_coalescer(fec_env);
+
+ irg_block_walk_graph(irg, NULL, arm_after_ra_walker, NULL);
+}
/**
* Initializes the code generator.
*/
-static void *arm_cg_init(ir_graph *irg)
+static void arm_init_graph(ir_graph *irg)
{
- static ir_type *int_tp = NULL;
- arm_isa_t *isa = (arm_isa_t *) be_get_irg_arch_env(irg);
- arm_code_gen_t *cg;
-
- if (! int_tp) {
- /* create an integer type with machine size */
- int_tp = new_type_primitive(mode_Is);
- }
-
- cg = XMALLOC(arm_code_gen_t);
- cg->impl = &arm_code_gen_if;
- cg->irg = irg;
- cg->reg_set = new_set(arm_cmp_irn_reg_assoc, 1024);
- cg->isa = isa;
- cg->int_tp = int_tp;
- cg->dump = (be_get_irg_options(irg)->dump_flags & DUMP_BE) ? 1 : 0;
-
- FIRM_DBG_REGISTER(cg->mod, "firm.be.arm.cg");
-
- /* enter the current code generator */
- isa->cg = cg;
-
- return (arch_code_generator_t *)cg;
+ (void) irg;
}
#define ID(x) new_id_from_chars(x, sizeof(x)-1)
- int_tp = new_type_primitive(mode_Is);
- uint_tp = new_type_primitive(mode_Iu);
+ int_tp = get_type_for_mode(mode_Is);
+ uint_tp = get_type_for_mode(mode_Iu);
/* ARM has neither a signed div instruction ... */
{
lower_intrinsics(records, n_records, /*part_block_used=*/0);
}
-
+const arch_isa_if_t arm_isa_if;
static arm_isa_t arm_isa_template = {
{
&arm_isa_if, /* isa interface */
5, /* reload costs */
true, /* we do have custom abi handling */
},
- 0, /* use generic register names instead of SP, LR, PC */
ARM_FPU_ARCH_FPE, /* FPU architecture */
- NULL, /* current code generator */
};
/**
arm_register_init();
- isa->cg = NULL;
be_emit_init(file_handle);
arm_create_opcodes(&arm_irn_ops);
be_emit_write_line();
inited = 1;
- return &isa->arch_env;
+ return &isa->base;
}
{
arm_isa_t *isa = self;
- be_gas_emit_decls(isa->arch_env.main_env);
+ be_gas_emit_decls(isa->base.main_env);
be_emit_exit();
free(self);
return 1;
}
-/**
- * Initializes the code generator interface.
- */
-static const arch_code_generator_if_t *arm_get_code_generator_if(void *self)
-{
- (void) self;
- return &arm_code_gen_if;
-}
-
list_sched_selector_t arm_sched_selector;
/**
return 0;
}
+static void arm_lower_for_target(void)
+{
+ int i;
+ int n_irgs = get_irp_n_irgs();
+
+ for (i = 0; i < n_irgs; ++i) {
+ ir_graph *irg = get_irp_irg(i);
+ lower_switch(irg, 256, true);
+ }
+}
+
/**
* Returns the libFirm configuration parameter for this backend.
*/
static const backend_params *arm_get_libfirm_params(void)
{
- static const ir_settings_if_conv_t ifconv = {
- 4, /* maxdepth, doesn't matter for Psi-conversion */
- arm_is_mux_allowed /* allows or disallows Mux creation for given selector */
- };
static ir_settings_arch_dep_t ad = {
1, /* allow subs */
1, /* Muls are fast enough on ARM but ... */
32, /* SMUL & UMUL available for 32 bit */
};
static backend_params p = {
- 1, /* need dword lowering */
0, /* don't support inline assembler yet */
- NULL, /* will be set later */
- NULL, /* but yet no creator function */
- NULL, /* context for create_intrinsic_fkt */
- NULL, /* ifconv_info will be set below */
+ 1, /* support Rotl nodes */
+ 1, /* big endian */
+ arm_lower_for_target, /* lowering function */
+ &ad, /* will be set later */
+ arm_is_mux_allowed, /* allow_ifconv function */
NULL, /* float arithmetic mode (TODO) */
0, /* no trampoline support: size 0 */
0, /* no trampoline support: align 0 */
4 /* alignment of stack parameter */
};
- p.dep_param = &ad;
- p.if_conv_info = &ifconv;
return &p;
}
static const lc_opt_table_entry_t arm_options[] = {
LC_OPT_ENT_ENUM_INT("fpunit", "select the floating point unit", &arch_fpu_var),
- LC_OPT_ENT_BOOL("gen_reg_names", "use generic register names", &arm_isa_template.gen_reg_names),
LC_OPT_LAST
};
arm_get_reg_class,
arm_get_reg_class_for_mode,
NULL,
- arm_get_code_generator_if,
arm_get_list_sched_selector,
arm_get_ilp_sched_selector,
arm_get_reg_class_alignment,
arm_get_irg_list,
NULL, /* mark remat */
arm_parse_asm_constraint,
- arm_is_valid_clobber
+ arm_is_valid_clobber,
+
+ arm_init_graph,
+ NULL, /* get_pic_base */
+ NULL, /* before_abi */
+ arm_prepare_graph,
+ arm_before_ra,
+ arm_after_ra,
+ arm_finish_irg,
+ arm_gen_routine,
};
BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_arm);