initial checkin for TEMPLATE backend
authorChristian Würdig <chriswue@ipd.info.uni-karlsruhe.de>
Wed, 15 Feb 2006 09:20:14 +0000 (09:20 +0000)
committerChristian Würdig <chriswue@ipd.info.uni-karlsruhe.de>
Wed, 15 Feb 2006 09:20:14 +0000 (09:20 +0000)
ir/be/TEMPLATE/TEMPLATE_emitter.c [new file with mode: 0644]
ir/be/TEMPLATE/TEMPLATE_emitter.h [new file with mode: 0644]
ir/be/TEMPLATE/TEMPLATE_gen_decls.c [new file with mode: 0644]
ir/be/TEMPLATE/TEMPLATE_gen_decls.h [new file with mode: 0644]
ir/be/TEMPLATE/TEMPLATE_new_nodes.c [new file with mode: 0644]
ir/be/TEMPLATE/TEMPLATE_new_nodes.h [new file with mode: 0644]
ir/be/TEMPLATE/TEMPLATE_nodes_attr.h [new file with mode: 0644]
ir/be/TEMPLATE/bearch_TEMPLATE.c [new file with mode: 0644]
ir/be/TEMPLATE/bearch_TEMPLATE.h [new file with mode: 0644]
ir/be/TEMPLATE/bearch_TEMPLATE_t.h [new file with mode: 0644]

diff --git a/ir/be/TEMPLATE/TEMPLATE_emitter.c b/ir/be/TEMPLATE/TEMPLATE_emitter.c
new file mode 100644 (file)
index 0000000..05f50e1
--- /dev/null
@@ -0,0 +1,479 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <limits.h>
+
+#include "xmalloc.h"
+#include "tv.h"
+#include "iredges.h"
+#include "debug.h"
+#include "irgwalk.h"
+#include "irprintf.h"
+#include "irop_t.h"
+#include "irargs_t.h"
+
+#include "../besched.h"
+
+#include "TEMPLATE_emitter.h"
+#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
+
+static const arch_env_t *arch_env = NULL;
+
+
+/*************************************************************
+ *             _       _    __   _          _
+ *            (_)     | |  / _| | |        | |
+ *  _ __  _ __ _ _ __ | |_| |_  | |__   ___| |_ __   ___ _ __
+ * | '_ \| '__| | '_ \| __|  _| | '_ \ / _ \ | '_ \ / _ \ '__|
+ * | |_) | |  | | | | | |_| |   | | | |  __/ | |_) |  __/ |
+ * | .__/|_|  |_|_| |_|\__|_|   |_| |_|\___|_| .__/ \___|_|
+ * | |                                       | |
+ * |_|                                       |_|
+ *************************************************************/
+
+/**
+ * Return a const or symconst as string.
+ */
+static const char *node_const_to_str(ir_node *n) {
+       /* TODO */
+}
+
+/**
+ * Returns node's offset as string.
+ */
+static char *node_offset_to_str(ir_node *n) {
+       /* TODO */
+}
+
+/* We always pass the ir_node which is a pointer. */
+static int TEMPLATE_get_arg_type(const lc_arg_occ_t *occ) {
+       return lc_arg_type_ptr;
+}
+
+
+/**
+ * Returns the register at in position pos.
+ */
+static const arch_register_t *get_in_reg(ir_node *irn, int pos) {
+       ir_node                *op;
+       const arch_register_t  *reg = NULL;
+
+       assert(get_irn_arity(irn) > pos && "Invalid IN position");
+
+       /* The out register of the operator at position pos is the
+          in register we need. */
+       op = get_irn_n(irn, pos);
+
+       reg = arch_get_irn_register(arch_env, op);
+
+       assert(reg && "no in register found");
+       return reg;
+}
+
+/**
+ * Returns the register at out position pos.
+ */
+static const arch_register_t *get_out_reg(ir_node *irn, int pos) {
+       ir_node                *proj;
+       const arch_register_t  *reg = NULL;
+
+       assert(get_irn_n_edges(irn) > pos && "Invalid OUT position");
+
+       /* 1st case: irn is not of mode_T, so it has only                 */
+       /*           one OUT register -> good                             */
+       /* 2nd case: irn is of mode_T -> collect all Projs and ask the    */
+       /*           Proj with the corresponding projnum for the register */
+
+       if (get_irn_mode(irn) != mode_T) {
+               reg = arch_get_irn_register(arch_env, irn);
+       }
+       else if (is_TEMPLATE_irn(irn)) {
+               reg = get_TEMPLATE_out_reg(irn, pos);
+       }
+       else {
+               const ir_edge_t *edge;
+
+               foreach_out_edge(irn, edge) {
+                       proj = get_edge_src_irn(edge);
+                       assert(is_Proj(proj) && "non-Proj from mode_T node");
+                       if (get_Proj_proj(proj) == pos) {
+                               reg = arch_get_irn_register(arch_env, proj);
+                               break;
+                       }
+               }
+       }
+
+       assert(reg && "no out register found");
+       return reg;
+}
+
+/**
+ * Returns the number of the in register at position pos.
+ */
+int get_TEMPLATE_reg_nr(ir_node *irn, int pos, int in_out) {
+       const arch_register_t *reg;
+
+       if (in_out == 1) {
+               reg = get_in_reg(irn, pos);
+       }
+       else {
+               reg = get_out_reg(irn, pos);
+       }
+
+       return arch_register_get_index(reg);
+}
+
+/**
+ * Returns the name of the in register at position pos.
+ */
+const char *get_TEMPLATE_reg_name(ir_node *irn, int pos, int in_out) {
+       const arch_register_t *reg;
+
+       if (in_out == 1) {
+               reg = get_in_reg(irn, pos);
+       }
+       else {
+               reg = get_out_reg(irn, pos);
+       }
+
+       return arch_register_get_name(reg);
+}
+
+/**
+ * Get the register name for a node.
+ */
+static int TEMPLATE_get_reg_name(lc_appendable_t *app,
+    const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
+{
+       const char *buf;
+       ir_node    *X  = arg->v_ptr;
+       int         nr = occ->width - 1;
+
+       if (!X)
+               return lc_arg_append(app, occ, "(null)", 6);
+
+       if (occ->conversion == 'S') {
+               buf = get_TEMPLATE_reg_name(X, nr, 1);
+       }
+       else { /* 'D' */
+               buf = get_TEMPLATE_reg_name(X, nr, 0);
+       }
+
+       lc_appendable_chadd(app, '%');
+       return lc_arg_append(app, occ, buf, strlen(buf));
+}
+
+/**
+ * Returns the tarval or offset of an ia32 as a string.
+ */
+static int TEMPLATE_const_to_str(lc_appendable_t *app,
+    const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
+{
+       const char *buf;
+       ir_node    *X = arg->v_ptr;
+
+       if (!X)
+               return lc_arg_append(app, occ, "(null)", 6);
+
+       if (occ->conversion == 'C') {
+               buf = node_const_to_str(X);
+       }
+       else { /* 'O' */
+               buf = node_offset_to_str(X);
+       }
+
+       return lc_arg_append(app, occ, buf, strlen(buf));
+}
+
+/**
+ * Determines the SSE suffix depending on the mode.
+ */
+static int TEMPLATE_get_mode_suffix(lc_appendable_t *app,
+    const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
+{
+       ir_node *X = arg->v_ptr;
+
+       if (!X)
+               return lc_arg_append(app, occ, "(null)", 6);
+
+       if (get_mode_size_bits(get_irn_mode(X)) == 32)
+               return lc_appendable_chadd(app, 's');
+       else
+               return lc_appendable_chadd(app, 'd');
+}
+
+/**
+ * Return the ia32 printf arg environment.
+ * We use the firm environment with some additional handlers.
+ */
+const lc_arg_env_t *TEMPLATE_get_arg_env(void) {
+       static lc_arg_env_t *env = NULL;
+
+       static const lc_arg_handler_t ia32_reg_handler   = { ia32_get_arg_type, ia32_get_reg_name };
+       static const lc_arg_handler_t ia32_const_handler = { ia32_get_arg_type, ia32_const_to_str };
+       static const lc_arg_handler_t ia32_mode_handler  = { ia32_get_arg_type, ia32_get_mode_suffix };
+
+       if(env == NULL) {
+               /* extend the firm printer */
+               env = firm_get_arg_env();
+                       //lc_arg_new_env();
+
+               lc_arg_register(env, "ia32:sreg", 'S', &ia32_reg_handler);
+               lc_arg_register(env, "ia32:dreg", 'D', &ia32_reg_handler);
+               lc_arg_register(env, "ia32:cnst", 'C', &ia32_const_handler);
+               lc_arg_register(env, "ia32:offs", 'O', &ia32_const_handler);
+               lc_arg_register(env, "ia32:mode", 'M', &ia32_mode_handler);
+       }
+
+       return env;
+}
+
+/**
+ * For 2-address code we need to make sure the first src reg is equal to dest reg.
+ */
+void equalize_dest_src(FILE *F, ir_node *n) {
+       if (get_ia32_reg_nr(n, 0, 1) != get_ia32_reg_nr(n, 0, 0)) {
+               if (get_irn_arity(n) > 1 && get_ia32_reg_nr(n, 1, 1) == get_ia32_reg_nr(n, 0, 0)) {
+                       if (! is_op_commutative(get_irn_op(n))) {
+                               /* we only need to exchange for non-commutative ops */
+                               lc_efprintf(ia32_get_arg_env(), F, "\txchg %1S, %2S\t\t\t/* xchg src1 <-> src2 for 2 address code */\n", n, n);
+                       }
+               }
+               else {
+                       lc_efprintf(ia32_get_arg_env(), F, "\tmovl %1S, %1D\t\t\t/* src -> dest for 2 address code */\n", n, n);
+               }
+       }
+}
+
+/*
+ * Add a number to a prefix. This number will not be used a second time.
+ */
+char *get_unique_label(char *buf, size_t buflen, const char *prefix) {
+       static unsigned long id = 0;
+       snprintf(buf, buflen, "%s%lu", prefix, ++id);
+       return buf;
+}
+
+
+/**
+ * Returns the target label for a control flow node.
+ */
+static char *get_cfop_target(const ir_node *irn, char *buf) {
+       ir_node *bl = get_irn_link(irn);
+
+       snprintf(buf, SNPRINTF_BUF_LEN, "BLOCK_%ld", get_irn_node_nr(bl));
+       return buf;
+}
+
+/*********************************************************
+ *                 _ _       _
+ *                (_) |     (_)
+ *   ___ _ __ ___  _| |_     _ _   _ _ __ ___  _ __  ___
+ *  / _ \ '_ ` _ \| | __|   | | | | | '_ ` _ \| '_ \/ __|
+ * |  __/ | | | | | | |_    | | |_| | | | | | | |_) \__ \
+ *  \___|_| |_| |_|_|\__|   | |\__,_|_| |_| |_| .__/|___/
+ *                         _/ |               | |
+ *                        |__/                |_|
+ *********************************************************/
+
+/**
+ * Emits code for a Switch (creates a jump table if
+ * possible otherwise a cmp-jmp cascade).
+ */
+void emit_TEMPLATE_Switch(const ir_node *irn, emit_env_t *emit_env) {
+       unsigned long       interval;
+       jmp_tbl_t          *tbl;
+       ir_node           **cases;
+       int                 def_projnum;
+       int                 do_jmp_tbl = 1;
+       const lc_arg_env_t *env        = ia32_get_arg_env();
+       FILE               *F          = emit_env->out;
+
+       /* TODO:                                                         */
+       /* - create list of projs, each corresponding to one switch case */
+       /* - determine the projnumber of the default case                */
+
+       tbl = create_jump_table(cases, def_projnum, "JMPTBL_");
+
+       /* two-complement's magic make this work without overflow */
+       interval = tbl.max_value - tbl.min_value;
+
+       /* check value interval: do not create jump table if interval is too large */
+       if (interval > 16 * 1024) {
+               do_jmp_tbl = 0;
+       }
+
+       /* check ratio of value interval to number of branches */
+       if (((float)(interval + 1) / (float)tbl.num_branches) > 8.0) {
+               do_jmp_tbl = 0;
+       }
+
+       if (do_jmp_tbl) {
+               /* TODO: emit table code */
+       }
+       else {
+               /* TODO: emit cmp - jmp cascade */
+       }
+
+       if (tbl.label)
+               free(tbl.label);
+       if (tbl.branches)
+               free(tbl.branches);
+}
+
+
+
+/***********************************************************************************
+ *                  _          __                                             _
+ *                 (_)        / _|                                           | |
+ *  _ __ ___   __ _ _ _ __   | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
+ * | '_ ` _ \ / _` | | '_ \  |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
+ * | | | | | | (_| | | | | | | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
+ * |_| |_| |_|\__,_|_|_| |_| |_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
+ *
+ ***********************************************************************************/
+
+/**
+ * Emits code for a node.
+ */
+void TEMPLATE_emit_node(ir_node *irn, void *env) {
+       emit_env_t *emit_env   = env;
+       firm_dbg_module_t *mod = emit_env->mod;
+       FILE              *F   = emit_env->out;
+
+       DBG((mod, LEVEL_1, "emitting code for %+F\n", irn));
+
+#define BE_EMIT(a) if (is_TEMPLATE_##a(irn)) { emit_TEMPLATE_##a(irn, emit_env); return; }
+
+       /* generated int emitter functions */
+       BE_EMIT(Copy);
+       BE_EMIT(Perm);
+
+       BE_EMIT(Const);
+
+       BE_EMIT(Add);
+       BE_EMIT(Add_i);
+       BE_EMIT(Sub);
+       BE_EMIT(Sub_i);
+       BE_EMIT(Minus);
+       BE_EMIT(Inc);
+       BE_EMIT(Dec);
+
+       BE_EMIT(And);
+       BE_EMIT(And_i);
+       BE_EMIT(Or);
+       BE_EMIT(Or_i);
+       BE_EMIT(Eor);
+       BE_EMIT(Eor_i);
+       BE_EMIT(Not);
+
+       BE_EMIT(Shl);
+       BE_EMIT(Shl_i);
+       BE_EMIT(Shr);
+       BE_EMIT(Shr_i);
+       BE_EMIT(RotL);
+       BE_EMIT(RotL_i);
+       BE_EMIT(RotR);
+
+       BE_EMIT(Mul);
+       BE_EMIT(Mul_i);
+
+       BE_EMIT(Store);
+       BE_EMIT(Load);
+
+       /* generated floating point emitter */
+       BE_EMIT(fConst);
+
+       BE_EMIT(fAdd);
+       BE_EMIT(fSub);
+       BE_EMIT(fMinus);
+
+       BE_EMIT(fMul);
+       BE_EMIT(fDiv);
+
+       BE_EMIT(fMin);
+       BE_EMIT(fMax);
+
+       BE_EMIT(fLoad);
+       BE_EMIT(fStore);
+
+       /* other emitter functions */
+//     BE_EMIT(Switch);
+
+       ir_fprintf(F, "\t\t\t\t\t/* %+F */\n", irn);
+}
+
+/**
+ * Walks over the nodes in a block connected by scheduling edges
+ * and emits code for each node.
+ */
+void TEMPLATE_gen_block(ir_node *block, void *env) {
+       ir_node *irn;
+
+       if (! is_Block(block))
+               return;
+
+       fprintf(((emit_env_t *)env)->out, "BLOCK_%ld:\n", get_irn_node_nr(block));
+       sched_foreach(block, irn) {
+               TEMPLATE_emit_node(irn, env);
+       }
+}
+
+
+/**
+ * Emits code for function start.
+ */
+void TEMPLATE_emit_start(FILE *F, ir_graph *irg) {
+       const char *irg_name = get_entity_name(get_irg_entity(irg));
+
+       /* TODO: emit function header */
+}
+
+/**
+ * Emits code for function end
+ */
+void TEMPLATE_emit_end(FILE *F, ir_graph *irg) {
+       const char *irg_name = get_entity_name(get_irg_entity(irg));
+
+       /* TODO: emit function end */
+}
+
+/**
+ * Sets labels for control flow nodes (jump target)
+ * TODO: Jump optimization
+ */
+void TEMPLATE_gen_labels(ir_node *block, void *env) {
+       ir_node *pred;
+       int n = get_Block_n_cfgpreds(block);
+
+       for (n--; n >= 0; n--) {
+               pred = get_Block_cfgpred(block, n);
+               set_irn_link(pred, block);
+       }
+}
+
+/**
+ * Main driver
+ */
+void TEMPLATE_gen_routine(FILE *F, ir_graph *irg, const ia32_code_gen_t *cg) {
+       emit_env_t emit_env;
+
+       emit_env.mod      = firm_dbg_register("firm.be.TEMPLATE.emit");
+       emit_env.out      = F;
+       emit_env.arch_env = cg->arch_env;
+       emit_env.cg       = cg;
+
+       /* set the global arch_env (needed by print hooks) */
+       arch_env = cg->arch_env;
+
+       TEMPLATE_emit_start(F, irg);
+       irg_block_walk_graph(irg, TEMPLATE_gen_labels, NULL, &emit_env);
+       irg_walk_blkwise_graph(irg, NULL, TEMPLATE_gen_block, &emit_env);
+       TEMPLATE_emit_end(F, irg);
+}
diff --git a/ir/be/TEMPLATE/TEMPLATE_emitter.h b/ir/be/TEMPLATE/TEMPLATE_emitter.h
new file mode 100644 (file)
index 0000000..d211d1f
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef _TEMPLATE_EMITTER_H_
+#define _TEMPLATE_EMITTER_H_
+
+#include "irargs_t.h"  // this also inlucdes <libcore/lc_print.h>
+#include "irnode.h"
+#include "debug.h"
+
+#include "../bearch.h"
+
+#include "bearch_TEMPLATE_t.h"
+
+typedef struct _emit_env_t {
+       firm_dbg_module_t         *mod;
+       FILE                      *out;
+       const arch_env_t          *arch_env;
+       const TEMPLATE_code_gen_t *cg;
+} emit_env_t;
+
+const lc_arg_env_t *TEMPLATE_get_arg_env(void);
+
+void equalize_dest_src(FILE *F, ir_node *n);
+
+int get_TEMPLATE_reg_nr(ir_node *irn, int posi, int in_out);
+const char *get_TEMPLATE_in_reg_name(ir_node *irn, int pos);
+
+void TEMPLATE_gen_routine(FILE *F, ir_graph *irg, const TEMPLATE_code_gen_t *cg);
+
+#endif /* _TEMPLATE_EMITTER_H_ */
diff --git a/ir/be/TEMPLATE/TEMPLATE_gen_decls.c b/ir/be/TEMPLATE/TEMPLATE_gen_decls.c
new file mode 100644 (file)
index 0000000..4851517
--- /dev/null
@@ -0,0 +1,597 @@
+/**
+ * Dumps global variables and constants as TEMPLATE assembler.
+ * @author Christian Wuerdig
+ * @date 14.02.2006
+ * @version $Id$
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "xmalloc.h"
+#include <obstack.h>
+
+#ifdef obstack_chunk_alloc
+# undef obstack_chunk_alloc
+# define obstack_chunk_alloc xmalloc
+#else
+# define obstack_chunk_alloc xmalloc
+# define obstack_chunk_free free
+#endif
+
+#include "tv.h"
+#include "irnode.h"
+#include "entity.h"
+#include "irprog.h"
+
+#include "TEMPLATE_gen_decls.h"
+
+/************************************************************************/
+
+/*
+ * returns the highest bit value
+ */
+static unsigned highest_bit(unsigned v)
+{
+  int res = -1;
+
+  if (v >= (1U << 16U)) {
+    res += 16;
+    v >>= 16;
+  }
+  if (v >= (1U << 8U)) {
+    res += 8;
+    v >>= 8;
+  }
+  if (v >= (1U << 4U)) {
+    res += 4;
+    v >>= 4;
+  }
+  if (v >= (1U << 2U)) {
+    res += 2;
+    v >>= 2;
+  }
+  if (v >= (1U << 1U)) {
+    res += 1;
+    v >>= 1;
+  }
+  if (v >= 1)
+    res += 1;
+
+  return res;
+}
+
+/*
+ * output the alignment
+ */
+static void TEMPLATE_dump_align(struct obstack *obst, int align)
+{
+  int h = highest_bit(align);
+
+  if ((1 << h) < align)
+    ++h;
+  align = (1 << h);
+
+  if (align > 1)
+    obstack_printf(obst, "\t.align %d\n", align);
+}
+
+static void dump_arith_tarval(struct obstack *obst, tarval *tv, int bytes)
+{
+  switch (bytes) {
+
+  case 1:
+    obstack_printf(obst, "0x%02x", get_tarval_sub_bits(tv, 0));
+    break;
+
+  case 2:
+    obstack_printf(obst, "0x%02x%02x", get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
+    break;
+
+  case 4:
+    obstack_printf(obst, "0x%02x%02x%02x%02x",
+       get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
+    break;
+
+  case 8:
+    obstack_printf(obst, "0x%02x%02x%02x%02x%02x%02x%02x%02x",
+       get_tarval_sub_bits(tv, 7), get_tarval_sub_bits(tv, 6), get_tarval_sub_bits(tv, 5), get_tarval_sub_bits(tv, 4),
+       get_tarval_sub_bits(tv, 3), get_tarval_sub_bits(tv, 2), get_tarval_sub_bits(tv, 1), get_tarval_sub_bits(tv, 0));
+    break;
+
+  case 10:
+  case 12:
+    break;
+
+  default:
+    fprintf(stderr, "Try to dump an tarval with %d bytes\n", bytes);
+    assert(0);
+  }
+}
+
+/*
+ * dump an arithmetic tarval
+ */
+static void TEMPLATE_dump_arith_tarval(struct obstack *obst, tarval *tv, int bytes)
+{
+  switch (bytes) {
+
+  case 1:
+    obstack_printf(obst, "\t.byte\t");
+    break;
+
+  case 2:
+    obstack_printf(obst, "\t.value\t");
+    break;
+
+  case 4:
+    obstack_printf(obst, "\t.long\t");
+    break;
+
+  case 8:
+    obstack_printf(obst, "\t.quad\t");
+    break;
+
+  case 10:
+  case 12:
+    break;
+
+  default:
+    fprintf(stderr, "Try to dump an tarval with %d bytes\n", bytes);
+    assert(0);
+  }
+  dump_arith_tarval(obst, tv, bytes);
+}
+
+
+/*
+ * dump an atomic value
+ */
+static void do_dump_atomic_init(struct obstack *obst, ir_node *init)
+{
+  ir_mode *mode = get_irn_mode(init);
+  int bytes     = get_mode_size_bytes(mode);
+  tarval *tv;
+
+  switch (get_irn_opcode(init)) {
+
+  case iro_Cast:
+    do_dump_atomic_init(obst, get_Cast_op(init));
+    return;
+
+  case iro_Conv:
+    do_dump_atomic_init(obst, get_Conv_op(init));
+    return;
+
+  case iro_Const:
+    tv = get_Const_tarval(init);
+
+    /* beware of old stuff */
+    assert(! mode_is_reference(mode));
+
+    /* it's a arithmetic value */
+    dump_arith_tarval(obst, tv, bytes);
+    return;
+
+  case iro_SymConst:
+    switch (get_SymConst_kind(init)) {
+    case symconst_addr_name:
+      obstack_printf(obst, "%s", get_id_str(get_SymConst_name(init)));
+      break;
+
+    case symconst_addr_ent:
+      obstack_printf(obst, "%s", get_entity_ld_name(get_SymConst_entity(init)));
+      break;
+
+    case symconst_size:
+      obstack_printf(obst, "%d", get_type_size_bytes(get_SymConst_type(init)));
+      break;
+
+    default:
+      assert(0 && "dump_atomic_init(): don't know how to init from this SymConst");
+    }
+    return;
+
+  case iro_Add:
+    do_dump_atomic_init(obst, get_Add_left(init));
+    obstack_printf(obst, " + ");
+    do_dump_atomic_init(obst, get_Add_right(init));
+    return;
+
+  case iro_Sub:
+    do_dump_atomic_init(obst, get_Sub_left(init));
+    obstack_printf(obst, " - ");
+    do_dump_atomic_init(obst, get_Sub_right(init));
+    return;
+
+  case iro_Mul:
+    do_dump_atomic_init(obst, get_Mul_left(init));
+    obstack_printf(obst, " * ");
+    do_dump_atomic_init(obst, get_Mul_right(init));
+    return;
+
+  default:
+    assert(0 && "dump_atomic_init(): unknown IR-node");
+  }
+}
+
+/*
+ * dump an atomic value
+ */
+static void dump_atomic_init(struct obstack *obst, ir_node *init)
+{
+  ir_mode *mode = get_irn_mode(init);
+  int bytes     = get_mode_size_bytes(mode);
+
+  switch (bytes) {
+
+  case 1:
+    obstack_printf(obst, "\t.byte\t");
+    break;
+
+  case 2:
+    obstack_printf(obst, "\t.value\t");
+    break;
+
+  case 4:
+    obstack_printf(obst, "\t.long\t");
+    break;
+
+  case 8:
+    obstack_printf(obst, "\t.quad\t");
+    break;
+
+  case 10:
+  case 12:
+    /* handled in arith */
+    break;
+
+  default:
+    fprintf(stderr, "Try to dump an tarval with %d bytes\n", bytes);
+    assert(0);
+  }
+
+  do_dump_atomic_init(obst, init);
+  obstack_printf(obst, "\n");
+}
+
+/************************************************************************/
+/* Routines to dump global variables                                    */
+/************************************************************************/
+
+/**
+ * Determine if an entity is a string constant
+ * @param ent The entity
+ * @return 1 if it is a string constant, 0 otherwise
+ */
+static int ent_is_string_const(entity *ent)
+{
+  int res = 0;
+  ir_type *ty;
+
+  ty = get_entity_type(ent);
+
+  /* if it's an array */
+  if (is_Array_type(ty)) {
+    ir_type *elm_ty = get_array_element_type(ty);
+
+    /* and the array's element type is primitive */
+    if (is_Primitive_type(elm_ty)) {
+      ir_mode *mode = get_type_mode(elm_ty);
+
+      /*
+       * and the mode of the element type is an int of
+       * the same size as the byte mode
+       */
+      if (mode_is_int(mode)
+        && get_mode_size_bits(mode) == get_mode_size_bits(mode_Bs))
+      {
+       int i, c, n;
+
+       n = get_compound_ent_n_values(ent);
+       for (i = 0; i < n; ++i) {
+         ir_node *irn = get_compound_ent_value(ent, i);
+         if(get_irn_opcode(irn) != iro_Const)
+           return 0;
+
+         c = (int) get_tarval_long(get_Const_tarval(irn));
+
+         if((i < n - 1 && !(isgraph(c) || isspace(c)))
+            || (i == n - 1 && c != '\0'))
+           return 0;
+       }
+
+       res = 1;
+      }
+    }
+  }
+
+  return res;
+}
+
+/**
+ * Dump a atring constant.
+ * No checks are made!!
+ * @param obst The obst to dump on.
+ * @param ent The entity to dump.
+ */
+static void dump_string_cst(struct obstack *obst, entity *ent)
+{
+  int i, n;
+
+  obstack_printf(obst, "\t.string \"");
+  n = get_compound_ent_n_values(ent);
+
+  for (i = 0; i < n-1; ++i) {
+    ir_node *irn;
+    int c;
+
+    irn = get_compound_ent_value(ent, i);
+    c = (int) get_tarval_long(get_Const_tarval(irn));
+
+    switch (c) {
+    case '"' : obstack_printf(obst, "\\\""); break;
+    case '\n': obstack_printf(obst, "\\n"); break;
+    case '\r': obstack_printf(obst, "\\r"); break;
+    case '\t': obstack_printf(obst, "\\t"); break;
+    default  :
+      if (isprint(c))
+       obstack_printf(obst, "%c", c);
+      else
+       obstack_printf(obst, "%O", c);
+      break;
+    }
+  }
+  obstack_printf(obst, "\"\n");
+}
+
+struct arr_info {
+  int n_elems;
+  int visit_cnt;
+  int size;
+};
+
+/*
+ * Dumps the initialization of global variables that are not
+ * "uninitialized".
+ */
+static void dump_global(struct obstack *rdata_obstack, struct obstack *data_obstack, struct obstack *comm_obstack, entity *ent)
+{
+  ir_type *ty         = get_entity_type(ent);
+  const char *ld_name = get_entity_ld_name(ent);
+  int align, h;
+  struct obstack *obst = data_obstack;
+
+  /*
+   * FIXME: did NOT work for partly constant values
+   */
+  if (! is_Method_type(ty)) {
+    ent_variability variability = get_entity_variability(ent);
+    visibility visibility = get_entity_visibility(ent);
+
+    if (variability == variability_constant) {
+      /* a constant entity, put it on the rdata */
+      obst = rdata_obstack;
+    }
+
+    /* check, wether it is initialized, if yes create data */
+    if (variability != variability_uninitialized) {
+      if (visibility == visibility_external_visible) {
+        obstack_printf(obst, ".globl\t%s\n", ld_name);
+      }
+      obstack_printf(obst, "\t.type\t%s,@object\n", ld_name);
+      obstack_printf(obst, "\t.size\t%s,%d\n", ld_name, (get_type_size_bits(ty) + 7) >> 3);
+
+      align = get_type_alignment_bytes(ty);
+      TEMPLATE_dump_align(obst, align);
+
+      obstack_printf(obst, "%s:\n", ld_name);
+
+      if (is_atomic_type(ty)) {
+       if (get_entity_visibility(ent) != visibility_external_allocated)
+          dump_atomic_init(obst, get_atomic_ent_value(ent));
+      }
+      else {
+       int i, size = 0;
+
+       if (ent_is_string_const(ent)) {
+         dump_string_cst(obst, ent);
+       }
+       else if (is_Array_type(ty)) {
+          int filler;
+
+          /* potential spare values should be already included! */
+                 for (i = 0; i < get_compound_ent_n_values(ent); ++i) {
+            entity *step = get_compound_ent_value_member(ent, i);
+            ir_type *stype = get_entity_type(step);
+
+            if (get_type_mode(stype)) {
+              int align = (get_type_alignment_bits(stype) + 7) >> 3;
+              int n     = size % align;
+
+              if (n > 0) {
+                obstack_printf(obst, "\t.zero\t%d\n", align - n);
+                size += align - n;
+              }
+            }
+            dump_atomic_init(obst, get_compound_ent_value(ent, i));
+            size += get_type_size_bytes(stype);
+         }
+          filler = get_type_size_bytes(ty) - size;
+
+          if (filler > 0)
+            obstack_printf(obst, "\t.zero\t%d\n", filler);
+        }
+        else if (is_compound_type(ty)) {
+          ir_node **vals;
+          int type_size, j;
+
+          /* Compound entities are NOT sorted.
+           * The sorting strategy used doesn't work for `value' compound fields nor
+           * for partially_constant entities.
+           */
+
+          /*
+           * in the worst case, every entity allocates one byte, so the type
+           * size should be equal or bigger the number of fields
+           */
+          type_size = get_type_size_bytes(ty);
+          vals      = xcalloc(type_size, sizeof(*vals));
+
+          /* collect the values and store them at the offsets */
+          for(i = 0; i < get_compound_ent_n_values(ent); ++i) {
+            int                 graph_length, aipos, offset;
+            struct arr_info     *ai;
+            int                 all_n = 1;
+            compound_graph_path *path = get_compound_ent_value_path(ent, i);
+
+            /* get the access path to the costant value */
+            graph_length = get_compound_graph_path_length(path);
+            ai = xcalloc(graph_length, sizeof(struct arr_info));
+
+            /* We wanna know how many arrays are on the path to the entity. We also have to know how
+             * many elements each array holds to calculate the offset for the entity. */
+            for (j = 0; j < graph_length; j++) {
+              entity  *step      = get_compound_graph_path_node(path, j);
+              ir_type *step_type = get_entity_type(step);
+              int     ty_size    = (get_type_size_bits(step_type) + 7) >> 3;
+              int     k, n       = 0;
+
+              if (is_Array_type(step_type))
+                for (k = 0; k < get_array_n_dimensions(step_type); k++)
+                  n += get_tarval_long(get_Const_tarval(get_array_upper_bound(step_type, k)));
+              if (n) all_n *= n;
+              ai[j].n_elems = n ? all_n + 1 : 0;
+              ai[j].visit_cnt = 0;
+              ai[j].size = ty_size;
+            }
+
+            aipos = graph_length - 1;
+            if (aipos) aipos--;
+
+            for (offset = j = 0; j < graph_length; j++) {
+              entity *step       = get_compound_graph_path_node(path, j);
+              ir_type *step_type = get_entity_type(step);
+              int ent_ofs        = get_entity_offset_bytes(step);
+              int stepsize       = 0;
+
+              /* add all positive offsets (= offsets in structs) */
+              if (ent_ofs >= 0) offset += ent_ofs;
+
+              if (j == graph_length - 1) {
+                stepsize = (get_type_size_bits(step_type) + 7) >> 3;
+
+                /* Search the next free position in vals depending on the information from above (ai). */
+                while (vals[offset]) {
+                  if (ai[aipos].visit_cnt < ai[aipos].n_elems) {
+                    offset += stepsize;
+                    ai[aipos].visit_cnt++;
+                  }
+                  else
+                    while (aipos >= 0 && ai[aipos].visit_cnt == ai[aipos].n_elems) {
+                      stepsize = ai[aipos--].size;
+                      offset  += stepsize;
+                  }
+                }
+
+                assert(aipos >= 0 && "couldn't store entity");
+                vals[offset] = get_compound_ent_value(ent, i);
+              }
+            }
+
+            free(ai);
+          }
+
+          /* now write them sorted */
+          for(i = 0; i < type_size; ) {
+            if (vals[i]) {
+              dump_atomic_init(obst, vals[i]);
+              i += (get_mode_size_bytes(get_irn_mode(vals[i])));
+            }
+            else {
+              /* a gap */
+              obstack_printf(obst, "\t.byte\t0\n");
+              ++i;
+            }
+          }
+          free(vals);
+        }
+        else {
+          assert(0 && "unsupported type");
+        }
+      }
+      obstack_printf(obst, "\n");
+    }
+    else if (visibility != visibility_external_allocated) {
+      if (visibility == visibility_local) {
+        obstack_printf(comm_obstack, "\t.local\t%s\n", ld_name);
+      }
+
+      /* calculate the alignment */
+      align = get_type_alignment_bytes(ty);
+      h = highest_bit(align);
+
+      if ((1 << h) < align)
+       ++h;
+      align = (1 << h);
+
+      if (align < 1)
+       align = 1;
+
+      obstack_printf(comm_obstack, "\t.comm\t%s,%d,%d\n", ld_name, (get_type_size_bits(ty) + 7) >> 3, align);
+    }
+  }
+}
+
+/*
+ * Dumps declarations of global variables and the initialization code.
+ */
+void TEMPLATE_dump_globals(struct obstack *rdata_obstack, struct obstack *data_obstack, struct obstack *comm_obstack)
+{
+  ir_type *gt = get_glob_type();
+  int i, n = get_class_n_members(gt);
+
+  for (i = 0; i < n; i++)
+    dump_global(rdata_obstack, data_obstack, comm_obstack, get_class_member(gt, i));
+}
+
+/************************************************************************/
+
+void TEMPLATE_gen_decls(FILE *out) {
+  struct obstack rodata, data, comm;
+  int    size;
+  char   *cp;
+
+  obstack_init(&rodata);
+  obstack_init(&data);
+  obstack_init(&comm);
+
+  TEMPLATE_dump_globals(&rodata, &data, &comm);
+
+  size = obstack_object_size(&data);
+  cp   = obstack_finish(&data);
+  if (size > 0) {
+    fprintf(out, "\t.data\n");
+    fwrite(cp, 1, size, out);
+  }
+
+  size = obstack_object_size(&rodata);
+  cp   = obstack_finish(&rodata);
+  if (size > 0) {
+    fprintf(out, "\t.section\t.rodata\n");
+    fwrite(cp, 1, size, out);
+  }
+
+  size = obstack_object_size(&comm);
+  cp   = obstack_finish(&comm);
+  if (size > 0) {
+    fprintf(out, "\t.common\n");
+    fwrite(cp, 1, size, out);
+  }
+
+  obstack_free(&rodata, NULL);
+  obstack_free(&data, NULL);
+  obstack_free(&comm, NULL);
+}
diff --git a/ir/be/TEMPLATE/TEMPLATE_gen_decls.h b/ir/be/TEMPLATE/TEMPLATE_gen_decls.h
new file mode 100644 (file)
index 0000000..0224dc0
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _TEMPLATE_GEN_DECLS_H_
+#define _TEMPLATE_GEN_DECLS_H_
+
+/**
+ * Generate all entities.
+ */
+void TEMPLATE_gen_decls(FILE *out);
+
+#endif /* _TEMPLATE_GEN_DECLS_H_ */
diff --git a/ir/be/TEMPLATE/TEMPLATE_new_nodes.c b/ir/be/TEMPLATE/TEMPLATE_new_nodes.c
new file mode 100644 (file)
index 0000000..670824f
--- /dev/null
@@ -0,0 +1,306 @@
+/**
+ * This file implements the creation of the achitecture specific firm opcodes
+ * and the coresponding node constructors for the TEMPLATE assembler irg.
+ * $Id$
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+
+#include "irprog_t.h"
+#include "irgraph_t.h"
+#include "irnode_t.h"
+#include "irmode_t.h"
+#include "ircons_t.h"
+#include "iropt_t.h"
+#include "irop.h"
+#include "firm_common_t.h"
+#include "irvrfy_t.h"
+
+#include "../bearch.h"
+
+#include "TEMPLATE_nodes_attr.h"
+#include "TEMPLATE_new_nodes.h"
+#include "gen_TEMPLATE_regalloc_if.h"
+
+
+
+/***********************************************************************************
+ *      _                                   _       _             __
+ *     | |                                 (_)     | |           / _|
+ *   __| |_   _ _ __ ___  _ __   ___ _ __   _ _ __ | |_ ___ _ __| |_ __ _  ___ ___
+ *  / _` | | | | '_ ` _ \| '_ \ / _ \ '__| | | '_ \| __/ _ \ '__|  _/ _` |/ __/ _ \
+ * | (_| | |_| | | | | | | |_) |  __/ |    | | | | | ||  __/ |  | || (_| | (_|  __/
+ *  \__,_|\__,_|_| |_| |_| .__/ \___|_|    |_|_| |_|\__\___|_|  |_| \__,_|\___\___|
+ *                       | |
+ *                       |_|
+ ***********************************************************************************/
+
+/**
+ * Dumper interface for dumping TEMPLATE nodes in vcg.
+ * @param n        the node to dump
+ * @param F        the output file
+ * @param reason   indicates which kind of information should be dumped
+ * @return 0 on success or != 0 on failure
+ */
+static int dump_node_TEMPLATE(ir_node *n, FILE *F, dump_reason_t reason) {
+       const char    *name, *p;
+       ir_mode       *mode = NULL;
+       int            bad  = 0;
+       int            i;
+       TEMPLATE_attr_t *attr;
+       const TEMPLATE_register_req_t **reqs;
+       const arch_register_t         **slots;
+
+       switch (reason) {
+               case dump_node_opcode_txt:
+                       name = get_irn_opname(n);
+                       fprintf(F, "%s", name);
+                       break;
+
+               case dump_node_mode_txt:
+                       mode = get_irn_mode(n);
+
+                       if (mode == mode_BB || mode == mode_ANY || mode == mode_BAD || mode == mode_T) {
+                               mode = NULL;
+                       }
+
+                       if (mode) {
+                               fprintf(F, "[%s]", get_mode_name(mode));
+                       }
+                       break;
+
+               case dump_node_nodeattr_txt:
+
+                       /* TODO: Dump node specific attributes which should */
+                       /* visible in node name (e.g. const or the like).   */
+
+                       break;
+
+               case dump_node_info_txt:
+                       attr = get_TEMPLATE_attr(n);
+
+                       /* dump IN requirements */
+                       if (get_irn_arity(n) > 0) {
+                               reqs = get_TEMPLATE_in_req_all(n);
+
+                               if (reqs) {
+                                       for (i = 0; i < get_irn_arity(n); i++) {
+                                               if (reqs[i]->req.type != arch_register_req_type_none) {
+                                                       fprintf(F, "in req #%d = [%s]\n", i, reqs[i]->req.cls->name);
+                                               }
+                                               else {
+                                                       fprintf(F, "in req #%d = n/a\n", i);
+                                               }
+                                       }
+
+                                       fprintf(F, "\n");
+                               }
+                               else {
+                                       fprintf(F, "in req = N/A\n");
+                               }
+                       }
+
+                       /* dump OUT requirements */
+                       if (attr->n_res > 0) {
+                               reqs = get_TEMPLATE_out_req_all(n);
+
+                               if (reqs) {
+                                       for (i = 0; i < attr->n_res; i++) {
+                                               if (reqs[i]->req.type != arch_register_req_type_none) {
+                                                       fprintf(F, "out req #%d = [%s]\n", i, reqs[i]->req.cls->name);
+                                               }
+                                               else {
+                                                       fprintf(F, "out req #%d = n/a\n", i);
+                                               }
+                                       }
+                               }
+                               else {
+                                       fprintf(F, "out req = N/A\n");
+                               }
+                       }
+
+                       /* dump assigned registers */
+                       slots = get_TEMPLATE_slots(n);
+                       if (slots && attr->n_res > 0) {
+                               for (i = 0; i < attr->n_res; i++) {
+                                       if (slots[i]) {
+                                               fprintf(F, "reg #%d = %s\n", i, slots[i]->name);
+                                       }
+                                       else {
+                                               fprintf(F, "reg #%d = n/a\n", i);
+                                       }
+                               }
+                       }
+
+                       break;
+       }
+
+       return bad;
+}
+
+
+
+/***************************************************************************************************
+ *        _   _                   _       __        _                    _   _               _
+ *       | | | |                 | |     / /       | |                  | | | |             | |
+ *   __ _| |_| |_ _ __   ___  ___| |_   / /_ _  ___| |_   _ __ ___   ___| |_| |__   ___   __| |___
+ *  / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
+ * | (_| | |_| |_| |    \__ \  __/ |_ / / (_| |  __/ |_  | | | | | |  __/ |_| | | | (_) | (_| \__ \
+ *  \__,_|\__|\__|_|    |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
+ *                                        __/ |
+ *                                       |___/
+ ***************************************************************************************************/
+
+/**
+ * Wraps get_irn_generic_attr() as it takes no const ir_node, so we need to do a cast.
+ * Firm was made by people hating const :-(
+ */
+TEMPLATE_attr_t *get_TEMPLATE_attr(const ir_node *node) {
+       assert(is_TEMPLATE_irn(node) && "need TEMPLATE node to get attributes");
+       return (TEMPLATE_attr_t *)get_irn_generic_attr((ir_node *)node);
+}
+
+/**
+ * Returns the argument register requirements of a TEMPLATE node.
+ */
+const TEMPLATE_register_req_t **get_TEMPLATE_in_req_all(const ir_node *node) {
+       TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
+       return attr->in_req;
+}
+
+/**
+ * Returns the result register requirements of an TEMPLATE node.
+ */
+const TEMPLATE_register_req_t **get_TEMPLATE_out_req_all(const ir_node *node) {
+       TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
+       return attr->out_req;
+}
+
+/**
+ * Returns the argument register requirement at position pos of an TEMPLATE node.
+ */
+const TEMPLATE_register_req_t *get_TEMPLATE_in_req(const ir_node *node, int pos) {
+       TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
+       return attr->in_req[pos];
+}
+
+/**
+ * Returns the result register requirement at position pos of an TEMPLATE node.
+ */
+const TEMPLATE_register_req_t *get_TEMPLATE_out_req(const ir_node *node, int pos) {
+       TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
+       return attr->out_req[pos];
+}
+
+/**
+ * Sets the OUT register requirements at position pos.
+ */
+void set_TEMPLATE_req_out(ir_node *node, const TEMPLATE_register_req_t *req, int pos) {
+       TEMPLATE_attr_t *attr   = get_TEMPLATE_attr(node);
+       attr->out_req[pos] = req;
+}
+
+/**
+ * Sets the IN register requirements at position pos.
+ */
+void set_TEMPLATE_req_in(ir_node *node, const TEMPLATE_register_req_t *req, int pos) {
+       TEMPLATE_attr_t *attr  = get_TEMPLATE_attr(node);
+       attr->in_req[pos] = req;
+}
+
+/**
+ * Returns the register flag of an TEMPLATE node.
+ */
+arch_irn_flags_t get_TEMPLATE_flags(const ir_node *node) {
+       TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
+       return attr->flags;
+}
+
+/**
+ * Sets the register flag of an TEMPLATE node.
+ */
+void set_TEMPLATE_flags(const ir_node *node, arch_irn_flags_t flags) {
+       TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
+       attr->flags      = flags;
+}
+
+/**
+ * Returns the result register slots of an TEMPLATE node.
+ */
+const arch_register_t **get_TEMPLATE_slots(const ir_node *node) {
+       TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
+       return attr->slots;
+}
+
+/**
+ * Returns the name of the OUT register at position pos.
+ */
+const char *get_TEMPLATE_out_reg_name(const ir_node *node, int pos) {
+       TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
+
+       assert(is_TEMPLATE_irn(node) && "Not an TEMPLATE node.");
+       assert(pos < attr->n_res && "Invalid OUT position.");
+       assert(attr->slots[pos]  && "No register assigned");
+
+       return arch_register_get_name(attr->slots[pos]);
+}
+
+/**
+ * Returns the index of the OUT register at position pos within its register class.
+ */
+int get_TEMPLATE_out_regnr(const ir_node *node, int pos) {
+       TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
+
+       assert(is_TEMPLATE_irn(node) && "Not an TEMPLATE node.");
+       assert(pos < attr->n_res && "Invalid OUT position.");
+       assert(attr->slots[pos]  && "No register assigned");
+
+       return arch_register_get_index(attr->slots[pos]);
+}
+
+/**
+ * Returns the OUT register at position pos.
+ */
+const arch_register_t *get_TEMPLATE_out_reg(const ir_node *node, int pos) {
+       TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
+
+       assert(is_TEMPLATE_irn(node) && "Not an TEMPLATE node.");
+       assert(pos < attr->n_res && "Invalid OUT position.");
+       assert(attr->slots[pos]  && "No register assigned");
+
+       return attr->slots[pos];
+}
+
+/**
+ * Sets the number of results.
+ */
+void set_TEMPLATE_n_res(ir_node *node, int n_res) {
+       TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
+       attr->n_res      = n_res;
+}
+
+/**
+ * Returns the number of results.
+ */
+int get_TEMPLATE_n_res(const ir_node *node) {
+       TEMPLATE_attr_t *attr = get_TEMPLATE_attr(node);
+       return attr->n_res;
+}
+
+
+
+/***************************************************************************************
+ *                  _                            _                   _
+ *                 | |                          | |                 | |
+ *  _ __   ___   __| | ___    ___ ___  _ __  ___| |_ _ __ _   _  ___| |_ ___  _ __ ___
+ * | '_ \ / _ \ / _` |/ _ \  / __/ _ \| '_ \/ __| __| '__| | | |/ __| __/ _ \| '__/ __|
+ * | | | | (_) | (_| |  __/ | (_| (_) | | | \__ \ |_| |  | |_| | (__| || (_) | |  \__ \
+ * |_| |_|\___/ \__,_|\___|  \___\___/|_| |_|___/\__|_|   \__,_|\___|\__\___/|_|  |___/
+ *
+ ***************************************************************************************/
+
+/* Include the generated constructor functions */
+#include "gen_TEMPLATE_new_nodes.c.inl"
diff --git a/ir/be/TEMPLATE/TEMPLATE_new_nodes.h b/ir/be/TEMPLATE/TEMPLATE_new_nodes.h
new file mode 100644 (file)
index 0000000..48d0b6d
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef _TEMPLATE_NEW_NODES_H_
+#define _TEMPLATE_NEW_NODES_H_
+
+/**
+ * Function prototypes for the assembler ir node constructors.
+ * $Id$
+ */
+
+#include "TEMPLATE_nodes_attr.h"
+
+/***************************************************************************************************
+ *        _   _                   _       __        _                    _   _               _
+ *       | | | |                 | |     / /       | |                  | | | |             | |
+ *   __ _| |_| |_ _ __   ___  ___| |_   / /_ _  ___| |_   _ __ ___   ___| |_| |__   ___   __| |___
+ *  / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
+ * | (_| | |_| |_| |    \__ \  __/ |_ / / (_| |  __/ |_  | | | | | |  __/ |_| | | | (_) | (_| \__ \
+ *  \__,_|\__|\__|_|    |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
+ *                                        __/ |
+ *                                       |___/
+ ***************************************************************************************************/
+
+/**
+ * Returns the attributes of an TEMPLATE node.
+ */
+TEMPLATE_attr *get_TEMPLATE_attr(const ir_node *node);
+
+/**
+ * Returns the argument register requirements of an TEMPLATE node.
+ */
+const TEMPLATE_register_req_t **get_TEMPLATE_in_req_all(const ir_node *node);
+
+/**
+ * Returns the result register requirements of an TEMPLATE node.
+ */
+const TEMPLATE_register_req_t **get_TEMPLATE_out_req_all(const ir_node *node);
+
+/**
+ * Returns the argument register requirements of an TEMPLATE node.
+ */
+const TEMPLATE_register_req_t *get_TEMPLATE_in_req(const ir_node *node, int pos);
+
+/**
+ * Returns the result register requirements of an TEMPLATE node.
+ */
+const TEMPLATE_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 TEMPLATE_register_req_t *req, int pos);
+
+/**
+ * Sets the IN register requirements at position pos.
+ */
+void set_TEMPLATE_req_in(ir_node *node, const TEMPLATE_register_req_t *req, int pos);
+
+/**
+ * Returns the register flag of an TEMPLATE node.
+ */
+arch_irn_flags_t get_TEMPLATE_flags(const ir_node *node);
+
+/**
+ * Sets the register flag of an TEMPLATE node.
+ */
+void set_TEMPLATE_flags(const ir_node *node, arch_irn_flags_t flags);
+
+/**
+ * Returns the result register slots of an TEMPLATE node.
+ */
+const arch_register_t **get_TEMPLATE_slots(const ir_node *node);
+
+/**
+ * Returns the name of the OUT register at position pos.
+ */
+const char *get_TEMPLATE_out_reg_name(const ir_node *node, int pos);
+
+/**
+ * Returns the index of the OUT register at position pos within its register class.
+ */
+int get_TEMPLATE_out_regnr(const ir_node *node, int pos);
+
+/**
+ * Returns the OUT register at position pos.
+ */
+const arch_register_t *get_TEMPLATE_out_reg(const ir_node *node, int pos);
+
+/**
+ * Sets the number of results.
+ */
+void set_TEMPLATE_n_res(ir_node *node, int n_res);
+
+/**
+ * Returns the number of results.
+ */
+int get_TEMPLATE_n_res(const ir_node *node);
+
+
+/* Include the generated headers */
+#include "gen_TEMPLATE_new_nodes.h"
+
+#endif /* _TEMPLATE_NEW_NODES_H_ */
diff --git a/ir/be/TEMPLATE/TEMPLATE_nodes_attr.h b/ir/be/TEMPLATE/TEMPLATE_nodes_attr.h
new file mode 100644 (file)
index 0000000..156ef65
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _TEMPLATE_NODES_ATTR_H_
+#define _TEMPLATE_NODES_ATTR_H_
+
+#include "../bearch.h"
+
+typedef struct _TEMPLATE_register_req_t {
+       const arch_register_req_t req;
+       int pos;   /**<< in case of "should be same/different" we need to remember the pos to get the irn */
+} TEMPLATE_register_req_t;
+
+
+typedef struct _TEMPLATE_attr_t {
+       arch_irn_flags_t flags;     /**<< indicating if spillable, rematerializeable ... etc. */
+       int              n_res;     /**<< number of results for this node */
+
+       const TEMPLATE_register_req_t **in_req;  /**<< register requirements for arguments */
+       const TEMPLATE_register_req_t **out_req; /**<< register requirements for results */
+
+       const arch_register_t **slots;          /**<< register slots for assigned registers */
+} TEMPLATE_attr_t;
+
+#endif /* _TEMPLATE_NODES_ATTR_H_ */
diff --git a/ir/be/TEMPLATE/bearch_TEMPLATE.c b/ir/be/TEMPLATE/bearch_TEMPLATE.c
new file mode 100644 (file)
index 0000000..8ca6d38
--- /dev/null
@@ -0,0 +1,496 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pseudo_irg.h"
+#include "irgwalk.h"
+#include "irprog.h"
+#include "irprintf.h"
+#include "ircons.h"
+#include "irgmod.h"
+
+#include "bitset.h"
+#include "debug.h"
+
+#include "../bearch.h"                /* the general register allocator interface */
+#include "../benode_t.h"
+#include "../belower.h"
+#include "../besched_t.h"
+#include "bearch_TEMPLATE_t.h"
+
+#include "TEMPLATE_new_nodes.h"           /* TEMPLATE nodes interface */
+#include "gen_TEMPLATE_regalloc_if.h"     /* the generated interface (register type and class defenitions) */
+#include "TEMPLATE_gen_decls.h"           /* interface declaration emitter */
+#include "TEMPLATE_transform.h"
+#include "TEMPLATE_emitter.h"
+#include "TEMPLATE_map_regs.h"
+
+#define DEBUG_MODULE "firm.be.TEMPLATE.isa"
+
+/* TODO: ugly, but we need it to get access to the registers assigned to Phi nodes */
+static set *cur_reg_set = NULL;
+
+/**************************************************
+ *                         _ _              _  __
+ *                        | | |            (_)/ _|
+ *  _ __ ___  __ _    __ _| | | ___   ___   _| |_
+ * | '__/ _ \/ _` |  / _` | | |/ _ \ / __| | |  _|
+ * | | |  __/ (_| | | (_| | | | (_) | (__  | | |
+ * |_|  \___|\__, |  \__,_|_|_|\___/ \___| |_|_|
+ *            __/ |
+ *           |___/
+ **************************************************/
+
+static ir_node *my_skip_proj(const ir_node *n) {
+       while (is_Proj(n))
+               n = get_Proj_pred(n);
+       return (ir_node *)n;
+}
+
+/**
+ * Return register requirements for a TEMPLATE node.
+ * If the node returns a tuple (mode_T) then the proj's
+ * will be asked for this information.
+ */
+static const arch_register_req_t *TEMPLATE_get_irn_reg_req(const void *self, arch_register_req_t *req, const ir_node *irn, int pos) {
+       const TEMPLATE_register_req_t *irn_req;
+       long               node_pos = pos == -1 ? 0 : pos;
+       ir_mode           *mode     = get_irn_mode(irn);
+       firm_dbg_module_t *mod      = firm_dbg_register(DEBUG_MODULE);
+
+       if (mode == mode_T || mode == mode_M) {
+               DBG((mod, LEVEL_1, "ignoring mode_T, mode_M node %+F\n", irn));
+               return NULL;
+       }
+
+       DBG((mod, LEVEL_1, "get requirements at pos %d for %+F ... ", pos, irn));
+
+       if (is_Proj(irn)) {
+               /* in case of a proj, we need to get the correct OUT slot */
+               /* of the node corresponding to the proj number */
+               if (pos == -1) {
+                       node_pos = TEMPLATE_translate_proj_pos(irn);
+               }
+               else {
+                       node_pos = pos;
+               }
+
+               irn = my_skip_proj(irn);
+
+               DB((mod, LEVEL_1, "skipping Proj, going to %+F at pos %d ... ", irn, node_pos));
+       }
+
+       /* get requirements for our own nodes */
+       if (is_TEMPLATE_irn(irn)) {
+               if (pos >= 0) {
+                       irn_req = get_TEMPLATE_in_req(irn, pos);
+               }
+               else {
+                       irn_req = get_TEMPLATE_out_req(irn, node_pos);
+               }
+
+               DB((mod, LEVEL_1, "returning reqs for %+F at pos %d\n", irn, pos));
+
+               memcpy(req, &(irn_req->req), sizeof(*req));
+
+               if (arch_register_req_is(&(irn_req->req), should_be_same) ||
+                       arch_register_req_is(&(irn_req->req), should_be_different)) {
+                       assert(irn_req->pos >= 0 && "should be same/different constraint for in -> out NYI");
+                       req->other = get_irn_n(irn, irn_req->pos);
+               }
+       }
+       /* get requirements for FIRM nodes */
+       else {
+               /* treat Phi like Const with default requirements */
+               if (is_Phi(irn)) {
+                       DB((mod, LEVEL_1, "returning standard reqs for %+F\n", irn));
+
+                       if (mode_is_float(mode)) {
+                               memcpy(req, &(TEMPLATE_default_req_TEMPLATE_floating_point.req), sizeof(*req));
+                       }
+                       else if (mode_is_int(mode) || mode_is_reference(mode)) {
+                               memcpy(req, &(TEMPLATE_default_req_TEMPLATE_general_purpose.req), sizeof(*req));
+                       }
+                       else if (mode == mode_T || mode == mode_M) {
+                               DBG((mod, LEVEL_1, "ignoring Phi node %+F\n", irn));
+                               return NULL;
+                       }
+                       else {
+                               assert(0 && "unsupported Phi-Mode");
+                       }
+               }
+               else if ((get_irn_op(irn) == op_Return) && pos > 0) {
+                       /* pos == 0 is Memory -> no requirements */
+                       DB((mod, LEVEL_1, "giving return (%+F) requirements\n", irn));
+
+                       if (pos == 1) {
+                               /* pos == 1 is Stackpointer */
+                               memcpy(req, &(TEMPLATE_default_req_TEMPLATE_general_purpose_r6.req), sizeof(*req));
+                       }
+                       else {
+                               if (mode_is_float(get_irn_mode(get_Return_res(irn, pos)))) {
+                                       /* fp result */
+                                       memcpy(req, &(TEMPLATE_default_req_TEMPLATE_floating_point_f0.req), sizeof(*req));
+                               }
+                               else {
+                                       /* integer result, 64bit results are returned as two 32bit values */
+                                       if (pos == 2) {
+                                               memcpy(req, &(TEMPLATE_default_req_TEMPLATE_general_purpose_r0.req), sizeof(*req));
+                                       }
+                                       else {
+                                               memcpy(req, &(TEMPLATE_default_req_TEMPLATE_general_purpose_r1.req), sizeof(*req));
+                                       }
+                               }
+                       }
+               }
+               else {
+                       DB((mod, LEVEL_1, "returning NULL for %+F (node not supported)\n", irn));
+                       req = NULL;
+               }
+       }
+
+       return req;
+}
+
+static void TEMPLATE_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) {
+       int pos = 0;
+
+       else if (is_Proj(irn)) {
+               pos = TEMPLATE_translate_proj_pos(irn);
+               irn = my_skip_proj(irn);
+       }
+
+       if (is_TEMPLATE_irn(irn)) {
+               const arch_register_t **slots;
+
+               slots      = get_TEMPLATE_slots(irn);
+               slots[pos] = reg;
+       }
+       else {
+               /* here we set the registers for the Phi nodes */
+               TEMPLATE_set_firm_reg(irn, reg, cur_reg_set);
+       }
+}
+
+static const arch_register_t *TEMPLATE_get_irn_reg(const void *self, const ir_node *irn) {
+       int pos = 0;
+       const arch_register_t *reg = NULL;
+
+       else if (is_Proj(irn)) {
+               pos = TEMPLATE_translate_proj_pos(irn);
+               irn = my_skip_proj(irn);
+       }
+
+       if (is_TEMPLATE_irn(irn)) {
+               const arch_register_t **slots;
+               slots = get_TEMPLATE_slots(irn);
+               reg   = slots[pos];
+       }
+       else {
+               reg = TEMPLATE_get_firm_reg(irn, cur_reg_set);
+       }
+
+       return reg;
+}
+
+static arch_irn_class_t TEMPLATE_classify(const void *self, const ir_node *irn) {
+       irn = my_skip_proj(irn);
+
+       if (is_cfop(irn)) {
+               return arch_irn_class_branch;
+       }
+       else if (is_TEMPLATE_irn(irn)) {
+               return arch_irn_class_normal;
+       }
+
+       return 0;
+}
+
+static arch_irn_flags_t TEMPLATE_get_flags(const void *self, const ir_node *irn) {
+       irn = my_skip_proj(irn);
+
+       if (is_TEMPLATE_irn(irn)) {
+               return get_TEMPLATE_flags(irn);
+       }
+       else if (is_Unknown(irn)) {
+               return arch_irn_flags_ignore;
+       }
+
+       return 0;
+}
+
+/* fill register allocator interface */
+
+static const arch_irn_ops_if_t TEMPLATE_irn_ops_if = {
+       TEMPLATE_get_irn_reg_req,
+       TEMPLATE_set_irn_reg,
+       TEMPLATE_get_irn_reg,
+       TEMPLATE_classify,
+       TEMPLATE_get_flags
+};
+
+TEMPLATE_irn_ops_t TEMPLATE_irn_ops = {
+       &TEMPLATE_irn_ops_if,
+       NULL
+};
+
+
+
+/**************************************************
+ *                _                         _  __
+ *               | |                       (_)/ _|
+ *   ___ ___   __| | ___  __ _  ___ _ __    _| |_
+ *  / __/ _ \ / _` |/ _ \/ _` |/ _ \ '_ \  | |  _|
+ * | (_| (_) | (_| |  __/ (_| |  __/ | | | | | |
+ *  \___\___/ \__,_|\___|\__, |\___|_| |_| |_|_|
+ *                        __/ |
+ *                       |___/
+ **************************************************/
+
+/**
+ * Transforms the standard firm graph into
+ * a TEMLPATE firm graph
+ */
+static void TEMPLATE_prepare_graph(void *self) {
+       TEMPLATE_code_gen_t *cg = self;
+
+       if (! is_pseudo_ir_graph(cg->irg)) {
+               irg_walk_blkwise_graph(cg->irg, TEMPLATE_place_consts, TEMPLATE_transform_node, cg);
+       }
+}
+
+
+
+/**
+ * Fix offsets and stacksize
+ */
+static void TEMPLATE_finish_irg(ir_graph *irg, TEMPLATE_code_gen_t *cg) {
+       /* TODO */
+}
+
+
+static void TEMPLATE_before_sched(void *self) {
+}
+
+static void TEMPLATE_before_ra(void *self) {
+}
+
+
+/**
+ * Creates a Store for a Spill
+ */
+static ir_node *TEMPLATE_lower_spill(void *self, ir_node *spill) {
+       TEMPLATE_code_gen_t *cg = self;
+       dbg_info        *dbg   = get_irn_dbg_info(spill);
+       ir_node         *block = get_nodes_block(spill);
+       ir_node         *ptr   = get_irg_frame(cg->irg);
+       ir_node         *val   = be_get_Spill_context(spill);
+       ir_node         *mem   = new_rd_NoMem(cg->irg);
+       ir_mode         *mode  = get_irn_mode(spill);
+       ir_node         *res;
+       entity          *ent   = be_get_spill_entity(spill);
+       unsigned         offs  = get_entity_offset_bytes(ent);
+
+       DB((cg->mod, LEVEL_1, "lower_spill: got offset %d for %+F\n", offs, ent));
+
+       /* TODO: create Store */
+
+       return res;
+}
+
+/**
+ * Create a Load for a Spill
+ */
+static ir_node *TEMPLATE_lower_reload(void *self, ir_node *reload) {
+       TEMPLATE_code_gen_t *cg = self;
+       dbg_info        *dbg   = get_irn_dbg_info(reload);
+       ir_node         *block = get_nodes_block(reload);
+       ir_node         *ptr   = get_irg_frame(cg->irg);
+       ir_mode         *mode  = get_irn_mode(reload);
+       ir_node         *pred  = get_irn_n(reload, 0);
+       tarval          *tv;
+       ir_node         *res;
+
+       /* TODO: create Load */
+
+       return res;
+}
+
+/**
+ * Returns the Stackregister
+ */
+static const arch_register_t *TEMPLATE_get_stack_register(void *self) {
+       /* TODO */
+}
+
+/**
+ * Emits the code, closes the output file and frees
+ * the code generator interface.
+ */
+static void TEMPLATE_codegen(void *self) {
+       TEMPLATE_code_gen_t *cg = self;
+       ir_graph           *irg = cg->irg;
+       FILE               *out = cg->out;
+
+       if (cg->emit_decls) {
+               TEMPLATE_gen_decls(cg->out);
+               cg->emit_decls = 0;
+       }
+
+       TEMPLATE_finish_irg(irg, cg);
+       dump_ir_block_graph_sched(irg, "-TEMPLATE-finished");
+       TEMPLATE_gen_routine(out, irg, cg);
+
+       cur_reg_set = NULL;
+
+       /* de-allocate code generator */
+       del_set(cg->reg_set);
+       free(self);
+}
+
+static void *TEMPLATE_cg_init(FILE *F, ir_graph *irg, const arch_env_t *arch_env);
+
+static const arch_code_generator_if_t TEMPLATE_code_gen_if = {
+       TEMPLATE_cg_init,
+       TEMPLATE_prepare_graph,
+       TEMPLATE_before_sched,   /* before scheduling hook */
+       TEMPLATE_before_ra,      /* before register allocation hook */
+       TEMPLATE_lower_spill,
+       TEMPLATE_lower_reload,
+       TEMPLATE_get_stack_register,
+       TEMPLATE_codegen         /* emit && done */
+};
+
+/**
+ * Initializes the code generator.
+ */
+static void *TEMPLATE_cg_init(FILE *F, ir_graph *irg, const arch_env_t *arch_env) {
+       TEMPLATE_isa_t      *isa = (TEMPLATE_isa_t *)arch_env->isa;
+       TEMPLATE_code_gen_t *cg  = xmalloc(sizeof(*cg));
+
+       cg->impl       = &TEMPLATE_code_gen_if;
+       cg->irg        = irg;
+       cg->reg_set    = new_set(TEMPLATE_cmp_irn_reg_assoc, 1024);
+       cg->mod        = firm_dbg_register("firm.be.TEMPLATE.cg");
+       cg->out        = F;
+       cg->arch_env   = arch_env;
+
+       isa->num_codegens++;
+
+       if (isa->num_codegens > 1)
+               cg->emit_decls = 0;
+       else
+               cg->emit_decls = 1;
+
+       cur_reg_set = cg->reg_set;
+
+       TEMPLATE_irn_ops.cg = cg;
+
+       return (arch_code_generator_t *)cg;
+}
+
+
+
+/*****************************************************************
+ *  ____             _                  _   _____  _____
+ * |  _ \           | |                | | |_   _|/ ____|  /\
+ * | |_) | __ _  ___| | _____ _ __   __| |   | | | (___   /  \
+ * |  _ < / _` |/ __| |/ / _ \ '_ \ / _` |   | |  \___ \ / /\ \
+ * | |_) | (_| | (__|   <  __/ | | | (_| |  _| |_ ____) / ____ \
+ * |____/ \__,_|\___|_|\_\___|_| |_|\__,_| |_____|_____/_/    \_\
+ *
+ *****************************************************************/
+
+/**
+ * Initializes the backend ISA and opens the output file.
+ */
+static void *TEMPLATE_init(void) {
+       static int inited = 0;
+       TEMPLATE_isa_t *isa   = xmalloc(sizeof(*isa));
+
+       isa->impl = &TEMPLATE_isa_if;
+
+       if(inited)
+               return NULL;
+
+       inited            = 1;
+       isa->num_codegens = 0;
+
+       TEMPLATE_register_init(isa);
+       TEMPLATE_create_opcodes();
+
+       return isa;
+}
+
+
+
+/**
+ * Closes the output file and frees the ISA structure.
+ */
+static void TEMPLATE_done(void *self) {
+       free(self);
+}
+
+
+
+static int TEMPLATE_get_n_reg_class(const void *self) {
+       return N_CLASSES;
+}
+
+static const arch_register_class_t *TEMPLATE_get_reg_class(const void *self, int i) {
+       assert(i >= 0 && i < N_CLASSES && "Invalid TEMPLATE register class requested.");
+       return &TEMPLATE_reg_classes[i];
+}
+
+static const void *TEMPLATE_get_irn_ops(const arch_irn_handler_t *self, const ir_node *irn) {
+       return &TEMPLATE_irn_ops;
+}
+
+const arch_irn_handler_t TEMPLATE_irn_handler = {
+       TEMPLATE_get_irn_ops
+};
+
+const arch_irn_handler_t *TEMPLATE_get_irn_handler(const void *self) {
+       return &TEMPLATE_irn_handler;
+}
+
+int TEMPLATE_to_appear_in_schedule(void *block_env, const ir_node *irn) {
+       return is_TEMPLATE_irn(irn);
+}
+
+/**
+ * Initializes the code generator interface.
+ */
+static const arch_code_generator_if_t *TEMPLATE_get_code_generator_if(void *self) {
+       return &TEMPLATE_code_gen_if;
+}
+
+list_sched_selector_t TEMPLATE_sched_selector;
+
+/**
+ * Returns the reg_pressure scheduler with to_appear_in_schedule() overloaded
+ */
+static const list_sched_selector_t *TEMPLATE_get_list_sched_selector(const void *self) {
+       memcpy(&TEMPLATE_sched_selector, trivial_selector, sizeof(list_sched_selector_t));
+       TEMPLATE_sched_selector.to_appear_in_schedule = TEMPLATE_to_appear_in_schedule;
+       return &TEMPLATE_sched_selector;
+}
+
+#ifdef WITH_LIBCORE
+static void TEMPLATE_register_options(lc_opt_entry_t *ent)
+{
+}
+#endif /* WITH_LIBCORE */
+
+const arch_isa_if_t TEMPLATE_isa_if = {
+#ifdef WITH_LIBCORE
+       TEMPLATE_register_options,
+#endif
+       TEMPLATE_init,
+       TEMPLATE_done,
+       TEMPLATE_get_n_reg_class,
+       TEMPLATE_get_reg_class,
+       TEMPLATE_get_irn_handler,
+       TEMPLATE_get_code_generator_if,
+       TEMPLATE_get_list_sched_selector,
+};
diff --git a/ir/be/TEMPLATE/bearch_TEMPLATE.h b/ir/be/TEMPLATE/bearch_TEMPLATE.h
new file mode 100644 (file)
index 0000000..4e9194b
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _BEARCH_TEMPLATE_H_
+#define _BEARCH_TEMPLATE_H_
+
+#include "../bearch.h"
+
+extern const arch_isa_if_t TEMPLATE_isa_if;
+
+#endif /* _BEARCH_TEMPLATE_H_ */
diff --git a/ir/be/TEMPLATE/bearch_TEMPLATE_t.h b/ir/be/TEMPLATE/bearch_TEMPLATE_t.h
new file mode 100644 (file)
index 0000000..cde5333
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef _BEARCH_TEMPLATE_T_H_
+#define _BEARCH_TEMPLATE_T_H_
+
+#include "debug.h"
+#include "bearch_TEMPLATE.h"
+#include "TEMPLATE_nodes_attr.h"
+
+
+typedef struct _TEMPLATE_code_gen_t {
+       const arch_code_generator_if_t *impl;           /* implementation */
+       ir_graph                       *irg;            /* current irg */
+       FILE                           *out;            /* output file */
+       const arch_env_t               *arch_env;       /* the arch env */
+       set                            *reg_set;        /* set to memorize registers for FIRM nodes (e.g. phi) */
+       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 TEMPLATE_register_req_t **reg_param_req;  /* hold the requirements for the reg param nodes */
+} TEMPLATE_code_gen_t;
+
+
+typedef struct _TEMPLATE_isa_t {
+       const arch_isa_if_t *impl;
+       int                  num_codegens;
+} TEMPLATE_isa_t;
+
+
+typedef struct _TEMPLATE_irn_ops_t {
+       const arch_irn_ops_if_t *impl;
+       TEMPLATE_code_gen_t         *cg;
+} TEMPLATE_irn_ops_t;
+
+
+#endif /* _BEARCH_TEMPLATE_T_H_ */