scripts: Reduce scope of variable.
[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 our %cpu;
36
37 # include spec file
38
39 my $return;
40
41 use strict "subs";
42 unless ($return = do $specfile) {
43         die "Fatal error: couldn't parse $specfile: $@" if $@;
44         die "Fatal error: couldn't do $specfile: $!"    unless defined $return;
45         die "Fatal error: couldn't run $specfile"       unless $return;
46 }
47 use strict "subs";
48
49 my $target_c   = $target_dir."/gen_".$arch."_regalloc_if.c";
50 my $target_h   = $target_dir."/gen_".$arch."_regalloc_if.h";
51
52 # helper function
53 sub map_flags {
54         my $prefix = shift;
55         my $flags  = shift || "none";
56         return join(" | ", map { "$prefix$_" } split(/\s*\|\s*/, $flags));
57 }
58
59 # stacks for output
60 my $regtypes_def; # stack for the register type variables definitions
61 my $regtypes_decl;# stack for the register type variables declarations
62 my @regclasses;   # stack for the register class variables
63 my $classdef;     # stack to define a name for a class index
64 my $regdef;       # stack to define a name for a register index
65 my $regdef2;
66 my $regcounts;
67 my $reginit;      # stack for the register type inits
68 my $single_constraints_decls;
69 my $single_constraints;
70
71 my $class_ptr;
72 my $class_idx = 0;
73
74 my %regclass2len = ();
75 my %reg2class = ();
76
77 $classdef .= "enum reg_classes {\n";
78
79 foreach my $class_name (keys(%reg_classes)) {
80         my @class = @{ $reg_classes{"$class_name"} };
81
82         my $idx = 0;
83         foreach (@class) {
84                 if (defined($_->{name})) {
85                         $reg2class{$_->{name}} = {
86                                 "class" => $class_name,
87                                 "index" => $idx
88                         };
89                 }
90                 $idx++;
91         }
92         $regclass2len{$class_name} = $idx;
93 }
94
95 sub get_limited_array {
96         my $reg      = shift;
97         my $regclass = $reg2class{"$reg"}{"class"};
98         my $ucname   = uc($reg);
99         my $result   = "{ ";
100
101         my $limitedbitsetlen = $regclass2len{$regclass};
102         my $arraylen         = ($limitedbitsetlen+31) / 32;
103         my $firstreg         = uc($reg_classes{$regclass}[0]->{"name"});
104         my $classuc          = uc($regclass);
105         my $first            = 1;
106         for (my $i = 0; $i < $arraylen; ++$i) {
107                 if ($first) {
108                         $first = 0;
109                 } else {
110                         $result .= ", ";
111                 }
112
113                 my $index = $reg2class{"$reg"}{"index"};
114                 if ($index >= $i*32 && $index < ($i+1)*32) {
115                         if ($i > 0) {
116                                 $result .= "(1 << (REG_${classuc}_${ucname} % 32))";
117                         } else {
118                                 $result .= "(1 << REG_${classuc}_${ucname})";
119                         }
120                 } else {
121                         $result .= "0";
122                 }
123         }
124         $result .= " }";
125 }
126
127 # generate register type and class variable, init function and default requirements
128 foreach my $class_name (keys(%reg_classes)) {
129         my @class         = @{ $reg_classes{"$class_name"} };
130         my $old_classname = $class_name;
131
132         $class_name = $arch."_".$class_name;
133         $class_ptr  = "&".$arch."_reg_classes[CLASS_".$class_name."]";
134         my $flags = pop(@class);
135         my $class_mode = $flags->{"mode"};
136         my $flags_prepared = map_flags("arch_register_class_flag_", $flags->{"flags"});
137
138         $single_constraints .= <<EOF;
139 static const arch_register_req_t ${arch}_class_reg_req_${old_classname} = {
140         arch_register_req_type_normal,
141         &${arch}_reg_classes[CLASS_${arch}_${old_classname}],
142         NULL,
143         0,
144         0,
145         1
146 };
147 EOF
148
149         $classdef .= "\tCLASS_$class_name = $class_idx,\n";
150         my $numregs = @class;
151         my $first_reg = "&${arch}_registers[REG_". uc($class[0]->{"name"}) . "]";
152         push(@regclasses, "{ $class_idx, \"$class_name\", $numregs, NULL, $first_reg, $flags_prepared, &${arch}_class_reg_req_${old_classname} }");
153
154         my $idx = 0;
155         $reginit .= "\t$arch\_reg_classes[CLASS_".$class_name."].mode = $class_mode;\n";
156         my $lastreg;
157         foreach (@class) {
158                 my $name   = $_->{"name"};
159                 my $ucname = uc($name);
160                 my $type   = map_flags("arch_register_type_", $_->{"type"});
161                 # realname is name if not set by user
162                 $_->{"realname"} = $_->{"name"} if (! exists($_->{"realname"}));
163                 my $realname = $_->{realname};
164                 my $classuc = uc($old_classname);
165
166                 $regdef  .= "\tREG_${ucname},\n";
167                 $regdef2 .= "\tREG_${classuc}_${ucname} = $idx,\n";
168                 my $dwarf_number = 0;
169                 if (defined($_->{dwarf})) {
170                         $dwarf_number = $_->{dwarf};
171                 }
172
173                 $regtypes_def .= <<EOF;
174         {
175                 "${realname}",
176                 ${class_ptr},
177                 REG_${classuc}_${ucname},
178                 REG_${ucname},
179                 ${type},
180                 &${arch}_single_reg_req_${old_classname}_${name},
181                 ${dwarf_number}
182         },
183 EOF
184
185                 my $limitedarray = get_limited_array($name);
186                 $single_constraints .= <<EOF;
187 static const unsigned ${arch}_limited_${old_classname}_${name} [] = ${limitedarray};
188 static const arch_register_req_t ${arch}_single_reg_req_${old_classname}_${name} = {
189         arch_register_req_type_limited,
190         ${class_ptr},
191         ${arch}_limited_${old_classname}_${name},
192         0,
193         0,
194         1
195 };
196 EOF
197
198                 $lastreg = $ucname;
199                 $idx++;
200         }
201         $regcounts .= "\tN_${class_name}_REGS = $numregs,\n";
202
203         $class_idx++;
204 }
205
206 my $archuc = uc($arch);
207
208 $classdef .= "\tN_${archuc}_CLASSES = ".scalar(keys(%reg_classes))."\n";
209 $classdef .= "};\n\n";
210
211 # generate header (external usage) file
212 open(OUT, ">$target_h") || die("Fatal error: Could not open $target_h, reason: $!\n");
213
214 my $creation_time = localtime(time());
215
216 print OUT<<EOF;
217 /**
218  * \@file
219  * \@brief Contains additional external requirements defs for external includes.
220  * \@note   DO NOT EDIT THIS FILE, your changes will be lost.
221  *         Edit $specfile instead.
222  *         created by: $0 $specfile $target_dir
223  * \@date   $creation_time
224  */
225 #ifndef FIRM_BE_${archuc}_GEN_${archuc}_REGALLOC_IF_H
226 #define FIRM_BE_${archuc}_GEN_${archuc}_REGALLOC_IF_H
227
228 #include "bearch.h"
229 #include "${arch}_nodes_attr.h"
230
231 /** global register indices for ${arch} registers */
232 enum reg_indices {
233 ${regdef}
234         N_${archuc}_REGISTERS
235 };
236 /** local register indices for ${arch} registers */
237 enum {
238 ${regdef2}
239 };
240
241 /** number of registers in ${arch} register classes. */
242 enum {
243 ${regcounts}
244 };
245 ${classdef}
246
247 extern const arch_register_t ${arch}_registers[N_${archuc}_REGISTERS];
248
249 extern arch_register_class_t ${arch}_reg_classes[N_${archuc}_CLASSES];
250
251 void ${arch}_register_init(void);
252
253 #endif
254 EOF
255 close(OUT);
256
257
258 # generate c file
259 open(OUT, ">$target_c") || die("Fatal error: Could not open $target_c, reason: $!\n");
260
261 $creation_time = localtime(time());
262
263 print OUT<<EOF;
264 /**
265  * \@file
266  * \@brief  The generated interface for the register allocator.
267  *          Contains register classes and types and register constraints
268  *          for all nodes where constraints were given in spec.
269  * \@note    DO NOT EDIT THIS FILE, your changes will be lost.
270  *          Edit $specfile instead.
271  *          created by: $0 $specfile $target_dir
272  * \$date    $creation_time
273  */
274 #include "config.h"
275
276 #include "gen_${arch}_regalloc_if.h"
277 #include "bearch_${arch}_t.h"
278 #include "irmode.h"
279
280 ${single_constraints}
281 EOF
282
283 print OUT "arch_register_class_t ${arch}_reg_classes[] = {\n\t".join(",\n\t", @regclasses)."\n};\n\n";
284
285 print OUT<<EOF;
286
287 /** The array of all registers in the ${arch} architecture, sorted by its global index.*/
288 const arch_register_t ${arch}_registers[] = {
289 ${regtypes_def}
290 };
291
292 /**
293  * Initializes ${arch} register classes.
294  */
295 void ${arch}_register_init(void)
296 {
297 ${reginit}
298 }
299 EOF
300 close(OUT);