changed names of generated files
[libfirm] / ir / be / scripts / generate_emitter.pl
1 #!/usr/bin/perl -w
2
3 # This script generates C code which emits assembler code for the
4 # assembler ir nodes. It takes a "emit" key from the node specification
5 # and substitutes lines starting with . with a corresponding fprintf().
6 # Creation: 2005/11/07
7 # $Id$
8
9 use strict;
10 use Data::Dumper;
11
12 my $specfile   = $ARGV[0];
13 my $target_dir = $ARGV[1];
14
15 our $arch;
16 our %nodes;
17
18 # include spec file
19
20 my $return;
21
22 no strict "subs";
23 unless ($return = do $specfile) {
24   warn "couldn't parse $specfile: $@" if $@;
25   warn "couldn't do $specfile: $!"    unless defined $return;
26   warn "couldn't run $specfile"       unless $return;
27 }
28 use strict "subs";
29
30 my $target_c = $target_dir."/gen_".$arch."_emitter.c";
31 my $target_h = $target_dir."/gen_".$arch."_emitter.h";
32
33 # stacks for output
34 my @obst_func;   # stack for the emit functions
35 my @obst_header;  # stack for the function prototypes
36
37 my $line;
38
39 foreach my $op (keys(%nodes)) {
40   my %n = %{ $nodes{"$op"} };
41
42   # skip this node description if no emit information is available
43   next if (!$n{"emit"} || length($n{"emit"}) < 1);
44
45   $line = "void emit_".$arch."_".$op."(FILE *F, ir_node *n)";
46   push(@obst_header, $line.";\n");
47   push(@obst_func, $line." {\n");
48
49   my @emit = split(/\n/, $n{"emit"});
50
51   foreach(@emit) {
52     # substitute only lines, starting with a '.'
53     if (/^(\d*)\.\s*/) {
54       my @params;
55       my $regkind;
56       my $indent = "  "; # default indent is 2 spaces
57
58       $indent = " " x $1 if ($1 && $1 > 0);
59       # remove indent, dot and trailing spaces
60       s/^\d*\.\s*//;
61       # substitute all format parameter
62       while (/%(([sd])(\d)|([co]))/) {
63         if ($4 && $4 eq "c") {
64           push(@params, "node_const_to_str(n)");
65         }
66         elsif ($4 && $4 eq "o") {
67           push(@params, "node_offset_to_str(n)");
68         }
69         else {
70           $regkind = ($2 eq "s" ? "source" : "dest");
71           push(@params, "get_".$regkind."_reg_name(n, $3)");
72         }
73         s/%$1/%%\%s/;
74       }
75       my $parm = "";
76       $parm = ", ".join(", ", @params) if (@params);
77       push(@obst_func, $indent.'fprintf(F, "\t'.$_.'\n"'.$parm.');'."\n");
78     }
79     else {
80       push(@obst_func, $_,"\n");
81     }
82   }
83   push(@obst_func, "}\n\n");
84 }
85
86 open(OUT, ">$target_h") || die("Could not open $target_h, reason: $!\n");
87
88 my $creation_time = localtime(time());
89
90 my $tmp = uc($arch);
91
92 print OUT<<EOF;
93 #ifndef _GEN_$tmp\_EMITTER_H_
94 #define _GEN_$tmp\_EMITTER_H_
95
96 /**
97  * Function prototypes for the emitter functions.
98  * DO NOT EDIT THIS FILE, your changes will be lost.
99  * Edit $specfile instead.
100  * created by: $0 $specfile $target_dir
101  * date:       $creation_time
102  */
103
104 #include "irnode.h"
105
106 EOF
107
108 print OUT @obst_header;
109
110 print OUT "#endif /* _GEN_$tmp\_EMITTER_H_ */\n";
111
112 close(OUT);
113
114 open(OUT, ">$target_c") || die("Could not open $target_c, reason: $!\n");
115
116 $creation_time = localtime(time());
117
118 print OUT<<EOF;
119 /**
120  * Generated functions to emit code for assembler ir nodes.
121  * DO NOT EDIT THIS FILE, your changes will be lost.
122  * Edit $specfile instead.
123  * created by: $0 $specfile $target_dir
124  * date:       $creation_time
125  */
126
127 #include <stdio.h>
128
129 #include "irnode.h"
130 #include "gen_$arch\_emitter.h"
131 #include "$arch\_emitter.h"
132 #include "$arch\_new_nodes.h"
133
134 EOF
135
136 print OUT @obst_func;
137
138 close(OUT);