#!/usr/bin/perl -w
+#
+# Copyright (C) 1995-2007 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 the C code which creates the irop's and
# their coresponding node constructors for all operations in a given spec
# so they can be used as normal firm nodes.
no strict "subs";
unless ($return = do $specfile) {
- warn "couldn't parse $specfile: $@" if $@;
- warn "couldn't do $specfile: $!" unless defined $return;
- warn "couldn't run $specfile" unless $return;
+ die "couldn't parse $specfile: $@" if $@;
+ die "couldn't do $specfile: $!" unless defined $return;
+ die "couldn't run $specfile" unless $return;
}
use strict "subs";
push(@obst_header, "void ".$arch."_create_opcodes(void);\n");
+# create default compare function
+if(defined($default_cmp_attr)) {
+ my $cmpcode = $default_cmp_attr;
+ push(@obst_cmp_attr, "static int default_cmp_attr(ir_node *a, ir_node *b) {\n");
+ if($cmpcode =~ m/attr_a/) {
+ push(@obst_cmp_attr, "\t$arch\_attr_t *attr_a = get_$arch\_attr(a);\n");
+ }
+ if($cmpcode =~ m/attr_b/) {
+ push(@obst_cmp_attr, "\t$arch\_attr_t *attr_b = get_$arch\_attr(b);\n");
+ }
+ push(@obst_cmp_attr, "\t${cmpcode}\n");
+ push(@obst_cmp_attr, "}\n\n");
+}
+
push(@obst_enum_op, "typedef enum _$arch\_opcodes {\n");
foreach my $op (keys(%nodes)) {
my %n = %{ $nodes{"$op"} };
for (my $idx = 0; $idx <= $#outs; $idx++) {
# check, if we have additional flags annotated to out
- if ($outs[$idx] =~ /:(S|I(\|(S|I))*)/) {
+ if ($outs[$idx] =~ /:((S|I)(\|(S|I))*)/) {
push(@out_flags, $1);
- $outs[$idx] =~ s/:(S|I(\|(S|I))*)//;
+ $outs[$idx] =~ s/:((S|I)(\|(S|I))*)//;
}
push(@obst_proj, " pn_$op\_".$outs[$idx]." = $idx,\n");
}
push(@obst_header, "ir_op *get_op_$op(void);\n");
push(@obst_header, "int is_$op(const ir_node *n);\n");
- $cmp_attr_func = 0;
+ my $cmp_attr_func;
+ if(defined($default_cmp_attr)) {
+ $cmp_attr_func = "default_cmp_attr";
+ }
# create compare attribute function if needed
- if (exists($n{"cmp_attr"}) || defined($default_cmp_attr)) {
+ 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, "\t$arch\_attr_t *attr_a = get_$arch\_attr(a);\n");
- push(@obst_cmp_attr, "\t$arch\_attr_t *attr_b = get_$arch\_attr(b);\n");
- push(@obst_cmp_attr, "\t(void) attr_a;\n");
- push(@obst_cmp_attr, "\t(void) attr_b;\n");
- if(exists($n{"cmp_attr"})) {
- push(@obst_cmp_attr, "\t".$n{"cmp_attr"}."\n");
- } else {
- push(@obst_cmp_attr, "\t$default_cmp_attr\n");
+ if($cmpcode =~ m/attr_a/) {
+ push(@obst_cmp_attr, "\t$arch\_attr_t *attr_a = get_$arch\_attr(a);\n");
+ }
+ if($cmpcode =~ m/attr_b/) {
+ push(@obst_cmp_attr, "\t$arch\_attr_t *attr_b = get_$arch\_attr(b);\n");
}
+ push(@obst_cmp_attr, "\t${cmpcode}\n");
push(@obst_cmp_attr, "}\n\n");
- $cmp_attr_func = 1;
+ $cmp_attr_func = "cmp_attr_${op}";
}
if (exists($n{"rd_constructor"}) && $n{"rd_constructor"} =~ /^NONE$/i) {
if (@in) {
$in_req_var = "_in_req_$op";
- $temp .= "\tstatic const $arch\_register_req_t *".$in_req_var."[] =\n";
+ $temp .= "\tstatic const arch_register_req_t *".$in_req_var."[] =\n";
$temp .= "\t{\n";
for ($idx = 0; $idx <= $#in; $idx++) {
- $temp .= "\t\t".$op."_reg_req_in_".$idx.",\n";
+ $temp .= "\t\t&".$op."_reg_req_in_".$idx.",\n";
}
$temp .= "\t};\n";
}
if (@out) {
$out_req_var = "_out_req_$op";
- $temp .= "\tstatic const $arch\_register_req_t *".$out_req_var."[] =\n";
+ $temp .= "\tstatic const arch_register_req_t *".$out_req_var."[] =\n";
$temp .= "\t{\n";
for ($idx = 0; $idx <= $#out; $idx++) {
- $temp .= "\t\t".$op."_reg_req_out_".$idx.",\n";
+ $temp .= "\t\t&".$op."_reg_req_out_".$idx.",\n";
}
$temp .= "\t};\n";
}
}
$temp .= "\n";
- $temp .= "\tif (!op_$op) {\n";
- $temp .= "\t\tassert(0);\n";
- $temp .= "\t\treturn NULL;\n";
- $temp .= "\t}\n\n";
+ $temp .= "\tassert(op_$op != NULL);\n\n";
+
for (my $i = 1; $i <= $arity; $i++) {
$temp .= "\tin[".($i - 1)."] = op".$i.";\n";
}
push(@obst_new_irop, "\n\tmemset(&ops, 0, sizeof(ops));\n");
push(@obst_new_irop, "\tops.dump_node = $arch\_dump_node;\n");
- if ($cmp_attr_func) {
- push(@obst_new_irop, "\tops.node_cmp_attr = cmp_attr_$op;\n");
+ if (defined($cmp_attr_func)) {
+ push(@obst_new_irop, "\tops.node_cmp_attr = ${cmp_attr_func};\n");
}
$n_opcodes++;
#define O irop_flag_machine_op
#define R (irop_flag_user << 0)
- ir_op_ops ops;
- int cur_opcode = get_next_ir_opcodes(iro_$arch\_last);
+ ir_op_ops ops;
+ int cur_opcode;
+ static int run_once = 0;
+
+ if (run_once)
+ return;
+ run_once = 1;
+
+ cur_opcode = get_next_ir_opcodes(iro_$arch\_last);
$arch\_opcode_start = cur_opcode;
ENDOFMAIN
open(OUT, ">$target_h") || die("Could not open $target_h, reason: $!\n");
-print OUT "#ifndef __GEN_$arch\_NEW_NODES_H__\n";
-print OUT "#define __GEN_$arch\_NEW_NODES_H__\n\n";
+my $creation_time = localtime(time());
+my $tmp = uc($arch);
+
+print OUT<<EOF;
+/**
+ * \@file
+ * \@brief Function prototypes for the new opcode functions.
+ * \@note DO NOT EDIT THIS FILE, your changes will be lost.
+ * Edit $specfile instead.
+ * created by: $0 $specfile $target_dir
+ * \@date $creation_time
+ */
+#ifndef FIRM_BE_${tmp}_GEN_${tmp}_NEW_NODES_H
+#define FIRM_BE_${tmp}_GEN_${tmp}_NEW_NODES_H
+
+EOF
+
print OUT @obst_enum_op;
print OUT "int is_$arch\_irn(const ir_node *node);\n\n";
print OUT "int get_$arch\_opcode_first(void);\n";
print OUT "int get_$arch\_irn_opcode(const ir_node *node);\n";
print OUT @obst_header;
print OUT @obst_proj;
-print OUT "\n#endif /* __GEN_$arch\_NEW_NODES_H__ */\n";
+
+print OUT <<EOF;
+#endif
+EOF
close(OUT);
return "oparity_trinary";
}
else {
- return "$arity";
+ return "oparity_any";
}
}
else {