diff options
Diffstat (limited to 'gcc/c-parse.in')
-rw-r--r-- | gcc/c-parse.in | 341 |
1 files changed, 338 insertions, 3 deletions
diff --git a/gcc/c-parse.in b/gcc/c-parse.in index fe0d51709eb..d1c8e2fa5fb 100644 --- a/gcc/c-parse.in +++ b/gcc/c-parse.in @@ -150,6 +150,14 @@ do { \ %token REALPART IMAGPART VA_ARG CHOOSE_EXPR TYPES_COMPATIBLE_P %token FUNC_NAME OFFSETOF +/* APPLE LOCAL begin CW asm blocks */ +/* This token is a pseudo-storage-class. */ +%token CW_ASM_KEYWORD +%type <ttype> CW_ASM_KEYWORD +/* These tokens indicate beginning and end of each asm line. */ +%token CW_ASM_BOL CW_ASM_EOL +/* APPLE LOCAL end CW asm blocks */ + /* Add precedence rules to solve dangling else s/r conflict */ %nonassoc IF %nonassoc ELSE @@ -242,6 +250,17 @@ do { \ %type <arginfotype> parmlist_or_identifiers parmlist_or_identifiers_1 %type <ttype> identifiers_or_typenames +/* APPLE LOCAL begin CW asm blocks */ +%type <ttype> cw_identifier +%type <exprtype> cw_asm_expr_no_commas cw_asm_unary_expr +%type <exprtype> cw_asm_primary +%type <ttype> cw_asm_operands cw_nonnull_asm_operands +%type <exprtype> cw_asm_operand +%type <ttype> cw_asm_stmt single_cw_asm_stmt +%type <ttype> cw_asm_compstmt cw_asm_compstmt_start +/*cw_asm_compstmt_nostart */ +/* APPLE LOCAL end CW asm blocks */ + %type <itype> setspecs setspecs_fp extension %type <location> save_location @@ -358,6 +377,8 @@ static int yylexname (void); static inline int _yylex (void); static int yylex (void); static void init_reswords (void); +/* APPLE LOCAL CW asm blocks */ +static int cw_asm_lineno = 0; /* Initialization routine for this file. */ void @@ -683,7 +704,8 @@ primary: finish_init (); maybe_warn_string_init (type, init); - if (pedantic && !flag_isoc99) + /* APPLE LOCAL AltiVec */ + if (pedantic && TREE_CODE (type) != VECTOR_TYPE && !flag_isoc99) pedwarn ("ISO C90 forbids compound literals"); $$.value = build_compound_literal (type, constructor); $$.original_code = ERROR_MARK; @@ -845,7 +867,8 @@ datadecl: where statement labels are allowed. */ lineno_decl: save_location decl - { } + /* APPLE LOCAL CW asm blocks */ + { if (flag_cw_asm_blocks) cw_asm_in_decl = 0; } ; /* records the type and storage class specs to use for processing @@ -1419,6 +1442,8 @@ any_word: scspec: STATIC + /* APPLE LOCAL CW asm blocks */ + | CW_ASM_KEYWORD | SCSPEC ; @@ -2028,6 +2053,11 @@ compstmt_start: '{' { $$ = c_begin_compound_stmt (true); } compstmt_nostart: '}' | maybe_label_decls compstmt_contents_nonempty '}' + /* APPLE LOCAL begin CW asm blocks */ + { + if (flag_cw_asm_blocks) cw_asm_block = 0; + } + /* APPLE LOCAL end CW asm blocks */ ; compstmt_contents_nonempty: @@ -2051,6 +2081,126 @@ compstmt: compstmt_start compstmt_nostart { $$ = c_end_compound_stmt ($1, true); } ; +/* APPLE LOCAL begin CW asm blocks */ +/* A CW-style asm statement is recognized by having a BOL token preceding it. */ +cw_asm_stmt: CW_ASM_BOL save_location cw_asm_stmt_list CW_ASM_EOL + +{ $$ = NULL_TREE; } + ; + +/* A single line may have multiple statements separated by ';'. */ +cw_asm_stmt_list: + /* empty */ + | single_cw_asm_stmt + {} + | cw_asm_stmt_list ';' single_cw_asm_stmt + | cw_asm_stmt_list ';' + ; + +cw_identifier: + identifier + | cw_identifier '.' + { $$ = cw_get_identifier ($1, "."); } + | cw_identifier '+' + { $$ = cw_get_identifier ($1, "+"); } + | cw_identifier '-' + { $$ = cw_get_identifier ($1, "-"); } + | '.' identifier + { $$ = prepend_char_identifier ($2, '.'); } + ; + +/* A single statement consists of one or more labels (identified by a + leading '@' and/or a trailing ':'), optionally followed by opcode + and operands. */ +single_cw_asm_stmt: + cw_identifier + { cw_asm_lineno = input_line; cw_asm_in_operands = 1; } + cw_asm_operands + { $$ = cw_asm_stmt ($1, $3, cw_asm_lineno); } + | identifier STATIC cw_asm_operand + { $$ = cw_asm_entry ($1, $2, $3.value); } + | identifier SCSPEC cw_asm_operand + { $$ = cw_asm_entry ($1, $2, $3.value); } + | cw_asm_label + {} + | cw_asm_label single_cw_asm_stmt + {} + ; + +cw_asm_label: + identifier ':' + { cw_asm_label ($1, 0); } + | '@' identifier + { cw_asm_label ($2, 1); } + | '@' identifier ':' + { cw_asm_label ($2, 1); } + ; + +cw_asm_stmts: + stmt + {} + | cw_asm_stmts stmt + {} + ; + +/* An asm block within a function is simpler than asm functions; no + declarations are possible, so we switch to the block interior state + immediately. */ +cw_asm_compstmt_start: ASM_KEYWORD '{' + { + if (flag_cw_asm_blocks) + { + cw_asm_state = cw_asm_asm; + cw_asm_block = 1; + cw_asm_at_bol = 1; + clear_cw_asm_labels (); + } + else + /* This will probably choke badly... */ + error ("asm blocks not enabled, use `-fasm-blocks'"); + $$ = c_begin_compound_stmt (true); + } + ; + +cw_asm_compstmt_nostart: + '}' + | cw_asm_compstmt_contents_nonempty '}' + { cw_asm_block = 0; } + ; + +cw_asm_compstmt_contents_nonempty: + cw_asm_stmts + | error + ; + +cw_asm_compstmt: cw_asm_compstmt_start cw_asm_compstmt_nostart + { $$ = c_end_compound_stmt ($1, true); } + ; + +cw_asm_operands: + /* empty */ + { $$ = NULL_TREE; } + | cw_nonnull_asm_operands + ; + +cw_nonnull_asm_operands: + cw_asm_operand + { $$ = build_tree_list (NULL_TREE, $1.value); } + | cw_nonnull_asm_operands ',' cw_asm_operand + { $$ = chainon ($1, build_tree_list (NULL_TREE, $3.value)); } + ; + +/* Alternatively this could go to the regular expr_no_commas, but then + all the semantic actions would need to be tweaked to handle the + possibility of CW asm coming through. For example, "offset(reg)" + would be handled by function call code (bleah). */ +cw_asm_operand: cw_asm_expr_no_commas + | cw_asm_operand '(' cw_asm_expr_no_commas ')' + { $$.value = cw_asm_build_register_offset ($1.value, $3.value); + $$.original_code = ERROR_MARK; } + ; +/* APPLE LOCAL end CW asm blocks */ + /* The forced readahead in here is because we might be at the end of a line, and the line and file won't be bumped until yylex absorbs the first token on the next line. */ @@ -2233,6 +2383,12 @@ stmt_nocomp: { $$ = NULL_TREE; } | switch_statement { $$ = NULL_TREE; } + /* APPLE LOCAL begin CW asm blocks */ + | cw_asm_compstmt + { $$ = c_finish_expr_stmt ($1); } + | cw_asm_stmt + { $$ = c_finish_expr_stmt ($1); } + /* APPLE LOCAL end CW asm blocks */ | BREAK ';' { $$ = c_finish_bc_stmt (&c_break_label, true); } | CONTINUE ';' @@ -2441,6 +2597,139 @@ start_string_translation: { c_lex_string_translate = 1; } ; +/* APPLE LOCAL begin CW asm blocks */ +cw_asm_expr_no_commas: + cw_asm_unary_expr + | cw_asm_expr_no_commas '+' cw_asm_expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | cw_asm_expr_no_commas '-' cw_asm_expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | cw_asm_expr_no_commas '*' cw_asm_expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | cw_asm_expr_no_commas '/' cw_asm_expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | cw_asm_expr_no_commas '%' cw_asm_expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | cw_asm_expr_no_commas LSHIFT cw_asm_expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | cw_asm_expr_no_commas RSHIFT cw_asm_expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | cw_asm_expr_no_commas ARITHCOMPARE cw_asm_expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | cw_asm_expr_no_commas EQCOMPARE cw_asm_expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | cw_asm_expr_no_commas '&' cw_asm_expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | cw_asm_expr_no_commas '|' cw_asm_expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | cw_asm_expr_no_commas '^' cw_asm_expr_no_commas + { $$ = parser_build_binary_op ($2, $1, $3); } + | cw_asm_expr_no_commas ANDAND + { $1.value = c_common_truthvalue_conversion + (default_conversion ($1.value)); + skip_evaluation += $1.value == boolean_false_node; } + cw_asm_expr_no_commas + { skip_evaluation -= $1.value == boolean_false_node; + $$ = parser_build_binary_op (TRUTH_ANDIF_EXPR, $1, $4); } + | cw_asm_expr_no_commas OROR + { $1.value = c_common_truthvalue_conversion + (default_conversion ($1.value)); + skip_evaluation += $1.value == boolean_true_node; } + cw_asm_expr_no_commas + { skip_evaluation -= $1.value == boolean_true_node; + $$ = parser_build_binary_op (TRUTH_ORIF_EXPR, $1, $4); } + ; + +cw_asm_unary_expr: + cw_asm_primary + | '*' cw_asm_unary_expr %prec UNARY + { $$.value = build_indirect_ref ($2.value, "unary *"); + $$.original_code = ERROR_MARK; } + | unop cw_asm_unary_expr %prec UNARY + { + if (TREE_CODE ($2.value) == COMPOUND_EXPR) + { + tree neg = build_unary_op ($1, TREE_OPERAND ($2.value, 0), 0); + tree reg = TREE_OPERAND ($2.value, 1); + $$.value = cw_asm_build_register_offset (neg, reg); + } + else + { + $$.value = build_unary_op ($1, $2.value, 0); + overflow_warning ($$.value); + } + $$.original_code = ERROR_MARK; + } + | sizeof cw_asm_unary_expr %prec UNARY + { skip_evaluation--; + if (TREE_CODE ($2.value) == COMPONENT_REF + && DECL_C_BIT_FIELD (TREE_OPERAND ($2.value, 1))) + error ("`sizeof' applied to a bit-field"); + else if (TREE_CODE ($2.value) == IDENTIFIER_NODE) + { + undeclared_variable ($2.value); + $2.value = error_mark_node; + } + $$.value = c_sizeof (TREE_TYPE ($2.value)); + $$.original_code = ERROR_MARK; } + | sizeof '(' typename ')' %prec HYPERUNARY + { skip_evaluation--; + $$.value = c_sizeof (groktypename ($3)); + $$.original_code = ERROR_MARK; } + | alignof cw_asm_unary_expr %prec UNARY + { skip_evaluation--; + $$.value = c_alignof_expr ($2.value); + $$.original_code = ERROR_MARK; } + | alignof '(' typename ')' %prec HYPERUNARY + { skip_evaluation--; + $$.value = c_alignof (groktypename ($3)); + $$.original_code = ERROR_MARK; } + ; + +cw_asm_primary: + IDENTIFIER + { + if (yychar == YYEMPTY) + yychar = YYLEX; + $$.value = build_external_ref ($1, yychar == '('); + $$.original_code = ERROR_MARK; + } + | '@' IDENTIFIER + { + tree atsignid = prepend_char_identifier ($2, '@'); + if (yychar == YYEMPTY) + yychar = YYLEX; + $$.value = build_external_ref (atsignid, yychar == '('); + $$.original_code = ERROR_MARK; + } + | CONSTANT + { $$.value = $1; $$.original_code = ERROR_MARK; } + | STRING + { $$.value = $1; $$.original_code = STRING_CST; } + | '(' cw_asm_expr_no_commas ')' + { char class = TREE_CODE_CLASS (TREE_CODE ($2.value)); + if (IS_EXPR_CODE_CLASS (class)) + $2.original_code = ERROR_MARK; + $$ = $2; } + | '(' error ')' + { $$.value = error_mark_node; $$.original_code = ERROR_MARK; } + | cw_asm_primary '[' cw_asm_expr_no_commas ']' %prec '.' + { $$.value = build_array_ref ($1.value, $3.value); + $$.original_code = ERROR_MARK; } + | TYPENAME '.' identifier + { $$.value = cw_asm_c_build_component_ref ($1, $3); + $$.original_code = ERROR_MARK; } + | cw_asm_primary '.' identifier + { $$.value = cw_asm_c_build_component_ref ($1.value, $3); + $$.original_code = ERROR_MARK; } + | cw_asm_primary POINTSAT identifier + { + tree expr = build_indirect_ref ($1.value, "->"); + $$.value = build_component_ref (expr, $3); + $$.original_code = ERROR_MARK; + } + ; +/* APPLE LOCAL end CW asm blocks */ /* This is what appears inside the parens in a function declarator. Its value is a list of ..._TYPE nodes. Attributes must appear here @@ -3110,6 +3399,8 @@ static const struct resword reswords[] = { "__inline", RID_INLINE, 0 }, { "__inline__", RID_INLINE, 0 }, { "__label__", RID_LABEL, 0 }, + /* APPLE LOCAL private extern */ + { "__private_extern__", RID_PRIVATE_EXTERN, 0 }, { "__real", RID_REALPART, 0 }, { "__real__", RID_REALPART, 0 }, { "__restrict", RID_RESTRICT, 0 }, @@ -3191,9 +3482,12 @@ static const struct resword reswords[] = }; #define N_reswords (sizeof reswords / sizeof (struct resword)) +/* APPLE LOCAL begin keep tables in sync comment */ /* Table mapping from RID_* constants to yacc token numbers. Unfortunately we have to have entries for all the keywords in all - three languages. */ + three languages (AND THEY MUST BE KEPT IN PARALLEL - see also + cp/lex.c). */ +/* APPLE LOCAL end keep tables in sync comment */ static const short rid_to_yy[RID_MAX] = { /* RID_STATIC */ STATIC, @@ -3213,6 +3507,8 @@ static const short rid_to_yy[RID_MAX] = /* C extensions */ /* RID_COMPLEX */ TYPESPEC, /* RID_THREAD */ SCSPEC, + /* APPLE LOCAL private extern */ + /* RID_PRIVATE_EXTERN */ SCSPEC, /* C++ */ /* RID_FRIEND */ 0, @@ -3373,8 +3669,30 @@ yylexname (void) && (!OBJC_IS_PQ_KEYWORD (rid_code) || objc_pq_context)) @@end_ifobjc { + /* APPLE LOCAL begin CW asm blocks */ + /* Outside of function bodies, "asm" either indicates a CW asm + function, or a GNU asm statement, which must be immediately + followed by '(', so sniff the next token to see which kind + must be meant, and change the CW keyword to a different + token type so we don't have grammar problems. */ + int yycode = rid_to_yy[(int) rid_code]; + if (yycode == ASM_KEYWORD && current_function_decl == NULL) + { + tree next_tok; + /* Take a sneak peek at the next token in the stream. */ + enum cpp_ttype next_tok_type = c_lex (&next_tok); + /* Now put it back. */ + _cpp_backup_tokens (parse_in, 1); + /* Change the code. No need to change the name though, + won't matter to parser. */ + if (next_tok_type != CPP_OPEN_PAREN) + yycode = CW_ASM_KEYWORD; + } + /* APPLE LOCAL end CW asm blocks */ /* Return the canonical spelling for this keyword. */ yylval.ttype = ridpointers[(int) rid_code]; + /* APPLE LOCAL CW asm blocks */ + return yycode; return rid_to_yy[(int) rid_code]; } } @@ -3465,6 +3783,14 @@ _yylex (void) case CPP_CLOSE_PAREN: OBJC_NEED_RAW_IDENTIFIER (0); return ')'; case CPP_SEMICOLON: OBJC_NEED_RAW_IDENTIFIER (0); return ';'; + /* APPLE LOCAL begin CW asm blocks */ + case CPP_ATSIGN: + /* If we're doing CW assembly, return this as a regular token + (indicates labels). */ + if (cw_asm_state >= cw_asm_decls) + return '@'; + /* APPLE LOCAL end CW asm blocks */ + case CPP_EOF: return 0; @@ -3484,6 +3810,15 @@ _yylex (void) case CPP_WSTRING: return STRING; + /* APPLE LOCAL begin CW asm blocks */ + /* Convert a lexer-returned beginning-of-line token into a + parser token. */ + case CPP_BOL: + return CW_ASM_BOL; + case CPP_EOL: + return CW_ASM_EOL; + /* APPLE LOCAL end CW asm blocks */ + case CPP_OBJC_STRING: return OBJC_STRING; |