--- gcc/config/vax/vax.c 2018/04/24 18:10:25 1.1 +++ gcc/config/vax/vax.c 2018/04/24 18:30:01 1.1.1.3 @@ -1,5 +1,5 @@ /* Subroutines for insn-output.c for Vax. - Copyright (C) 1987 Free Software Foundation, Inc. + Copyright (C) 1987, 1994, 1995 Free Software Foundation, Inc. This file is part of GNU CC. @@ -15,7 +15,8 @@ GNU General Public License for more deta You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ #include #include "config.h" @@ -28,7 +29,9 @@ the Free Software Foundation, 675 Mass A #include "insn-flags.h" #include "output.h" #include "insn-attr.h" - +#ifdef VMS_TARGET +#include "tree.h" +#endif /* This is like nonimmediate_operand with a restriction on the type of MEM. */ @@ -451,7 +454,6 @@ vax_rtx_cost (x) case FIX: c = 7; /* 17 on VAX 2 */ break; - case LSHIFT: case ASHIFT: case LSHIFTRT: case ASHIFTRT: @@ -593,12 +595,12 @@ static REAL_VALUE_TYPE float_values[4]; static int inited_float_values = 0; -void -check_float_value (mode, d) +int +check_float_value (mode, d, overflow) enum machine_mode mode; REAL_VALUE_TYPE *d; + int overflow; { - if (inited_float_values == 0) { int i; @@ -606,7 +608,14 @@ check_float_value (mode, d) { float_values[i] = REAL_VALUE_ATOF (float_strings[i], DFmode); } - inited_float_values = 1; + + inited_float_values = 1; + } + + if (overflow) + { + bcopy (&float_values[0], d, sizeof (REAL_VALUE_TYPE)); + return 1; } if ((mode) == SFmode) @@ -615,60 +624,131 @@ check_float_value (mode, d) bcopy (d, &r, sizeof (REAL_VALUE_TYPE)); if (REAL_VALUES_LESS (float_values[0], r)) { - error ("magnitude of constant too large for `float'"); bcopy (&float_values[0], d, sizeof (REAL_VALUE_TYPE)); + return 1; } else if (REAL_VALUES_LESS (r, float_values[1])) { - error ("magnitude of constant too large for `float'"); bcopy (&float_values[1], d, sizeof (REAL_VALUE_TYPE)); + return 1; } else if (REAL_VALUES_LESS (dconst0, r) && REAL_VALUES_LESS (r, float_values[2])) { - warning ("`float' constant truncated to zero"); bcopy (&dconst0, d, sizeof (REAL_VALUE_TYPE)); + return 1; } else if (REAL_VALUES_LESS (r, dconst0) && REAL_VALUES_LESS (float_values[3], r)) { - warning ("`float' constant truncated to zero"); bcopy (&dconst0, d, sizeof (REAL_VALUE_TYPE)); + return 1; } } + + return 0; } +#ifdef VMS_TARGET +/* Additional support code for VMS target. */ + /* Linked list of all externals that are to be emitted when optimizing for the global pointer if they haven't been declared by the end of the program with an appropriate .comm or initialization. */ +static struct extern_list { struct extern_list *next; /* next external */ char *name; /* name of the external */ -} *extern_head = 0; + int size; /* external's actual size */ + int in_const; /* section type flag */ +} *extern_head = 0, *pending_head = 0; -/* Return 1 if NAME has already had an external definition; - 0 if it has not (so caller should output one). */ +/* Check whether NAME is already on the external definition list. If not, + add it to either that list or the pending definition list. */ -int -vms_check_external (name) +void +vms_check_external (decl, name, pending) + tree decl; char *name; + int pending; { - register struct extern_list *p; + register struct extern_list *p, *p0; for (p = extern_head; p; p = p->next) if (!strcmp (p->name, name)) - return 1; + return; + + for (p = pending_head, p0 = 0; p; p0 = p, p = p->next) + if (!strcmp (p->name, name)) + { + if (pending) + return; + + /* Was pending, but has now been defined; move it to other list. */ + if (p == pending_head) + pending_head = p->next; + else + p0->next = p->next; + p->next = extern_head; + extern_head = p; + return; + } + /* Not previously seen; create a new list entry. */ p = (struct extern_list *)permalloc ((long) sizeof (struct extern_list)); - p->next = extern_head; p->name = name; - extern_head = p; - return 0; + + if (pending) + { + /* Save the size and section type and link to `pending' list. */ + p->size = (DECL_SIZE (decl) == 0) ? 0 : + TREE_INT_CST_LOW (size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl), + size_int (BITS_PER_UNIT))); + p->in_const = (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl)); + + p->next = pending_head; + pending_head = p; + } + else + { + /* Size and section type don't matter; link to `declared' list. */ + p->size = p->in_const = 0; /* arbitrary init */ + + p->next = extern_head; + extern_head = p; + } + return; +} + +void +vms_flush_pending_externals (file) + FILE *file; +{ + register struct extern_list *p; + + while (pending_head) + { + /* Move next pending declaration to the "done" list. */ + p = pending_head; + pending_head = p->next; + p->next = extern_head; + extern_head = p; + + /* Now output the actual declaration. */ + if (p->in_const) + const_section (); + else + data_section (); + fputs (".comm ", file); + assemble_name (file, p->name); + fprintf (file, ",%d\n", p->size); + } } +#endif /* VMS_TARGET */ #ifdef VMS -/* Additional support code for VMS. */ +/* Additional support code for VMS host. */ #ifdef QSORT_WORKAROUND /* @@ -677,7 +757,8 @@ vms_check_external (name) and is longword aligned, you cannot safely sort anything which is either not a multiple of 4 in size or not longword aligned. A static "move-by-longword" optimization flag inside qsort() is - never reset. This is known of affect VMS V4.6 through VMS V5.5-1. + never reset. This is known of affect VMS V4.6 through VMS V5.5-1, + and was finally fixed in VMS V5.5-2. In this work-around an insertion sort is used for simplicity. The qsort code from glibc should probably be used instead.