#include "gen_TEMPLATE_emitter.h"
#include "TEMPLATE_nodes_attr.h"
#include "TEMPLATE_new_nodes.h"
-#include "TEMPLATE_map_regs.h"
#define SNPRINTF_BUF_LEN 128
+++ /dev/null
-/*
- * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
- *
- * This file is part of libFirm.
- *
- * This file may be distributed and/or modified under the terms of the
- * GNU General Public License version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * Licensees holding valid libFirm Professional Edition licenses may use
- * this file in accordance with the libFirm Commercial License.
- * Agreement provided with the Software.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE.
- */
-
-/**
- * @file
- * @brief Register mapping for firm nodes. Stolen from bearch_firm :)
- * @version $Id$
- */
-#include "config.h"
-
-#include <stdlib.h>
-
-#include "TEMPLATE_map_regs.h"
-#include "TEMPLATE_new_nodes.h"
-
-/* Mapping to store registers in firm nodes */
-
-struct TEMPLATE_irn_reg_assoc {
- const ir_node *irn;
- const arch_register_t *reg;
-};
-
-int TEMPLATE_cmp_irn_reg_assoc(const void *a, const void *b, size_t size) {
- const struct TEMPLATE_irn_reg_assoc *x = a;
- const struct TEMPLATE_irn_reg_assoc *y = b;
- (void) size;
-
- return x->irn != y->irn;
-}
-
-static struct TEMPLATE_irn_reg_assoc *get_irn_reg_assoc(const ir_node *irn, set *reg_set) {
- struct TEMPLATE_irn_reg_assoc templ;
- unsigned int hash;
-
- templ.irn = irn;
- templ.reg = NULL;
- hash = HASH_PTR(irn);
-
- return set_insert(reg_set, &templ, sizeof(templ), hash);
-}
-
-void TEMPLATE_set_firm_reg(ir_node *irn, const arch_register_t *reg, set *reg_set) {
- struct TEMPLATE_irn_reg_assoc *assoc = get_irn_reg_assoc(irn, reg_set);
- assoc->reg = reg;
-}
-
-const arch_register_t *TEMPLATE_get_firm_reg(const ir_node *irn, set *reg_set) {
- struct TEMPLATE_irn_reg_assoc *assoc = get_irn_reg_assoc(irn, reg_set);
- return assoc->reg;
-}
-
-
-
-/**
- * Translates the projnum into a "real" argument position for register
- * requirements dependend on the predecessor.
- */
-long TEMPLATE_translate_proj_pos(const ir_node *proj) {
- ir_node *pred = get_Proj_pred(proj);
- long nr = get_Proj_proj(proj);
-
- if (is_TEMPLATE_Load(pred)) {
- if (nr == pn_Load_res)
- return 0;
- assert(0 && "unsupported Proj(Load) number");
- }
- else if (is_TEMPLATE_Store(pred)) {
- return 0;
- }
- else if (is_TEMPLATE_fDiv(pred)) {
- if (nr == pn_Quot_res)
- return 0;
- else
- assert(0 && "there should be no more Projs for a fDiv");
- }
-
-// assert(0 && "unsupported Proj(X)");
- return nr;
-}
+++ /dev/null
-/*
- * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
- *
- * This file is part of libFirm.
- *
- * This file may be distributed and/or modified under the terms of the
- * GNU General Public License version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * Licensees holding valid libFirm Professional Edition licenses may use
- * this file in accordance with the libFirm Commercial License.
- * Agreement provided with the Software.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE.
- */
-
-/**
- * @file
- * @brief declarations for the register allocation interface
- * @version $Id$
- */
-#ifndef FIRM_BE_TEMPLATE_TEMPLATE_MAP_REGS_H
-#define FIRM_BE_TEMPLATE_TEMPLATE_MAP_REGS_H
-
-#include "irnode.h"
-#include "set.h"
-
-#include "../bearch.h"
-#include "TEMPLATE_nodes_attr.h"
-
-int TEMPLATE_cmp_irn_reg_assoc(const void *a, const void *b, size_t len);
-void TEMPLATE_set_firm_reg(ir_node *irn, const arch_register_t *reg, set *reg_set);
-const arch_register_t *TEMPLATE_get_firm_reg(const ir_node *irn, set *reg_set);
-
-long TEMPLATE_translate_proj_pos(const ir_node *proj);
-
-#endif
* |_|
***********************************************************************************/
-/**
- * Dumps the register requirements for either in or out.
- */
-static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs,
- int inout) {
- char *dir = inout ? "out" : "in";
- int max = inout ? (int) arch_irn_get_n_outs(n) : get_irn_arity(n);
- char buf[1024];
- int i;
-
- memset(buf, 0, sizeof(buf));
-
- if (reqs) {
- for (i = 0; i < max; i++) {
- fprintf(F, "%sreq #%d =", dir, i);
- arch_dump_register_req(F, reqs[i], n);
- fprintf(F, "\n");
- }
-
- fprintf(F, "\n");
- } else {
- fprintf(F, "%sreq = N/A\n", dir);
- }
-}
-
-
/**
* Dumper interface for dumping TEMPLATE nodes in vcg.
* @param n the node to dump
* @param reason indicates which kind of information should be dumped
* @return 0 on success or != 0 on failure
*/
-static int TEMPLATE_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
- ir_mode *mode = NULL;
- int bad = 0;
- int i, n_res, flags;
- const arch_register_req_t **reqs;
+static int TEMPLATE_dump_node(ir_node *n, FILE *F, dump_reason_t reason)
+{
+ ir_mode *mode = NULL;
switch (reason) {
- case dump_node_opcode_txt:
- fprintf(F, "%s", get_irn_opname(n));
- break;
-
- case dump_node_mode_txt:
- mode = get_irn_mode(n);
-
- if (mode) {
- fprintf(F, "[%s]", get_mode_name(mode));
- }
- else {
- fprintf(F, "[?NOMODE?]");
- }
- break;
-
- case dump_node_nodeattr_txt:
-
- /* TODO: dump some attributes which should show up */
- /* in node name in dump (e.g. consts or the like) */
-
- break;
-
- case dump_node_info_txt:
- fprintf(F, "=== TEMPLATE attr begin ===\n");
-
- /* dump IN requirements */
- if (get_irn_arity(n) > 0) {
- reqs = get_TEMPLATE_in_req_all(n);
- dump_reg_req(F, n, reqs, 0);
- }
-
- n_res = arch_irn_get_n_outs(n);
- if (n_res > 0) {
- /* dump OUT requirements */
- reqs = get_TEMPLATE_out_req_all(n);
- dump_reg_req(F, n, reqs, 1);
-
- /* dump assigned registers */
- for (i = 0; i < n_res; i++) {
- const arch_register_t *reg = arch_irn_get_register(n, i);
-
- fprintf(F, "reg #%d = %s\n", i, reg ? arch_register_get_name(reg) : "n/a");
- }
- fprintf(F, "\n");
- }
-
- /* dump n_res */
- fprintf(F, "n_res = %d\n", n_res);
-
- /* dump flags */
- fprintf(F, "flags =");
- flags = arch_irn_get_flags(n);
- if (flags == arch_irn_flags_none) {
- fprintf(F, " none");
- }
- else {
- if (flags & arch_irn_flags_dont_spill) {
- fprintf(F, " unspillable");
- }
- if (flags & arch_irn_flags_rematerializable) {
- fprintf(F, " remat");
- }
- if (flags & arch_irn_flags_modify_flags) {
- fprintf(F, " modify_flags");
- }
- }
- fprintf(F, " (%d)\n", flags);
-
- /* TODO: dump all additional attributes */
-
- fprintf(F, "=== TEMPLATE attr end ===\n");
- /* end of: case dump_node_info_txt */
- break;
- }
+ case dump_node_opcode_txt:
+ fprintf(F, "%s", get_irn_opname(n));
+ break;
+ case dump_node_mode_txt:
+ mode = get_irn_mode(n);
- return bad;
-}
+ if (mode) {
+ fprintf(F, "[%s]", get_mode_name(mode));
+ } else {
+ fprintf(F, "[?NOMODE?]");
+ }
+ break;
+
+ case dump_node_nodeattr_txt:
+ /* TODO: dump some attributes which should show up */
+ /* in node name in dump (e.g. consts or the like) */
+ break;
+
+ case dump_node_info_txt:
+ arch_dump_reqs_and_registers(F, n);
+ break;
+ }
+
+ return 0;
+}
/***************************************************************************************************
* _ _ _ __ _ _ _ _
* |___/
***************************************************************************************************/
-const TEMPLATE_attr_t *get_TEMPLATE_attr_const(const ir_node *node) {
+const TEMPLATE_attr_t *get_TEMPLATE_attr_const(const ir_node *node)
+{
assert(is_TEMPLATE_irn(node) && "need TEMPLATE node to get attributes");
return (const TEMPLATE_attr_t *)get_irn_generic_attr_const(node);
}
-TEMPLATE_attr_t *get_TEMPLATE_attr(ir_node *node) {
+TEMPLATE_attr_t *get_TEMPLATE_attr(ir_node *node)
+{
assert(is_TEMPLATE_irn(node) && "need TEMPLATE node to get attributes");
return (TEMPLATE_attr_t *)get_irn_generic_attr(node);
}
/**
* Returns the argument register requirements of a TEMPLATE node.
*/
-const arch_register_req_t **get_TEMPLATE_in_req_all(const ir_node *node) {
+const arch_register_req_t **get_TEMPLATE_in_req_all(const ir_node *node)
+{
const TEMPLATE_attr_t *attr = get_TEMPLATE_attr_const(node);
return attr->in_req;
}
-/**
- * Returns the result register requirements of an TEMPLATE node.
- */
-const arch_register_req_t **get_TEMPLATE_out_req_all(const ir_node *node) {
- const TEMPLATE_attr_t *attr = get_TEMPLATE_attr_const(node);
- return attr->out_req;
-}
-
/**
* Returns the argument register requirement at position pos of an TEMPLATE node.
*/
-const arch_register_req_t *get_TEMPLATE_in_req(const ir_node *node, int pos) {
+const arch_register_req_t *get_TEMPLATE_in_req(const ir_node *node, int pos)
+{
const TEMPLATE_attr_t *attr = get_TEMPLATE_attr_const(node);
return attr->in_req[pos];
}
/**
* Returns the result register requirement at position pos of an TEMPLATE node.
*/
-const arch_register_req_t *get_TEMPLATE_out_req(const ir_node *node, int pos) {
- const TEMPLATE_attr_t *attr = get_TEMPLATE_attr_const(node);
- return attr->out_req[pos];
-}
-
-/**
- * Sets the OUT register requirements at position pos.
- */
-void set_TEMPLATE_req_out(ir_node *node, const arch_register_req_t *req, int pos) {
- TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
- attr->out_req[pos] = req;
+const arch_register_req_t *get_TEMPLATE_out_req(const ir_node *node, int pos)
+{
+ const backend_info_t *info = be_get_info(node);
+ return info->out_infos[pos].req;
}
/**
* Sets the IN register requirements at position pos.
*/
-void set_TEMPLATE_req_in(ir_node *node, const arch_register_req_t *req, int pos) {
+void set_TEMPLATE_req_in(ir_node *node, const arch_register_req_t *req, int pos)
+{
TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
attr->in_req[pos] = req;
}
*/
void init_TEMPLATE_attributes(ir_node *node, arch_irn_flags_t flags,
const arch_register_req_t **in_reqs,
- const arch_register_req_t **out_reqs,
const be_execution_unit_t ***execution_units,
int n_res)
{
(void) execution_units;
arch_irn_set_flags(node, flags);
- attr->out_req = out_reqs;
attr->in_req = in_reqs;
info = be_get_info(node);
*
***************************************************************************************/
-static
-int TEMPLATE_compare_attr(ir_node *a, ir_node *b)
+static int TEMPLATE_compare_attr(ir_node *a, ir_node *b)
{
const TEMPLATE_attr_t *attr_a = get_TEMPLATE_attr_const(a);
const TEMPLATE_attr_t *attr_b = get_TEMPLATE_attr_const(b);
*/
const arch_register_req_t **get_TEMPLATE_in_req_all(const ir_node *node);
-/**
- * Returns the result register requirements of an TEMPLATE node.
- */
-const arch_register_req_t **get_TEMPLATE_out_req_all(const ir_node *node);
-
/**
* Returns the argument register requirements of an TEMPLATE node.
*/
*/
const arch_register_req_t *get_TEMPLATE_out_req(const ir_node *node, int pos);
-/**
- * Sets the OUT register requirements at position pos.
- */
-void set_TEMPLATE_req_out(ir_node *node, const arch_register_req_t *req, int pos);
-
/**
* Sets the IN register requirements at position pos.
*/
#include "TEMPLATE_nodes_attr.h"
#include "TEMPLATE_transform.h"
#include "TEMPLATE_new_nodes.h"
-#include "TEMPLATE_map_regs.h"
#include "gen_TEMPLATE_regalloc_if.h"
-extern ir_op *get_op_Mulh(void);
-
-
-
-/****************************************************************************************************
- * _ _ __ _ _
- * | | | | / _| | | (_)
- * _ __ ___ __| | ___ | |_ _ __ __ _ _ __ ___| |_ ___ _ __ _ __ ___ __ _| |_ _ ___ _ __
- * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __| _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
- * | | | | (_) | (_| | __/ | |_| | | (_| | | | \__ \ || (_) | | | | | | | | (_| | |_| | (_) | | | |
- * |_| |_|\___/ \__,_|\___| \__|_| \__,_|_| |_|___/_| \___/|_| |_| |_| |_|\__,_|\__|_|\___/|_| |_|
- *
- ****************************************************************************************************/
+DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
/**
* Creates an TEMPLATE Add.
* @param op2 second operator
* @return the created TEMPLATE Add node
*/
-static ir_node *gen_Add(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
+static ir_node *gen_Add(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2)
+{
return new_bd_TEMPLATE_Add(env->dbg, env->block, op1, op2, env->mode);
}
* @param mode node mode
* @return the created TEMPLATE Mul node
*/
-static ir_node *gen_Mul(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
+static ir_node *gen_Mul(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2)
+{
if (mode_is_float(env->mode)) {
return new_bd_TEMPLATE_fMul(env->dbg, env->block, op1, op2, env->mode);
- }
- else {
+ } else {
return new_bd_TEMPLATE_Mul(env->dbg, env->block, op1, op2, env->mode);
}
}
* @param mode node mode
* @return the created TEMPLATE And node
*/
-static ir_node *gen_And(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
+static ir_node *gen_And(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2)
+{
return new_bd_TEMPLATE_And(env->dbg, env->block, op1, op2, env->mode);
}
* @param mode node mode
* @return the created TEMPLATE Or node
*/
-static ir_node *gen_Or(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
+static ir_node *gen_Or(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2)
+{
return new_bd_TEMPLATE_Or(env->dbg, env->block, op1, op2, env->mode);
}
* @param mode node mode
* @return the created TEMPLATE Eor node
*/
-static ir_node *gen_Eor(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
+static ir_node *gen_Eor(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2)
+{
return new_bd_TEMPLATE_Eor(env->dbg, env->block, op1, op2, env->mode);
}
* @param mode node mode
* @return the created TEMPLATE Sub node
*/
-static ir_node *gen_Sub(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
+static ir_node *gen_Sub(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2)
+{
if (mode_is_float(env->mode)) {
return new_bd_TEMPLATE_fSub(env->dbg, env->block, op1, op2, env->mode);
- }
- else {
+ } else {
return new_bd_TEMPLATE_Sub(env->dbg, env->block, op1, op2, env->mode);
}
}
* @param mode node mode
* @return the created TEMPLATE fDiv node
*/
-static ir_node *gen_Quot(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
+static ir_node *gen_Quot(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2)
+{
return new_bd_TEMPLATE_fDiv(env->dbg, env->block, op1, op2, env->mode);
}
* @param mode node mode
* @return the created TEMPLATE Shl node
*/
-static ir_node *gen_Shl(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
+static ir_node *gen_Shl(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2)
+{
return new_bd_TEMPLATE_Shl(env->dbg, env->block, op1, op2, env->mode);
}
* @param mode node mode
* @return the created TEMPLATE Shr node
*/
-static ir_node *gen_Shr(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2) {
+static ir_node *gen_Shr(TEMPLATE_transform_env_t *env, ir_node *op1, ir_node *op2)
+{
return new_bd_TEMPLATE_Shr(env->dbg, env->block, op1, op2, env->mode);
}
* @param mode node mode
* @return the created TEMPLATE Minus node
*/
-static ir_node *gen_Minus(TEMPLATE_transform_env_t *env, ir_node *op) {
+static ir_node *gen_Minus(TEMPLATE_transform_env_t *env, ir_node *op)
+{
if (mode_is_float(env->mode)) {
return new_bd_TEMPLATE_fMinus(env->dbg, env->block, op, env->mode);
}
* @param mode node mode
* @return the created TEMPLATE Not node
*/
-static ir_node *gen_Not(TEMPLATE_transform_env_t *env, ir_node *op) {
+static ir_node *gen_Not(TEMPLATE_transform_env_t *env, ir_node *op)
+{
return new_bd_TEMPLATE_Not(env->dbg, env->block, op, env->mode);
}
* @param mode node mode
* @return the created TEMPLATE Load node
*/
-static ir_node *gen_Load(TEMPLATE_transform_env_t *env) {
+static ir_node *gen_Load(TEMPLATE_transform_env_t *env)
+{
ir_node *node = env->irn;
if (mode_is_float(env->mode)) {
* @param mode node mode
* @return the created TEMPLATE Store node
*/
-static ir_node *gen_Store(TEMPLATE_transform_env_t *env) {
+static ir_node *gen_Store(TEMPLATE_transform_env_t *env)
+{
ir_node *node = env->irn;
if (mode_is_float(env->mode)) {
* @param node the firm node
* @param env the debug module
*/
-void TEMPLATE_transform_node(ir_node *node, void *env) {
-#ifdef DEBUG_libfirm
- TEMPLATE_code_gen_t *cgenv = (TEMPLATE_code_gen_t *)env;
-#endif
+void TEMPLATE_transform_node(ir_node *node, void *env)
+{
ir_opcode code = get_irn_opcode(node);
ir_node *asm_node = NULL;
TEMPLATE_transform_env_t tenv;
tenv.dbg = get_irn_dbg_info(node);
tenv.irg = current_ir_graph;
tenv.irn = node;
-#ifdef DEBUG_libfirm
- tenv.mod = cgenv->mod;
-#endif
tenv.mode = get_irn_mode(node);
#define UNOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_op(node)); break
#define IGN(a) case iro_##a: break
#define BAD(a) case iro_##a: goto bad
- DBG((tenv.mod, LEVEL_1, "check %+F ... ", node));
+ DBG((dbg, LEVEL_1, "check %+F ... ", node));
switch (code) {
BINOP(Add);
if (asm_node) {
exchange(node, asm_node);
- DB((tenv.mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
+ DB((dbg, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node));
}
else {
- DB((tenv.mod, LEVEL_1, "ignored\n"));
+ DB((dbg, LEVEL_1, "ignored\n"));
}
}
+
+void TEMPLATE_init_transform(void)
+{
+ FIRM_DBG_REGISTER(dbg, "firm.be.TEMPLATE.transform");
+}
#ifndef FIRM_BE_TEMPLATE_TEMPLATE_TRANSFORM_H
#define FIRM_BE_TEMPLATE_TEMPLATE_TRANSFORM_H
+void TEMPLATE_init_transform(void);
+
void TEMPLATE_transform_node(ir_node *node, void *env);
#endif
#include "gen_TEMPLATE_regalloc_if.h"
#include "TEMPLATE_transform.h"
#include "TEMPLATE_emitter.h"
-#include "TEMPLATE_map_regs.h"
-/* TODO: ugly, but we need it to get access to the registers assigned to Phi nodes */
-static set *cur_reg_set = NULL;
+DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
/**************************************************
* _ _ _ __
* Transforms the standard firm graph into
* a TEMLPATE firm graph
*/
-static void TEMPLATE_prepare_graph(void *self) {
+static void TEMPLATE_prepare_graph(void *self)
+{
TEMPLATE_code_gen_t *cg = self;
irg_walk_blkwise_graph(cg->irg, NULL, TEMPLATE_transform_node, cg);
/**
* Called immediatly before emit phase.
*/
-static void TEMPLATE_finish_irg(void *self) {
+static void TEMPLATE_finish_irg(void *self)
+{
TEMPLATE_code_gen_t *cg = self;
ir_graph *irg = cg->irg;
}
-static void TEMPLATE_before_ra(void *self) {
+static void TEMPLATE_before_ra(void *self)
+{
(void) self;
/* Some stuff you need to do after scheduling but before register allocation */
}
-static void TEMPLATE_after_ra(void *self) {
+static void TEMPLATE_after_ra(void *self)
+{
(void) self;
/* Some stuff you need to do immediatly after register allocation */
}
* Emits the code, closes the output file and frees
* the code generator interface.
*/
-static void TEMPLATE_emit_and_done(void *self) {
+static void TEMPLATE_emit_and_done(void *self)
+{
TEMPLATE_code_gen_t *cg = self;
ir_graph *irg = cg->irg;
TEMPLATE_gen_routine(cg, irg);
- cur_reg_set = NULL;
-
/* de-allocate code generator */
- del_set(cg->reg_set);
free(cg);
}
/**
* Initializes the code generator.
*/
-static void *TEMPLATE_cg_init(be_irg_t *birg) {
+static void *TEMPLATE_cg_init(be_irg_t *birg)
+{
const arch_env_t *arch_env = be_get_birg_arch_env(birg);
TEMPLATE_isa_t *isa = (TEMPLATE_isa_t *) arch_env;
TEMPLATE_code_gen_t *cg = XMALLOC(TEMPLATE_code_gen_t);
cg->impl = &TEMPLATE_code_gen_if;
cg->irg = be_get_birg_irg(birg);
- cg->reg_set = new_set(TEMPLATE_cmp_irn_reg_assoc, 1024);
cg->isa = isa;
cg->birg = birg;
- FIRM_DBG_REGISTER(cg->mod, "firm.be.TEMPLATE.cg");
-
- cur_reg_set = cg->reg_set;
return (arch_code_generator_t *)cg;
}
*
*****************************************************************/
+const arch_isa_if_t TEMPLATE_isa_if;
static TEMPLATE_isa_t TEMPLATE_isa_template = {
{
&TEMPLATE_isa_if, /* isa interface implementation */
/**
* Initializes the backend ISA and opens the output file.
*/
-static arch_env_t *TEMPLATE_init(FILE *outfile) {
+static arch_env_t *TEMPLATE_init(FILE *outfile)
+{
static int run_once = 0;
TEMPLATE_isa_t *isa;
/**
* Closes the output file and frees the ISA structure.
*/
-static void TEMPLATE_done(void *self) {
+static void TEMPLATE_done(void *self)
+{
TEMPLATE_isa_t *isa = self;
/* emit now all global declarations */
void be_init_arch_TEMPLATE(void)
{
be_register_isa_if("TEMPLATE", &TEMPLATE_isa_if);
+ FIRM_DBG_REGISTER(dbg, "firm.be.TEMPLATE.cg");
+ TEMPLATE_init_transform();
}
-
BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_TEMPLATE);
+++ /dev/null
-/*
- * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
- *
- * This file is part of libFirm.
- *
- * This file may be distributed and/or modified under the terms of the
- * GNU General Public License version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * Licensees holding valid libFirm Professional Edition licenses may use
- * this file in accordance with the libFirm Commercial License.
- * Agreement provided with the Software.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE.
- */
-
-/**
- * @file
- * @brief declarations for TEMPLATE backend
- * @version $Id$
- */
-#ifndef FIRM_BE_TEMPLATE_BEARCH_TEMPLATE_H
-#define FIRM_BE_TEMPLATE_BEARCH_TEMPLATE_H
-
-#include "../bearch.h"
-
-extern const arch_isa_if_t TEMPLATE_isa_if;
-
-#endif
#define FIRM_BE_TEMPLATE_BEARCH_TEMPLATE_T_H
#include "debug.h"
-#include "bearch_TEMPLATE.h"
#include "TEMPLATE_nodes_attr.h"
#include "be.h"
#include "../beemitter.h"
struct TEMPLATE_code_gen_t {
const arch_code_generator_if_t *impl; /**< implementation */
ir_graph *irg; /**< current irg */
- set *reg_set; /**< set to memorize registers for FIRM nodes (e.g. phi) */
TEMPLATE_isa_t *isa; /**< the isa instance */
const be_irg_t *birg; /**< The be-irg (contains additional information about the irg) */
- DEBUG_ONLY(firm_dbg_module_t *mod;) /**< debugging module */
};
struct TEMPLATE_isa_t {
- arch_env_t arch_env; /**< must be derived from arch_isa */
+ arch_env_t arch_env; /**< must be derived from arch_isa */
};
/**
* for transformation walker
*/
struct TEMPLATE_transform_env_t {
- dbg_info *dbg; /**< The node debug info */
- ir_graph *irg; /**< The irg, the node should be created in */
- ir_node *block; /**< The block, the node should belong to */
- ir_node *irn; /**< The irn, to be transformed */
- ir_mode *mode; /**< The mode of the irn */
- DEBUG_ONLY(firm_dbg_module_t *mod;) /**< The firm debugger */
+ dbg_info *dbg; /**< The node debug info */
+ ir_graph *irg; /**< The irg, the node should be created in */
+ ir_node *block; /**< The block, the node should belong to */
+ ir_node *irn; /**< The irn, to be transformed */
+ ir_mode *mode; /**< The mode of the irn */
};
#endif
* |_|
***********************************************************************************/
-/**
- * Dumps the register requirements for either in or out.
- */
-static void dump_reg_req(FILE *F, const ir_node *node,
- const arch_register_req_t **reqs, int inout) {
- char *dir = inout ? "out" : "in";
- int max = inout ? (int) arch_irn_get_n_outs(node) : get_irn_arity(node);
- char buf[1024];
- int i;
-
- memset(buf, 0, sizeof(buf));
-
- if (reqs) {
- for (i = 0; i < max; i++) {
- fprintf(F, "%sreq #%d =", dir, i);
- arch_dump_register_req(F, reqs[i], node);
- fprintf(F, "\n");
- }
-
- fprintf(F, "\n");
- } else {
- fprintf(F, "%sreq = N/A\n", dir);
- }
-}
-
/**
* Dumper interface for dumping arm nodes in vcg.
* @param n the node to dump
* @param reason indicates which kind of information should be dumped
* @return 0 on success or != 0 on failure
*/
-static int arm_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
+static int arm_dump_node(ir_node *n, FILE *F, dump_reason_t reason)
+{
ir_mode *mode = NULL;
- int bad = 0;
- int i, n_res, flags;
arm_attr_t *attr = get_arm_attr(n);
- const arch_register_req_t **reqs;
arm_shift_modifier mod;
switch (reason) {
break;
case dump_node_info_txt:
- fprintf(F, "=== arm attr begin ===\n");
-
- /* dump IN requirements */
- if (get_irn_arity(n) > 0) {
- reqs = get_arm_in_req_all(n);
- dump_reg_req(F, n, reqs, 0);
- }
-
- n_res = arch_irn_get_n_outs(n);
- if (n_res > 0) {
- /* dump OUT requirements */
- reqs = get_arm_out_req_all(n);
- dump_reg_req(F, n, reqs, 1);
-
- /* dump assigned registers */
- for (i = 0; i < n_res; i++) {
- const arch_register_t *reg = arch_irn_get_register(n, i);
-
- fprintf(F, "reg #%d = %s\n", i, reg ? arch_register_get_name(reg) : "n/a");
- }
- fprintf(F, "\n");
- }
- fprintf(F, "\n");
-
- /* dump n_res */
- fprintf(F, "n_res = %d\n", n_res);
-
- /* dump flags */
- fprintf(F, "flags =");
- flags = arch_irn_get_flags(n);
- if (flags == arch_irn_flags_none) {
- fprintf(F, " none");
- }
- else {
- if (flags & arch_irn_flags_dont_spill) {
- fprintf(F, " unspillable");
- }
- if (flags & arch_irn_flags_rematerializable) {
- fprintf(F, " remat");
- }
- if (flags & arch_irn_flags_modify_flags) {
- fprintf(F, " modify_flags");
- }
- }
- fprintf(F, " (%d)\n", flags);
+ arch_dump_reqs_and_registers(F, n);
if (is_arm_CopyB(n)) {
fprintf(F, "size = %lu\n", get_arm_imm_value(n));
if (is_arm_CmpBra(n) && get_arm_CondJmp_proj_num(n) >= 0) {
fprintf(F, "proj_num = (%d)\n", get_arm_CondJmp_proj_num(n));
}
- /* TODO: dump all additional attributes */
-
- fprintf(F, "=== arm attr end ===\n");
- /* end of: case dump_node_info_txt */
break;
}
- return bad;
+
+ return 0;
}
return attr->in_req;
}
-/**
- * Returns the result register requirements of an arm node.
- */
-const arch_register_req_t **get_arm_out_req_all(const ir_node *node) {
- const arm_attr_t *attr = get_arm_attr_const(node);
- return attr->out_req;
-}
-
/**
* Returns the argument register requirement at position pos of an arm node.
*/
/**
* Returns the result register requirement at position pos of an arm node.
*/
-const arch_register_req_t *get_arm_out_req(const ir_node *node, int pos) {
- const arm_attr_t *attr = get_arm_attr_const(node);
- return attr->out_req[pos];
-}
-
-/**
- * Sets the OUT register requirements at position pos.
- */
-void set_arm_req_out(ir_node *node, const arch_register_req_t *req, int pos) {
- arm_attr_t *attr = get_arm_attr(node);
- attr->out_req[pos] = req;
-}
-
-/**
- * Sets the complete OUT requirements of node.
- */
-void set_arm_req_out_all(ir_node *node, const arch_register_req_t **reqs) {
- arm_attr_t *attr = get_arm_attr(node);
- attr->out_req = reqs;
+const arch_register_req_t *get_arm_out_req(const ir_node *node, int pos)
+{
+ const backend_info_t *info = be_get_info(node);
+ return info->out_infos[pos].req;
}
/**
/* Set the ARM machine node attributes to default values. */
static void init_arm_attributes(ir_node *node, int flags,
const arch_register_req_t ** in_reqs,
- const arch_register_req_t ** out_reqs,
const be_execution_unit_t ***execution_units,
int n_res) {
ir_graph *irg = get_irn_irg(node);
arch_irn_set_flags(node, flags);
attr->in_req = in_reqs;
- attr->out_req = out_reqs;
attr->instr_fl = (ARM_COND_AL << 3) | ARM_SHF_NONE;
attr->imm_value = 0;
*/
const arch_register_req_t **get_arm_in_req_all(const ir_node *node);
-/**
- * Returns the result register requirements of an arm node.
- */
-const arch_register_req_t **get_arm_out_req_all(const ir_node *node);
-
/**
* Returns the argument register requirements of an arm node.
*/
*/
const arch_register_req_t *get_arm_out_req(const ir_node *node, int pos);
-/**
- * Sets the OUT register requirements at position pos.
- */
-void set_arm_req_out(ir_node *node, const arch_register_req_t *req, int pos);
-
-/**
- * Sets the complete OUT requirements of node.
- */
-void set_arm_req_out_all(ir_node *node, const arch_register_req_t **reqs);
-
/**
* Sets the IN register requirements at position pos.
*/
except_attr exc; /**< the exception attribute. MUST be the first one. */
const arch_register_req_t **in_req; /**< register requirements for arguments */
- const arch_register_req_t **out_req; /**< register requirements for results */
ir_mode *op_mode; /**< operation mode if different from node's mode */
unsigned instr_fl; /**< condition code, shift modifier */
$default_copy_attr = "arm_copy_attr";
%init_attr = (
- arm_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);",
- arm_SymConst_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);",
- arm_CondJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);",
- arm_SwitchJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);",
- arm_fpaConst_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);",
+ arm_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
+ arm_SymConst_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
+ arm_CondJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
+ arm_SwitchJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
+ arm_fpaConst_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
);
%compare_attr = (
}
}
+void arch_dump_reqs_and_registers(FILE *F, const ir_node *node)
+{
+ int n_ins = get_irn_arity(node);
+ int n_outs = arch_irn_get_n_outs(node);
+ arch_irn_flags_t flags = arch_irn_get_flags(node);
+ int i;
+
+ for (i = 0; i < n_ins; ++i) {
+ const arch_register_req_t *req = arch_get_in_register_req(node, i);
+ fprintf(F, "inreq #%d = ", i);
+ arch_dump_register_req(F, req, node);
+ fputs("\n", F);
+ }
+ for (i = 0; i < n_outs; ++i) {
+ const arch_register_req_t *req = arch_get_out_register_req(node, i);
+ fprintf(F, "outreq #%d = ", i);
+ arch_dump_register_req(F, req, node);
+ fputs("\n", F);
+ }
+ for (i = 0; i < n_outs; ++i) {
+ const arch_register_t *reg = arch_irn_get_register(node, i);
+ const arch_register_req_t *req = arch_get_out_register_req(node, i);
+ if (req->cls == NULL)
+ continue;
+ fprintf(F, "reg #%d = %s\n", i, reg != NULL ? reg->name : "n/a");
+ }
+
+ fprintf(F, "flags =");
+ if (flags == arch_irn_flags_none) {
+ fprintf(F, " none");
+ } else {
+ if (flags & arch_irn_flags_dont_spill) {
+ fprintf(F, " unspillable");
+ }
+ if (flags & arch_irn_flags_rematerializable) {
+ fprintf(F, " remat");
+ }
+ if (flags & arch_irn_flags_modify_flags) {
+ fprintf(F, " modify_flags");
+ }
+ }
+ fprintf(F, " (%d)\n", flags);
+}
+
static const arch_register_req_t no_requirement = {
arch_register_req_type_none,
NULL,
void arch_dump_register_req(FILE *F, const arch_register_req_t *req,
const ir_node *node);
+void arch_dump_register_reqs(FILE *F, const ir_node *node);
+void arch_dump_reqs_and_registers(FILE *F, const ir_node *node);
+
/**
* Node classification. Mainly used for statistics.
*/
int be_dump_phi_reg_reqs(ir_node *node, FILE *F, dump_reason_t reason)
{
- backend_info_t *info;
- int i;
- int arity;
-
switch(reason) {
case dump_node_opcode_txt:
fputs(get_op_name(get_irn_op(node)), F);
case dump_node_nodeattr_txt:
break;
case dump_node_info_txt:
- info = be_get_info(node);
-
- /* we still have a little problem with the initialisation order. This
- dump function is attached to the Phi ops before we can be sure
- that all backend infos have been constructed... */
- if (info != NULL) {
- const arch_register_req_t *req = info->out_infos[0].req;
- const arch_register_t *reg = arch_irn_get_register(node, 0);
-
- arity = get_irn_arity(node);
- for (i = 0; i < arity; ++i) {
- fprintf(F, "inreq #%d = ", i);
- arch_dump_register_req(F, req, node);
- fputs("\n", F);
- }
- fprintf(F, "outreq #0 = ");
- arch_dump_register_req(F, req, node);
- fputs("\n", F);
-
- fputs("\n", F);
-
- fprintf(F, "reg #0 = %s\n", reg != NULL ? reg->name : "n/a");
- }
-
+ arch_dump_reqs_and_registers(F, node);
break;
default:
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
-/* TODO: ugly */
-static set *cur_reg_set = NULL;
-
ir_mode *mode_fpcw = NULL;
ia32_code_gen_t *ia32_current_cg = NULL;
ia32_gen_routine(cg, irg);
}
- cur_reg_set = NULL;
-
/* remove it from the isa */
cg->isa->cg = NULL;
ia32_current_cg = NULL;
/* de-allocate code generator */
- del_set(cg->reg_set);
free(cg);
}
cg->impl = &ia32_code_gen_if;
cg->irg = birg->irg;
- cg->reg_set = new_set(ia32_cmp_irn_reg_assoc, 1024);
cg->isa = isa;
cg->birg = birg;
cg->blk_sched = NULL;
}
#endif /* NDEBUG */
- cur_reg_set = cg->reg_set;
-
assert(ia32_current_cg == NULL);
ia32_current_cg = cg;
return &ia32_reg_classes[CLASS_ia32_gp];
}
+/**
+ * Returns the register for parameter nr.
+ */
+static const arch_register_t *ia32_get_RegParam_reg(unsigned cc, unsigned nr,
+ const ir_mode *mode)
+{
+ static const arch_register_t *gpreg_param_reg_fastcall[] = {
+ &ia32_gp_regs[REG_ECX],
+ &ia32_gp_regs[REG_EDX],
+ NULL
+ };
+ static const unsigned MAXNUM_GPREG_ARGS = 3;
+
+ static const arch_register_t *gpreg_param_reg_regparam[] = {
+ &ia32_gp_regs[REG_EAX],
+ &ia32_gp_regs[REG_EDX],
+ &ia32_gp_regs[REG_ECX]
+ };
+
+ static const arch_register_t *gpreg_param_reg_this[] = {
+ &ia32_gp_regs[REG_ECX],
+ NULL,
+ NULL
+ };
+
+ static const arch_register_t *fpreg_sse_param_reg_std[] = {
+ &ia32_xmm_regs[REG_XMM0],
+ &ia32_xmm_regs[REG_XMM1],
+ &ia32_xmm_regs[REG_XMM2],
+ &ia32_xmm_regs[REG_XMM3],
+ &ia32_xmm_regs[REG_XMM4],
+ &ia32_xmm_regs[REG_XMM5],
+ &ia32_xmm_regs[REG_XMM6],
+ &ia32_xmm_regs[REG_XMM7]
+ };
+
+ static const arch_register_t *fpreg_sse_param_reg_this[] = {
+ NULL, /* in case of a "this" pointer, the first parameter must not be a float */
+ };
+ static const unsigned MAXNUM_SSE_ARGS = 8;
+
+ if ((cc & cc_this_call) && nr == 0)
+ return gpreg_param_reg_this[0];
+
+ if (! (cc & cc_reg_param))
+ return NULL;
+
+ if (mode_is_float(mode)) {
+ if (!ia32_cg_config.use_sse2 || (cc & cc_fpreg_param) == 0)
+ return NULL;
+ if (nr >= MAXNUM_SSE_ARGS)
+ return NULL;
+
+ if (cc & cc_this_call) {
+ return fpreg_sse_param_reg_this[nr];
+ }
+ return fpreg_sse_param_reg_std[nr];
+ } else if (mode_is_int(mode) || mode_is_reference(mode)) {
+ unsigned num_regparam;
+
+ if (get_mode_size_bits(mode) > 32)
+ return NULL;
+
+ if (nr >= MAXNUM_GPREG_ARGS)
+ return NULL;
+
+ if (cc & cc_this_call) {
+ return gpreg_param_reg_this[nr];
+ }
+ num_regparam = cc & ~cc_bits;
+ if (num_regparam == 0) {
+ /* default fastcall */
+ return gpreg_param_reg_fastcall[nr];
+ }
+ if (nr < num_regparam)
+ return gpreg_param_reg_regparam[nr];
+ return NULL;
+ }
+
+ panic("unknown argument mode");
+}
+
/**
* Get the ABI restrictions for procedure calls.
* @param self The this pointer.
int clobbers_flags = 0;
unsigned clobber_bits[N_CLASSES];
int out_size;
+ backend_info_t *info;
memset(&clobber_bits, 0, sizeof(clobber_bits));
if (arity == 0)
be_dep_on_frame(new_node);
- set_ia32_out_req_all(new_node, out_reg_reqs);
+ info = be_get_info(new_node);
+ for (i = 0; i < out_arity; ++i) {
+ info->out_infos[i].req = out_reg_reqs[i];
+ }
set_ia32_in_req_all(new_node, in_reg_reqs);
SET_IA32_ORIG_NODE(new_node, node);
}
}
+static inline bool is_unknown_reg(const arch_register_t *reg)
+{
+ if(reg == &ia32_gp_regs[REG_GP_UKNWN]
+ || reg == &ia32_xmm_regs[REG_XMM_UKNWN]
+ || reg == &ia32_vfp_regs[REG_VFP_UKNWN])
+ return true;
+
+ return false;
+}
+
/**
* Emits code for Copy/CopyKeep.
*/
return 32;
}
+static inline bool is_unknown_reg(const arch_register_t *reg)
+{
+ if(reg == &ia32_gp_regs[REG_GP_UKNWN]
+ || reg == &ia32_xmm_regs[REG_XMM_UKNWN]
+ || reg == &ia32_vfp_regs[REG_VFP_UKNWN])
+ return true;
+
+ return false;
+}
+
/**
* Insert copies for all ia32 nodes where the should_be_same requirement
* is not fulfilled.
*/
static void assure_should_be_same_requirements(ir_node *node)
{
- const arch_register_req_t **reqs;
const arch_register_t *out_reg, *in_reg;
int n_res, i;
ir_node *in_node, *block;
- reqs = get_ia32_out_req_all(node);
n_res = arch_irn_get_n_outs(node);
block = get_nodes_block(node);
ir_node *perm_proj0;
ir_node *perm_proj1;
ir_node *uses_out_reg;
- const arch_register_req_t *req = reqs[i];
+ const arch_register_req_t *req = arch_get_out_register_req(node, i);
const arch_register_class_t *cls;
int uses_out_reg_pos;
same_pos = get_first_same(req);
/* get in and out register */
- out_reg = arch_irn_get_register(node, i);
- in_node = get_irn_n(node, same_pos);
- in_reg = arch_get_irn_register(in_node);
+ out_reg = arch_irn_get_register(node, i);
+ in_node = get_irn_n(node, same_pos);
+ in_reg = arch_get_irn_register(in_node);
/* requirement already fulfilled? */
if (in_reg == out_reg)
*/
static void fix_am_source(ir_node *irn)
{
- const arch_register_req_t **reqs;
int n_res, i;
/* check only ia32 nodes with source address mode */
if (get_ia32_am_support(irn) != ia32_am_binary)
return;
- reqs = get_ia32_out_req_all(irn);
n_res = arch_irn_get_n_outs(irn);
for (i = 0; i < n_res; i++) {
- const arch_register_t *out_reg;
- int same_pos;
- ir_node *same_node;
- const arch_register_t *same_reg;
- ir_node *load_res;
+ const arch_register_req_t *req = arch_get_out_register_req(irn, i);
+ const arch_register_t *out_reg;
+ int same_pos;
+ ir_node *same_node;
+ const arch_register_t *same_reg;
+ ir_node *load_res;
- if (!arch_register_req_is(reqs[i], should_be_same))
+ if (!arch_register_req_is(req, should_be_same))
continue;
/* get in and out register */
out_reg = arch_irn_get_register(irn, i);
- same_pos = get_first_same(reqs[i]);
+ same_pos = get_first_same(req);
same_node = get_irn_n(irn, same_pos);
same_reg = arch_get_irn_register(same_node);
#include "gen_ia32_regalloc_if.h"
#include "bearch_ia32_t.h"
-#define MAXNUM_GPREG_ARGS 3
-#define MAXNUM_SSE_ARGS 8
-
/* this is the order of the assigned registers used for parameter passing */
-static const arch_register_t *gpreg_param_reg_fastcall[] = {
- &ia32_gp_regs[REG_ECX],
- &ia32_gp_regs[REG_EDX],
- NULL
-};
-
-static const arch_register_t *gpreg_param_reg_regparam[] = {
- &ia32_gp_regs[REG_EAX],
- &ia32_gp_regs[REG_EDX],
- &ia32_gp_regs[REG_ECX]
-};
-
-static const arch_register_t *gpreg_param_reg_this[] = {
- &ia32_gp_regs[REG_ECX],
- NULL,
- NULL
-};
-
-static const arch_register_t *fpreg_sse_param_reg_std[] = {
- &ia32_xmm_regs[REG_XMM0],
- &ia32_xmm_regs[REG_XMM1],
- &ia32_xmm_regs[REG_XMM2],
- &ia32_xmm_regs[REG_XMM3],
- &ia32_xmm_regs[REG_XMM4],
- &ia32_xmm_regs[REG_XMM5],
- &ia32_xmm_regs[REG_XMM6],
- &ia32_xmm_regs[REG_XMM7]
-};
-
-static const arch_register_t *fpreg_sse_param_reg_this[] = {
- NULL, /* in case of a "this" pointer, the first parameter must not be a float */
-};
-
-
-/* Mapping to store registers in firm nodes */
-
-struct ia32_irn_reg_assoc {
- const ir_node *irn;
- const arch_register_t *reg;
-};
-
-int ia32_cmp_irn_reg_assoc(const void *a, const void *b, size_t len) {
- const struct ia32_irn_reg_assoc *x = a;
- const struct ia32_irn_reg_assoc *y = b;
- (void) len;
-
- return x->irn != y->irn;
-}
-
-static struct ia32_irn_reg_assoc *get_irn_reg_assoc(const ir_node *irn, set *reg_set) {
- struct ia32_irn_reg_assoc templ;
- unsigned int hash;
-
- templ.irn = irn;
- templ.reg = NULL;
- hash = hash_irn(irn);
-
- return set_insert(reg_set, &templ, sizeof(templ), hash);
-}
-
-void ia32_set_firm_reg(ir_node *irn, const arch_register_t *reg, set *reg_set) {
- struct ia32_irn_reg_assoc *assoc = get_irn_reg_assoc(irn, reg_set);
- assoc->reg = reg;
-}
-
-const arch_register_t *ia32_get_firm_reg(const ir_node *irn, set *reg_set) {
- struct ia32_irn_reg_assoc *assoc = get_irn_reg_assoc(irn, reg_set);
- return assoc->reg;
-}
void ia32_build_16bit_reg_map(pmap *reg_map) {
pmap_insert(reg_map, &ia32_gp_regs[REG_EAX], "ax");
return e->value;
}
-
-/**
- * Returns the register for parameter nr.
- */
-const arch_register_t *ia32_get_RegParam_reg(unsigned cc, size_t nr,
- const ir_mode *mode)
-{
- if ((cc & cc_this_call) && nr == 0)
- return gpreg_param_reg_this[0];
-
- if (! (cc & cc_reg_param))
- return NULL;
-
- if (mode_is_float(mode)) {
- if (!ia32_cg_config.use_sse2 || (cc & cc_fpreg_param) == 0)
- return NULL;
- if (nr >= MAXNUM_SSE_ARGS)
- return NULL;
-
- if (cc & cc_this_call) {
- return fpreg_sse_param_reg_this[nr];
- }
- return fpreg_sse_param_reg_std[nr];
- } else if (mode_is_int(mode) || mode_is_reference(mode)) {
- unsigned num_regparam;
-
- if (get_mode_size_bits(mode) > 32)
- return NULL;
-
- if (nr >= MAXNUM_GPREG_ARGS)
- return NULL;
-
- if (cc & cc_this_call) {
- return gpreg_param_reg_this[nr];
- }
- num_regparam = cc & ~cc_bits;
- if (num_regparam == 0) {
- /* default fastcall */
- return gpreg_param_reg_fastcall[nr];
- }
- if (nr < num_regparam)
- return gpreg_param_reg_regparam[nr];
- return NULL;
- }
-
- panic("unknown argument mode");
-}
#include "bearch_ia32_t.h"
#include "gen_ia32_regalloc_if.h"
-/**
- * Set compare function
- */
-int ia32_cmp_irn_reg_assoc(const void *a, const void *b, size_t len);
-
-/**
- * Assigns a register to a firm node.
- */
-void ia32_set_firm_reg(ir_node *irn, const arch_register_t *reg, set *reg_set);
-
-/**
- * Gets the register assigned to a firm node.
- */
-const arch_register_t *ia32_get_firm_reg(const ir_node *irn, set *reg_set);
-
/**
* Enters for each general purpose register the corresponding 16bit
* name into a pmap.
*/
const char *ia32_get_mapped_reg_name(pmap *reg_map, const arch_register_t *reg);
-/**
- * Returns the register for parameter nr.
- */
-const arch_register_t *ia32_get_RegParam_reg(unsigned cc, size_t nr,
- const ir_mode *mode);
-
-static inline int is_unknown_reg(const arch_register_t *reg)
-{
- if(reg == &ia32_gp_regs[REG_GP_UKNWN]
- || reg == &ia32_xmm_regs[REG_XMM_UKNWN]
- || reg == &ia32_vfp_regs[REG_VFP_UKNWN])
- return 1;
-
- return 0;
-}
-
-#endif /* FIRM_BE_IA32_IA32_MAP_REGS_H */
+#endif
* |_|
***********************************************************************************/
-/**
- * Dumps the register requirements for either in or out.
- */
-static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs,
- int inout) {
- char *dir = inout ? "out" : "in";
- int max = inout ? (int) arch_irn_get_n_outs(n) : get_irn_arity(n);
- char buf[1024];
- int i;
-
- memset(buf, 0, sizeof(buf));
-
- if (reqs) {
- for (i = 0; i < max; i++) {
- fprintf(F, "%sreq #%d =", dir, i);
- arch_dump_register_req(F, reqs[i], n);
- fprintf(F, "\n");
- }
-
- fprintf(F, "\n");
- }
- else {
- fprintf(F, "%sreq = N/A\n", dir);
- }
-}
-
/**
* Dumper interface for dumping ia32 nodes in vcg.
* @param n the node to dump
static int ia32_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
ir_mode *mode = NULL;
int bad = 0;
- int i, n_res, flags;
- const arch_register_req_t **reqs;
switch (reason) {
case dump_node_opcode_txt:
break;
case dump_node_info_txt:
- fprintf(F, "=== IA32 attr begin ===\n");
-
- /* dump IN requirements */
- if (get_irn_arity(n) > 0) {
- reqs = get_ia32_in_req_all(n);
- dump_reg_req(F, n, reqs, 0);
- }
-
- n_res = arch_irn_get_n_outs(n);
- if (n_res > 0) {
- /* dump OUT requirements */
- reqs = get_ia32_out_req_all(n);
- dump_reg_req(F, n, reqs, 1);
-
- /* dump assigned registers */
- for (i = 0; i < n_res; i++) {
- const arch_register_t *reg = arch_irn_get_register(n, i);
-
- fprintf(F, "reg #%d = %s\n", i, reg ? arch_register_get_name(reg) : "n/a");
- }
- fprintf(F, "\n");
- }
+ arch_dump_reqs_and_registers(F, n);
/* dump op type */
fprintf(F, "op = ");
fprintf(F, "size = %u\n", get_ia32_copyb_size(n));
}
- fprintf(F, "n_res = %d\n", n_res);
fprintf(F, "use_frame = %d\n", is_ia32_use_frame(n));
fprintf(F, "commutative = %d\n", is_ia32_commutative(n));
fprintf(F, "need stackent = %d\n", is_ia32_need_stackent(n));
fprintf(F, "is reload = %d\n", is_ia32_is_reload(n));
fprintf(F, "latency = %d\n", get_ia32_latency(n));
- /* dump flags */
- fprintf(F, "flags =");
- flags = arch_irn_get_flags(n);
- if (flags == arch_irn_flags_none) {
- fprintf(F, " none");
- }
- else {
- if (flags & arch_irn_flags_dont_spill) {
- fprintf(F, " unspillable");
- }
- if (flags & arch_irn_flags_rematerializable) {
- fprintf(F, " remat");
- }
- if (flags & arch_irn_flags_modify_flags) {
- fprintf(F, " modify_flags");
- }
- }
- fprintf(F, " (%d)\n", flags);
-
/* dump frame entity */
fprintf(F, "frame entity = ");
if (get_ia32_frame_ent(n)) {
fprintf(F, "\n");
#endif /* NDEBUG */
- fprintf(F, "=== IA32 attr end ===\n");
- /* end of: case dump_node_info_txt */
break;
}
attr->in_req = reqs;
}
-/**
- * Returns the result register requirements of an ia32 node.
- */
-const arch_register_req_t **get_ia32_out_req_all(const ir_node *node) {
- const ia32_attr_t *attr = get_ia32_attr_const(node);
- return attr->out_req;
-}
-
-/**
- * Sets the result register requirements of an ia32 node.
- */
-void set_ia32_out_req_all(ir_node *node, const arch_register_req_t **reqs) {
- ia32_attr_t *attr = get_ia32_attr(node);
- attr->out_req = reqs;
-}
-
/**
* Returns the argument register requirement at position pos of an ia32 node.
*/
/**
* Returns the result register requirement at position pos of an ia32 node.
*/
-const arch_register_req_t *get_ia32_out_req(const ir_node *node, int pos) {
- const ia32_attr_t *attr = get_ia32_attr_const(node);
- if(attr->out_req == NULL)
- return arch_no_register_req;
-
- return attr->out_req[pos];
-}
-
-/**
- * Sets the OUT register requirements at position pos.
- */
-void set_ia32_req_out(ir_node *node, const arch_register_req_t *req, int pos) {
- ia32_attr_t *attr = get_ia32_attr(node);
- attr->out_req[pos] = req;
+const arch_register_req_t *get_ia32_out_req(const ir_node *node, int pos)
+{
+ backend_info_t *info = be_get_info(node);
+ return info->out_infos[pos].req;
}
/**
* Sets the IN register requirements at position pos.
*/
-void set_ia32_req_in(ir_node *node, const arch_register_req_t *req, int pos) {
+void set_ia32_req_in(ir_node *node, const arch_register_req_t *req, int pos)
+{
ia32_attr_t *attr = get_ia32_attr(node);
attr->in_req[pos] = req;
}
/**
* Get the list of available execution units.
*/
-const be_execution_unit_t ***get_ia32_exec_units(const ir_node *node) {
+const be_execution_unit_t ***get_ia32_exec_units(const ir_node *node)
+{
const ia32_attr_t *attr = get_ia32_attr_const(node);
return attr->exec_units;
}
/**
* Get the exception label attribute.
*/
-unsigned get_ia32_exc_label(const ir_node *node) {
+unsigned get_ia32_exc_label(const ir_node *node)
+{
const ia32_attr_t *attr = get_ia32_attr_const(node);
return attr->data.has_except_label;
}
/**
* Set the exception label attribute.
*/
-void set_ia32_exc_label(ir_node *node, unsigned flag) {
+void set_ia32_exc_label(ir_node *node, unsigned flag)
+{
ia32_attr_t *attr = get_ia32_attr(node);
attr->data.has_except_label = flag;
}
/**
* Return the exception label id.
*/
-ir_label_t get_ia32_exc_label_id(const ir_node *node) {
+ir_label_t get_ia32_exc_label_id(const ir_node *node)
+{
const ia32_attr_t *attr = get_ia32_attr_const(node);
assert(attr->data.has_except_label);
/**
* Assign the exception label id.
*/
-void set_ia32_exc_label_id(ir_node *node, ir_label_t id) {
+void set_ia32_exc_label_id(ir_node *node, ir_label_t id)
+{
ia32_attr_t *attr = get_ia32_attr(node);
assert(attr->data.has_except_label);
*/
void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags,
const arch_register_req_t **in_reqs,
- const arch_register_req_t **out_reqs,
const be_execution_unit_t ***execution_units,
int n_res)
{
arch_irn_set_flags(node, flags);
set_ia32_in_req_all(node, in_reqs);
- set_ia32_out_req_all(node, out_reqs);
attr->exec_units = execution_units;
#ifndef NDEBUG
*/
void set_ia32_in_req_all(ir_node *node, const arch_register_req_t **reqs);
-/**
- * Returns the result register requirements of an ia32 node.
- */
-const arch_register_req_t **get_ia32_out_req_all(const ir_node *node);
-
-/**
- * Sets the result register requirements of an ia32 node.
- */
-void set_ia32_out_req_all(ir_node *node, const arch_register_req_t **reqs);
-
/**
* Returns the argument register requirements of an ia32 node.
*/
const arch_register_req_t *get_ia32_in_req(const ir_node *node, int pos);
-
-/**
- * Returns the result register requirements of an ia32 node.
- */
const arch_register_req_t *get_ia32_out_req(const ir_node *node, int pos);
-/**
- * Sets the OUT register requirements at position pos.
- */
-void set_ia32_req_out(ir_node *node, const arch_register_req_t *req, int pos);
-
/**
* Sets the IN register requirements at position pos.
*/
*/
void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags,
const arch_register_req_t **in_reqs,
- const arch_register_req_t **out_reqs,
const be_execution_unit_t ***execution_units,
int n_res);
const be_execution_unit_t ***exec_units; /**< list of units this operation can be executed on */
const arch_register_req_t **in_req; /**< register requirements for arguments */
- const arch_register_req_t **out_req; /**< register requirements for results */
ir_label_t exc_label; /**< the exception label iff this instruction can throw an exception */
%init_attr = (
ia32_asm_attr_t =>
- "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
+ "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
"\tinit_ia32_x87_attributes(res);".
"\tinit_ia32_asm_attributes(res);",
ia32_attr_t =>
- "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);",
+ "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);",
ia32_call_attr_t =>
- "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
+ "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
"\tinit_ia32_call_attributes(res, pop, call_tp);",
ia32_condcode_attr_t =>
- "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
+ "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
"\tinit_ia32_condcode_attributes(res, pnc);",
ia32_copyb_attr_t =>
- "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
+ "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
"\tinit_ia32_copyb_attributes(res, size);",
ia32_immediate_attr_t =>
- "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
+ "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
"\tinit_ia32_immediate_attributes(res, symconst, symconst_sign, no_pic_adjust, offset);",
ia32_x87_attr_t =>
- "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
+ "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
"\tinit_ia32_x87_attributes(res);",
ia32_climbframe_attr_t =>
- "\tinit_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
+ "\tinit_ia32_attributes(res, flags, in_reqs, exec_units, n_res);\n".
"\tinit_ia32_climbframe_attributes(res, count);",
);
# very strict constraints
op_flags => "C",
cmp_attr => "return 1;",
+ reg_req => { in => [ "none", "none" ],
+ out => [ "none", "none", "none", "none" ] },
+ ins => [ "left", "right" ],
outs => [ "res_low", "flags", "M", "res_high" ],
- arity => 2
},
IMul => {
l_IMul => {
op_flags => "C",
cmp_attr => "return 1;",
+ reg_req => { in => [ "none", "none" ],
+ out => [ "none", "none", "none", "none" ] },
+ ins => [ "left", "right" ],
outs => [ "res_low", "flags", "M", "res_high" ],
- arity => 2
},
And => {
l_ShlDep => {
cmp_attr => "return 1;",
+ reg_req => { in => [ "none", "none", "none" ], out => [ "none" ] },
ins => [ "val", "count", "dep" ],
- arity => 3
},
ShlD => {
l_ShlD => {
cmp_attr => "return 1;",
+ reg_req => { in => [ "none", "none", "none" ], out => [ "none" ] },
ins => [ "val_high", "val_low", "count" ],
- arity => 3,
},
Shr => {
l_ShrDep => {
cmp_attr => "return 1;",
+ reg_req => { in => [ "none", "none", "none" ], out => [ "none" ] },
ins => [ "val", "count", "dep" ],
- arity => 3
},
ShrD => {
l_ShrD => {
cmp_attr => "return 1;",
- arity => 3,
+ reg_req => { in => [ "none", "none", "none" ], out => [ "none" ] },
ins => [ "val_high", "val_low", "count" ],
},
l_SarDep => {
cmp_attr => "return 1;",
ins => [ "val", "count", "dep" ],
- arity => 3
+ reg_req => { in => [ "none", "none", "none" ], out => [ "none" ] },
},
Ror => {
xStoreSimple => {
op_flags => "L|F",
state => "exc_pinned",
- reg_req => { in => [ "gp", "gp", "none", "xmm" ] },
+ reg_req => { in => [ "gp", "gp", "none", "xmm" ], out => [ "none" ] },
ins => [ "base", "index", "mem", "val" ],
+ outs => [ "M" ],
emit => '. mov%XXM %S3, %AM',
latency => 0,
units => [ "SSE" ],
op_flags => "L|F",
cmp_attr => "return 1;",
ins => [ "val_high", "val_low" ],
+ reg_req => { in => [ "none", "none" ], out => [ "none" ] }
},
l_FloattoLL => {
cmp_attr => "return 1;",
ins => [ "val" ],
outs => [ "res_high", "res_low" ],
+ reg_req => { in => [ "none" ], out => [ "none", "none" ] }
},
# CopyB
vfist => {
state => "exc_pinned",
- reg_req => { in => [ "gp", "gp", "none", "vfp", "fpcw" ] },
+ reg_req => { in => [ "gp", "gp", "none", "vfp", "fpcw" ], out => [ "none" ] },
ins => [ "base", "index", "mem", "val", "fpcw" ],
+ outs => [ "M" ],
latency => 4,
units => [ "VFP" ],
mode => "mode_M",
fxch => {
op_flags => "R|K",
- reg_req => { },
+ reg_req => { out => [ "none" ] },
cmp_attr => "return 1;",
emit => '. fxch %X0',
attr_type => "ia32_x87_attr_t",
fpush => {
op_flags => "R|K",
- reg_req => {},
+ reg_req => { out => [ "none" ] },
cmp_attr => "return 1;",
emit => '. fld %X0',
attr_type => "ia32_x87_attr_t",
fpop => {
op_flags => "K",
- reg_req => { },
+ reg_req => { out => [ "none" ] },
cmp_attr => "return 1;",
emit => '. fstp %X0',
attr_type => "ia32_x87_attr_t",
ffreep => {
op_flags => "K",
- reg_req => { },
+ reg_req => { out => [ "none" ] },
cmp_attr => "return 1;",
emit => '. ffreep %X0',
attr_type => "ia32_x87_attr_t",
emms => {
op_flags => "K",
- reg_req => { },
+ reg_req => { out => [ "none" ] },
cmp_attr => "return 1;",
emit => '. emms',
attr_type => "ia32_x87_attr_t",
femms => {
op_flags => "K",
- reg_req => { },
+ reg_req => { out => [ "none" ] },
cmp_attr => "return 1;",
emit => '. femms',
attr_type => "ia32_x87_attr_t",
* |_|
***********************************************************************************/
-/**
- * Dumps the register requirements for either in or out.
- */
-static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs,
- int inout)
-{
- char *dir = inout ? "out" : "in";
- int max = inout ? (int) arch_irn_get_n_outs(n) : get_irn_arity(n);
- char buf[1024];
- int i;
-
- memset(buf, 0, sizeof(buf));
-
- if (reqs) {
- for (i = 0; i < max; i++) {
- fprintf(F, "%sreq #%d =", dir, i);
- arch_dump_register_req(F, reqs[i], n);
- fprintf(F, "\n");
- }
-
- fprintf(F, "\n");
- } else {
- fprintf(F, "%sreq = N/A\n", dir);
- }
-}
-
-
/**
* Dumper interface for dumping mips nodes in vcg.
* @param n the node to dump
* @param reason indicates which kind of information should be dumped
* @return 0 on success or != 0 on failure
*/
-static int mips_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
- int bad = 0;
- int i, n_res, flags;
- const arch_register_req_t **reqs;
-
+static int mips_dump_node(ir_node *n, FILE *F, dump_reason_t reason)
+{
switch (reason) {
case dump_node_opcode_txt:
fprintf(F, "%s", get_irn_opname(n));
break;
case dump_node_info_txt:
- fprintf(F, "=== mips attr begin ===\n");
-
- /* dump IN requirements */
- if (get_irn_arity(n) > 0) {
- reqs = get_mips_in_req_all(n);
- dump_reg_req(F, n, reqs, 0);
- }
-
- n_res = arch_irn_get_n_outs(n);
- if (n_res > 0) {
- /* dump OUT requirements */
- reqs = get_mips_out_req_all(n);
- dump_reg_req(F, n, reqs, 1);
-
- /* dump assigned registers */
- for (i = 0; i < n_res; i++) {
- const arch_register_t *reg = arch_irn_get_register(n, i);
-
- fprintf(F, "reg #%d = %s\n", i, reg ? arch_register_get_name(reg) : "n/a");
- }
- fprintf(F, "\n");
- }
-
- /* dump n_res */
- fprintf(F, "n_res = %d\n", n_res);
-
- /* dump flags */
- fprintf(F, "flags =");
- flags = arch_irn_get_flags(n);
- if (flags == arch_irn_flags_none) {
- fprintf(F, " none");
- }
- else {
- if (flags & arch_irn_flags_dont_spill) {
- fprintf(F, " unspillable");
- }
- if (flags & arch_irn_flags_rematerializable) {
- fprintf(F, " remat");
- }
- if (flags & arch_irn_flags_modify_flags) {
- fprintf(F, " modify_flags");
- }
- }
- fprintf(F, " (%d)\n", flags);
-
- fprintf(F, "=== mips attr end ===\n");
- /* end of: case dump_node_info_txt */
+ arch_dump_reqs_and_registers(F, n);
break;
}
-
- return bad;
+ return 0;
}
return attr->in_req;
}
-/**
- * Returns the result register requirements of an mips node.
- */
-const arch_register_req_t **get_mips_out_req_all(const ir_node *node)
-{
- const mips_attr_t *attr = get_mips_attr_const(node);
- return attr->out_req;
-}
-
/**
* Returns the argument register requirement at position pos of an mips node.
*/
*/
const arch_register_req_t *get_mips_out_req(const ir_node *node, int pos)
{
- const mips_attr_t *attr = get_mips_attr_const(node);
- return attr->out_req[pos];
-}
-
-/**
- * Sets the OUT register requirements at position pos.
- */
-void set_mips_req_out(ir_node *node, const arch_register_req_t *req, int pos)
-{
- mips_attr_t *attr = get_mips_attr(node);
- attr->out_req[pos] = req;
+ const backend_info_t *info = be_get_info(node);
+ return info->out_infos[pos].req;
}
/**
*/
static void init_mips_attributes(ir_node *node, arch_irn_flags_t flags,
const arch_register_req_t **in_reqs,
- const arch_register_req_t **out_reqs,
const be_execution_unit_t ***execution_units,
int n_res)
{
(void) execution_units;
arch_irn_set_flags(node, flags);
- attr->out_req = out_reqs;
attr->in_req = in_reqs;
info = be_get_info(node);
*/
const arch_register_req_t **get_mips_in_req_all(const ir_node *node);
-/**
- * Returns the result register requirements of an mips node.
- */
-const arch_register_req_t **get_mips_out_req_all(const ir_node *node);
-
/**
* Returns the argument register requirements of an mips node.
*/
int switch_default_pn; /**< proj number of default case in switch */
const arch_register_req_t **in_req; /**< register requirements for arguments */
- const arch_register_req_t **out_req; /**< register requirements for results */
} mips_attr_t;
typedef enum mips_immediate_type_t {
$mode_gp = "mode_Iu";
%init_attr = (
- mips_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);",
+ mips_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, exec_units, n_res);",
- mips_immediate_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
+ mips_immediate_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, exec_units, n_res);\n".
"\tinit_mips_immediate_attributes(res, imm_type, entity, val);",
- mips_load_store_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);\n".
+ mips_load_store_attr_t => "\tinit_mips_attributes(res, flags, in_reqs, exec_units, n_res);\n".
"\tinit_mips_load_store_attributes(res, entity, offset);",
);
* |_|
***********************************************************************************/
-/**
- * Dumps the register requirements for either in or out.
- */
-static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs, int inout) {
- char *dir = inout ? "out" : "in";
- int max = inout ? (int) arch_irn_get_n_outs(n) : get_irn_arity(n);
- char buf[1024];
- int i;
-
- memset(buf, 0, sizeof(buf));
-
- if (reqs) {
- for (i = 0; i < max; i++) {
- fprintf(F, "%sreq #%d =", dir, i);
- arch_dump_register_req(F, reqs[i], n);
- fprintf(F, "\n");
- }
-
- fprintf(F, "\n");
- } else {
- fprintf(F, "%sreq = N/A\n", dir);
- }
-}
-
-
/**
* Dumper interface for dumping ppc32 nodes in vcg.
* @param n the node to dump
* @param reason indicates which kind of information should be dumped
* @return 0 on success or != 0 on failure
*/
-static int ppc32_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
+static int ppc32_dump_node(ir_node *n, FILE *F, dump_reason_t reason)
+{
ir_mode *mode = NULL;
int bad = 0;
- int i, n_res, flags;
- const arch_register_req_t **reqs;
switch (reason) {
case dump_node_opcode_txt:
break;
case dump_node_info_txt:
- fprintf(F, "=== ppc attr begin ===\n");
-
- /* dump IN requirements */
- if (get_irn_arity(n) > 0) {
- reqs = get_ppc32_in_req_all(n);
- dump_reg_req(F, n, reqs, 0);
- }
-
- n_res = arch_irn_get_n_outs(n);
- if (n_res > 0) {
- /* dump OUT requirements */
- reqs = get_ppc32_out_req_all(n);
- dump_reg_req(F, n, reqs, 1);
-
- /* dump assigned registers */
- for (i = 0; i < n_res; i++) {
- const arch_register_t *reg = arch_irn_get_register(n, i);
-
- fprintf(F, "reg #%d = %s\n", i, reg ? arch_register_get_name(reg) : "n/a");
- }
- fprintf(F, "\n");
- }
-
- /* dump n_res */
- fprintf(F, "n_res = %d\n", n_res);
-
- /* dump flags */
- fprintf(F, "flags =");
- flags = arch_irn_get_flags(n);
- if (flags == arch_irn_flags_none) {
- fprintf(F, " none");
- }
- else {
- if (flags & arch_irn_flags_dont_spill) {
- fprintf(F, " unspillable");
- }
- if (flags & arch_irn_flags_rematerializable) {
- fprintf(F, " remat");
- }
- if (flags & arch_irn_flags_modify_flags) {
- fprintf(F, " modify_flags");
- }
- }
- fprintf(F, " (%d)\n", flags);
-
- /* TODO: dump all additional attributes */
-
- fprintf(F, "=== ppc attr end ===\n");
- /* end of: case dump_node_info_txt */
+ arch_dump_reqs_and_registers(F, n);
break;
}
return attr->in_req;
}
-/**
- * Returns the result register requirements of an ppc node.
- */
-const arch_register_req_t **get_ppc32_out_req_all(const ir_node *node) {
- const ppc32_attr_t *attr = get_ppc32_attr_const(node);
- return attr->out_req;
-}
-
/**
* Returns the argument register requirement at position pos of an ppc node.
*/
/**
* Returns the result register requirement at position pos of an ppc node.
*/
-const arch_register_req_t *get_ppc32_out_req(const ir_node *node, int pos) {
- const ppc32_attr_t *attr = get_ppc32_attr_const(node);
- return attr->out_req[pos];
-}
-
-/**
- * Sets the OUT register requirements at position pos.
- */
-void set_ppc32_req_out(ir_node *node, const arch_register_req_t *req, int pos) {
- ppc32_attr_t *attr = get_ppc32_attr(node);
- attr->out_req[pos] = req;
+const arch_register_req_t *get_ppc32_out_req(const ir_node *node, int pos)
+{
+ const backend_info_t *info = be_get_info(node);
+ return info->out_infos[pos].req;
}
/**
* Initializes ppc specific node attributes
*/
void init_ppc32_attributes(ir_node *node, int flags,
- const arch_register_req_t **in_reqs, const arch_register_req_t **out_reqs,
+ const arch_register_req_t **in_reqs,
const be_execution_unit_t ***execution_units,
int n_res) {
ir_graph *irg = get_irn_irg(node);
arch_irn_set_flags(node, flags);
attr->in_req = in_reqs;
- attr->out_req = out_reqs;
attr->content_type = ppc32_ac_None;
attr->offset_mode = ppc32_ao_Illegal;
*/
const arch_register_req_t **get_ppc32_in_req_all(const ir_node *node);
-/**
- * Returns the result register requirements of an ppc node.
- */
-const arch_register_req_t **get_ppc32_out_req_all(const ir_node *node);
-
/**
* Returns the argument register requirements of an ppc node.
*/
*/
const arch_register_req_t *get_ppc32_out_req(const ir_node *node, int pos);
-/**
- * Sets the OUT register requirements at position pos.
- */
-void set_ppc32_req_out(ir_node *node, const arch_register_req_t *req, int pos);
-
/**
* Sets the IN register requirements at position pos.
*/
except_attr exc; /**< the exception attribute. MUST be the first one. */
const arch_register_req_t **in_req; /**< register requirements for arguments */
- const arch_register_req_t **out_req; /**< register requirements for results */
ppc32_attr_content_type content_type;
ppc32_attr_offset_mode offset_mode;
}
if(!defined(%init_attr)) {
%init_attr = (
- "$default_attr_type" => "\tinit_${arch}_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res);",
+ "$default_attr_type" => "\tinit_${arch}_attributes(res, flags, in_reqs, exec_units, n_res);",
);
}
if(!defined($default_cmp_attr)) {
# emit constructor code
if (!exists($n{"rd_constructor"})) { # default constructor
- $temp = "\tir_node *res;\n";
- $temp .= "\tir_op *op = op_${op};\n";
- $temp .= "\tint flags = 0;\n";
+ $temp = <<EOF;
+ ir_node *res;
+ ir_op *op = op_${op};
+ int flags = 0;
+ backend_info_t *info;
+EOF
if($arity == $ARITY_DYNAMIC) {
- $temp .= "\tint arity = -1;\n";
- $temp .= "\tir_node **in = NULL;\n";
+ $temp .= <<EOF;
+ int arity = -1;
+ ir_node **in = NULL;
+EOF
} elsif($arity == $ARITY_VARIABLE) {
} else {
- $temp .= "\tint arity = $arity;\n";
+ $temp .= <<EOF;
+ int arity = $arity;
+EOF
if($arity > 0) {
- $temp .= "\tir_node *in[$arity];\n";
+ $temp .= <<EOF;
+ ir_node *in[$arity];
+EOF
} else {
- $temp .= "\tir_node **in = NULL;\n";
+ $temp .= <<EOF;
+ ir_node **in = NULL;
+EOF
}
}
if($out_arity == $ARITY_DYNAMIC) {
- $temp .= "\tint n_res = -1;\n";
+ $temp .= <<EOF;
+ int n_res = -1;
+EOF
} elsif($out_arity == $ARITY_VARIABLE) {
} else {
- $temp .= "\tint n_res = ${out_arity};\n";
+ $temp .= <<EOF;
+ int n_res = ${out_arity};
+EOF
}
if (defined($known_mode)) {
- $temp .= "\tir_mode *mode = ${known_mode};\n";
+ $temp .= <<EOF;
+ ir_mode *mode = ${known_mode};
+EOF
}
# set up static variables for cpu execution unit assigments
if (exists($n{"units"})) {
$temp .= gen_execunit_list_initializer($n{"units"});
} else {
- $temp .= "\tstatic const be_execution_unit_t ***exec_units = NULL;\n";
+ $temp .= <<EOF;
+ static const be_execution_unit_t ***exec_units = NULL;
+EOF
}
undef my $in_req_var;
undef my $out_req_var;
+ my $set_out_reqs = "";
+
# set up static variables for requirements and registers
if (exists($n{"reg_req"})) {
my %req = %{ $n{"reg_req"} };
die "Fatal error: Out-Arity and number of out requirements don't match for ${op}\n";
}
- $temp .= "\tstatic const arch_register_req_t *out_reqs[] =\n";
- $temp .= "\t{\n";
for ($idx = 0; $idx <= $#out; $idx++) {
my $req = $out[$idx];
my $reqstruct = generate_requirements($req, \%n, $op, $idx, 0);
- $temp .= "\t\t& ${reqstruct},\n";
+ $set_out_reqs .= <<EOF;
+ info->out_infos[${idx}].req = &${reqstruct};
+EOF
}
- $temp .= "\t};\n";
} else {
if($out_arity > 0) {
die "Fatal error: need out requirements for ${op}\n";
}
- $temp .= "\tstatic const arch_register_req_t **out_reqs = NULL;\n";
}
} else {
$temp .= "\tstatic const arch_register_req_t **in_reqs = NULL;\n";
- $temp .= "\tstatic const arch_register_req_t **out_reqs = NULL;\n";
}
if(exists($n{"init_attr"})) {
$temp .= "\t${attr_type} *attr;\n";
$temp .= "\n";
}
- $temp .= "\t/* create node */\n";
- $temp .= "\tassert(op != NULL);\n";
- $temp .= "\tres = new_ir_node(db, current_ir_graph, block, op, mode, arity, in);\n";
- $temp .= "\n";
-
- $temp .= "\t/* init node attributes */\n";
# lookup init function
my $attr_init_code = $init_attr{$attr_type};
if(!defined($attr_init_code)) {
die "Fatal error: Couldn't find attribute initialisation code for type '${attr_type}'";
}
- $temp .= "${attr_init_code}\n";
+ my $custominit = "";
if(defined($custom_init_attr_func)) {
- $temp .= &$custom_init_attr_func(\%n, $op);
+ $custominit .= &$custom_init_attr_func(\%n, $op);
}
- $temp .= "\n";
+
+ $temp .= <<EOF;
+ /* create node */
+ assert(op != NULL);
+ res = new_ir_node(db, current_ir_graph, block, op, mode, arity, in);
+
+ /* init node attributes */
+ ${attr_init_code}
+ ${custominit}
+ info = be_get_info(res);
+ ${set_out_reqs}
+
+EOF
if (exists($n{"init_attr"})) {
$temp .= "\tattr = get_irn_generic_attr(res);\n";
$temp .= "\t".$n{"init_attr"}."\n";
}
- $temp .= "\t/* optimize node */\n";
- $temp .= "\tres = optimize_node(res);\n";
- $temp .= "\tirn_vrfy_irg(res, current_ir_graph);\n";
- $temp .= "\n";
+ $temp .= <<EOF;
+ /* optimize node */
+ res = optimize_node(res);
+ irn_vrfy_irg(res, current_ir_graph);
- $temp .= "\treturn res;\n";
+ return res;
+EOF
push(@obst_constructor, $temp);
}
#include "gen_${arch}_regalloc_if.h"
#include "gen_${arch}_machine.h"
#include "bearch_${arch}_t.h"
-#include "${arch}_map_regs.h"
#include "irmode.h"
${single_constraints_decls}