add Linux grof support
[libfirm] / ir / be / ia32 / bearch_ia32.c
index d20c867..32f1dc2 100644 (file)
@@ -51,6 +51,7 @@
 #include "xmalloc.h"
 #include "irtools.h"
 #include "iroptimize.h"
+#include "instrument.h"
 
 #include "../beabi.h"
 #include "../beirg_t.h"
@@ -76,7 +77,6 @@
 #include "gen_ia32_regalloc_if.h"
 #include "gen_ia32_machine.h"
 #include "ia32_transform.h"
-#include "ia32_pbqp_transform.h"
 #include "ia32_emitter.h"
 #include "ia32_map_regs.h"
 #include "ia32_optimize.h"
 #include "ia32_fpu.h"
 #include "ia32_architecture.h"
 
+#ifdef FIRM_GRGEN_BE
+#include "ia32_pbqp_transform.h"
+#endif
+
 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
 
 /* TODO: ugly */
@@ -374,22 +378,23 @@ static void ia32_set_frame_entity(const void *self, ir_node *irn, ir_entity *ent
        set_ia32_frame_ent(irn, ent);
 }
 
-static void ia32_set_frame_offset(const void *self, ir_node *irn, int bias) {
+static void ia32_set_frame_offset(const void *self, ir_node *irn, int bias)
+{
        const ia32_irn_ops_t *ops = self;
 
-       if (get_ia32_frame_ent(irn)) {
-               if (is_ia32_Pop(irn)) {
-                       int omit_fp = be_abi_omit_fp(ops->cg->birg->abi);
-                       if (omit_fp) {
-                               /* Pop nodes modify the stack pointer before calculating the destination
-                                * address, so fix this here
-                                */
-                               bias -= 4;
-                       }
-               }
+       if (get_ia32_frame_ent(irn) == NULL)
+               return;
 
-               add_ia32_am_offs_int(irn, bias);
+       if (is_ia32_Pop(irn)) {
+               int omit_fp = be_abi_omit_fp(ops->cg->birg->abi);
+               if (omit_fp) {
+                       /* Pop nodes modify the stack pointer before calculating the
+                        * destination address, so fix this here
+                        */
+                       bias -= 4;
+               }
        }
+       add_ia32_am_offs_int(irn, bias);
 }
 
 static int ia32_get_sp_bias(const void *self, const ir_node *node)
@@ -493,7 +498,7 @@ static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_
 
        if (env->flags.try_omit_fp) {
                /* simply remove the stack frame here */
-               curr_sp = be_new_IncSP(env->isa->sp, env->irg, bl, curr_sp, BE_STACK_FRAME_SIZE_SHRINK);
+               curr_sp = be_new_IncSP(env->isa->sp, env->irg, bl, curr_sp, BE_STACK_FRAME_SIZE_SHRINK, 0);
                add_irn_dep(curr_sp, *mem);
        } else {
                const ia32_isa_t *isa     = (ia32_isa_t *)env->isa;
@@ -923,6 +928,10 @@ static ia32_irn_ops_t ia32_irn_ops = {
  *                       |___/
  **************************************************/
 
+static ir_entity *mcount = NULL;
+
+#define ID(s) new_id_from_chars(s, sizeof(s) - 1)
+
 static void ia32_before_abi(void *self) {
        lower_mode_b_config_t lower_mode_b_config = {
                mode_Iu,  /* lowered mode */
@@ -932,8 +941,18 @@ static void ia32_before_abi(void *self) {
        ia32_code_gen_t *cg = self;
 
        ir_lower_mode_b(cg->irg, &lower_mode_b_config);
-       if(cg->dump)
+       if (cg->dump)
                be_dump(cg->irg, "-lower_modeb", dump_ir_block_graph_sched);
+       if (cg->gprof) {
+               if (mcount == NULL) {
+                       ir_type *tp = new_type_method(ID("FKT.mcount"), 0, 0);
+                       mcount = new_entity(get_glob_type(), ID("mcount"), tp);
+                       /* FIXME: enter the right ld_ident here */
+                       set_entity_ld_ident(mcount, get_entity_ident(mcount));
+                       set_entity_visibility(mcount, visibility_external_allocated);
+               }
+               instrument_initcall(cg->irg, mcount);
+       }
 }
 
 /**
@@ -954,18 +973,15 @@ static void ia32_prepare_graph(void *self) {
        edges_activate(cg->irg);
 #endif
 
-       if(cg->dump)
+       if (cg->dump)
                be_dump(cg->irg, "-pre_transform", dump_ir_block_graph_sched);
 
-        /* used for examination purposes only
-         * if(cg->dump)
-                dump_irg_grgen(cg->irg, "-pre_transform");
-         */
-
-        /* transform nodes into assembler instructions by PBQP magic */
-        ia32_transform_graph_by_pbqp(cg);
+#ifdef FIRM_GRGEN_BE
+       /* transform nodes into assembler instructions by PBQP magic */
+       ia32_transform_graph_by_pbqp(cg);
+#endif
 
-       if(cg->dump)
+       if (cg->dump)
                be_dump(cg->irg, "-after_pbqp_transform", dump_ir_block_graph_sched);
 
        /* transform remaining nodes into assembler instructions */
@@ -1046,7 +1062,7 @@ static void turn_back_am(ir_node *node)
        clear_ia32_am_sc_sign(node);
 
        /* rewire mem-proj */
-       if(get_irn_mode(node) == mode_T) {
+       if (get_irn_mode(node) == mode_T) {
                mem_proj = NULL;
                foreach_out_edge(node, edge) {
                        ir_node *out = get_edge_src_irn(edge);
@@ -1063,7 +1079,7 @@ static void turn_back_am(ir_node *node)
        }
 
        set_ia32_op_type(node, ia32_Normal);
-       if(sched_is_scheduled(node))
+       if (sched_is_scheduled(node))
                sched_add_before(node, load);
 }
 
@@ -1074,7 +1090,7 @@ static ir_node *flags_remat(ir_node *node, ir_node *after)
        ir_node        *block;
        ir_node        *copy;
 
-       if(is_Block(after)) {
+       if (is_Block(after)) {
                block = after;
        } else {
                block = get_nodes_block(after);
@@ -1515,10 +1531,30 @@ static void ia32_codegen(void *self) {
        free(cg);
 }
 
+/**
+ * Returns the node representing the PIC base.
+ */
+static ir_node *ia32_get_pic_base(void *self) {
+       ir_node         *block;
+       ia32_code_gen_t *cg      = self;
+       ir_node         *get_eip = cg->get_eip;
+       if (get_eip != NULL)
+               return get_eip;
+
+       block       = get_irg_start_block(cg->irg);
+       get_eip     = new_rd_ia32_GetEIP(NULL, cg->irg, block);
+       cg->get_eip = get_eip;
+
+       add_irn_dep(get_eip, get_irg_frame(cg->irg));
+
+       return get_eip;
+}
+
 static void *ia32_cg_init(be_irg_t *birg);
 
 static const arch_code_generator_if_t ia32_code_gen_if = {
        ia32_cg_init,
+       ia32_get_pic_base,   /* return node used as base in pic code addresses */
        ia32_before_abi,     /* before abi introduce hook */
        ia32_prepare_graph,
        NULL,                /* spill */
@@ -1533,17 +1569,18 @@ static const arch_code_generator_if_t ia32_code_gen_if = {
  * Initializes a IA32 code generator.
  */
 static void *ia32_cg_init(be_irg_t *birg) {
-       ia32_isa_t      *isa = (ia32_isa_t *)birg->main_env->arch_env->isa;
+       ia32_isa_t      *isa = (ia32_isa_t *)birg->main_env->arch_env.isa;
        ia32_code_gen_t *cg  = xcalloc(1, sizeof(*cg));
 
        cg->impl      = &ia32_code_gen_if;
        cg->irg       = birg->irg;
        cg->reg_set   = new_set(ia32_cmp_irn_reg_assoc, 1024);
-       cg->arch_env  = birg->main_env->arch_env;
+       cg->arch_env  = &birg->main_env->arch_env;
        cg->isa       = isa;
        cg->birg      = birg;
        cg->blk_sched = NULL;
        cg->dump      = (birg->main_env->options->dump_flags & DUMP_BE) ? 1 : 0;
+       cg->gprof     = (birg->main_env->options->gprof) ? 1 : 0;
 
        /* enter it */
        isa->cg = cg;
@@ -1614,6 +1651,7 @@ static ia32_isa_t ia32_isa_template = {
                &ia32_gp_regs[REG_ESP],  /* stack pointer register */
                &ia32_gp_regs[REG_EBP],  /* base pointer register */
                -1,                      /* stack direction */
+               16,                      /* stack alignment */
                NULL,                    /* main environment */
                7,                       /* costs for a spill instruction */
                5,                       /* costs for a reload instruction */
@@ -2109,6 +2147,8 @@ static lc_opt_enum_int_var_t gas_var = {
 
 static const lc_opt_table_entry_t ia32_options[] = {
        LC_OPT_ENT_ENUM_INT("gasmode", "set the GAS compatibility mode", &gas_var),
+       LC_OPT_ENT_INT("stackalign", "set stack alignment for calls",
+                      &ia32_isa_template.arch_isa.stack_alignment),
        LC_OPT_LAST
 };