| /* Build executable statement trees. |
| Copyright (C) 2000, 2001, 2002, 2004, 2005, 2006 |
| Free Software Foundation, Inc. |
| Contributed by Andy Vaught |
| |
| This file is part of GCC. |
| |
| 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 2, 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 COPYING. If not, write to the Free |
| Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA |
| 02110-1301, USA. */ |
| |
| /* Executable statements are strung together into a singly linked list |
| of code structures. These structures are later translated into GCC |
| GENERIC tree structures and from there to executable code for a |
| target. */ |
| |
| #include "config.h" |
| #include "system.h" |
| #include "gfortran.h" |
| |
| gfc_code new_st; |
| |
| |
| /* Zeroes out the new_st structure. */ |
| |
| void |
| gfc_clear_new_st (void) |
| { |
| |
| memset (&new_st, '\0', sizeof (new_st)); |
| new_st.op = EXEC_NOP; |
| } |
| |
| |
| /* Get a gfc_code structure. */ |
| |
| gfc_code * |
| gfc_get_code (void) |
| { |
| gfc_code *c; |
| |
| c = gfc_getmem (sizeof (gfc_code)); |
| c->loc = gfc_current_locus; |
| return c; |
| } |
| |
| |
| /* Given some part of a gfc_code structure, append a set of code to |
| its tail, returning a pointer to the new tail. */ |
| |
| gfc_code * |
| gfc_append_code (gfc_code * tail, gfc_code * new) |
| { |
| |
| if (tail != NULL) |
| { |
| while (tail->next != NULL) |
| tail = tail->next; |
| |
| tail->next = new; |
| } |
| |
| while (new->next != NULL) |
| new = new->next; |
| |
| return new; |
| } |
| |
| |
| /* Free a single code structure, but not the actual structure itself. */ |
| |
| void |
| gfc_free_statement (gfc_code * p) |
| { |
| |
| if (p->expr) |
| gfc_free_expr (p->expr); |
| if (p->expr2) |
| gfc_free_expr (p->expr2); |
| |
| switch (p->op) |
| { |
| case EXEC_NOP: |
| case EXEC_ASSIGN: |
| case EXEC_INIT_ASSIGN: |
| case EXEC_GOTO: |
| case EXEC_CYCLE: |
| case EXEC_RETURN: |
| case EXEC_IF: |
| case EXEC_PAUSE: |
| case EXEC_STOP: |
| case EXEC_EXIT: |
| case EXEC_WHERE: |
| case EXEC_IOLENGTH: |
| case EXEC_POINTER_ASSIGN: |
| case EXEC_DO_WHILE: |
| case EXEC_CONTINUE: |
| case EXEC_TRANSFER: |
| case EXEC_LABEL_ASSIGN: |
| case EXEC_ENTRY: |
| case EXEC_ARITHMETIC_IF: |
| break; |
| |
| case EXEC_CALL: |
| case EXEC_ASSIGN_CALL: |
| gfc_free_actual_arglist (p->ext.actual); |
| break; |
| |
| case EXEC_SELECT: |
| if (p->ext.case_list) |
| gfc_free_case_list (p->ext.case_list); |
| break; |
| |
| case EXEC_DO: |
| gfc_free_iterator (p->ext.iterator, 1); |
| break; |
| |
| case EXEC_ALLOCATE: |
| case EXEC_DEALLOCATE: |
| gfc_free_alloc_list (p->ext.alloc_list); |
| break; |
| |
| case EXEC_OPEN: |
| gfc_free_open (p->ext.open); |
| break; |
| |
| case EXEC_CLOSE: |
| gfc_free_close (p->ext.close); |
| break; |
| |
| case EXEC_BACKSPACE: |
| case EXEC_ENDFILE: |
| case EXEC_REWIND: |
| case EXEC_FLUSH: |
| gfc_free_filepos (p->ext.filepos); |
| break; |
| |
| case EXEC_INQUIRE: |
| gfc_free_inquire (p->ext.inquire); |
| break; |
| |
| case EXEC_READ: |
| case EXEC_WRITE: |
| gfc_free_dt (p->ext.dt); |
| break; |
| |
| case EXEC_DT_END: |
| /* The ext.dt member is a duplicate pointer and doesn't need to |
| be freed. */ |
| break; |
| |
| case EXEC_FORALL: |
| gfc_free_forall_iterator (p->ext.forall_iterator); |
| break; |
| |
| case EXEC_OMP_DO: |
| case EXEC_OMP_END_SINGLE: |
| case EXEC_OMP_PARALLEL: |
| case EXEC_OMP_PARALLEL_DO: |
| case EXEC_OMP_PARALLEL_SECTIONS: |
| case EXEC_OMP_SECTIONS: |
| case EXEC_OMP_SINGLE: |
| case EXEC_OMP_WORKSHARE: |
| case EXEC_OMP_PARALLEL_WORKSHARE: |
| gfc_free_omp_clauses (p->ext.omp_clauses); |
| break; |
| |
| case EXEC_OMP_CRITICAL: |
| gfc_free ((char *) p->ext.omp_name); |
| break; |
| |
| case EXEC_OMP_FLUSH: |
| gfc_free_namelist (p->ext.omp_namelist); |
| break; |
| |
| case EXEC_OMP_ATOMIC: |
| case EXEC_OMP_BARRIER: |
| case EXEC_OMP_MASTER: |
| case EXEC_OMP_ORDERED: |
| case EXEC_OMP_END_NOWAIT: |
| break; |
| |
| default: |
| gfc_internal_error ("gfc_free_statement(): Bad statement"); |
| } |
| } |
| |
| |
| /* Free a code statement and all other code structures linked to it. */ |
| |
| void |
| gfc_free_statements (gfc_code * p) |
| { |
| gfc_code *q; |
| |
| for (; p; p = q) |
| { |
| q = p->next; |
| |
| if (p->block) |
| gfc_free_statements (p->block); |
| gfc_free_statement (p); |
| gfc_free (p); |
| } |
| } |
| |