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