aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLinus Torvalds <torvalds@penguin.transmeta.com>2003-05-23 17:41:39 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:00:45 -0700
commita10932174ca47672bc8f62a5b98fbcfb34ee534b (patch)
tree7365f1793fd1f1f23db7de1704aeb0dbce372da1
parente5b62a635d5a9d7b5da58922086bb3c9570eb36c (diff)
downloadsparse-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.c4
-rw-r--r--expression.c10
-rw-r--r--expression.h5
-rw-r--r--parse.c13
-rw-r--r--parse.h1
-rw-r--r--show-parse.c9
-rw-r--r--symbol.c5
-rw-r--r--symbol.h5
8 files changed, 45 insertions, 7 deletions
diff --git a/evaluate.c b/evaluate.c
index a11ccea4..458bc830 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -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
diff --git a/parse.c b/parse.c
index e6a9ec83..d717680d 100644
--- a/parse.c
+++ b/parse.c
@@ -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) {
diff --git a/parse.h b/parse.h
index 42fa0811..e47e7e0f 100644
--- a/parse.h
+++ b/parse.h
@@ -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.
diff --git a/symbol.c b/symbol.c
index 2cab128d..77d0ee40 100644
--- a/symbol.c
+++ b/symbol.c
@@ -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 },
diff --git a/symbol.h b/symbol.h
index 7450dfed..495f629d 100644
--- a/symbol.h
+++ b/symbol.h
@@ -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 */