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().
17 our $comment_string_end;
20 our $spec_version = 1;
27 unless ($return = do $specfile) {
28 warn "couldn't parse $specfile: $@" if $@;
29 warn "couldn't do $specfile: $!" unless defined $return;
30 warn "couldn't run $specfile" unless $return;
34 my $comment_string_quoted = quotemeta($comment_string);
36 my $target_c = $target_dir."/gen_".$arch."_emitter.c";
37 my $target_h = $target_dir."/gen_".$arch."_emitter.h";
40 my @obst_func; # stack for the emit functions
41 my @obst_register; # stack for emitter register code
51 my @tokens = ($template =~ m/[^\%]+|\%[a-zA-Z_][a-zA-Z0-9_]*|\%./g);
52 push(@{$result}, "${indent}${arch}_emit_char(env, '\t');\n");
55 if (/%\./) { last SWITCH; }
56 if (/%%/) { push(@{$result}, "${indent}${arch}_emit_char(env, '%');\n"); last SWITCH; }
58 if(defined($emit_templates{$1})) {
59 push(@{$result}, "${indent}$emit_templates{$1}\n");
61 print "Warning: No emit_template defined for '$1'\n";
62 push(@{$result}, "${indent}$1(env, node);\n");
66 push(@{$result}, "${indent}${arch}_emit_cstring(env, \"$_\");\n");
69 push(@{$result}, "${indent}${arch}_emit_finish_line(env, node);\n");
74 foreach my $op (keys(%nodes)) {
75 my %n = %{ $nodes{"$op"} };
77 # skip this node description if no emit information is available
78 next if (!defined($n{"emit"}));
80 $line = "static void emit_".$arch."_".$op."(${arch}_emit_env_t *env, const ir_node *node)";
82 push(@obst_register, " BE_EMIT($op);\n");
84 if($n{"emit"} eq "") {
85 push(@obst_func, $line." {\n");
86 push(@obst_func, "}\n\n");
90 push(@obst_func, $line." {\n");
91 my @emit = split(/\n/, $n{"emit"});
93 if($spec_version < 3) { last; }
95 foreach my $template (@emit) {
96 # substitute only lines, starting with a '.'
97 if ($template =~ /^(\s*)\.\s*(.*)/) {
99 create_emitter(\@obst_func, $indent, $2);
101 push(@obst_func, "\t$template\n");
105 push(@obst_func, "}\n\n");
108 open(OUT, ">$target_h") || die("Could not open $target_h, reason: $!\n");
110 my $creation_time = localtime(time());
115 #ifndef _GEN_$tmp\_EMITTER_H_
116 #define _GEN_$tmp\_EMITTER_H_
119 * Function prototypes for the emitter functions.
120 * DO NOT EDIT THIS FILE, your changes will be lost.
121 * Edit $specfile instead.
122 * created by: $0 $specfile $target_dir
123 * date: $creation_time
127 #include "$arch\_emitter.h"
129 void $arch\_register_spec_emitters(void);
131 #endif /* _GEN_$tmp\_EMITTER_H_ */
137 open(OUT, ">$target_c") || die("Could not open $target_c, reason: $!\n");
139 $creation_time = localtime(time());
143 * Generated functions to emit code for assembler ir nodes.
144 * DO NOT EDIT THIS FILE, your changes will be lost.
145 * Edit $specfile instead.
146 * created by: $0 $specfile $target_dir
147 * date: $creation_time
157 #include "irprog_t.h"
159 #include "gen_${arch}_emitter.h"
160 #include "${arch}_new_nodes.h"
161 #include "${arch}_emitter.h"
165 print OUT @obst_func;
169 * Enters the emitter functions for handled nodes into the generic
170 * pointer of an opcode.
172 void $arch\_register_spec_emitters(void) {
174 #define BE_EMIT(a) op_$arch\_##a->ops.generic = (op_func)emit_$arch\_##a
176 /* generated emitter functions */
179 print OUT @obst_register;