aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiri Slaby <jslaby@suse.cz>2010-06-10 10:33:30 +0200
committerChristopher Li <sparse@chrisli.org>2010-06-17 17:21:10 -0700
commit7ccc8abebad14639c22549cf55193e50b728802f (patch)
tree943721a43840fdc71f50b351f9bb3f00a0bcc6ca
parentAdding asm goto label test case (diff)
downloadsparse-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.c8
-rw-r--r--parse.c23
-rw-r--r--parse.h1
3 files changed, 32 insertions, 0 deletions
diff --git a/evaluate.c b/evaluate.c
index cdbd064..f8343c2 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -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)
diff --git a/parse.c b/parse.c
index f5c5497..caf10b9 100644
--- a/parse.c
+++ b/parse.c
@@ -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");
}
diff --git a/parse.h b/parse.h
index 02b8585..6b21e23 100644
--- a/parse.h
+++ b/parse.h
@@ -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;