From 20c5275b37ba3a7d5d3a6adadd88ca47982e2df8 Mon Sep 17 00:00:00 2001 From: Moritz Kroll Date: Wed, 3 Dec 2008 11:07:26 +0000 Subject: [PATCH] Added first version of partial specification for IR nodes [r24252] --- ir/ir/ir_spec.pl | 405 ++++++++++++++++++++++++++++++++++++++++++++++ ir/ir/ircons.c | 77 ++++++++- scripts/gen_ir.pl | 295 +++++++++++++++++++++++++++++++++ 3 files changed, 776 insertions(+), 1 deletion(-) create mode 100755 ir/ir/ir_spec.pl create mode 100755 scripts/gen_ir.pl diff --git a/ir/ir/ir_spec.pl b/ir/ir/ir_spec.pl new file mode 100755 index 000000000..aa8600ee8 --- /dev/null +++ b/ir/ir/ir_spec.pl @@ -0,0 +1,405 @@ +# This is the specification for the IR nodes +# Code is generated by scripts/gen_ir.pl +# +# $Id$ + +$NONE = "#_#_#_#_#_NONE_#_#_#_#_#"; +$MANUALFROMPARAM = "#_#_#_#_#_MANUALFROMPARAM_#_#_#_#_#"; + +# The IR node description is done as a perl hash with the following structure: +# +# %nodes = ( +# +# => { +# op => use given node type instead of opname +# or 0 is this is an abstract node type (default: none) +# when present, no ir_op will be created +# is_a => name of another IR node description from which all data +# except "op" is inherited (default: none), +# mode => the mode of the op (default: parameter), +# op_flags => "N|L|C|X|I|F|Y|H|c|K|S|M|NB|NI" (default: "N"), +# state => "floats|pinned|mem_pinned|exc_pinned" (default: "floats"), +# arity => "dynamic|variable" +# dynamic allows to add inputs later, +# variable means, that the ins are given at construction time +# (default: automatically from args) +# block => the block for the node (default: parameter) +# ins => [ "in1", "in2", ... ] list of node inputs (default: none) +# attrs_name => name of the attribute structure +# (default if attrs exists: lcfirst(opname)), +# attrs_type => type of the attribute structure (default: auto generated), +# attrs => ordered list of attributes which will default to parameters +# after the ins and the mode parameters +# [ +# { +# type => the C type of the attribute or "bit", +# name => the name of the attribute, +# init => an initializer instead of a parameter +# or $MANUALFROMPARAM to disable automatic +# initialization but still using a parameter +# or $NONE to disable initialization completely +# by also not using a parameter +# (default: parameter), +# initname => name to access attribute +# when present, attribute will not be added +# to the according attribute struct +# (default: ".".name) +# comment => documentation for the attribute +# }, ... +# ] (default: none), +# init => additional initialization code to be emitted after the +# attribute initialization (default: none) +# optimize => whether optimize_node should be called (0|1, default: 1), +# d_pre => code to be inserted at the begining of the new_d_* function +# (may include declarations and statements, default: none), +# d_post => code to be inserted into the new_d_* function after the call +# to the new_rd_* function whose result is stored in the +# local variable res (default: none) +# }, +# +# +# +# ); # close the %nodes initializer +# + +# op_flags: flags for the operation corresponding to the firm irop_flags: +# N irop_flag_none +# L irop_flag_labeled +# C irop_flag_commutative +# X irop_flag_cfopcode +# I irop_flag_ip_cfopcode +# F irop_flag_fragile +# Y irop_flag_forking +# H irop_flag_highlevel +# c irop_flag_constlike +# K irop_flag_keep +# S irop_flag_start_block +# M irop_flag_uses_memory +# NB irop_flag_dump_noblock +# NI irop_flag_dump_noinput +# + +%nodes = ( + +Start => { + mode => "mode_T", + op_flags => "X", + state => "pinned" +}, + +End => { + mode => "mode_X", + op_flags => "X", + state => "pinned", + arity => "dynamic" +}, + +Block => { + mode => "mode_BB", + op_flags => "L", + state => "pinned", + arity => "variable", + block => "NULL", + attrs => [ + { + type => "ir_graph *", + name => "irg", + init => "irg", + comment => "The graph this block belongs to." + }, + { + type => "ir_visited_t", + name => "block_visited", + init => $NONE, + comment => "For the walker that walks over all blocks." + }, + { + type => "bit", + name => "is_matured", + init => $NONE, + comment => "If set, all in-nodes of the block are fixed." + }, + { + type => "bit", + name => "is_dead", + init => "0", + comment => "If set, the block is dead (and could be replace by a Bad." + }, + { + type => "bit", + name => "is_mb_head", + init => "1", + comment => "Set if this block is a macroblock head." + }, + { + type => "bit", + name => "has_label", + init => "0", + comment => "Set if this block has a label assigned." + }, + { + type => "bit", + name => "marked", + init => $NONE, # TODO: This is uninitialized!! + comment => "Can be set/unset to temporary mark a block." + }, + { + type => "ir_node **", + name => "graph_arr", + init => $NONE, # TODO: This is uninitialized!! + comment => "An array to store all parameters." + }, + { + type => "ir_dom_info", + name => "dom", + init => $NONE, # TODO: This is uninitialized!! + comment => "Datastructure that holds information about dominators. + @@@ \@todo + Eventually overlay with graph_arr as only valid + in different phases. Eventually inline the whole + datastructure." + }, + { + type => "ir_dom_info", + name => "pdom", + init => $NONE, # TODO: This is uninitialized!! + comment => "Datastructure that holds information about post-dominators." + }, + { + type => "ir_node **", + name => "in_cg", + init => "NULL", + comment => "array with predecessors in + * interprocedural_view, if they differ + * from intraprocedural predecessors" + }, + { + type => "unsigned *", + name => "backedge", + init => "new_backedge_arr(irg->obst, arity)", + comment => "Raw Bitfield n set to true if pred n is backedge." + }, + { + type => "unsigned *", + name => "cg_backedge", + init => "NULL", + comment => "Raw Bitfield n set to true if pred n is interprocedural backedge." + }, + { + type => "ir_extblk *", + name => "extblk", + init => "NULL", + comment => "The extended basic block this block belongs to." + }, + { + type => "ir_region *", + name => "region", + init => $NONE, # TODO: This is uninitialized!! + comment => "The immediate structural region this block belongs to." + }, + { + type => "unsigned", + name => "mb_depth", + init => "0", + comment => "The macroblock depth: A distance from the macroblock header." + }, + { + type => "ir_label_t", + name => "label", + init => "0", + comment => "The block label if assigned." + }, + { + type => "ir_node *", + name => "phis", + init => $NONE, # TODO: This is uninitialized!! + comment => "The list of Phi nodes in this block." + }, + { + type => "struct list_head", + name => "succ_head", + init => $NONE, # TODO: This is uninitialized!! + comment => "A list head for all successor edges of a block." + }, + ], + init => "\t/* macroblock header */\n". + "\tres->in[0] = res;\n\n". + "\tset_Block_matured(res, 1);\n". + "\tset_Block_block_visited(res, 0);\n", + optimize => 0, + d_pre => "\tint i;\n\tint has_unknown = 0;\n", + d_post => "\t/* Create and initialize array for Phi-node construction. */\n". + "\tif (get_irg_phase_state(current_ir_graph) == phase_building) {\n". + "\t\tres->attr.block.graph_arr = NEW_ARR_D(ir_node *, current_ir_graph->obst,\n". + "\t\t current_ir_graph->n_loc);\n". + "\t\tmemset(res->attr.block.graph_arr, 0, sizeof(ir_node *) * current_ir_graph->n_loc);\n". + "\t}\n\n". + "\tfor (i = arity-1; i >= 0; i--)\n". + "\t\tif (is_Unknown(in[i])) {\n". + "\t\thas_unknown = 1;\n". + "\t\tbreak;\n". + "\t}\n". + "\tif (!has_unknown) res = optimize_node(res);\n". + "\tcurrent_ir_graph->current_block = res;\n". + "\tIRN_VRFY_IRG(res, current_ir_graph);\n" +}, + +Const_type => { + op => "Const", + op_flags => "c|S", + mode => "get_tarval_mode(tv)", + block => "get_irg_start_block(irg)", + attrs_name => "con", + attrs => [ + { + type => "tarval *", + name => "tv" + }, + { + type => "ir_type *", + name => "tp", + init => $MANUALFROMPARAM + } + ], + init => "set_Const_type(res, tp);\n" +}, + +Id => { + ins => [ "val" ] +}, + +Proj => { + ins => [ "arg" ], + attrs_type => "long", + attrs => [ + { + type => "long", + name => "proj", + initname => "", + } + ], + init => "assert(get_Proj_pred(res));\n". + "\tassert(get_nodes_block(get_Proj_pred(res)));\n" +}, + +# Conv => { +# ins => [ "op" ], +# attrs => [ +# { +# type => "char", +# name => "strict", +# #init => "0", +# comment => "If set, this is a strict Conv that cannot be removed." +# } +# ] +# }, + +Cast => { + op_flags => "H", + mode => "get_irn_mode(op)", + ins => [ "op" ], + attrs => [ + { + type => "ir_type *", + name => "totype", + comment => "Type of the casted node." + } + ], + init => "assert(is_atomic_type(totype));\n" +}, + +Jmp => { + op_flags => "X", + state => "pinned", + mode => "mode_X" +}, + +IJmp => { + op_flags => "X", + state => "pinned", + mode => "mode_X", + ins => [ "target" ] +}, + +Cond => { + op_flags => "X|Y", + state => "pinned", + mode => "mode_T", + ins => [ "selector" ], + attrs => [ + { + type => "cond_kind", + name => "kind", + init => "dense", + comment => "Flavor of Cond." + }, + { + type => "long", + name => "default_proj", + init => "0", + comment => "Only for non-binary Conds: biggest Proj number, i.e. the one used for default." + }, + { + type => "cond_jmp_predicate", + name => "pred", + init => "COND_JMP_PRED_NONE", + comment => "Only for binary Conds: The jump predication." + }, + + ] +}, + +Tuple => { + op_flags => "L", + mode => "mode_T", + arity => "variable" +}, + +BinOp => { + op => 0, + ins => [ "left", "right" ] +}, + +Cmp => { + is_a => "BinOp", + mode => "mode_T" +}, + +Add => { + is_a => "BinOp", + op_flags => "C", +}, + +Div => { + mode => "mode_T", + op_flags => "F|M", + state => "exc_pinned", + ins => [ "mem", "left", "right" ], + attrs_name => "divmod", + attrs => [ + { + type => "except_attr", + name => "exc", + init => $NONE + }, + { + type => "ir_mode *", + name => "res_mode" + }, + { + type => "op_pin_state", + name => "state", + initname => ".exc.pin_state" + }, + { + type => "char", + name => "no_remainder", + init => "0" + } + ], + d_post => "\t#if PRECISE_EXC_CONTEXT\n". + "\tfirm_alloc_frag_arr(res, op_Div, &res->attr.except.frag_arr);\n". + "\t#endif\n" +} + +); diff --git a/ir/ir/ircons.c b/ir/ir/ircons.c index 4be1b1701..b83715f84 100644 --- a/ir/ir/ircons.c +++ b/ir/ir/ircons.c @@ -44,6 +44,9 @@ #include "iredges_t.h" #include "irflag_t.h" +/* Uncomment to use original code instead of generated one */ +// #define USE_ORIGINAL + /* when we need verifying */ #ifdef NDEBUG # define IRN_VRFY_IRG(res, irg) @@ -164,6 +167,9 @@ new_d_##instr(dbg_info *db, ir_node *op, ir_mode *mode) { \ return new_bd_##instr(db, current_ir_graph->current_block, op, mode); \ } +#ifndef USE_ORIGINAL +#include "gen_ir_cons.c.inl" +#else /** * Constructs a Block with a fixed number of predecessors. @@ -219,6 +225,7 @@ new_bd_End(dbg_info *db, ir_node *block) { IRN_VRFY_IRG(res, irg); return res; } /* new_bd_End */ +#endif /** * Creates a Phi node with all predecessors. Calling this constructor @@ -256,6 +263,7 @@ new_bd_Phi(dbg_info *db, ir_node *block, int arity, ir_node **in, ir_mode *mode) return res; } /* new_bd_Phi */ +#ifdef USE_ORIGINAL static ir_node * new_bd_Const_type(dbg_info *db, tarval *con, ir_type *tp) { ir_node *res; @@ -270,6 +278,7 @@ new_bd_Const_type(dbg_info *db, tarval *con, ir_type *tp) { return res; } /* new_bd_Const_type */ +#endif static ir_node * new_bd_Const(dbg_info *db, tarval *con) { @@ -285,6 +294,7 @@ new_bd_Const_long(dbg_info *db, ir_mode *mode, long value) { return new_rd_Const(db, irg, new_tarval_from_long(value, mode)); } /* new_bd_Const_long */ +#ifdef USE_ORIGINAL static ir_node * new_bd_Id(dbg_info *db, ir_node *block, ir_node *val, ir_mode *mode) { ir_node *res; @@ -314,6 +324,7 @@ new_bd_Proj(dbg_info *db, ir_node *block, ir_node *arg, ir_mode *mode, IRN_VRFY_IRG(res, irg); return res; } /* new_bd_Proj */ +#endif static ir_node * new_bd_defaultProj(dbg_info *db, ir_node *block, ir_node *arg, @@ -340,6 +351,7 @@ new_bd_Conv(dbg_info *db, ir_node *block, ir_node *op, ir_mode *mode, int strict return res; } /* new_bd_Conv */ +#ifdef USE_ORIGINAL static ir_node * new_bd_Cast(dbg_info *db, ir_node *block, ir_node *op, ir_type *to_tp) { ir_node *res; @@ -366,13 +378,16 @@ new_bd_Tuple(dbg_info *db, ir_node *block, int arity, ir_node **in) { } /* new_bd_Tuple */ NEW_BD_BINOP(Add) +#endif NEW_BD_BINOP(Sub) NEW_BD_UNOP(Minus) NEW_BD_BINOP(Mul) NEW_BD_BINOP(Mulh) NEW_BD_DIVOP(Quot) NEW_BD_DIVOP(DivMod) +#ifdef USE_ORIGINAL NEW_BD_DIVOP(Div) +#endif NEW_BD_DIVOP(Mod) NEW_BD_BINOP(And) NEW_BD_BINOP(Or) @@ -405,6 +420,7 @@ static ir_node *new_bd_DivRL(dbg_info *db, ir_node *block, return res; } +#ifdef USE_ORIGINAL static ir_node * new_bd_Cmp(dbg_info *db, ir_node *block, ir_node *op1, ir_node *op2) { ir_node *in[2]; @@ -453,6 +469,7 @@ new_bd_Cond(dbg_info *db, ir_node *block, ir_node *c) { IRN_VRFY_IRG(res, irg); return res; } /* new_bd_Cond */ +#endif static ir_node * new_bd_Call(dbg_info *db, ir_node *block, ir_node *store, @@ -840,6 +857,7 @@ new_bd_ASM(dbg_info *db, ir_node *block, int arity, ir_node *in[], ir_asm_constr /* private interfaces, for professional use only */ /* --------------------------------------------- */ +#ifdef USE_ORIGINAL /* Constructs a Block with a fixed number of predecessors. Does not set current_block. Can not be used with automatic Phi node construction. */ @@ -878,6 +896,7 @@ new_rd_End(dbg_info *db, ir_graph *irg, ir_node *block) { return res; } /* new_rd_End */ +#endif /* Creates a Phi node with all predecessors. Calling this constructor is only allowed if the corresponding block is mature. */ @@ -893,6 +912,7 @@ new_rd_Phi(dbg_info *db, ir_graph *irg, ir_node *block, int arity, ir_node **in, return res; } /* new_rd_Phi */ +#ifdef USE_ORIGINAL ir_node * new_rd_Const_type(dbg_info *db, ir_graph *irg, tarval *con, ir_type *tp) { ir_node *res; @@ -904,15 +924,20 @@ new_rd_Const_type(dbg_info *db, ir_graph *irg, tarval *con, ir_type *tp) { return res; } /* new_rd_Const_type */ +#endif ir_node * new_rd_Const(dbg_info *db, ir_graph *irg, tarval *con) { ir_node *res; +#ifdef USE_ORIGINAL ir_graph *rem = current_ir_graph; current_ir_graph = irg; res = new_bd_Const_type(db, con, firm_unknown_type); current_ir_graph = rem; +#else + res = new_rd_Const_type(db, irg, con, firm_unknown_type); +#endif return res; } /* new_rd_Const */ @@ -922,6 +947,7 @@ new_rd_Const_long(dbg_info *db, ir_graph *irg, ir_mode *mode, long value) { return new_rd_Const(db, irg, new_tarval_from_long(value, mode)); } /* new_rd_Const_long */ +#ifdef USE_ORIGINAL ir_node * new_rd_Id(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *val, ir_mode *mode) { ir_node *res; @@ -946,6 +972,7 @@ new_rd_Proj(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *arg, ir_mode * return res; } /* new_rd_Proj */ +#endif ir_node * new_rd_defaultProj(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *arg, @@ -972,6 +999,7 @@ new_rd_Conv(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *op, ir_mode *m return res; } /* new_rd_Conv */ +#ifdef USE_ORIGINAL ir_node * new_rd_Cast(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *op, ir_type *to_tp) { ir_node *res; @@ -997,13 +1025,16 @@ new_rd_Tuple(dbg_info *db, ir_graph *irg, ir_node *block, int arity, ir_node **i } /* new_rd_Tuple */ NEW_RD_BINOP(Add) +#endif NEW_RD_BINOP(Sub) NEW_RD_UNOP(Minus) NEW_RD_BINOP(Mul) NEW_RD_BINOP(Mulh) NEW_RD_DIVOP(Quot) NEW_RD_DIVOP(DivMod) +#ifdef USE_ORIGINAL NEW_RD_DIVOP(Div) +#endif NEW_RD_DIVOP(Mod) NEW_RD_BINOP(And) NEW_RD_BINOP(Or) @@ -1029,6 +1060,7 @@ ir_node *new_rd_DivRL(dbg_info *db, ir_graph *irg, ir_node *block, return res; } +#ifdef USE_ORIGINAL ir_node * new_rd_Cmp(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *op1, ir_node *op2) { @@ -1077,6 +1109,7 @@ new_rd_Cond(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *c) { return res; } /* new_rd_Cond */ +#endif ir_node * new_rd_Call(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *store, @@ -1422,6 +1455,7 @@ ir_node *new_rd_ASM(dbg_info *db, ir_graph *irg, ir_node *block, } /* new_rd_ASM */ +#ifdef USE_ORIGINAL ir_node *new_r_Block(ir_graph *irg, int arity, ir_node **in) { return new_rd_Block(NULL, irg, arity, in); } @@ -1440,6 +1474,7 @@ ir_node *new_r_IJmp(ir_graph *irg, ir_node *block, ir_node *tgt) { ir_node *new_r_Cond(ir_graph *irg, ir_node *block, ir_node *c) { return new_rd_Cond(NULL, irg, block, c); } +#endif ir_node *new_r_Return(ir_graph *irg, ir_node *block, ir_node *store, int arity, ir_node **in) { return new_rd_Return(NULL, irg, block, store, arity, in); @@ -1450,9 +1485,11 @@ ir_node *new_r_Const(ir_graph *irg, tarval *con) { ir_node *new_r_Const_long(ir_graph *irg, ir_mode *mode, long value) { return new_rd_Const_long(NULL, irg, mode, value); } +#ifdef USE_ORIGINAL ir_node *new_r_Const_type(ir_graph *irg, tarval *con, ir_type *tp) { return new_rd_Const_type(NULL, irg, con, tp); } +#endif ir_node *new_r_SymConst(ir_graph *irg, ir_node *block, ir_mode *mode, symconst_symbol value, symconst_kind symkind) { return new_rd_SymConst(NULL, irg, block, mode, value, symkind); @@ -1471,10 +1508,12 @@ ir_node *new_r_Call(ir_graph *irg, ir_node *block, ir_node *store, ir_type *tp) { return new_rd_Call(NULL, irg, block, store, callee, arity, in, tp); } +#ifdef USE_ORIGINAL ir_node *new_r_Add(ir_graph *irg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) { return new_rd_Add(NULL, irg, block, op1, op2, mode); } +#endif ir_node *new_r_Sub(ir_graph *irg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) { return new_rd_Sub(NULL, irg, block, op1, op2, mode); @@ -1499,10 +1538,12 @@ ir_node *new_r_DivMod(ir_graph *irg, ir_node *block, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) { return new_rd_DivMod(NULL, irg, block, memop, op1, op2, mode, state); } +#ifdef USE_ORIGINAL ir_node *new_r_Div(ir_graph *irg, ir_node *block, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) { return new_rd_Div(NULL, irg, block, memop, op1, op2, mode, state); } +#endif ir_node *new_r_DivRL(ir_graph *irg, ir_node *block, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) { return new_rd_DivRL(NULL, irg, block, memop, op1, op2, mode, state); @@ -1555,17 +1596,21 @@ ir_node *new_r_Borrow(ir_graph *irg, ir_node *block, ir_node *op, ir_node *k, ir_mode *mode) { return new_rd_Borrow(NULL, irg, block, op, k, mode); } +#ifdef USE_ORIGINAL ir_node *new_r_Cmp(ir_graph *irg, ir_node *block, ir_node *op1, ir_node *op2) { return new_rd_Cmp(NULL, irg, block, op1, op2); } +#endif ir_node *new_r_Conv(ir_graph *irg, ir_node *block, ir_node *op, ir_mode *mode) { return new_rd_Conv(NULL, irg, block, op, mode); } +#ifdef USE_ORIGINAL ir_node *new_r_Cast(ir_graph *irg, ir_node *block, ir_node *op, ir_type *to_tp) { return new_rd_Cast(NULL, irg, block, op, to_tp); } +#endif ir_node *new_r_Phi(ir_graph *irg, ir_node *block, int arity, ir_node **in, ir_mode *mode) { return new_rd_Phi(NULL, irg, block, arity, in, mode); @@ -1589,14 +1634,17 @@ ir_node *new_r_Free(ir_graph *irg, ir_node *block, ir_node *store, ir_node *new_r_Sync(ir_graph *irg, ir_node *block, int arity, ir_node *in[]) { return new_rd_Sync(NULL, irg, block, arity, in); } +#ifdef USE_ORIGINAL ir_node *new_r_Proj(ir_graph *irg, ir_node *block, ir_node *arg, ir_mode *mode, long proj) { return new_rd_Proj(NULL, irg, block, arg, mode, proj); } +#endif ir_node *new_r_defaultProj(ir_graph *irg, ir_node *block, ir_node *arg, long max_proj) { return new_rd_defaultProj(NULL, irg, block, arg, max_proj); } +#ifdef USE_ORIGINAL ir_node *new_r_Tuple(ir_graph *irg, ir_node *block, int arity, ir_node **in) { return new_rd_Tuple(NULL, irg, block, arity, in ); @@ -1605,6 +1653,7 @@ ir_node *new_r_Id(ir_graph *irg, ir_node *block, ir_node *val, ir_mode *mode) { return new_rd_Id(NULL, irg, block, val, mode); } +#endif ir_node *new_r_Bad(ir_graph *irg) { return get_irg_bad(irg); } @@ -1667,6 +1716,8 @@ ir_node *new_r_ASM(ir_graph *irg, ir_node *block, /** public interfaces */ /** construction tools */ +#ifdef USE_ORIGINAL + /** * * - create a new Start node in the current block @@ -1729,6 +1780,7 @@ new_d_Block(dbg_info *db, int arity, ir_node **in) { return res; } /* new_d_Block */ +#endif /* ***********************************************************************/ /* Methods necessary for automatic Phi node creation */ @@ -2264,6 +2316,7 @@ new_d_Const_long(dbg_info *db, ir_mode *mode, long value) { return new_bd_Const_long(db, mode, value); } /* new_d_Const_long */ +#ifdef USE_ORIGINAL ir_node * new_d_Const_type(dbg_info *db, tarval *con, ir_type *tp) { return new_bd_Const_type(db, con, tp); @@ -2279,6 +2332,7 @@ ir_node * new_d_Proj(dbg_info *db, ir_node *arg, ir_mode *mode, long proj) { return new_bd_Proj(db, current_ir_graph->current_block, arg, mode, proj); } /* new_d_Proj */ +#endif ir_node * new_d_defaultProj(dbg_info *db, ir_node *arg, long max_proj) { @@ -2301,6 +2355,7 @@ new_d_strictConv(dbg_info *db, ir_node *op, ir_mode *mode) { return new_bd_Conv(db, current_ir_graph->current_block, op, mode, 1); } /* new_d_strictConv */ +#ifdef USE_ORIGINAL ir_node * new_d_Cast(dbg_info *db, ir_node *op, ir_type *to_tp) { return new_bd_Cast(db, current_ir_graph->current_block, op, to_tp); @@ -2312,6 +2367,7 @@ new_d_Tuple(dbg_info *db, int arity, ir_node **in) { } /* new_d_Tuple */ NEW_D_BINOP(Add) +#endif NEW_D_BINOP(Sub) NEW_D_UNOP(Minus) NEW_D_BINOP(Mul) @@ -2358,6 +2414,7 @@ new_d_DivMod(dbg_info *db, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode * return res; } /* new_d_DivMod */ +#ifdef USE_ORIGINAL ir_node * new_d_Div(dbg_info *db, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) { ir_node *res; @@ -2368,6 +2425,7 @@ new_d_Div(dbg_info *db, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mod return res; } /* new_d_Div */ +#endif ir_node * new_d_DivRL(dbg_info *db, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) { @@ -2403,6 +2461,7 @@ NEW_D_UNOP(Abs) NEW_D_BINOP(Carry) NEW_D_BINOP(Borrow) +#ifdef USE_ORIGINAL ir_node * new_d_Cmp(dbg_info *db, ir_node *op1, ir_node *op2) { return new_bd_Cmp(db, current_ir_graph->current_block, op1, op2); @@ -2422,6 +2481,7 @@ ir_node * new_d_Cond(dbg_info *db, ir_node *c) { return new_bd_Cond(db, current_ir_graph->current_block, c); } /* new_d_Cond */ +#endif ir_node * new_d_Call(dbg_info *db, ir_node *store, ir_node *callee, int arity, ir_node **in, @@ -2826,7 +2886,7 @@ irp_finalize_cons(void) { irp->phase_state = phase_high; } /* irp_finalize_cons */ - +#ifdef USE_ORIGINAL ir_node *new_Block(int arity, ir_node **in) { return new_d_Block(NULL, arity, in); } @@ -2845,6 +2905,7 @@ ir_node *new_IJmp(ir_node *tgt) { ir_node *new_Cond(ir_node *c) { return new_d_Cond(NULL, c); } +#endif ir_node *new_Return(ir_node *store, int arity, ir_node *in[]) { return new_d_Return(NULL, store, arity, in); } @@ -2856,9 +2917,11 @@ ir_node *new_Const_long(ir_mode *mode, long value) { return new_d_Const_long(NULL, mode, value); } +#ifdef USE_ORIGINAL ir_node *new_Const_type(tarval *con, ir_type *tp) { return new_d_Const_type(NULL, con, tp); } +#endif ir_node *new_SymConst_type(ir_mode *mode, symconst_symbol value, symconst_kind kind, ir_type *type) { return new_d_SymConst_type(NULL, mode, value, kind, type); @@ -2877,9 +2940,11 @@ ir_node *new_Call(ir_node *store, ir_node *callee, int arity, ir_node **in, ir_type *tp) { return new_d_Call(NULL, store, callee, arity, in, tp); } +#ifdef USE_ORIGINAL ir_node *new_Add(ir_node *op1, ir_node *op2, ir_mode *mode) { return new_d_Add(NULL, op1, op2, mode); } +#endif ir_node *new_Sub(ir_node *op1, ir_node *op2, ir_mode *mode) { return new_d_Sub(NULL, op1, op2, mode); } @@ -2898,9 +2963,11 @@ ir_node *new_Quot(ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_ ir_node *new_DivMod(ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) { return new_d_DivMod(NULL, memop, op1, op2, mode, state); } +#ifdef USE_ORIGINAL ir_node *new_Div(ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) { return new_d_Div(NULL, memop, op1, op2, mode, state); } +#endif ir_node *new_DivRL(ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) { return new_d_DivRL(NULL, memop, op1, op2, mode, state); } @@ -2940,18 +3007,22 @@ ir_node *new_Carry(ir_node *op1, ir_node *op2, ir_mode *mode) { ir_node *new_Borrow(ir_node *op1, ir_node *op2, ir_mode *mode) { return new_d_Borrow(NULL, op1, op2, mode); } +#ifdef USE_ORIGINAL ir_node *new_Cmp(ir_node *op1, ir_node *op2) { return new_d_Cmp(NULL, op1, op2); } +#endif ir_node *new_Conv(ir_node *op, ir_mode *mode) { return new_d_Conv(NULL, op, mode); } ir_node *new_strictConv(ir_node *op, ir_mode *mode) { return new_d_strictConv(NULL, op, mode); } +#ifdef USE_ORIGINAL ir_node *new_Cast(ir_node *op, ir_type *to_tp) { return new_d_Cast(NULL, op, to_tp); } +#endif ir_node *new_Phi(int arity, ir_node **in, ir_mode *mode) { return new_d_Phi(NULL, arity, in, mode); } @@ -2972,18 +3043,22 @@ ir_node *new_Free(ir_node *store, ir_node *ptr, ir_node *size, ir_node *new_Sync(int arity, ir_node *in[]) { return new_d_Sync(NULL, arity, in); } +#ifdef USE_ORIGINAL ir_node *new_Proj(ir_node *arg, ir_mode *mode, long proj) { return new_d_Proj(NULL, arg, mode, proj); } +#endif ir_node *new_defaultProj(ir_node *arg, long max_proj) { return new_d_defaultProj(NULL, arg, max_proj); } +#ifdef USE_ORIGINAL ir_node *new_Tuple(int arity, ir_node **in) { return new_d_Tuple(NULL, arity, in); } ir_node *new_Id(ir_node *val, ir_mode *mode) { return new_d_Id(NULL, val, mode); } +#endif ir_node *new_Bad(void) { return get_irg_bad(current_ir_graph); } diff --git a/scripts/gen_ir.pl b/scripts/gen_ir.pl new file mode 100755 index 000000000..a5d2f4e02 --- /dev/null +++ b/scripts/gen_ir.pl @@ -0,0 +1,295 @@ +#!/usr/bin/perl -w + +# +# 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. +# + +# This script generates C code for the IR nodes specified +# in ../ir/ir/ir_spec.pl. +# +# $Id$ + +use strict; + +my $specfile = $ARGV[0]; +my $target_dir = $ARGV[1]; +my $target_cons = $target_dir."/gen_ir_cons.c.inl"; + +our %nodes; +our $NONE; +our $MANUALFROMPARAM; + +# include spec file + +my $return; + +no strict "subs"; +unless ($return = do $specfile) { + die "Fatal error: couldn't parse $specfile: $@" if $@; + die "Fatal error: couldn't do $specfile: $!" unless defined $return; + die "Fatal error: couldn't run $specfile" unless $return; +} +use strict "subs"; + +my @text_cons; +my $ARITY_DYNAMIC = -1; +my $ARITY_VARIABLE = "arity"; +my $had_error = 0; + +# generate IR node constructors + +foreach my $nodename (keys(%nodes)) { + my %curnode = %{ $nodes{"$nodename"} }; + + my $op_name; + if (exists($curnode{"op"})) { + $op_name = $curnode{"op"}; + } else { + $op_name = $nodename; + } + + if ($op_name eq 0) { + next; + } + + print "${op_name}\n"; + + # handle inheritance + + my @hierarchy; + my %curop = %curnode; + my $supername; + push(@hierarchy, $nodename); + while (exists($curop{"is_a"})) { + $supername = $curop{"is_a"}; + push(@hierarchy, $supername); + %curop = %{ $nodes{$supername} }; + } + my %node; + foreach my $cursupername (reverse @hierarchy) { + # print " - $cursupername\n"; + my %supernode = %{ $nodes{$cursupername} }; + foreach my $keyname (keys(%supernode)) { + # print " --- $keyname\n"; + if ($keyname eq "op") { + next; + } + my $value = $supernode{$keyname}; + $node{$keyname} = $value; + } + } + + # check op_flags and state fields + + if (!exists($node{"op_flags"})) { + $node{"op_flags"} = "N"; + } + if (!exists($node{"state"})) { + $node{"state"} = "floats"; + } + + # calculate arity + + my $arity = 0; + + if (exists($node{"arity"})) { + $arity = $node{"arity"}; + if (exists($node{"ins"})) { + print "ERROR: $nodename defines \"arity\" AND \"ins\" field\n"; + $had_error = 1; + } + } elsif (exists($node{"ins"})) { + $arity = scalar(@{ $node{"ins"} }); + } + + if ($arity eq "dynamic") { + $arity = $ARITY_DYNAMIC; + } elsif ($arity eq "variable") { + $arity = $ARITY_VARIABLE; + } + + # build new_rd_$nodename function + + push(@text_cons, "ir_node *new_rd_$nodename(dbg_info *db, ir_graph *irg"); + + my @text_paramdecls; + my @text_paramuse; + + my $block_name; + if (!exists($node{"block"})) { + push(@text_cons, ", ir_node *block"); + $block_name = "block"; + } else { + $block_name = $node{"block"}; + } + + if (exists($node{"ins"})) { + my @ins = @{ $node{"ins"} }; + + foreach my $inname (@ins) { + push(@text_paramdecls, "ir_node *$inname"); + push(@text_paramuse, "$inname"); + } + } elsif ($arity eq $ARITY_VARIABLE) { + push(@text_paramdecls, "int arity, ir_node **in"); + push(@text_paramuse, "arity, in"); + } + + my $mode_name; + if (exists($node{"mode"})) { + $mode_name = $node{"mode"}; + } else { + $mode_name = "mode"; + push(@text_paramdecls, "ir_mode *mode"); + push(@text_paramuse, "mode"); + } + + if (exists($node{"attrs"})) { + my @attrs = @{ $node{"attrs"} }; + + if (!exists($node{"attrs_name"})) { + $node{"attrs_name"} = lcfirst($nodename); + } + + foreach my $attritem (@attrs) { + my %attr = %{ $attritem }; + if (!exists($attr{"init"}) || $attr{"init"} eq $MANUALFROMPARAM) { + push(@text_paramdecls, $attr{"type"}. " ".$attr{"name"}); + push(@text_paramuse, $attr{"name"}); + } + } + } + + push(@text_cons, ", " . join(", ", @text_paramdecls)) if @text_paramdecls; + push(@text_cons, ")\n{\n". + "\tir_node *res;\n"); + + my $in_array = "NULL"; + if ($arity eq $ARITY_VARIABLE) { + $in_array = "in"; + } elsif ($arity > 0) { + push(@text_cons, "\tir_node *in[$arity];\n"); + $in_array = "in"; + + my @ins = @{ $node{"ins"} }; + for (my $idx = 0; $idx <= $#ins; $idx++) { + push(@text_cons, "\tin[$idx] = ".$ins[$idx].";\n"); + } + } + + push(@text_cons, "\tres = new_ir_node(db, irg, $block_name, op_$op_name, $mode_name, $arity, $in_array);\n"); + + if (exists($node{"attrs"})) { + my @attrs = @{ $node{"attrs"} }; + + foreach my $attritem (@attrs) { + my %attr = %{ $attritem }; + if (!exists($attr{"init"}) || $attr{"init"} ne $MANUALFROMPARAM && + $attr{"init"} ne $NONE) { + my $initname = exists($attr{"initname"}) ? $attr{"initname"} : "." . $attr{"name"}; + my $initval = exists($attr{"init"}) ? $attr{"init"} : $attr{"name"}; + push(@text_cons, "\tres->attr.".$node{"attrs_name"}."$initname = $initval;\n"); + } + } + } + + if (exists($node{"init"})) { + push(@text_cons, $node{"init"}); + } + + if (!exists($node{"optimize"}) || $node{"optimize"} eq 1) { + push(@text_cons, "\tres = optimize_node(res);\n"); + } + + push(@text_cons, "\tIRN_VRFY_IRG(res, irg);\n". + "\treturn res;\n". + "}\n\n"); + + # build new_r_$nodename function + + push(@text_cons, "ir_node *new_r_$nodename(ir_graph *irg"); + push(@text_cons, ", ir_node *block") unless exists($node{"block"}); + push(@text_cons, ", " . join(", ", @text_paramdecls)) if @text_paramdecls; + push(@text_cons, ")\n" + ."{\n" + ."\treturn new_rd_$nodename(NULL, irg"); + push(@text_cons, ", block") unless exists($node{"block"}); + push(@text_cons, ", " . join(", ", @text_paramuse)) if @text_paramuse; + push(@text_cons, ");\n" + ."}\n\n"); + + # build new_d_$nodename function + + push(@text_cons, "ir_node *new_d_$nodename(dbg_info *db"); + push(@text_cons, ", " . join(", ", @text_paramdecls)) if @text_paramdecls; + push(@text_cons, ")\n" + ."{\n" + ."\tir_node *res;\n"); + push(@text_cons, $node{"d_pre"}) if exists($node{"d_pre"}); + push(@text_cons, "\tres = new_rd_$nodename(db, current_ir_graph"); + push(@text_cons, ", current_ir_graph->current_block") unless exists($node{"block"}); + push(@text_cons, ", " . join(", ", @text_paramuse)) if @text_paramuse; + push(@text_cons, ");\n"); + push(@text_cons, $node{"d_post"}) if exists($node{"d_post"}); + push(@text_cons, "\treturn res;\n" + ."}\n\n"); + + # build new_$nodename function + + push(@text_cons, "ir_node *new_$nodename("); + if (@text_paramdecls) { + push(@text_cons, join(", ", @text_paramdecls)); + } else { + push(@text_cons, "void"); + } + push(@text_cons, ")\n" + ."{\n" + ."\treturn new_d_$nodename(NULL"); + push(@text_cons, ", " . join(", ", @text_paramuse)) if @text_paramuse; + push(@text_cons, ");\n" + ."}\n\n"); + +# push(@text_cons, "ir_node *new_bd_$nodename(dbg_info *db"); +# if (!exists($node{"block"})) { +# push(@text_cons, ", ir_node *block"); +# } +# push(@text_cons, @text_paramdecls); +# push(@text_cons, ")\n" +# ."{\n" +# ."\treturn new_rd_$nodename(db, current_ir_graph"); +# if (!exists($node{"block"})) { +# push(@text_cons, ", block"); +# } +# push(@text_cons, @text_paramuse); +# push(@text_cons, ");\n" +# ."}\n\n"); +} + +!$had_error || die; + +# emit the code + +print "Emitting code to $target_cons\n"; + +open(OUT, ">$target_cons") || die("Fatal error: Could not open $target_cons, reason: $!\n"); + +print OUT @text_cons; + +close(OUT); + +print "Done.\n" -- 2.20.1