/* Check dynamic stack usage in serial clauses. Copyright (C) 2025 Jose E. Marchesi. Written by Jose E. Marchesi. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see . */ /* This file implements a phase that determines what serial clauses contain phrases whose elaboration may involve dynamic stack allocation. It annotates the SERIAL_CLAUSE parse nodes by setting the DYNAMIC_STACK_ALLOCS flag. */ #include "config.h" #include "system.h" #include "coretypes.h" #include "options.h" #include "a68.h" /* Uncomment the following line for debugging traces. */ /* #define SERIAL_DSA_DEBUG */ static void serial_dsa_check_serial_clause (NODE_T *p, bool *dsa) { for (; p != NO_NODE; FORWARD (p)) { if (IS (p, GENERATOR)) { /* LOC generators always result in dyamic stack allocation regardless of the mode of the allocated value. */ if (IS (SUB (p), LOC_SYMBOL)) { #ifdef SERIAL_DSA_DEBUG fprintf (stderr, "serial_dsa: %s:%d: loc generator implies DSA\n", FILENAME (LINE (INFO (p))), LINE_NUMBER (p)); #endif *dsa = true; return; } } else if (IS (p, DEFINING_IDENTIFIER)) { /* Variable declarations of values with sample loc generators will result in dynamic stack allocation. Note that label declarations do no have a mode, so we have to check for MOID (p). */ if (MOID (p) != NO_MOID && IS_REF (MOID (p))) { bool heap = HEAP (TAX (p)) == HEAP_SYMBOL; if (HAS_ROWS (SUB (MOID (p))) && !heap) { #ifdef SERIAL_DSA_DEBUG fprintf (stderr, "serial_dsa: %s:%d: defining identifier %s implies DSA\n", FILENAME (LINE (INFO (p))), LINE_NUMBER (p), NSYMBOL (p)); #endif *dsa = true; return; } } } else { /* Inner serial clauses will take care of their own. Code in routine texts will not impact the stack of the containing serial clause. */ if (!IS (p, SERIAL_CLAUSE) && !IS (p, ROUTINE_TEXT)) serial_dsa_check_serial_clause (SUB (p), dsa); } } } void a68_serial_dsa (NODE_T *p) { for (; p != NO_NODE; FORWARD (p)) { a68_serial_dsa (SUB (p)); if (IS (p, SERIAL_CLAUSE)) { bool dsa = false; serial_dsa_check_serial_clause (SUB (p), &dsa); DYNAMIC_STACK_ALLOCS (p) = dsa; #ifdef SERIAL_DSA_DEBUG if (dsa) { fprintf (stderr, "serial_dsa: %s:%d: marking serial clause %p as DSA\n", FILENAME (LINE (INFO (p))), LINE_NUMBER (p), (void *) p); } #endif } } }