diff options
| author | Linus Torvalds <torvalds@penguin.transmeta.com> | 2003-05-23 17:41:39 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-07 21:00:45 -0700 |
| commit | a10932174ca47672bc8f62a5b98fbcfb34ee534b (patch) | |
| tree | 7365f1793fd1f1f23db7de1704aeb0dbce372da1 | |
| parent | e5b62a635d5a9d7b5da58922086bb3c9570eb36c (diff) | |
| download | sparse-dev-a10932174ca47672bc8f62a5b98fbcfb34ee534b.tar.gz | |
Parse and evaluate gcc computed goto extensions: label addressing
(&&label) and computed goto (goto *expr).
Add label ctype for __label__ identifier. This is still quite broken
(it should create a block-symbol in the NS_LABEL namespace, right now
it creates a regular symbol).
| -rw-r--r-- | evaluate.c | 4 | ||||
| -rw-r--r-- | expression.c | 10 | ||||
| -rw-r--r-- | expression.h | 5 | ||||
| -rw-r--r-- | parse.c | 13 | ||||
| -rw-r--r-- | parse.h | 1 | ||||
| -rw-r--r-- | show-parse.c | 9 | ||||
| -rw-r--r-- | symbol.c | 5 | ||||
| -rw-r--r-- | symbol.h | 5 |
8 files changed, 45 insertions, 7 deletions
@@ -1499,6 +1499,10 @@ struct symbol *evaluate_expression(struct expression *expr) expr->ctype = evaluate_statement(expr->statement); return expr->ctype; + case EXPR_LABEL: + expr->ctype = &ptr_ctype; + return &ptr_ctype; + /* These can not exist as stand-alone expressions */ case EXPR_INITIALIZER: case EXPR_IDENTIFIER: diff --git a/expression.c b/expression.c index 6e8cddf7..149eb992 100644 --- a/expression.c +++ b/expression.c @@ -326,6 +326,16 @@ static struct token *unary_expression(struct token *token, struct expression **t *tree = unary; return cast_expression(token->next, &unary->unop); } + + /* Gcc extension: &&label gives the address of a label */ + if (match_op(token, SPECIAL_LOGICAL_AND) && + token_type(token->next) == TOKEN_IDENT) { + struct expression *label = alloc_expression(token->pos, EXPR_LABEL); + label->label_symbol = label_symbol(token->next); + *tree = label; + return token->next->next; + } + } return postfix_expression(token, tree); diff --git a/expression.h b/expression.h index 529578a3..27b85c09 100644 --- a/expression.h +++ b/expression.h @@ -30,6 +30,7 @@ enum expression_type { EXPR_COMMA, EXPR_COMPARE, EXPR_BITFIELD, + EXPR_LABEL, EXPR_INITIALIZER, // initializer list EXPR_IDENTIFIER, // identifier in initializer EXPR_INDEX, // index in initializer @@ -88,6 +89,10 @@ struct expression { unsigned char bitpos, nrbits; struct expression *address; }; + // EXPR_LABEL + struct label_expr { + struct symbol *label_symbol; + }; // EXPR_INITIALIZER struct expression_list *expr_list; // EXPR_IDENTIFIER @@ -64,7 +64,7 @@ static struct symbol *lookup_or_create_symbol(enum namespace ns, enum type type, * it also ends up using function scope instead of the * regular symbol scope. */ -static struct symbol *label_symbol(struct token *token) +struct symbol *label_symbol(struct token *token) { return lookup_or_create_symbol(NS_LABEL, SYM_LABEL, token); } @@ -810,12 +810,15 @@ default_statement: if (token->ident == &goto_ident) { stmt->type = STMT_GOTO; - token = token->next; - if (token_type(token) == TOKEN_IDENT) { + token = token->next; + if (match_op(token, '*')) { + token = parse_expression(token->next, &stmt->goto_expression); + } else if (token_type(token) == TOKEN_IDENT) { stmt->goto_label = label_symbol(token); token = token->next; - } else - warn(token->pos, "invalid label"); + } else { + warn(token->pos, "Expected identifier or goto expression"); + } return expect(token, ';', "at end of statement"); } if (token->ident == &asm_ident || token->ident == &__asm___ident || token->ident == &__asm_ident) { @@ -79,6 +79,7 @@ struct statement { extern struct token *parse_expression(struct token *, struct expression **); extern struct token *statement_list(struct token *, struct statement_list **); +extern struct symbol *label_symbol(struct token *token); extern int show_statement(struct statement *); extern void show_statement_list(struct statement_list *, const char *); diff --git a/show-parse.c b/show-parse.c index 556e01e8..31dfcfb5 100644 --- a/show-parse.c +++ b/show-parse.c @@ -824,6 +824,13 @@ static int show_bitfield_expr(struct expression *expr) return show_access(expr); } +int show_label_expr(struct expression *expr) +{ + int new = new_pseudo(); + printf("\tmovi.%d\t\tv%d,.L%p\n",BITS_IN_POINTER, new, expr->label_symbol); + return new; +} + static int show_conditional_expr(struct expression *expr) { int cond = show_expression(expr->conditional); @@ -931,6 +938,8 @@ int show_expression(struct expression *expr) return show_conditional_expr(expr); case EXPR_STATEMENT: return show_statement_expr(expr); + case EXPR_LABEL: + return show_label_expr(expr); // None of these should exist as direct expressions: they are only // valid as sub-expressions of initializers. @@ -376,6 +376,7 @@ struct sym_init { { "__signed", &int_type, MOD_SIGNED }, { "__signed__", &int_type, MOD_SIGNED }, { "unsigned", &int_type, MOD_UNSIGNED }, + { "__label__", &label_type, MOD_LABEL | MOD_UNSIGNED }, /* Type qualifiers */ { "const", NULL, MOD_CONST }, @@ -432,6 +433,7 @@ struct sym_init eval_init_table[] = { */ struct symbol int_type, fp_type, + label_type, vector_type, bad_type; @@ -446,7 +448,7 @@ struct symbol bool_ctype, void_ctype, long_ctype, ulong_ctype, llong_ctype, ullong_ctype, float_ctype, double_ctype, ldouble_ctype, - string_ctype, ptr_ctype; + string_ctype, ptr_ctype, label_ctype; struct ctype_declare { struct symbol *ptr; @@ -457,6 +459,7 @@ struct ctype_declare { } ctype_declaration[] = { { &bool_ctype, 0, BITS_IN_INT, MAX_INT_ALIGNMENT, &int_type }, { &void_ctype, 0, -1, 0, NULL }, + { &label_ctype, MOD_LABEL | MOD_UNSIGNED, BITS_IN_POINTER, MAX_INT_ALIGNMENT, &label_type }, { &char_ctype, MOD_SIGNED | MOD_CHAR, BITS_IN_CHAR, MAX_INT_ALIGNMENT, &int_type }, { &uchar_ctype, MOD_UNSIGNED | MOD_CHAR, BITS_IN_CHAR, MAX_INT_ALIGNMENT, &int_type }, @@ -125,9 +125,12 @@ struct symbol { #define MOD_ACCESSED 0x400000 #define MOD_TOPLEVEL 0x800000 // scoping.. +#define MOD_LABEL 0x1000000 + /* Basic types */ extern struct symbol void_type, int_type, + label_type, fp_type, vector_type, bad_type; @@ -140,7 +143,7 @@ extern struct symbol bool_ctype, void_ctype, long_ctype, ulong_ctype, llong_ctype, ullong_ctype, float_ctype, double_ctype, ldouble_ctype, - string_ctype, ptr_ctype; + string_ctype, ptr_ctype, label_type; /* Basic identifiers */ |
