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