1 # Copyright (C) 2013-2024 Free Software Foundation, Inc.
3 # This program is free software; you can redistribute it and/or modify it
4 # under the terms of the GNU General Public License as published by the
5 # Free Software Foundation; either version 3, or (at your option) any
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; see the file COPYING3. If not see
15 # <http://www.gnu.org/licenses/>.
17 # This Awk script takes passes.def and writes pass-instances.def,
18 # counting the instances of each kind of pass, adding an instance number
19 # to everywhere that NEXT_PASS or PUSH_INSERT_PASSES_WITHIN are used.
20 # Also handle INSERT_PASS_AFTER, INSERT_PASS_BEFORE and REPLACE_PASS
23 # For example, the single-instanced pass:
24 # NEXT_PASS (pass_warn_unused_result);
25 # becomes this in the output:
26 # NEXT_PASS (pass_warn_unused_result, 1);
28 # The various instances of
29 # NEXT_PASS (pass_copy_prop);
31 # NEXT_PASS (pass_copy_prop, 1);
33 # NEXT_PASS (pass_copy_prop, 8);
34 # (currently there are 8 instances of that pass)
36 # INSERT_PASS_AFTER (pass_copy_prop, 1, pass_stv);
38 # NEXT_PASS (pass_stv, 1);
39 # immediately after the NEXT_PASS (pass_copy_prop, 1) line,
40 # similarly INSERT_PASS_BEFORE inserts immediately before that line.
41 # REPLACE_PASS (pass_copy_prop, 1, pass_stv, true);
42 # will replace NEXT_PASS (pass_copy_prop, 1) line with
43 # NEXT_PASS (pass_stv, 1, true);
44 # line and renumber all higher pass_copy_prop instances if any.
46 # Usage: awk -f gen-pass-instances.awk passes.def
49 print "/* This file is auto-generated by gen-pass-instances.awk";
50 print " from passes.def. */";
54 function parse_line
(line
, fnname
, len_of_call
, len_of_start
,
55 len_of_open
, len_of_close
,
56 len_of_args
, args_start_at
,
57 args_str
, len_of_prefix
,
61 # Find call expression.
62 call_starts_at =
match(line
, fnname
" \\(.+\\)");
63 if (call_starts_at ==
0)
66 # Length of the call expression.
67 len_of_call =
RLENGTH;
69 len_of_start =
length(fnname
" (");
70 len_of_open =
length("(");
71 len_of_close =
length(")");
74 len_of_args = len_of_call
- (len_of_start
+ len_of_close
);
75 args_start_at = call_starts_at
+ len_of_start
;
76 args_str =
substr(line
, args_start_at
, len_of_args
);
77 split(args_str
, args
, ",");
79 # Find call expression prefix
80 len_of_prefix = call_starts_at
- 1;
81 prefix =
substr(line
, 1, len_of_prefix
);
83 # Find call expression postfix
84 postfix_starts_at = call_starts_at
+ len_of_call
;
85 postfix =
substr(line
, postfix_starts_at
);
89 function adjust_linenos
(above
, increment
, p
, i
)
92 if (pass_lines
[p
] >= above
)
93 pass_lines
[p
] += increment
;
95 for (i = lineno
- 1; i
>= above
; i
--)
96 lines
[i
+ increment
] = lines
[i
];
98 for (i = above
; i
< lineno
; i
++)
99 lines
[i
+ increment
] = lines
[i
];
103 function insert_remove_pass
(line
, fnname
, arg3
, i
)
105 parse_line
($
0, fnname
);
107 if (pass_name ==
"PASS")
109 pass_num = args
[2] + 0;
111 sub(/^
[ \t]*/, "", arg3
);
112 new_line = prefix
"NEXT_PASS (" arg3
;
113 # Add the optional params back.
117 new_line = new_line
"," args
[i
];
120 new_line = new_line
")" postfix
;
121 if (!pass_lines
[pass_name
, pass_num
])
123 print "ERROR: Can't locate instance of the pass mentioned in " fnname
;
129 function insert_pass
(line
, fnname
, after
, num
)
131 if (insert_remove_pass
(line
, fnname
))
133 num = pass_lines
[pass_name
, pass_num
];
134 adjust_linenos
(num
+ after
, 1);
137 if (args
[3] in pass_counts
)
138 pass_counts
[pass_name
]++;
140 pass_counts
[pass_name
] =
1;
142 pass_lines
[pass_name
, pass_counts
[pass_name
]] = num
+ after
;
143 lines
[num
+ after
] = new_line
;
146 function replace_pass
(line
, fnname
, num
, i
)
148 if (insert_remove_pass
(line
, "REPLACE_PASS"))
150 num = pass_lines
[pass_name
, pass_num
];
151 for (i = pass_counts
[pass_name
]; i
> pass_num
; i
--)
152 pass_lines
[pass_name
, i
- 1] = pass_lines
[pass_name
, i
];
153 delete pass_lines
[pass_name
, pass_counts
[pass_name
]];
154 if (pass_counts
[pass_name
] ==
1)
155 delete pass_counts
[pass_name
];
157 pass_counts
[pass_name
]--;
161 if (args
[3] in pass_counts
)
162 pass_counts
[pass_name
]++;
164 pass_counts
[pass_name
] =
1;
166 pass_lines
[pass_name
, pass_counts
[pass_name
]] = num
;
167 lines
[num
] = new_line
;
170 /INSERT_PASS_AFTER \
(.
+\
)/ {
171 insert_pass
($
0, "INSERT_PASS_AFTER", 1);
175 /INSERT_PASS_BEFORE \
(.
+\
)/ {
176 insert_pass
($
0, "INSERT_PASS_BEFORE", 0);
180 /REPLACE_PASS \
(.
+\
)/ {
181 replace_pass
($
0, "REPLACE_PASS");
186 ret = parse_line
($
0, "NEXT_PASS");
192 if (pass_name in pass_counts
)
193 pass_counts
[pass_name
]++;
195 pass_counts
[pass_name
] =
1;
197 pass_lines
[pass_name
, pass_counts
[pass_name
]] = lineno
;
199 lines
[lineno
++] = $
0;
203 for (i =
1; i
< lineno
; i
++)
205 ret = parse_line
(lines
[i
], "NEXT_PASS");
208 # Set pass_name argument, an optional with_arg argument
211 while (args
[num_args
+ 2])
214 # Set pass_final_counts
215 if (pass_name in pass_final_counts
)
216 pass_final_counts
[pass_name
]++;
218 pass_final_counts
[pass_name
] =
1;
220 pass_num = pass_final_counts
[pass_name
];
222 # Print call expression with extra pass_num argument
226 printf "NEXT_PASS_WITH_ARG";
232 printf " (%s, %s", pass_name
, pass_num
;
233 for (j =
0; j
< num_args
; j
++)
234 printf ",%s", args
[j
+2];
235 printf ")%s\n", postfix
;
240 ret = parse_line
(lines
[i
], "PUSH_INSERT_PASSES_WITHIN");
245 pass_num = pass_final_counts
[pass_name
];
248 print "ERROR: Can't locate instance of the pass mentioned in " pass_name
;
253 printf "PUSH_INSERT_PASSES_WITHIN";
254 printf " (%s, %s", pass_name
, pass_num
;
255 printf ")%s\n", postfix
;
262 # print out the #undefs
263 print "#undef INSERT_PASSES_AFTER"
264 print "#undef PUSH_INSERT_PASSES_WITHIN"
265 print "#undef POP_INSERT_PASSES"
266 print "#undef NEXT_PASS"
267 print "#undef NEXT_PASS_WITH_ARG"
268 print "#undef NEXT_PASS_WITH_ARGS"
269 print "#undef TERMINATE_PASS_LIST"