[PATCH 5/6] saner collect_arg() code generation
Al Viro <[email protected]> Tue, 31 Mar 2026 09:07:28 +0100
| Newsgroups | org.kernel.vger.linux-sparse |
|---|---|
| Message-ID | <[email protected]> |
1) gently coax gcc code generator away from screwing the bitfields
handling it is so keen to do - pass struct position from the caller
by value, with .newline already cleared (with inlined helper that
does trimming), do *not* let collect_arg() see that it's always
setting ->pos.newline to 0 (otherwise the FPOS tries to peel the damn
thing apart, turning mask-then-or into a bleeding horror).
2) get rid of 'vararg' checks for commas by changing the way we
keep track of nesting parentheses - instead of
number of '(' - number of ')'
use
2 * number of '(' - 2 * number of ')' + vararg
That still recognizes the closing parenthesis of argument list
(counter gets negative there, vararg or no vararg) and it does
recognize an argument-terminating comma without having to look
at 'vararg' - just check if counter is zero.
Reduces spills nicely.
3) do *not* use eof_token() as loop termination condition, compare
token_type() with TOKEN_EOF instead. Yes, it's faster to compare
the pointer with constant instead, but it is *not* going to match
that unless we have an unterminated argument list and we are going
to check for TOKEN_STREAM{BEGIN,END} immediately afterwards anyway,
with the same "leave the loop now" on match, so these checks combine
nicely.
Signed-off-by: Al Viro <[email protected]>
---
pre-process.c | 44 ++++++++++++++++++++++++++------------------
1 file changed, 26 insertions(+), 18 deletions(-)
diff --git a/pre-process.c b/pre-process.c
index e62d6379..a368b9ed 100644
--- a/pre-process.c
+++ b/pre-process.c
@@ -255,42 +255,41 @@ static void expand_list(struct token **list)
static void preprocessor_line(struct stream *stream, struct token **line);
-static struct token *collect_arg(struct token *prev, bool vararg, const struct position *pos)
+static struct token *collect_arg(struct token *prev, bool vararg, struct position pos)
{
struct stream *stream = input_streams + prev->pos.stream;
struct token **p = &prev->next;
struct token *next;
- int nesting = 0;
+ int nesting = vararg;
- while (!eof_token(next = scan_next(p))) {
+ while (1) {
+ next = scan_next(p);
+ if (token_type(next) == TOKEN_STREAMBEGIN ||
+ token_type(next) == TOKEN_STREAMEND ||
+ token_type(next) == TOKEN_EOF)
+ break;
if (token_type(next) == TOKEN_DIRECTIVE) {
preprocessor_line(stream, p);
__free_token(next); /* Free the '#' token */
continue;
}
- switch (token_type(next)) {
- case TOKEN_STREAMEND:
- case TOKEN_STREAMBEGIN:
- *p = &eof_token_entry;
- return next;
- }
if (false_nesting) {
*p = next->next;
__free_token(next);
continue;
}
if (match_op(next, '(')) {
- nesting++;
+ nesting += 2;
} else if (match_op(next, ')')) {
- if (!nesting--)
+ if ((nesting -= 2) < 0)
break;
- } else if (match_op(next, ',') && !nesting && !vararg) {
+ } else if (match_op(next, ',') && !nesting) {
break;
}
- next->pos.stream = pos->stream;
- next->pos.line = pos->line;
- next->pos.pos = pos->pos;
- next->pos.newline = 0;
+ next->pos.stream = pos.stream;
+ next->pos.line = pos.line;
+ next->pos.pos = pos.pos;
+ next->pos.newline = pos.newline;
p = &next->next;
}
*p = &eof_token_entry;
@@ -305,6 +304,15 @@ struct arg {
struct token *arg[3];
};
+static inline struct position location(const struct position *p)
+{
+ return (struct position) {
+ .stream = p->stream,
+ .line = p->line,
+ .pos = p->pos
+ };
+}
+
static int collect_arguments(struct token *what, int fixed, bool vararg, struct arg *args)
{
struct token *start = scan_next(&what->next);
@@ -317,7 +325,7 @@ static int collect_arguments(struct token *what, int fixed, bool vararg, struct
if (!match_op(start, '('))
return 0;
for (commas = 0; commas < fixed; commas++) {
- next = collect_arg(start, false, &what->pos);
+ next = collect_arg(start, false, location(&what->pos));
if (token_type(next) != TOKEN_SPECIAL)
goto Eclosing;
args[commas + 1].arg[ARG_QUOTED] = start->next;
@@ -329,7 +337,7 @@ static int collect_arguments(struct token *what, int fixed, bool vararg, struct
start = next;
}
if (commas == fixed) {
- next = collect_arg(start, true, &what->pos);
+ next = collect_arg(start, true, location(&what->pos));
if (token_type(next) != TOKEN_SPECIAL)
goto Eclosing;
v = start->next;
--
2.47.3