draft for register width specifications
[libfirm] / ir / be / scripts / generate_new_opcodes.pl
index 683aed8..f08371d 100755 (executable)
@@ -48,6 +48,7 @@ our $custom_init_attr_func;
 our %compare_attr;
 our %copy_attr;
 our %reg_classes;
+our %custom_irn_flags;
 
 # include spec file
 
@@ -206,7 +207,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"})) {
@@ -407,17 +410,21 @@ 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",
+               );
+               if (defined(%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 .= "\tflags |= " . $known_irn_flags{$flag} . ";\n";
                        }
                }
                $temp .= "\n";
@@ -445,6 +452,7 @@ EOF
        ${attr_init_code}
        ${custominit}
        info = be_get_info(res);
+       (void) info; /* avoid potential warning */
        ${set_out_reqs}
 
 EOF
@@ -634,271 +642,9 @@ 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 = <<EOF;
-#      ir_node        *res;
-#      ir_op          *op      = op_${op};
-#      int             flags   = 0;
-#      backend_info_t *info;
-#EOF
-#
-#                      if($arity == $ARITY_DYNAMIC) {
-#                              $temp .= <<EOF;
-#      int             arity   = -1;
-#      ir_node       **in      = NULL;
-#EOF
-#                      } elsif($arity == $ARITY_VARIABLE) {
-#                      } else {
-#                              $temp .= <<EOF;
-#      int             arity   = $arity;
-#EOF
-#                              if($arity > 0) {
-#                                      $temp .= <<EOF;
-#      ir_node        *in[$arity];
-#EOF
-#                              } else {
-#                                      $temp .= <<EOF;
-#      ir_node       **in    = NULL;
-#EOF
-#                              }
-#                      }
-#                      if($out_arity == $ARITY_DYNAMIC) {
-#                              $temp .= <<EOF;
-#      int             n_res   = -1;
-#EOF
-#                      } elsif($out_arity == $ARITY_VARIABLE) {
-#                      } else {
-#                              $temp .= <<EOF;
-#      int             n_res   = ${out_arity};
-#EOF
-#                      }
-#
-#                      if (defined($known_mode)) {
-#                              $temp .= <<EOF;
-#      ir_mode        *mode    = ${known_mode};
-#EOF
-#                      }
-#
-#                      # set up static variables for cpu execution unit assigments
-#                      if (exists($n{"units"})) {
-#                              $temp .= gen_execunit_list_initializer($n{"units"});
-#                      } else {
-#                              $temp .= <<EOF;
-#      static const be_execution_unit_t ***exec_units = NULL;
-#EOF
-#                      }
-#
-#                      undef my $in_req_var;
-#                      undef my $out_req_var;
-#
-#                      my $set_out_reqs = "";
-#
-#                      # set up static variables for requirements and registers
-#                      if (exists($n{"reg_req"})) {
-#                              my %req = %{ $n{"reg_req"} };
-#                              my $idx;
-#
-#                              undef my @in;
-#                              @in = @{ $req{"in"} } if (exists($req{"in"}));
-#                              undef my @out;
-#                              @out = @{ $req{"out"} } if exists(($req{"out"}));
-#
-#                              for(my $idx = 0; $idx < $#in; $idx++) {
-#                                      my $req = $in[$idx];
-#                                      generate_requirements($req, \%n, $op, $idx, 1);
-#                              }
-#                              for(my $idx = 0; $idx < $#out; $idx++) {
-#                                      my $req = $out[$idx];
-#                                      generate_requirements($req, \%n, $op, $idx, 0);
-#                              }
-#
-#                              if (@in) {
-#                                      if($arity >= 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 .= <<EOF;
-#      info->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 .= <<EOF;
-#      /* create node */
-#      assert(op != NULL);
-#      res = new_ir_node(db, current_ir_graph, block, op, mode, arity, in);
-#
-#      /* init node attributes */
-#      ${attr_init_code}
-#      ${custominit}
-#      info = be_get_info(res);
-#      ${set_out_reqs}
-#
-#EOF
-#
-#                      if (exists($n{"init_attr"})) {
-#                              $temp .= "\tattr = get_irn_generic_attr(res);\n";
-#                              $temp .= "\t".$n{"init_attr"}."\n";
-#                      }
-#
-#                      $temp .= <<EOF;
-#      /* optimize node */
-#      res = optimize_node(res);
-#      irn_vrfy_irg(res, current_ir_graph);
-#
-#      return res;
-#EOF
-#
-#                      $obst_constructor .= $temp;
-#              }
-#              else { # user defined constructor
-#                      $obst_constructor .= $n{"rd_constructor"};
-#              }
-#
-#              # close constructor function
-#              $obst_constructor .= "}\n\n";
-#      } # constructor creation
-
        # set default values for state and flags if not given
        $n{"state"}    = "floats" if (! exists($n{"state"}));
-       $n{"op_flags"} = "N"      if (! exists($n{"op_flags"}));
-
+       $n{"op_flags"} = ["none"] if (! exists($n{"op_flags"}));
 
        push(@obst_new_irop, "\n\tmemset(&ops, 0, sizeof(ops));\n");
        push(@obst_new_irop, "\tops.be_ops        = be_ops;\n");
@@ -918,9 +664,23 @@ EOF
                push(@obst_new_irop, "\tops.hash = ${hash_func};\n");
        }
 
+       my %known_flags = map { $_ => 1 } (
+               "none", "labeled", "commutative", "cfopcode", "op_cfopcode",
+               "fragile", "forking", "highlevel", "constlike", "always_opt",
+               "keep", "start_block", "uses_memory", "dump_noblock",
+               "dump_noinput", "machine", "machine_op", "cse_neutral"
+       );
+       foreach my $flag (@{$n{"op_flags"}}) {
+               if (not defined($known_flags{$flag})) {
+                       print STDERR "WARNING: Flag '$flag' in opcode $op is unknown\n";
+               }
+       }
+       my @mapped = map { "irop_flag_$_" } @{$n{"op_flags"}};
+       my $op_flags = join('|', @mapped);
+
        $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_$op = new_ir_op(cur_opcode + iro_$op, \"$op\", op_pin_state_".$n{"state"}.", $op_flags";
+       $temp .= "|irop_flag_machine, ".translate_arity($arity).", 0, sizeof(${attr_type}), &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)) {
@@ -1038,7 +798,6 @@ void $arch\_create_opcodes(const arch_irn_ops_t *be_ops) {
 #define L   irop_flag_labeled
 #define C   irop_flag_commutative
 #define X   irop_flag_cfopcode
-#define I   irop_flag_ip_cfopcode
 #define F   irop_flag_fragile
 #define Y   irop_flag_forking
 #define H   irop_flag_highlevel
@@ -1108,6 +867,7 @@ EOF
 print OUT @obst_enum_op;
 print OUT <<EOF;
 int is_${arch}_irn(const ir_node *node);
+int is_${arch}_op(const ir_op *op);
 
 int get_${arch}_opcode_first(void);
 int get_${arch}_opcode_last(void);
@@ -1522,7 +1282,8 @@ sub generate_requirements {
        NULL,                         /* regclass */
        NULL,                         /* limit bitset */
        0,                            /* same pos */
-       0                             /* different pos */
+       0,                            /* different pos */
+       0                             /* width */
 };
 
 EOF
@@ -1536,7 +1297,8 @@ EOF
        & ${arch}_reg_classes[CLASS_${arch}_${class}],
        NULL,        /* limit bitset */
        0,           /* same pos */
-       0            /* different pos */
+       0,           /* different pos */
+       1            /* width */
 };
 
 EOF
@@ -1571,7 +1333,8 @@ EOF
        & ${arch}_reg_classes[CLASS_${arch}_${class}],
        ${limit_bitset},
        ${same_pos},        /* same pos */
-       ${different_pos}        /* different pos */
+       ${different_pos},       /* different pos */
+       1             /* width */
 };
 
 EOF