diff options
author | 2010-06-10 10:33:30 +0200 | |
---|---|---|
committer | 2010-06-17 17:21:10 -0700 | |
commit | 7ccc8abebad14639c22549cf55193e50b728802f (patch) | |
tree | 943721a43840fdc71f50b351f9bb3f00a0bcc6ca | |
parent | Adding asm goto label test case (diff) | |
download | sparse-7ccc8abebad14639c22549cf55193e50b728802f.tar.gz sparse-7ccc8abebad14639c22549cf55193e50b728802f.tar.bz2 sparse-7ccc8abebad14639c22549cf55193e50b728802f.zip |
parser: add support for asm goto
As of gcc 4.5, asm goto("jmp %l[label]" : OUT : IN : CLOB : LABELS) is
supported. Add this support to the parser so that it won't choke on
the newest Linux kernel when compiling with gcc 4.5.
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Christopher Li <sparse@chrisli.org>
-rw-r--r-- | evaluate.c | 8 | ||||
-rw-r--r-- | parse.c | 23 | ||||
-rw-r--r-- | parse.h | 1 |
3 files changed, 32 insertions, 0 deletions
@@ -3151,6 +3151,7 @@ static void verify_input_constraint(struct expression *expr, const char *constra static void evaluate_asm_statement(struct statement *stmt) { struct expression *expr; + struct symbol *sym; int state; expr = stmt->asm_string; @@ -3227,6 +3228,13 @@ static void evaluate_asm_statement(struct statement *stmt) continue; expression_error(expr, "asm clobber is not a string"); } END_FOR_EACH_PTR(expr); + + FOR_EACH_PTR(stmt->asm_labels, sym) { + if (!sym || sym->type != SYM_LABEL) { + sparse_error(stmt->pos, "bad asm label"); + return; + } + } END_FOR_EACH_PTR(sym); } static void evaluate_case_statement(struct statement *stmt) @@ -1891,12 +1891,33 @@ static struct token *parse_asm_clobbers(struct token *token, struct statement *s return token; } +static struct token *parse_asm_labels(struct token *token, struct statement *stmt, + struct symbol_list **labels) +{ + struct symbol *label; + + do { + token = token->next; /* skip ':' and ',' */ + if (token_type(token) != TOKEN_IDENT) + return token; + label = label_symbol(token); + add_symbol(labels, label); + token = token->next; + } while (match_op(token, ',')); + return token; +} + static struct token *parse_asm_statement(struct token *token, struct statement *stmt) { + int is_goto = 0; + token = token->next; stmt->type = STMT_ASM; if (match_idents(token, &__volatile___ident, &__volatile_ident, &volatile_ident, NULL)) { token = token->next; + } else if (match_idents(token, &goto_ident, NULL)) { + is_goto = 1; + token = token->next; } token = expect(token, '(', "after asm"); token = parse_expression(token, &stmt->asm_string); @@ -1906,6 +1927,8 @@ static struct token *parse_asm_statement(struct token *token, struct statement * token = parse_asm_operands(token, stmt, &stmt->asm_inputs); if (match_op(token, ':')) token = parse_asm_clobbers(token, stmt, &stmt->asm_clobbers); + if (is_goto && match_op(token, ':')) + token = parse_asm_labels(token, stmt, &stmt->asm_labels); token = expect(token, ')', "after asm"); return expect(token, ';', "at end of asm-statement"); } @@ -106,6 +106,7 @@ struct statement { struct expression_list *asm_outputs; struct expression_list *asm_inputs; struct expression_list *asm_clobbers; + struct symbol_list *asm_labels; }; struct /* range */ { struct expression *range_expression; |