bescripts: Copy all common node attributes into the constructor variants.
[libfirm] / ir / be / scripts / generate_regalloc_if.pl
1 #!/usr/bin/perl -w
2
3 #
4 # Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
5 #
6 # This file is part of libFirm.
7 #
8 # This file may be distributed and/or modified under the terms of the
9 # GNU General Public License version 2 as published by the Free Software
10 # Foundation and appearing in the file LICENSE.GPL included in the
11 # packaging of this file.
12 #
13 # Licensees holding valid libFirm Professional Edition licenses may use
14 # this file in accordance with the libFirm Commercial License.
15 # Agreement provided with the Software.
16 #
17 # This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
18 # WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 # PURPOSE.
20 #
21
22 # This script generates C code which creates ands sets up functions and
23 # data structures for the register allocator.
24 # Creation: 2005/11/14
25
26 use strict;
27 use Data::Dumper;
28 use integer;
29
30 my $specfile   = $ARGV[0];
31 my $target_dir = $ARGV[1];
32
33 our $arch;
34 our %reg_classes;
35
36 # include spec file
37
38 my $return;
39
40 use strict "subs";
41 unless ($return = do $specfile) {
42         die "Fatal error: couldn't parse $specfile: $@" if $@;
43         die "Fatal error: couldn't do $specfile: $!"    unless defined $return;
44         die "Fatal error: couldn't run $specfile"       unless $return;
45 }
46 use strict "subs";
47
48 my $target_c   = $target_dir."/gen_".$arch."_regalloc_if.c";
49 my $target_h   = $target_dir."/gen_".$arch."_regalloc_if.h";
50
51 # helper function
52 sub map_flags {
53         my $prefix = shift;
54         my $flags  = shift || "none";
55         return join(" | ", map { "$prefix$_" } split(/\s*\|\s*/, $flags));
56 }
57
58 # stacks for output
59 my $regtypes_def; # stack for the register type variables definitions
60 my @regclasses;   # stack for the register class variables
61 my $classdef;     # stack to define a name for a class index
62 my $regdef;       # stack to define a name for a register index
63 my $regdef2;
64 my $regcounts;
65 my $reginit;      # stack for the register type inits
66 my $single_constraints;
67
68 my $class_ptr;
69 my $class_idx = 0;
70
71 my %regclass2len = ();
72 my %reg2class = ();
73
74 $classdef .= "enum reg_classes {\n";
75
76 foreach my $class_name (keys(%reg_classes)) {
77         my @class = @{ $reg_classes{"$class_name"} };
78
79         my $idx = 0;
80         foreach (@class) {
81                 if (defined($_->{name})) {
82                         $reg2class{$_->{name}} = {
83                                 "class" => $class_name,
84                                 "index" => $idx
85                         };
86                 }
87                 $idx++;
88         }
89         $regclass2len{$class_name} = $idx;
90 }
91
92 sub get_limited_array {
93         my $reg      = shift;
94         my $regclass = $reg2class{"$reg"}{"class"};
95         my $ucname   = uc($reg);
96         my $result   = "{ ";
97
98         my $limitedbitsetlen = $regclass2len{$regclass};
99         my $arraylen         = ($limitedbitsetlen+31) / 32;
100         my $firstreg         = uc($reg_classes{$regclass}[0]->{"name"});
101         my $classuc          = uc($regclass);
102         my $first            = 1;
103         for (my $i = 0; $i < $arraylen; ++$i) {
104                 if ($first) {
105                         $first = 0;
106                 } else {
107                         $result .= ", ";
108                 }
109
110                 my $index = $reg2class{"$reg"}{"index"};
111                 if ($index >= $i*32 && $index < ($i+1)*32) {
112                         if ($i > 0) {
113                                 $result .= "(1 << (REG_${classuc}_${ucname} % 32))";
114                         } else {
115                                 $result .= "(1 << REG_${classuc}_${ucname})";
116                         }
117                 } else {
118                         $result .= "0";
119                 }
120         }
121         $result .= " }";
122 }
123
124 # generate register type and class variable, init function and default requirements
125 foreach my $class_name (keys(%reg_classes)) {
126         my @class         = @{ $reg_classes{"$class_name"} };
127         my $old_classname = $class_name;
128
129         $class_name = $arch."_".$class_name;
130         $class_ptr  = "&".$arch."_reg_classes[CLASS_".$class_name."]";
131         my $flags = pop(@class);
132         my $class_mode = $flags->{"mode"};
133         my $flags_prepared = map_flags("arch_register_class_flag_", $flags->{"flags"});
134
135         $single_constraints .= <<EOF;
136 static const arch_register_req_t ${arch}_class_reg_req_${old_classname} = {
137         arch_register_req_type_normal,
138         &${arch}_reg_classes[CLASS_${arch}_${old_classname}],
139         NULL,
140         0,
141         0,
142         1
143 };
144 EOF
145
146         $classdef .= "\tCLASS_$class_name = $class_idx,\n";
147         my $numregs = @class;
148         my $first_reg = "&${arch}_registers[REG_". uc($class[0]->{"name"}) . "]";
149         push(@regclasses, "{ $class_idx, \"$class_name\", $numregs, NULL, $first_reg, $flags_prepared, &${arch}_class_reg_req_${old_classname} }");
150
151         my $idx = 0;
152         $reginit .= "\t$arch\_reg_classes[CLASS_".$class_name."].mode = $class_mode;\n";
153         my $lastreg;
154         foreach (@class) {
155                 my $name   = $_->{"name"};
156                 my $ucname = uc($name);
157                 my $type   = map_flags("arch_register_type_", $_->{"type"});
158                 # realname is name if not set by user
159                 $_->{"realname"} = $_->{"name"} if (! exists($_->{"realname"}));
160                 my $realname = $_->{realname};
161                 my $classuc = uc($old_classname);
162
163                 $regdef  .= "\tREG_${ucname},\n";
164                 $regdef2 .= "\tREG_${classuc}_${ucname} = $idx,\n";
165                 my $dwarf_number = 0;
166                 if (defined($_->{dwarf})) {
167                         $dwarf_number = $_->{dwarf};
168                 }
169
170                 $regtypes_def .= <<EOF;
171         {
172                 "${realname}",
173                 ${class_ptr},
174                 REG_${classuc}_${ucname},
175                 REG_${ucname},
176                 ${type},
177                 &${arch}_single_reg_req_${old_classname}_${name},
178                 ${dwarf_number}
179         },
180 EOF
181
182                 my $limitedarray = get_limited_array($name);
183                 $single_constraints .= <<EOF;
184 static const unsigned ${arch}_limited_${old_classname}_${name} [] = ${limitedarray};
185 static const arch_register_req_t ${arch}_single_reg_req_${old_classname}_${name} = {
186         arch_register_req_type_limited,
187         ${class_ptr},
188         ${arch}_limited_${old_classname}_${name},
189         0,
190         0,
191         1
192 };
193 EOF
194
195                 $lastreg = $ucname;
196                 $idx++;
197         }
198         $regcounts .= "\tN_${class_name}_REGS = $numregs,\n";
199
200         $class_idx++;
201 }
202
203 my $archuc = uc($arch);
204
205 $classdef .= "\tN_${archuc}_CLASSES = ".scalar(keys(%reg_classes))."\n";
206 $classdef .= "};\n\n";
207
208 # generate header (external usage) file
209 open(OUT, ">$target_h") || die("Fatal error: Could not open $target_h, reason: $!\n");
210
211 my $creation_time = localtime(time());
212
213 print OUT<<EOF;
214 /**
215  * \@file
216  * \@brief Contains additional external requirements defs for external includes.
217  * \@note   DO NOT EDIT THIS FILE, your changes will be lost.
218  *         Edit $specfile instead.
219  *         created by: $0 $specfile $target_dir
220  * \@date   $creation_time
221  */
222 #ifndef FIRM_BE_${archuc}_GEN_${archuc}_REGALLOC_IF_H
223 #define FIRM_BE_${archuc}_GEN_${archuc}_REGALLOC_IF_H
224
225 #include "bearch.h"
226 #include "${arch}_nodes_attr.h"
227
228 /** global register indices for ${arch} registers */
229 enum reg_indices {
230 ${regdef}
231         N_${archuc}_REGISTERS
232 };
233 /** local register indices for ${arch} registers */
234 enum {
235 ${regdef2}
236 };
237
238 /** number of registers in ${arch} register classes. */
239 enum {
240 ${regcounts}
241 };
242 ${classdef}
243
244 extern const arch_register_t ${arch}_registers[N_${archuc}_REGISTERS];
245
246 extern arch_register_class_t ${arch}_reg_classes[N_${archuc}_CLASSES];
247
248 void ${arch}_register_init(void);
249
250 #endif
251 EOF
252 close(OUT);
253
254
255 # generate c file
256 open(OUT, ">$target_c") || die("Fatal error: Could not open $target_c, reason: $!\n");
257
258 $creation_time = localtime(time());
259
260 print OUT<<EOF;
261 /**
262  * \@file
263  * \@brief  The generated interface for the register allocator.
264  *          Contains register classes and types and register constraints
265  *          for all nodes where constraints were given in spec.
266  * \@note    DO NOT EDIT THIS FILE, your changes will be lost.
267  *          Edit $specfile instead.
268  *          created by: $0 $specfile $target_dir
269  * \$date    $creation_time
270  */
271 #include "config.h"
272
273 #include "gen_${arch}_regalloc_if.h"
274 #include "bearch_${arch}_t.h"
275 #include "irmode.h"
276
277 ${single_constraints}
278 EOF
279
280 print OUT "arch_register_class_t ${arch}_reg_classes[] = {\n\t".join(",\n\t", @regclasses)."\n};\n\n";
281
282 print OUT<<EOF;
283
284 /** The array of all registers in the ${arch} architecture, sorted by its global index.*/
285 const arch_register_t ${arch}_registers[] = {
286 ${regtypes_def}
287 };
288
289 /**
290  * Initializes ${arch} register classes.
291  */
292 void ${arch}_register_init(void)
293 {
294 ${reginit}
295 }
296 EOF
297 close(OUT);