#include "list.h"
#include "ident.h"
+#include "be.h"
#include "belistsched.h"
#include "beabi_t.h"
* @param env The architecture environment.
* @return A newly created code generator.
*/
- void *(*init)(FILE *file, ir_graph *irg, const arch_env_t *env);
+ void *(*init)(FILE *file, const be_irg_t *birg);
/**
* Called, when the graph is being normalized.
cg_if = isa->impl->get_code_generator_if(isa);
/* get a code generator for this graph. */
- birg.cg = cg_if->init(file_handle, birg.irg, env.arch_env);
+ birg.cg = cg_if->init(file_handle, &birg);
/* create the code generator and generate code. */
prepare_graph(&birg);
#include "irgwalk.h"
#include "type.h"
+#include "../be_t.h"
#include "../bearch.h"
#include "../besched.h"
#include "../beutil.h"
free(self);
}
-static void *firm_cg_init(FILE *file_handle, ir_graph *irg, const arch_env_t *env);
+static void *firm_cg_init(FILE *file_handle, const be_irg_t *birg);
static const arch_code_generator_if_t firm_code_gen_if = {
firm_cg_init,
firm_codegen_done
};
-static void *firm_cg_init(FILE *file_handle, ir_graph *irg, const arch_env_t *env)
+static void *firm_cg_init(FILE *file_handle, const be_irg_t *birg)
{
firm_code_gen_t *cg = xmalloc(sizeof(*cg));
cg->impl = &firm_code_gen_if;
- cg->irg = irg;
+ cg->irg = birg->irg;
return cg;
}
#include "../benode_t.h"
#include "../belower.h"
#include "../besched_t.h"
+#include "../be.h"
#include "bearch_ia32_t.h"
#include "ia32_new_nodes.h" /* ia32 nodes interface */
#define is_Start(irn) (get_irn_opcode(irn) == iro_Start)
ir_node *ia32_new_NoReg_gp(ia32_code_gen_t *cg) {
- if (! cg->noreg_gp) {
- cg->noreg_gp = be_new_NoReg(&ia32_gp_regs[REG_XXX], cg->irg, get_irg_start_block(cg->irg));
- }
-
- return cg->noreg_gp;
+ return be_abi_get_callee_save_irn(cg->birg->abi, &ia32_gp_regs[REG_XXX]);
}
ir_node *ia32_new_NoReg_fp(ia32_code_gen_t *cg) {
- if (! cg->noreg_fp) {
- cg->noreg_fp = be_new_NoReg(&ia32_fp_regs[REG_XXXX], cg->irg, get_irg_start_block(cg->irg));
- }
-
- return cg->noreg_fp;
+ return be_abi_get_callee_save_irn(cg->birg->abi, &ia32_fp_regs[REG_XXXX]);
}
/**************************************************
return (ir_node *)n;
}
-static int is_Call_Proj(const ir_node *n) {
- if (is_Proj(n) &&
- is_Proj(get_Proj_pred(n)) &&
- get_irn_mode(get_Proj_pred(n)) == mode_T &&
- is_ia32_Call(get_Proj_pred(get_Proj_pred(n))))
- {
- return 1;
- }
-
- return 0;
-}
-
-static int is_Start_Proj(const ir_node *n) {
- if (is_Proj(n) &&
- is_Proj(get_Proj_pred(n)) &&
- get_irn_mode(get_Proj_pred(n)) == mode_T &&
- is_Start(get_Proj_pred(get_Proj_pred(n))))
- {
- return 1;
- }
-
- return 0;
-}
-
-static int is_P_frame_base_Proj(const ir_node *n) {
- if (is_Proj(n) &&
- is_Start(get_Proj_pred(n)) &&
- get_Proj_proj(n) == pn_Start_P_frame_base)
- {
- return 1;
- }
-
- return 0;
-}
-
-static int is_used_by_Keep(const ir_node *n) {
- return be_is_Keep(get_edge_src_irn(get_irn_out_edge_first(n)));
-}
-
/**
* Return register requirements for an ia32 node.
* If the node returns a tuple (mode_T) then the proj's
*/
static void ia32_codegen(void *self) {
ia32_code_gen_t *cg = self;
- ir_graph *irg = cg->irg;
- FILE *out = cg->out;
+ ir_graph *irg = cg->irg;
+ FILE *out = cg->out;
if (cg->emit_decls) {
ia32_gen_decls(cg->out);
free(self);
}
-static void *ia32_cg_init(FILE *F, ir_graph *irg, const arch_env_t *arch_env);
+static void *ia32_cg_init(FILE *F, const be_irg_t *birg);
static const arch_code_generator_if_t ia32_code_gen_if = {
ia32_cg_init,
/**
* Initializes the code generator.
*/
-static void *ia32_cg_init(FILE *F, ir_graph *irg, const arch_env_t *arch_env) {
- ia32_isa_t *isa = (ia32_isa_t *)arch_env->isa;
+static void *ia32_cg_init(FILE *F, const be_irg_t *birg) {
+ 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 = irg;
+ cg->irg = birg->irg;
cg->reg_set = new_set(ia32_cmp_irn_reg_assoc, 1024);
cg->mod = firm_dbg_register("firm.be.ia32.cg");
cg->out = F;
- cg->arch_env = arch_env;
+ cg->arch_env = birg->main_env->arch_env;
cg->types = pmap_create();
cg->tv_ent = pmap_create();
- cg->noreg_gp = NULL;
- cg->noreg_fp = NULL;
+ cg->birg = birg;
isa->num_codegens++;
#include "debug.h"
#include "bearch_ia32.h"
#include "ia32_nodes_attr.h"
+#include "../be.h"
/* some typedefs */
set *reg_set; /**< set to memorize registers for non-ia32 nodes (e.g. phi nodes) */
firm_dbg_module_t *mod; /**< debugging module */
int emit_decls; /**< flag indicating if decls were already emitted */
- int has_alloca; /**< indicates whether the irg contains an alloca or not */
- const ia32_register_req_t **reg_param_req; /**< hold the requirements for the reg param nodes */
pmap *types; /**< A map of modes to primitive types */
pmap *tv_ent; /**< A map of entities that store tarvals */
- ir_node *noreg_gp; /**< Holds the unique per irg GP NoReg node */
- ir_node *noreg_fp; /**< Holds the unique per irg FP NoReg node */
+ const be_irg_t *birg; /**< The be-irg (contains additional information about the irg) */
} ia32_code_gen_t;
typedef struct _ia32_isa_t {
********************/
void emit_ia32_Call(ir_node *irn, emit_env_t *emit_env) {
- int i, n = get_irn_arity(irn);
- int args_size = 0;
- ir_node *sync = get_irn_n(irn, n - 1);
- FILE *F = emit_env->out;
- const lc_arg_env_t *env = ia32_get_arg_env();
-
- if (get_irn_op(sync) == op_Sync) {
- /* We have stack arguments */
- ir_node **args = get_Sync_preds_arr(sync);
-
- for (i = 0; i < get_Sync_n_preds(sync); i++) {
- ir_node *n = get_irn_n(args[i], 1);
- lc_efprintf(env, F, "\tpush %1D\t\t\t\t/* push %+F(%+F) on stack */\n", n, args[i], n);
-
- if (mode_is_float(get_irn_mode(n))) {
- args_size += 4;
- }
- else {
- args_size += 16;
- }
- }
- }
-
- lc_efprintf(env, F, "\tcall %C\t\t\t/* %+F */\n", irn, irn);
-
- if (get_irn_op(sync) == op_Sync) {
- /* We had stack arguments: clear the stack */
- fprintf(F, "\tadd %d, ", args_size);
- if (emit_env->cg->has_alloca) {
- fprintf(F, "%%ebp");
- }
- else {
- fprintf(F, "%%esp");
- }
- fprintf(F, "\t\t\t\t/* clear stack after call */\n");
- }
-}
-
-
-
-/**
- * Emits code for Alloca (increase stack pointer, cpoy to destination)
- */
-void emit_Alloca(ir_node *irn, emit_env_t *emit_env, int is_imm) {
- const lc_arg_env_t *env = ia32_get_arg_env();
- FILE *F = emit_env->out;
- char *sp;
-
- if (emit_env->cg->has_alloca) {
- sp = "%ebp";
- }
- else {
- sp = "%esp";
- }
-
-
- /* allocate the memory */
- fprintf(F, "\tsub %s", sp);
-
- if (is_imm) {
- lc_efprintf(env, F, "%C", irn);
- }
- else {
- lc_efprintf(env, F, "%1S", irn);
- }
-
- fprintf(F, "\t\t\t\t/* reserve memory on stack */\n");
-
- /* copy the new stack pointer to destination register */
- lc_efprintf(env, F, "\tmov %s, %1D\t\t\t/* copy stack pointer to destination */\n", sp, irn);
-}
-
-void emit_ia32_Alloca(ir_node *irn, emit_env_t *emit_env) {
- emit_Alloca(irn, emit_env, 0);
}
-void emit_ia32_Alloca_i(ir_node *irn, emit_env_t *emit_env) {
- emit_Alloca(irn, emit_env, 1);
-}
/***********************************************************************************
ia32_am_flavour_t am_flavour; /**<< the concrete addrmode characteristics */
struct obstack *am_offs; /**<< offsets for AddrMode */
- char offs_sign; /**<< the sign of the first offset */
int am_scale; /**<< addrmode scale for index register */
+ char offs_sign; /**<< the sign of the first offset */
+
+ char use_frame; /**<< indicates whether the operation uses the frame pointer or not */
tarval *tv; /**<< tarval for immediate operations */
char *sc; /**<< symconst name */
char *cnst; /**<< points to the string representation of the constant value (either tv or sc) */
- char use_frame; /**<< indicates whether the operation uses the frame pointer or not */
-
ir_mode *ls_mode; /**<< the mode of the stored/loaded value */
ia32_op_flavour_t op_flav; /**<< flavour of an op (flavour_Div/Mod/DivMod/Mul/Mulh) */
# 1 - caller save (register must be saved by the caller of a function)
# 2 - callee save (register must be saved by the called function)
# 4 - ignore (do not assign this register)
-# 8 - this is the stack pointer
-# 16 - this is the base pointer
# NOTE: Make sure to list the registers returning the call-result before all other
# caller save registers and in the correct order, otherwise it will break
# the magic!