-
- Downloads
c: Implement C2Y N3355 - Named Loops [PR117022]
The following patch implements the C2Y N3355 - Named Loops paper. I've tried to implement it lazily, rather than proactively e.g. push labels to a vector just in case the following statement is iteration statement, switch statement or one of the loop pragmas followed by iteration statement the patch just notes the last statement in cur_stmt_list if any before c_parser_label/c_parser_all_labels and passes it down to the iteration/switch statement parsing routines, which then search backward for LABEL_EXPRs before they reach the given stop statement. The patch then adds one extra argument to {FOR,WHILE,DO,BREAK,CONTINUE,SWITCH}_STMT, which is set to a canonical name LABEL_DECL (the last named label before the construct). If one just refers to the innermost construct with a fancy name, it is in the end parsed the same as break/continue without an identifier (i.e. NULL_TREE argument), and if a loop or switch has name(s) but break/continue to that isn't used, the name is set to NULL_TREE. At c-gimplify.cc time the name is then pushed into a hash map mapping it to a pair of labels. I've implemented it also for ObjC foreach loops (which have break/continue handled during parsing, not during c-gimplify.cc). As for OpenMP/OpenACC, the patch right now pretends no OpenMP loop has a name, until something different is decided in the standard. As shown in the testcases, most break identifier/continue identifier cases aren't really useful in OpenMP code, a break identifier or continue identifier jumping out of an OpenMP region is certainly invalid (such regions have to be single entry single exit, so escaping it through goto/break lab/continue lab violates that), similarly break is disallowed in the innermost OpenMP nested loop, just continue is allowed, so the only thing that would make sense for OpenMP (second gomp testcase) would be allowing to give name to the innermost loop in OpenMP canonical loop nest (except that labels aren't allowed in the syntax right now in between the loops) and only continue to that label. For collapse(1) loops that would be a label before the #pragma or [[omp::directive (parallel for)]] etc. And of course, what already works fine in the patch is break/continue to non-OpenMP loops nested in OpenMP loops. 2024-10-12 Jakub Jelinek <jakub@redhat.com> PR c/117022 gcc/c-family/ * c-common.def (FOR_STMT, WHILE_STMT, DO_STMT, BREAK_STMT, CONTINUE_STMT, SWITCH_STMT): Add an extra operand, *_NAME and document it. * c-common.h (bc_hash_map_t): New typedef. (struct bc_state): Add bc_hash_map member. (WHILE_NAME, DO_NAME, FOR_NAME, BREAK_NAME, CONTINUE_NAME, SWITCH_STMT_NAME): Define. * c-pretty-print.cc (c_pretty_printer::statement): Print BREAK_STMT or CONTINUE_STMT operand if any. * c-gimplify.cc (bc_hash_map): New static variable. (note_named_bc, release_named_bc): New functions. (save_bc_state): Save and clear bc_hash_map. (restore_bc_state): Assert NULL and restore bc_hash_map. (genericize_c_loop): Add NAME argument, call note_named_bc and release_named_bc if non-NULL around the body walk. (genericize_for_stmt, genericize_while_stmt, genericize_do_stmt): Adjust callers of it. (genericize_switch_stmt): Rename break_block variable to blab. Call note_named_bc and release_named_bc if SWITCH_STMT_NAME is non-NULL around the body walk. (genericize_continue_stmt): Handle non-NULL CONTINUE_NAME. (genericize_break_stmt): Handle non-NULL BREAK_NAME. (c_genericize): Delete and clear bc_hash_map. gcc/c/ * c-tree.h: Implement C2Y N3355 - Named loops. (C_DECL_LOOP_NAME, C_DECL_SWITCH_NAME, C_DECL_LOOP_SWITCH_NAME_VALID, C_DECL_LOOP_SWITCH_NAME_USED, IN_NAMED_STMT): Define. (c_get_loop_names, c_release_loop_names, c_finish_bc_name): Declare. (c_start_switch): Add NAME argument. (c_finish_bc_stmt): Likewise. * c-lang.h (struct language_function): Add loop_names and loop_names_hash members. * c-parser.cc (c_parser_external_declaration, c_parser_declaration_or_fndef, c_parser_struct_or_union_specifier, c_parser_parameter_declaration): Adjust c_parser_pragma caller. (get_before_labels): New function. (c_parser_compound_statement_nostart): Call get_before_labels when needed, adjust c_parser_pragma and c_parser_statement_after_labels callers. (c_parser_statement): Call get_before_labels first and pass it to c_parser_statement_after_labels. (c_parser_bc_name): New function. (c_parser_statement_after_labels): Add BEFORE_LABELS argument. Pass it down to c_parser_switch_statement, c_parser_while_statement, c_parser_do_statement, c_parser_for_statement and c_parser_pragma. Call c_parser_bc_name for RID_BREAK and RID_CONTINUE and pass it as another argument to c_finish_bc_stmt. (c_parser_if_body, c_parser_else_body): Call get_before_labels early and pass it to c_parser_statement_after_labels. (c_parser_switch_statement): Add BEFORE_LABELS argument. Call c_get_loop_names, if named, pass switch_name to c_start_switch, mark it valid and set IN_NAMED_STMT bit in in_statement before parsing body, otherwise clear IN_NAMED_STMT bit before that parsing. Run c_release_loop_names at the end. (c_parser_while_statement, c_parser_do_statement, c_parser_for_statement): Add BEFORE_LABELS argument. Call c_get_loop_names, if named, mark it valid and set IN_NAMED_STMT bit in in_statement before parsing body, otherwise clear IN_NAMED_STMT before that parsing, arrange for the loop name if used to be another *_STMT argument. (c_parser_objc_class_instance_variables, c_parser_objc_methodprotolist): Adjust c_parser_pragma callers. (c_parser_pragma): Add BEFORE_LABELS argument. Pass it down to c_parser_for_statement, c_parser_while_statement or c_parser_do_statement. (c_parser_omp_loop_nest, c_maybe_parse_omp_decl): Adjust c_parser_pragma callers. * c-decl.cc (loop_names, loop_names_hash): New static variables. (add_stmt): Set STATEMENT_LIST_HAS_LABEL after push_stmt_list rather than before it. (c_push_function_context): Save and clear loop_names and loop_names_hash. (c_pop_function_context): Release or delete, restore and clear loop_names and loop_names_hash. (c_get_loop_names, c_release_loop_names, c_finish_bc_name): New functions. * c-typeck.cc (c_start_switch): Add SWITCH_NAME argument, pass it down to build_stmt. (c_finish_bc_stmt): Add NAME argument. Mark of IN_NAMED_STMT bit of in_statement in swtiches. Use label for IN_OBJC_FOREACH only if name is NULL. If name is non-NULL and C_DECL_LOOP_NAME and C_DECL_SWITCH_NAME are both set, assume outer ObjC foreach and dig labels from DECL_CHAIN of name. Pass NAME to build_stmt otherwise. gcc/cp/ * semantics.cc (begin_while_stmt, begin_do_stmt, begin_for_stmt, finish_break_stmt, finish_continue_stmt, begin_switch_stmt): Pass another NULL_TREE to build_stmt calls. gcc/testsuite/ * gcc.dg/c23-named-loops-1.c: New test. * gcc.dg/c23-named-loops-5.c: New test. * gcc.dg/c2y-named-loops-1.c: New test. * gcc.dg/c2y-named-loops-2.c: New test. * gcc.dg/c2y-named-loops-4.c: New test. * gcc.dg/c2y-named-loops-5.c: New test. * gcc.dg/c2y-named-loops-6.c: New test. * gcc.dg/c2y-named-loops-7.c: New test. * gcc.dg/gnu99-named-loops-1.c: New test. * gcc.dg/gnu99-named-loops-2.c: New test. * gcc.dg/gnu99-named-loops-3.c: New test. * gcc.dg/gnu99-named-loops-4.c: New test. * gcc.dg/gnu2y-named-loops-3.c: New test. * gcc.dg/gomp/named-loops-1.c: New test. * gcc.dg/gomp/named-loops-2.c: New test. * objc.dg/named-loops-1.m: New test.
Showing
- gcc/c-family/c-common.def 18 additions, 15 deletionsgcc/c-family/c-common.def
- gcc/c-family/c-common.h 20 additions, 6 deletionsgcc/c-family/c-common.h
- gcc/c-family/c-gimplify.cc 76 additions, 16 deletionsgcc/c-family/c-gimplify.cc
- gcc/c-family/c-pretty-print.cc 16 additions, 1 deletiongcc/c-family/c-pretty-print.cc
- gcc/c/c-decl.cc 230 additions, 3 deletionsgcc/c/c-decl.cc
- gcc/c/c-lang.h 2 additions, 0 deletionsgcc/c/c-lang.h
- gcc/c/c-parser.cc 185 additions, 46 deletionsgcc/c/c-parser.cc
- gcc/c/c-tree.h 27 additions, 3 deletionsgcc/c/c-tree.h
- gcc/c/c-typeck.cc 17 additions, 7 deletionsgcc/c/c-typeck.cc
- gcc/cp/semantics.cc 8 additions, 6 deletionsgcc/cp/semantics.cc
- gcc/testsuite/gcc.dg/c23-named-loops-1.c 144 additions, 0 deletionsgcc/testsuite/gcc.dg/c23-named-loops-1.c
- gcc/testsuite/gcc.dg/c23-named-loops-5.c 5 additions, 0 deletionsgcc/testsuite/gcc.dg/c23-named-loops-5.c
- gcc/testsuite/gcc.dg/c2y-named-loops-1.c 144 additions, 0 deletionsgcc/testsuite/gcc.dg/c2y-named-loops-1.c
- gcc/testsuite/gcc.dg/c2y-named-loops-2.c 45 additions, 0 deletionsgcc/testsuite/gcc.dg/c2y-named-loops-2.c
- gcc/testsuite/gcc.dg/c2y-named-loops-4.c 159 additions, 0 deletionsgcc/testsuite/gcc.dg/c2y-named-loops-4.c
- gcc/testsuite/gcc.dg/c2y-named-loops-5.c 5 additions, 0 deletionsgcc/testsuite/gcc.dg/c2y-named-loops-5.c
- gcc/testsuite/gcc.dg/c2y-named-loops-6.c 32 additions, 0 deletionsgcc/testsuite/gcc.dg/c2y-named-loops-6.c
- gcc/testsuite/gcc.dg/c2y-named-loops-7.c 32 additions, 0 deletionsgcc/testsuite/gcc.dg/c2y-named-loops-7.c
- gcc/testsuite/gcc.dg/gnu2y-named-loops-3.c 117 additions, 0 deletionsgcc/testsuite/gcc.dg/gnu2y-named-loops-3.c
- gcc/testsuite/gcc.dg/gnu99-named-loops-1.c 144 additions, 0 deletionsgcc/testsuite/gcc.dg/gnu99-named-loops-1.c
Loading
Please register or sign in to comment