X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fscripts%2Fgenerate_new_opcodes.pl;h=ea15f9d89e0d04b4ceb6738a6fbd392668df91a5;hb=5025bfbdddadddabb850763898ad508935eebe43;hp=ca98ff494cef04b2431fb04f74c2b68bd90e04b7;hpb=ea75e9d38674b468f602a0699fb64b9c01254797;p=libfirm diff --git a/ir/be/scripts/generate_new_opcodes.pl b/ir/be/scripts/generate_new_opcodes.pl index ca98ff494..ea15f9d89 100755 --- a/ir/be/scripts/generate_new_opcodes.pl +++ b/ir/be/scripts/generate_new_opcodes.pl @@ -23,7 +23,6 @@ # 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; @@ -48,6 +47,7 @@ our $custom_init_attr_func; our %compare_attr; our %copy_attr; our %reg_classes; +our %custom_irn_flags; # include spec file @@ -67,15 +67,15 @@ 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, 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}", ); @@ -116,6 +116,7 @@ my @obst_opvar; # stack for the "ir_op *op__ = NULL;" state 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_free_irop; # stack for free_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 @@ -159,6 +160,7 @@ foreach my $class_name (keys(%reg_classes)) { $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; @@ -206,7 +208,9 @@ sub create_constructor { } elsif($out_arity eq "dynamic") { $out_arity = $ARITY_DYNAMIC; } - + if ($out_arity != 0 && $out_arity != 1 && !defined($known_mode)) { + $known_mode = "mode_T"; + } my $comment = $n->{"comment"}; if(!exists($n->{"comment"})) { @@ -267,10 +271,11 @@ sub create_constructor { # emit constructor code $temp = <{"units"})) { - $temp .= gen_execunit_list_initializer($n->{"units"}); - } else { - $temp .= <out_infos[${idx}].req = &${reqstruct}; + info->out_infos[${idx}].req = &${reqstruct}; EOF } } else { @@ -407,26 +403,34 @@ EOF # set flags if (exists($n->{"irn_flags"})) { $temp .= "\t/* flags */\n"; - foreach my $flag (split(/\|/, $n->{"irn_flags"})) { - if ($flag eq "R") { - $temp .= "\tflags |= arch_irn_flags_rematerializable;\n"; - } elsif ($flag eq "N") { - $temp .= "\tflags |= arch_irn_flags_dont_spill;\n"; - } elsif ($flag eq "F") { - $temp .= "\tflags |= arch_irn_flags_modify_flags;\n"; - } elsif ($flag eq "J") { - $temp .= "\t flags |= arch_irn_flags_simple_jump;\n"; + my %known_irn_flags = ( + "none" => "arch_irn_flags_none", + "dont_spill" => "arch_irn_flags_dont_spill", + "rematerializable" => "arch_irn_flags_rematerializable", + "modify_flags" => "arch_irn_flags_modify_flags", + "simple_jump" => "arch_irn_flags_simple_jump", + "not_scheduled" => "arch_irn_flags_not_scheduled", + ); + if (%custom_irn_flags) { + %known_irn_flags = (%known_irn_flags, %custom_irn_flags); + } + foreach my $flag (@{$n->{"irn_flags"}}) { + if (not defined($known_irn_flags{$flag})) { + print STDERR "WARNING: irn_flag '$flag' in opcode $op is unknown\n"; } else { - die "Fatal error: unknown flag $flag for ${op}\n"; + $temp .= "\tirn_flags_ |= " . $known_irn_flags{$flag} . ";\n"; } } $temp .= "\n"; } # lookup init function - my $attr_init_code = $init_attr{$attr_type}; - if(!defined($attr_init_code)) { - die "Fatal error: Couldn't find attribute initialisation code for type '${attr_type}'"; + 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)) { + die "Fatal error: Couldn't find attribute initialisation code for type '${attr_type}'"; + } } my $custominit = ""; if(defined($custom_init_attr_func)) { @@ -439,25 +443,27 @@ EOF $temp .= <{"init_attr"})) { - $temp .= "\tattr = get_irn_generic_attr(res);\n"; + $temp .= "\tattr = (${attr_type}*)get_irn_generic_attr(res);\n"; + $temp .= "\t(void) attr; /* avoid potential warning */\n"; $temp .= "\t".$n->{"init_attr"}."\n"; } $temp .= < 0) { + $obst_proj .= "\nenum pn_${op} {\n"; - for (my $idx = 0; $idx <= $#outs; $idx++) { - # check, if we have additional flags annotated to out - if ($outs[$idx] =~ /:((S|I)(\|(S|I))*)/) { - push(@out_flags, $1); - $outs[$idx] =~ s/:((S|I)(\|(S|I))*)//; + for (my $idx = 0; $idx <= $#outs; $idx++) { + # check, if we have additional flags annotated to out + if ($outs[$idx] =~ /:((S|I)(\|(S|I))*)/) { + push(@out_flags, $1); + $outs[$idx] =~ s/:((S|I)(\|(S|I))*)//; + } + $obst_proj .= "\tpn_${op}_".$outs[$idx]." = ${idx},\n"; } - $obst_proj .= "\tpn_${op}_".$outs[$idx]." = ${idx},\n"; - } - $obst_proj .= "};\n"; + $obst_proj .= "};\n"; + } # outs have names, it must be a mode_T node if (!defined($n{mode})) { $n{mode} = "mode_T"; @@ -546,11 +554,13 @@ foreach my $op (keys(%nodes)) { die "Fatal error: Op ${op} has different number of ins and arity\n"; } - $obst_proj .= "\nenum n_$op {\n"; - for (my $idx = 0; $idx <= $#ins; $idx++) { - $obst_proj .= "\tn_${op}_".$ins[$idx]." = ${idx},\n"; + if ($#ins >= 0) { + $obst_proj .= "\nenum n_$op {\n"; + for (my $idx = 0; $idx <= $#ins; $idx++) { + $obst_proj .= "\tn_${op}_".$ins[$idx]." = ${idx},\n"; + } + $obst_proj .= "};\n"; } - $obst_proj .= "};\n"; } # Create opcode @@ -583,14 +593,14 @@ EOF if (exists($n{"cmp_attr"})) { my $cmpcode = $n{"cmp_attr"}; - push(@obst_cmp_attr, "static int cmp_attr_$op(ir_node *a, ir_node *b) {\n"); + push(@obst_cmp_attr, "static int cmp_attr_$op(const ir_node *a, const ir_node *b) {\n"); if($cmpcode =~ m/attr_a/) { - push(@obst_cmp_attr, "\t${attr_type} *attr_a = get_irn_generic_attr(a);\n"); + push(@obst_cmp_attr, "\tconst ${attr_type} *attr_a = get_irn_generic_attr_const(a);\n"); } else { push(@obst_cmp_attr, "\t(void) a;\n"); } if($cmpcode =~ m/attr_b/) { - push(@obst_cmp_attr, "\t${attr_type} *attr_b = get_irn_generic_attr(b);\n"); + push(@obst_cmp_attr, "\tconst ${attr_type} *attr_b = get_irn_generic_attr_const(b);\n"); } else { push(@obst_cmp_attr, "\t(void) b;\n"); } @@ -598,6 +608,8 @@ EOF push(@obst_cmp_attr, "}\n\n"); $cmp_attr_func = "cmp_attr_${op}"; + } elsif ($attr_type eq "") { + $cmp_attr_func = "NULL"; } else { if(defined($compare_attr{${attr_type}})) { $cmp_attr_func = $compare_attr{${attr_type}}; @@ -634,282 +646,26 @@ EOF create_constructor($orig_op, $constr, \%cstr, \%n); } -# if (exists($n{"rd_constructor"}) && $n{"rd_constructor"} =~ /^NONE$/i) { -# # we explicitly skip the constructor if the specification entry says NONE -# } else { -# my $comment = $n{"comment"}; -# if(!exists($n{"comment"})) { -# $comment = "construct ${orig_op} node"; -# } -# $comment = -# "/**\n". -# " * ${comment}\n". -# " */\n"; -# -# $obst_constructor .= $comment; -# -# # create constructor head -# my $complete_args = ""; -# $temp = ""; -# -# $temp = "ir_node *new_bd_$op(dbg_info *db, ir_node *block"; -# if (!exists($n{"args"})) { # default args -# if ($arity == $ARITY_VARIABLE) { -# $complete_args = ", int arity, ir_node *in[]"; -# } elsif ($arity == $ARITY_DYNAMIC) { -# $complete_args = ""; -# } else { -# for (my $i = 0; $i < $arity; $i++) { -# my $opname = "op${i}"; -# if (exists($n{"ins"})) { -# my @ins = @{ $n{"ins"} }; -# $opname = $ins[$i]; -# } -# -# $complete_args .= ", ir_node *${opname}"; -# } -# } -# if ($out_arity == $ARITY_VARIABLE) { -# $complete_args .= ", int n_res"; -# } -# -# if (!defined($known_mode)) { -# $complete_args .= ", ir_mode *mode"; -# } -# } else { # user defined args -# for my $href (@{ $n{"args"} }) { -# $href->{"type"} .= " " if ($href->{"type"} !~ / [*]?$/); # put a space between name and type if there is none at the end -# $complete_args .= ", ".$href->{"type"}.$href->{"name"}; -# } -# } -# -# # we have additional attribute arguements -# if (exists($n{"attr"})) { -# $complete_args .= ", ".$n{"attr"}; -# } -# -# $temp .= "$complete_args)"; -# $obst_constructor .= "${temp}\n{\n"; -# $obst_header .= $comment; -# $obst_header .= "${temp};\n"; -# -# # emit constructor code -# if (!exists($n{"rd_constructor"})) { # default constructor -# $temp = < 0) { -# $temp .= <= 0 && scalar(@in) != $arity) { -# die "Fatal error: Arity and number of in requirements don't match for ${op}\n"; -# } -# -# $temp .= "\tstatic const arch_register_req_t *in_reqs[] =\n"; -# $temp .= "\t{\n"; -# for ($idx = 0; $idx <= $#in; $idx++) { -# my $req = $in[$idx]; -# my $reqstruct = generate_requirements($req, \%n, $op, $idx, 1); -# $temp .= "\t\t& ${reqstruct},\n"; -# } -# $temp .= "\t};\n"; -# } else { -# if($arity > 0) { -# die "Fatal error: need in requirements for ${op}\n"; -# } -# $temp .= "\tstatic const arch_register_req_t **in_reqs = NULL;\n"; -# } -# -# if (@out) { -# if($out_arity >= 0 && scalar(@out) != $out_arity) { -# die "Fatal error: Out-Arity and number of out requirements don't match for ${op}\n"; -# } -# -# for ($idx = 0; $idx <= $#out; $idx++) { -# my $req = $out[$idx]; -# my $reqstruct = generate_requirements($req, \%n, $op, $idx, 0); -# $set_out_reqs .= <out_infos[${idx}].req = &${reqstruct}; -#EOF -# } -# } else { -# if($out_arity > 0) { -# die "Fatal error: need out requirements for ${op}\n"; -# } -# } -# } else { -# $temp .= "\tstatic const arch_register_req_t **in_reqs = NULL;\n"; -# } -# if(exists($n{"init_attr"})) { -# $temp .= "\t${attr_type} *attr;\n"; -# } -# -# $temp .= "\n"; -# -# if($arity > 0) { -# $temp .= "\t/* construct in array */\n"; -# for (my $i = 0; $i < $arity; $i++) { -# my $opname = "op${i}"; -# if (exists($n{"ins"})) { -# my @ins = @{ $n{"ins"} }; -# $opname = $ins[$i]; -# } -# -# $temp .= "\tin[${i}] = ${opname};\n"; -# } -# $temp .= "\n"; -# } -# -# # set flags -# if (exists($n{"irn_flags"})) { -# $temp .= "\t/* flags */\n"; -# foreach my $flag (split(/\|/, $n{"irn_flags"})) { -# if ($flag eq "R") { -# $temp .= "\tflags |= arch_irn_flags_rematerializable;\n"; -# } elsif ($flag eq "N") { -# $temp .= "\tflags |= arch_irn_flags_dont_spill;\n"; -# } elsif ($flag eq "J") { -# $temp .= "\t flags |= arch_irn_flags_simple_jump;\n"; -# } else { -# die "Fatal error: unknown flag $flag for ${op}\n"; -# } -# } -# $temp .= "\n"; -# } -# -# # lookup init function -# my $attr_init_code = $init_attr{$attr_type}; -# if(!defined($attr_init_code)) { -# die "Fatal error: Couldn't find attribute initialisation code for type '${attr_type}'"; -# } -# my $custominit = ""; -# if(defined($custom_init_attr_func)) { -# $custominit .= &$custom_init_attr_func(\%n, $op); -# } -# -# $temp .= < 1 } ( + "none", "commutative", "cfopcode", "unknown_jump", "fragile", + "forking", "highlevel", "constlike", "always_opt", "keep", + "start_block", "uses_memory", "dump_noblock", "cse_neutral" + ); + my $is_fragile = 0; + foreach my $flag (@{$n{"op_flags"}}) { + if (not defined($known_flags{$flag})) { + print STDERR "WARNING: Flag '$flag' in opcode $op is unknown\n"; + } + if ($flag eq "fragile") { + $is_fragile = 1; + } + } + my @mapped = map { "irop_flag_$_" } @{$n{"op_flags"}}; + my $op_flags = join('|', @mapped); + + my $attr_size = "0"; + if ($attr_type ne "") { + $attr_size = "sizeof(${attr_type})" + } + $n_opcodes++; - $temp = "\top_$op = new_ir_op(cur_opcode + iro_$op, \"$op\", op_pin_state_".$n{"state"}.", ".$n{"op_flags"}; - $temp .= "|M, ".translate_arity($arity).", 0, sizeof(${attr_type}), &ops);\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}, &ops);\n"; push(@obst_new_irop, $temp); - 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"); - } - push(@obst_new_irop, "\tset_op_attr(op_$op, attr);\n"); + if ($is_fragile) { + push(@obst_new_irop, "\tir_op_set_memory_index(op, n_${op}_mem);\n"); + push(@obst_new_irop, "\tir_op_set_fragile_indices(op, pn_${op}_X_regular, pn_${op}_X_except);\n"); + } + push(@obst_new_irop, "\tset_op_tag(op, $arch\_op_tag);\n"); + if(defined($n{op_attr_init})) { + push(@obst_new_irop, "\t".$n{op_attr_init}."\n"); } + push(@obst_new_irop, "\top_${op} = op;\n"); + + push(@obst_free_irop, "\tfree_ir_op(op_$op); op_$op = NULL;\n"); push(@obst_enum_op, "\tiro_$op,\n"); @@ -944,7 +725,10 @@ push(@obst_enum_op, "\n} $arch\_opcodes;\n\n"); open(OUT, ">$target_c") || die("Fatal error: Could not open $target_c, reason: $!\n"); -print OUT "#include \"gen_$arch\_regalloc_if.h\"\n\n"; +print OUT "#include \"gen_$arch\_regalloc_if.h\"\n"; +print OUT "#include \"irverify_t.h\"\n"; +print OUT "#include \"fourcc.h\"\n"; +print OUT "\n"; print OUT @obst_cmp_attr; print OUT "\n"; print OUT @obst_opvar; @@ -1016,7 +800,7 @@ 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; @@ -1263,7 +956,7 @@ sub get_reg_class { } ### -# Returns the index of a given register within it's register class. +# Returns the index of a given register within its register class. # @return index or undef ### sub get_reg_index { @@ -1478,7 +1171,10 @@ CHECK_REQS: foreach (@regs) { } elsif(defined($temp)) { $temp .= " | "; } - $temp .= "BIT(REG_".uc(${reg}).")"; + my $firstreg = uc($reg_classes{$class}[0]->{"name"}); + my $classuc = uc($class); + my $reguc = uc($reg); + $temp .= "BIT(REG_${classuc}_${reguc})"; } if(defined($temp)) { push(@obst_limit_func, "${temp}"); @@ -1502,6 +1198,7 @@ sub generate_requirements { my $idx = shift; my $is_in = shift; my $class = ""; + my $width = 1; my $result; my @req_type_mask; @@ -1511,6 +1208,10 @@ sub generate_requirements { push(@req_type_mask, "arch_register_req_type_ignore"); } elsif ($f eq "S") { push(@req_type_mask, "arch_register_req_type_produces_sp"); + } elsif ($f eq "a") { + push(@req_type_mask, "arch_register_req_type_aligned"); + } elsif ($f eq "2" or $f eq "4" or $f eq "8") { + $width = int($f); } } } @@ -1523,7 +1224,8 @@ sub generate_requirements { NULL, /* regclass */ NULL, /* limit bitset */ 0, /* same pos */ - 0 /* different pos */ + 0, /* different pos */ + 0 /* width */ }; EOF @@ -1537,7 +1239,8 @@ EOF & ${arch}_reg_classes[CLASS_${arch}_${class}], NULL, /* limit bitset */ 0, /* same pos */ - 0 /* different pos */ + 0, /* different pos */ + $width /* width */ }; EOF @@ -1572,7 +1275,8 @@ EOF & ${arch}_reg_classes[CLASS_${arch}_${class}], ${limit_bitset}, ${same_pos}, /* same pos */ - ${different_pos} /* different pos */ + ${different_pos}, /* different pos */ + $width /* width */ }; EOF