X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fscripts%2Fgenerate_new_opcodes.pl;h=d4f3a18b465820ae898c89c022854a0b68e546c9;hb=fef8dc3eff6468d7d65485af8e1ac9884c504e1a;hp=08ce0c977fa2d52584d88a44b5eab96aa6176fb4;hpb=1350645390c1ab5f39ab987d9c3dfb2b031e56ec;p=libfirm diff --git a/ir/be/scripts/generate_new_opcodes.pl b/ir/be/scripts/generate_new_opcodes.pl index 08ce0c977..d4f3a18b4 100755 --- a/ir/be/scripts/generate_new_opcodes.pl +++ b/ir/be/scripts/generate_new_opcodes.pl @@ -23,23 +23,15 @@ # their coresponding node constructors for all operations in a given spec # so they can be used as normal firm nodes. # Creation: 2005/10/19 -# $Id$ use strict; use Data::Dumper; my $specfile = $ARGV[0]; my $target_dir = $ARGV[1]; -my $state = 1; -my $cur_op = ""; -my $line_nr = 0; our $arch; -our $additional_opcodes; our %nodes; -our %operands; -our %cpu; -our $default_op_attr_type; our $default_attr_type; our $default_cmp_attr; our $default_copy_attr; @@ -68,60 +60,33 @@ my $target_h = $target_dir."/gen_".$arch."_new_nodes.h"; if(!defined($default_attr_type)) { $default_attr_type = "${arch}_attr_t"; } -if(!defined(%init_attr)) { +if(! %init_attr) { %init_attr = ( - "$default_attr_type" => "\tinit_${arch}_attributes(res, irn_flags_, in_reqs, exec_units, n_res);", + "$default_attr_type" => "\tinit_${arch}_attributes(res, irn_flags_, in_reqs, n_res);", ); } if(!defined($default_cmp_attr)) { $default_cmp_attr = "${arch}_compare_attr"; } -if(!defined(%compare_attr)) { +if(! %compare_attr) { %compare_attr = ( "${default_attr_type}" => "${default_cmp_attr}", ); } -# Operands are really just nodes with some special constraints, we check -# these and create new entries in the nodes hashmap -foreach my $op (keys(%operands)) { - my %operand = %{ $operands{"$op"} }; - my %op_node; - - # constraints - if(defined($operand{op_flags})) { die "Fatal error: operands can't have op_flags ($op)"; } - if(defined($operand{cmp_attr})) { die "Fatal error: cmp_attr not allowed for operands ($op)"; } - if(defined($operand{mode})) { die "Operand must not have a mode defined ($op)"; } - if(defined($operand{out_arity})) { die "operand must not have out_arity defined ($op)"; } - if(defined($nodes{$op})) { die "$op defined as operand and as node"; }; - - - foreach my $flag (keys(%operand)) { - $op_node{$flag} = $operand{$flag}; - } - $op_node{op_flags} = "O"; - $op_node{cmp_attr} = 'return 1;'; - $op_node{mode} = 'mode_ANY'; - - $nodes{$op} = \%op_node; -} - -#print Dumper(%nodes); -#print Dumper(%operands); - # create c code file from specs -my @obst_limit_func; -my @obst_reg_reqs; -my @obst_opvar; # stack for the "ir_op *op__ = NULL;" statements -my @obst_get_opvar; # stack for the get_op__() functions -my $obst_constructor; # stack for node constructor functions -my @obst_new_irop; # stack for the new_ir_op calls -my @obst_enum_op; # stack for creating the _opcode enum -my $obst_header; # stack for function prototypes -my @obst_is_archirn; # stack for the is_$arch_irn() function -my @obst_cmp_attr; # stack for the compare attribute functions -my $obst_proj = ""; # stack for the pn_ numbers +my $obst_limit_func = ""; # +my $obst_reg_reqs = ""; # +my $obst_opvar = ""; # buffer for the "ir_op *op__ = NULL;" statements +my $obst_get_opvar = ""; # buffer for the get_op__() functions +my $obst_constructor = ""; # buffer for node constructor functions +my $obst_new_irop = ""; # buffer for the new_ir_op calls +my $obst_free_irop = ""; # buffer for free_ir_op calls +my $obst_enum_op = ""; # buffer for creating the _opcode enum +my $obst_header = ""; # buffer for function prototypes +my $obst_cmp_attr = ""; # buffer for the compare attribute functions +my $obst_proj = ""; # buffer for the pn_ numbers my $orig_op; my $arity; my $cmp_attr_func; @@ -156,10 +121,8 @@ foreach my $class_name (keys(%reg_classes)) { } -# for registering additional opcodes -$n_opcodes += $additional_opcodes if (defined($additional_opcodes)); - $obst_header .= "void ${arch}_create_opcodes(const arch_irn_ops_t *be_ops);\n"; +$obst_header .= "void ${arch}_free_opcodes(void);\n"; sub create_constructor { my $op = shift; @@ -314,15 +277,6 @@ EOF EOF } - # set up static variables for cpu execution unit assigments - if (exists($n->{"units"})) { - $temp .= gen_execunit_list_initializer($n->{"units"}); - } else { - $temp .= < "arch_irn_flags_simple_jump", "not_scheduled" => "arch_irn_flags_not_scheduled", ); - if (defined(%custom_irn_flags)) { + if (%custom_irn_flags) { %known_irn_flags = (%known_irn_flags, %custom_irn_flags); } foreach my $flag (@{$n->{"irn_flags"}}) { @@ -433,7 +387,7 @@ EOF } # lookup init function - my $attr_init_code = "(void)in;(void)exec_units;(void)irn_flags_;(void)in_reqs;(void)n_res;"; + my $attr_init_code = "(void)in;(void)irn_flags_;(void)in_reqs;(void)n_res;"; if ($attr_type ne "") { $attr_init_code = $init_attr{$attr_type}; if(!defined($attr_init_code)) { @@ -482,7 +436,7 @@ EOF $obst_constructor .= "}\n\n"; } -push(@obst_enum_op, "typedef enum ${arch}_opcodes {\n"); +$obst_enum_op .= "typedef enum ${arch}_opcodes {\n"; foreach my $op (keys(%nodes)) { my %n = %{ $nodes{"$op"} }; my $known_mode; @@ -572,11 +526,9 @@ foreach my $op (keys(%nodes)) { } # Create opcode - push(@obst_opvar, "ir_op *op_$op = NULL;\n"); - push(@obst_get_opvar, "ir_op *get_op_$op(void) { return op_$op; }\n"); - push(@obst_get_opvar, "int is_$op(const ir_node *n) { return get_$arch\_irn_opcode(n) == iro_$op; }\n\n"); - - push(@obst_is_archirn, "is_$op(node)"); + $obst_opvar .= "ir_op *op_$op = NULL;\n"; + $obst_get_opvar .= "ir_op *get_op_$op(void) { return op_$op; }\n"; + $obst_get_opvar .= "int is_$op(const ir_node *n) { return get_$arch\_irn_opcode(n) == iro_$op; }\n\n"; $obst_header .= < 1 } ( - "none", "labeled", "commutative", "cfopcode", "unknown_jump", "fragile", - "forking", "highlevel", "constlike", "always_opt", "keep", - "start_block", "uses_memory", "dump_noblock", "dump_noinput", - "machine", "machine_op", "cse_neutral" + "none", "commutative", "cfopcode", "unknown_jump", "fragile", + "forking", "highlevel", "constlike", "keep", "start_block", + "uses_memory", "dump_noblock", "cse_neutral" ); my $is_fragile = 0; foreach my $flag (@{$n{"op_flags"}}) { @@ -700,45 +635,59 @@ EOF } $n_opcodes++; - $temp = "\top_$op = new_ir_op(cur_opcode + iro_$op, \"$op\", op_pin_state_".$n{"state"}.", $op_flags"; - $temp .= "|irop_flag_machine, ".translate_arity($arity).", 0, ${attr_size}, &ops);\n"; - push(@obst_new_irop, $temp); - if ($is_fragile) { - push(@obst_new_irop, "\tir_op_set_fragile_indices(op_${op}, n_${op}_mem, pn_${op}_X_regular, pn_${op}_X_except);\n"); + $temp = "\top = new_ir_op(cur_opcode + iro_$op, \"$op\", op_pin_state_".$n{"state"}.", $op_flags"; + $temp .= ", ".translate_arity($arity).", 0, ${attr_size});\n"; + $obst_new_irop .= $temp; + $obst_new_irop .= "\top->ops.be_ops = be_ops;\n"; + $obst_new_irop .= "\top->ops.dump_node = ${dump_func};\n"; + if (defined($cmp_attr_func)) { + $obst_new_irop .= "\top->ops.node_cmp_attr = ${cmp_attr_func};\n"; } - push(@obst_new_irop, "\tset_op_tag(op_$op, $arch\_op_tag);\n"); - if(defined($default_op_attr_type)) { - push(@obst_new_irop, "\tattr = &attrs[iro_$op];\n"); - if(defined($n{op_attr_init})) { - push(@obst_new_irop, "\t".$n{op_attr_init}."\n"); + my $copy_attr_func = $copy_attr{$attr_type}; + if (!defined($copy_attr_func)) { + # don't set a copy_attr function if the node has no additional attributes. + if ($attr_type ne "") { + $copy_attr_func = $default_copy_attr; } - push(@obst_new_irop, "\tset_op_attr(op_$op, attr);\n"); } + if (defined($copy_attr_func)) { + $obst_new_irop .= "\top->ops.copy_attr = ${copy_attr_func};\n"; + } + if (defined($hash_func)) { + $obst_new_irop .= "\top->ops.hash = ${hash_func};\n"; + } + + if ($is_fragile) { + $obst_new_irop .= "\tir_op_set_memory_index(op, n_${op}_mem);\n"; + $obst_new_irop .= "\tir_op_set_fragile_indices(op, pn_${op}_X_regular, pn_${op}_X_except);\n"; + } + $obst_new_irop .= "\tset_op_tag(op, $arch\_op_tag);\n"; + if(defined($n{op_attr_init})) { + $obst_new_irop .= "\t".$n{op_attr_init}."\n"; + } + $obst_new_irop .= "\top_${op} = op;\n"; + + $obst_free_irop .= "\tfree_ir_op(op_$op); op_$op = NULL;\n"; - push(@obst_enum_op, "\tiro_$op,\n"); + $obst_enum_op .= "\tiro_$op,\n"; $obst_header .= "\n"; } -push(@obst_enum_op, "\tiro_$arch\_last_generated,\n"); -push(@obst_enum_op, "\tiro_$arch\_last = iro_$arch\_last_generated"); -push(@obst_enum_op, " + $additional_opcodes") if (defined($additional_opcodes)); -push(@obst_enum_op, "\n} $arch\_opcodes;\n\n"); +$obst_enum_op .= "\tiro_$arch\_last\n"; +$obst_enum_op .= "} $arch\_opcodes;\n\n"; # emit the code open(OUT, ">$target_c") || die("Fatal error: Could not open $target_c, reason: $!\n"); -print OUT "#include \"gen_$arch\_regalloc_if.h\"\n"; -print OUT "#include \"irverify_t.h\"\n"; -print OUT "\n"; -print OUT @obst_cmp_attr; -print OUT "\n"; -print OUT @obst_opvar; -print OUT "\n"; -print OUT @obst_get_opvar; -print OUT "\n"; - print OUT<= 4) { $d = uc(substr($arch, 3, 1)); } -print OUT< add them all - my $tp_name = "$arch\_execution_units_$unit"; - my $idx = 0; - foreach (@{ $cpu{"$unit"} }) { - next if ($idx++ == 0); # skip first element (it's not a unit) - my $unit_name = "$uc_arch\_EXECUNIT_TP_$unit\_$_"; - push(@{ $init{"$unit"} }, "\t\t&".$tp_name."[".$unit_name."]"); - } - } - else { - # operation can be executed only a certain unit - # -> find corresponding unit type - my $found = 0; -TP_SEARCH: foreach my $cur_type (keys(%cpu)) { - foreach my $cur_unit (@{ $cpu{"$cur_type"} }) { - if ($unit eq $cur_unit) { - my $tp_name = "$arch\_execution_units_$cur_type"; - my $unit_name = "$uc_arch\_EXECUNIT_TP_$cur_type\_$unit"; - push(@{ $init{"$unit"} }, "\t\t&".$tp_name."[".$unit_name."]"); - $found = 1; - last TP_SEARCH; - } - } - } - - if (! $found) { - print STDERR "Invalid execution unit $unit specified!\n"; - } - } - } - - # prepare the 2-dim array init - foreach my $key (keys(%init)) { - $ret .= "\tstatic const be_execution_unit_t *allowed_units_".$key."[] =\n"; - $ret .= "\t{\n"; - foreach (@{ $init{"$key"} }) { - $ret .= "$_,\n"; - } - $ret .= "\t\tNULL\n"; - $ret .= "\t};\n"; - $ret2 .= "\t\tallowed_units_$key,\n"; - } - $ret2 .= "\t\tNULL\n"; - - $ret .= "\tstatic const be_execution_unit_t **exec_units[] =\n"; - $ret .= "\t{\n"; - $ret .= $ret2; - $ret .= "\t};\n"; - - return $ret; -} - sub mangle_requirements { my $reqs = shift; my $class = shift; @@ -1224,7 +1075,7 @@ CHECK_REQS: foreach (@regs) { $limit_bitsets{$limit_name} = $limit_name; - push(@obst_limit_func, "static const unsigned " . $limit_name . "[] = { "); + $obst_limit_func .= "static const unsigned $limit_name\[] = { "; my $first = 1; my $limitbitsetlen = $regclass2len{$class}; my $limitarraylen = ($limitbitsetlen+31) / 32; @@ -1234,7 +1085,7 @@ CHECK_REQS: foreach (@regs) { if($first) { $first = 0; } else { - push(@obst_limit_func, ", "); + $obst_limit_func .= ", "; } my $temp; if($neg) { @@ -1251,13 +1102,9 @@ CHECK_REQS: foreach (@regs) { my $reguc = uc($reg); $temp .= "BIT(REG_${classuc}_${reguc})"; } - if(defined($temp)) { - push(@obst_limit_func, "${temp}"); - } else { - push(@obst_limit_func, "0"); - } + $obst_limit_func .= $temp || "0"; } - push(@obst_limit_func, " };\n"); + $obst_limit_func .= " };\n"; } return ($class, $limit_name, $same_pos, $different_pos); @@ -1362,9 +1209,7 @@ EOF return $name; } $requirements{$name} = $name; - push(@obst_reg_reqs, <