diff options
author | Richard Henderson <rth@redhat.com> | 2009-09-14 13:17:24 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2009-09-14 13:17:24 -0700 |
commit | 1c384bf142c81baaad7f04c5d3fdaebcbafc5b0c (patch) | |
tree | d43d66a4da24c2d77ee8f88fc747f6a2f149435f /gcc/cp/parser.c | |
parent | 40c88b9403ef1e2b2e93ff70a5fb794916027665 (diff) | |
download | gcc-1c384bf142c81baaad7f04c5d3fdaebcbafc5b0c.zip gcc-1c384bf142c81baaad7f04c5d3fdaebcbafc5b0c.tar.gz gcc-1c384bf142c81baaad7f04c5d3fdaebcbafc5b0c.tar.bz2 |
builtins.c (expand_builtin_synchronize): Use gimple_build_asm_vec.
* builtins.c (expand_builtin_synchronize): Use gimple_build_asm_vec.
* cfgbuild.c (make_edges): Handle asm goto.
* cfglayout.c (fixup_reorder_chain): Likewise.
* cfgrtl.c (patch_jump_insn): Likewise.
* gimple-pretty-print.c (dump_gimple_asm): Likewise.
* gimple.c (gimple_build_asm_1): Add and use nlabels parameter.
(gimple_build_asm_vec): Add and use labels parameter.
(gimple_build_asm): Remove.
(walk_gimple_asm): Walk labels too.
* gimple.def (GIMPLE_ASM): Update docs.
* gimple.h: Update decls.
(struct gimple_statement_asm): Change nc to use unsigned char;
add nl member.
(gimple_asm_nlabels): New.
(gimple_asm_label_op, gimple_asm_set_label_op): New.
* gimplify.c (gimplify_asm_expr): Copy labels from ASM_EXPR
into gimple_build_asm_vec.
* jump.c (mark_jump_label_asm): New.
(mark_jump_label): Use it.
(redirect_jump_1): Handle asm goto.
(invert_jump_1): Soft fail if X is null.
* recog.c (extract_asm_operands): New.
(asm_noperands): Use it; handle asm labels.
(decode_asm_operands): Use extract_asm_operands.
(asm_operand_ok): Properly handle empty string.
* reg-stack.c (get_asm_operands_in_out): Rename from
get_asm_operand_n_inputs; use extract_asm_operands; return both
inputs and outputs by reference; update all callers.
* rtl.def (ASM_OPERANDS): Add label vector as operand 6.
* rtl.h (ASM_OPERANDS_LABEL_VEC): New.
(ASM_OPERANDS_LABEL_LENGTH, ASM_OPERANDS_LABEL): New.
(ASM_OPERANDS_SOURCE_LOCATION): Renumber.
(extract_asm_operands): Declare.
* stmt.c (expand_asm_operands): Add and use labels parameter.
(check_unique_operand_names): Likewise.
(resolve_asm_operand_names, resolve_operand_name_1): Likewise.
(expand_asm_stmt): Handle asm labels.
* tree-cfg.c (make_gimple_asm_edges): New.
(make_edges): Use it.
(cleanup_dead_labels): Handle asm labels.
(is_ctrl_altering_stmt): Likewise.
(gimple_redirect_edge_and_branch): Likewise.
* tree.def (ASM_EXPR): Add 5th operand.
* tree.h (ASM_LABELS): New.
(resolve_asm_operand_names): Update decl.
* c-parser.c (c_parser_asm_statement): Parse asm goto.
(c_parser_asm_goto_operands): New.
* c-tree.h (build_asm_expr): Update decl.
* c-typeck.c (build_asm_expr): Add and use labels parameter.
* doc/extend.texi: Document asm goto.
gcc/ada/
* gcc-interface/trans.c (Pragma_to_gnu): Use build5 for ASM_EXPR.
gcc/cp/
* cp-tree.h (finish_asm_stmt): Update decl.
* parser.c (cp_parser_asm_definition): Parse asm goto.
(cp_parser_asm_label_list): New.
* pt.c (tsubst_copy_asm_operands): Don't recurse on labels.
(tsubst_expr): Handle asm labels.
* semantics.c (finish_asm_stmt): Add and use labels parameter.
gcc/testsuite/
* c-c++-common/asmgoto-1.c, c-c++-common/asmgoto-2.c,
c-c++-common/asmgoto-3.c, gcc.c-torture/compile/asmgoto-1.c,
gcc.dg/tree-ssa/asmgoto-1.c: New files.
Co-Authored-By: Jakub Jelinek <jakub@redhat.com>
From-SVN: r151701
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r-- | gcc/cp/parser.c | 99 |
1 files changed, 94 insertions, 5 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 14733b8..55effed 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1859,6 +1859,8 @@ static tree cp_parser_asm_operand_list (cp_parser *); static tree cp_parser_asm_clobber_list (cp_parser *); +static tree cp_parser_asm_label_list + (cp_parser *); static tree cp_parser_attributes_opt (cp_parser *); static tree cp_parser_attribute_list @@ -12531,7 +12533,10 @@ cp_parser_using_directive (cp_parser* parser) : asm-operand-list [opt] ) ; asm volatile [opt] ( string-literal : asm-operand-list [opt] : asm-operand-list [opt] - : asm-operand-list [opt] ) ; */ + : asm-clobber-list [opt] ) ; + asm volatile [opt] goto ( string-literal : : asm-operand-list [opt] + : asm-clobber-list [opt] + : asm-goto-list ) ; */ static void cp_parser_asm_definition (cp_parser* parser) @@ -12540,11 +12545,14 @@ cp_parser_asm_definition (cp_parser* parser) tree outputs = NULL_TREE; tree inputs = NULL_TREE; tree clobbers = NULL_TREE; + tree labels = NULL_TREE; tree asm_stmt; bool volatile_p = false; bool extended_p = false; bool invalid_inputs_p = false; bool invalid_outputs_p = false; + bool goto_p = false; + const char *missing = NULL; /* Look for the `asm' keyword. */ cp_parser_require_keyword (parser, RID_ASM, "%<asm%>"); @@ -12557,6 +12565,15 @@ cp_parser_asm_definition (cp_parser* parser) /* Consume the token. */ cp_lexer_consume_token (parser->lexer); } + if (cp_parser_allow_gnu_extensions_p (parser) + && parser->in_function_body + && cp_lexer_next_token_is_keyword (parser->lexer, RID_GOTO)) + { + /* Remember that we saw the `goto' keyword. */ + goto_p = true; + /* Consume the token. */ + cp_lexer_consume_token (parser->lexer); + } /* Look for the opening `('. */ if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>")) return; @@ -12581,6 +12598,7 @@ cp_parser_asm_definition (cp_parser* parser) { bool inputs_p = false; bool clobbers_p = false; + bool labels_p = false; /* The extended syntax was used. */ extended_p = true; @@ -12596,7 +12614,8 @@ cp_parser_asm_definition (cp_parser* parser) && cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE) && cp_lexer_next_token_is_not (parser->lexer, - CPP_CLOSE_PAREN)) + CPP_CLOSE_PAREN) + && !goto_p) outputs = cp_parser_asm_operand_list (parser); if (outputs == error_mark_node) @@ -12618,6 +12637,8 @@ cp_parser_asm_definition (cp_parser* parser) if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON) && cp_lexer_next_token_is_not (parser->lexer, + CPP_SCOPE) + && cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)) inputs = cp_parser_asm_operand_list (parser); @@ -12632,16 +12653,41 @@ cp_parser_asm_definition (cp_parser* parser) if (clobbers_p || cp_lexer_next_token_is (parser->lexer, CPP_COLON)) { + clobbers_p = true; /* Consume the `:' or `::'. */ cp_lexer_consume_token (parser->lexer); /* Parse the clobbers. */ if (cp_lexer_next_token_is_not (parser->lexer, - CPP_CLOSE_PAREN)) + CPP_COLON) + && cp_lexer_next_token_is_not (parser->lexer, + CPP_CLOSE_PAREN)) clobbers = cp_parser_asm_clobber_list (parser); } + else if (goto_p + && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE)) + /* The labels are coming next. */ + labels_p = true; + + /* Look for labels. */ + if (labels_p + || (goto_p && cp_lexer_next_token_is (parser->lexer, CPP_COLON))) + { + labels_p = true; + /* Consume the `:' or `::'. */ + cp_lexer_consume_token (parser->lexer); + /* Parse the labels. */ + labels = cp_parser_asm_label_list (parser); + } + + if (goto_p && !labels_p) + missing = clobbers_p ? "%<:%>" : "%<:%> or %<::%>"; } + else if (goto_p) + missing = "%<:%> or %<::%>"; + /* Look for the closing `)'. */ - if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>")) + if (!cp_parser_require (parser, missing ? CPP_COLON : CPP_CLOSE_PAREN, + missing ? missing : "%<)%>")) cp_parser_skip_to_closing_parenthesis (parser, true, false, /*consume_paren=*/true); cp_parser_require (parser, CPP_SEMICOLON, "%<;%>"); @@ -12652,7 +12698,7 @@ cp_parser_asm_definition (cp_parser* parser) if (parser->in_function_body) { asm_stmt = finish_asm_stmt (volatile_p, string, outputs, - inputs, clobbers); + inputs, clobbers, labels); /* If the extended syntax was not used, mark the ASM_EXPR. */ if (!extended_p) { @@ -16866,6 +16912,49 @@ cp_parser_asm_clobber_list (cp_parser* parser) return clobbers; } +/* Parse an asm-label-list. + + asm-label-list: + identifier + asm-label-list , identifier + + Returns a TREE_LIST, indicating the labels in the order that they + appeared. The TREE_VALUE of each node is a label. */ + +static tree +cp_parser_asm_label_list (cp_parser* parser) +{ + tree labels = NULL_TREE; + + while (true) + { + tree identifier, label, name; + + /* Look for the identifier. */ + identifier = cp_parser_identifier (parser); + if (!error_operand_p (identifier)) + { + label = lookup_label (identifier); + if (TREE_CODE (label) == LABEL_DECL) + { + TREE_USED (label) = 1; + check_goto (label); + name = build_string (IDENTIFIER_LENGTH (identifier), + IDENTIFIER_POINTER (identifier)); + labels = tree_cons (name, label, labels); + } + } + /* If the next token is not a `,', then the list is + complete. */ + if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) + break; + /* Consume the `,' token. */ + cp_lexer_consume_token (parser->lexer); + } + + return nreverse (labels); +} + /* Parse an (optional) series of attributes. attributes: |