From a9918088423b3109a324d5818a830c59bc2504b0 Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Mon, 19 Sep 1994 16:36:31 +0000 Subject: [PATCH] more vms work from Pat Rankin --- gas/config/obj-vms.c | 502 +++++++++++++++++++++++++++---------------- gas/config/obj-vms.h | 89 ++++++-- 2 files changed, 395 insertions(+), 196 deletions(-) diff --git a/gas/config/obj-vms.c b/gas/config/obj-vms.c index 647067da5d0..3ff5718284b 100644 --- a/gas/config/obj-vms.c +++ b/gas/config/obj-vms.c @@ -1,5 +1,5 @@ /* vms.c -- Write out a VAX/VMS object file - Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc. + Copyright (C) 1987, 1988, 1992, 1994 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -191,6 +191,12 @@ static int final_pass; */ static int struct_number; +/* This is used to distinguish between D_float and G_float for telling + the debugger about doubles. gcc outputs the same .stabs regardless + of whether -mg is used to select alternate doubles. */ + +static int vax_g_doubles = 0; + /* * Variable descriptors are used tell the debugger the data types of certain @@ -322,7 +328,7 @@ const segT N_TYPE_seg[N_TYPE + 2] = * use with VMS. */ -char const_flag = 0; +char const_flag = IN_DEFAULT_SECTION; void s_const () @@ -366,7 +372,7 @@ vms_resolve_symbol_redef (sym) as_warn ("compiler redefined zero-size common symbol `%s'", S_GET_NAME (sym)); sym->sy_frag = frag_now; - S_GET_OTHER(sym) = const_flag; + S_SET_OTHER(sym, const_flag); S_SET_VALUE(sym, obstack_next_free(& frags) - frag_now->fr_literal); /* Keep N_EXT bit. */ sym->sy_symbol.n_type |= SEGMENT_TO_SYMBOL_TYPE((int) now_seg); @@ -376,6 +382,38 @@ vms_resolve_symbol_redef (sym) return 0; } +/* `tc_frob_label' handler for colon(symbols.c), used to examine the + dummy label(s) gcc inserts at the beginning of each file it generates. + gcc 1.x put "gcc_compiled."; gcc 2.x (as of 2.6) puts "gcc2_compiled." + and "__gnu_language_" and possibly "__vax__doubles". */ + +void +vms_check_for_special_label (symbolP) +symbolS *symbolP; +{ + /* Special labels only occur prior to explicit section directives. */ + if ((const_flag & IN_DEFAULT_SECTION) != 0) + { + char *sym_name = S_GET_NAME(symbolP); + + if (*sym_name == '_') + ++sym_name; + + if (!strcmp (sym_name, "__vax_g_doubles")) + vax_g_doubles = 1; +#if 0 /* not necessary */ + else if (!strcmp (sym_name, "__vax_d_doubles")) + vax_g_doubles = 0; +#endif +#if 0 /* these are potential alternatives to tc-vax.c's md_parse_options() */ + else if (!strcmp (sym_name, "gcc_compiled.")) + flag_one = 1; + else if (!strcmp (sym_name, "__gnu_language_cplusplus")) + flag_hash_long_names = 1; +#endif + } + return; +} void obj_read_begin_hook () @@ -932,7 +970,7 @@ VMS_TBT_Routine_End (Max_Size, sp) symbolS *symbolP; int Size = 0x7fffffff; char Local[16]; - + valueT sym_value, sp_value = S_GET_VALUE (sp); for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) { @@ -940,21 +978,27 @@ VMS_TBT_Routine_End (Max_Size, sp) { if (*S_GET_NAME (symbolP) == 'L') continue; - if ((S_GET_VALUE (symbolP) > S_GET_VALUE (sp)) && - (S_GET_VALUE (symbolP) < Size)) - Size = S_GET_VALUE (symbolP); + sym_value = S_GET_VALUE (symbolP); + if (sym_value > sp_value && sym_value < Size) + Size = sym_value; + + /* + * Dummy labels like "gcc_compiled." should no longer reach here. + */ +#if 0 + else /* check if gcc_compiled. has size of zero */ - if ((S_GET_VALUE (symbolP) == S_GET_VALUE (sp)) && + if (sym_value == sp_value && sp != symbolP && (!strcmp (S_GET_NAME (sp), "gcc_compiled.") || !strcmp (S_GET_NAME (sp), "gcc2_compiled."))) - Size = S_GET_VALUE (symbolP); - + Size = sym_value; +#endif } } if (Size == 0x7fffffff) Size = Max_Size; - Size -= S_GET_VALUE (sp); /* and get the size of the routine */ + Size -= sp_value; /* and get the size of the routine */ /* * Record Size */ @@ -1247,7 +1291,7 @@ VMS_TBT_Source_File (Filename, ID_Number) Status = sys$open (&Fab); if (!(Status & 1)) { - printf ("gas: Couldn't find source file \"%s\", Error = %%X%x\n", + printf ("gas: Couldn't find source file \"%s\", status=%%X%x\n", Filename, Status); return (0); } @@ -1467,7 +1511,7 @@ find_file (sp) /* This routine converts a number string into an integer, and stops when it - * sees an invalid character the return value is the address of the character + * sees an invalid character. The return value is the address of the character * just past the last character read. No error is generated. */ static char * @@ -1477,7 +1521,7 @@ cvt_integer (str, rtn) { int ival, neg; neg = *str == '-' ? ++str, -1 : 1; - ival = 0; /* first get the number of the type for dbx */ + ival = 0; while ((*str <= '9') && (*str >= '0')) ival = 10 * ival + *str++ - '0'; *rtn = neg * ival; @@ -1643,18 +1687,19 @@ array_suffix (spnt2) spnt1 = find_symbol (spnt1->type2); } total_size = total_size * spnt1->data_size; - push (spnt1->data_size, 2); + push (spnt1->data_size, 2); /* element size */ if (spnt1->VMS_type == DBG_S_C_ADVANCED_TYPE) push (0, 1); else - push (spnt1->VMS_type, 1); - push (4, 1); - for (i = 0; i < 6; i++) - push (0, 1); - push (0xc0, 1); - push (rank, 1); + push (spnt1->VMS_type, 1); /* element type */ + push (DSC_K_CLASS_A, 1); /* descriptor class */ + push (0, 4); /* base address */ + push (0, 1); /* scale factor -- not applicable */ + push (0, 1); /* digit count -- not applicable */ + push (0xc0, 1); /* flags: multiplier block & bounds present */ + push (rank, 1); /* number of dimensions */ push (total_size, 4); - push (0, 4); + push (0, 4); /* pointer to element [0][0]...[0] */ spnt1 = spnt; while (spnt1->advanced == ARRAY) { @@ -1673,7 +1718,7 @@ array_suffix (spnt2) /* this routine generates the start of a variable descriptor based upon * a struct/union/enum that has yet to be defined. We define this spot as * a new location, and save four bytes for the address. When the struct is - * finally defined, then we can go back and plug in the correct address + * finally defined, then we can go back and plug in the correct address. */ static new_forward_ref (dbx_type) @@ -1686,7 +1731,7 @@ new_forward_ref (dbx_type) fpnt->dbx_type = dbx_type; fpnt->struc_numb = ++structure_count; fpnt->resolved = 'N'; - push (3, -1); + push (DST_K_TS_IND, -1); /* indirect type specification */ total_len = 5; push (total_len, -2); struct_number = -fpnt->struc_numb; @@ -1723,7 +1768,8 @@ gen1 (spnt, array_suffix_len) return 1; } push (0, -4); - push (0xfa02, -2); + push (DST_K_VFLAGS_DSC, -1); + push (DST_K_TS_DSC, -1); /* descriptor type specification */ total_len = -2; return 1; case STRUCT: @@ -1742,7 +1788,7 @@ gen1 (spnt, array_suffix_len) case POINTER: spnt1 = find_symbol (spnt->type2); i = 1; - if (spnt1 == (struct VMS_DBG_Symbol *) NULL) + if (!spnt1) new_forward_ref (spnt->type2); else i = gen1 (spnt1, 0); @@ -1758,7 +1804,7 @@ gen1 (spnt, array_suffix_len) while (spnt1->advanced == ARRAY) { spnt1 = find_symbol (spnt1->type2); - if (spnt1 == (struct VMS_DBG_Symbol *) NULL) + if (!spnt1) { printf ("gcc-as warning(debugger output):"); printf ("Forward reference error, dbx type %d\n", @@ -1781,8 +1827,9 @@ gen1 (spnt, array_suffix_len) push (0, -2); total_len += 2; push (total_len, -2); - push (0xfa, -1); - push (0x0101, -2); + push (DST_K_VFLAGS_DSC, -1); + push (1, -1); /* flags: element value spec included */ + push (1, -1); /* one dimension */ push (DBG_S_C_COMPLEX_ARRAY, -1); } total_len += array_suffix_len + 8; @@ -1801,16 +1848,22 @@ generate_suffix (spnt, dbx_type) struct VMS_DBG_Symbol *spnt; int dbx_type; { + static CONST char pvoid[6] = { + 5, /* record.length == 5 */ + DST_K_TYPSPEC, /* record.type == 1 (type specification) */ + 0, /* name.length == 0, no name follows */ + 1, 0, /* type.length == 1 {2 bytes, little endian} */ + DBG_S_C_VOID /* type.type == 5 (pointer to unspecified) */ + }; int ilen; int i; - static CONST char pvoid[6] = {5, 0xaf, 0, 1, 0, 5}; struct VMS_DBG_Symbol *spnt1; Apoint = 0; Lpnt = MAX_DEBUG_RECORD - 1; total_len = 0; struct_number = 0; overflow = 0; - if (spnt == (struct VMS_DBG_Symbol *) NULL) + if (!spnt) new_forward_ref (dbx_type); else { @@ -1818,7 +1871,8 @@ generate_suffix (spnt, dbx_type) return 0; /* no suffix needed */ gen1 (spnt, 0); } - push (0x00af, -2); + push (0, -1); /* no name (len==0) */ + push (DST_K_TYPSPEC, -1); total_len += 4; push (total_len, -1); /* if the variable descriptor overflows the record, output a descriptor for @@ -1851,8 +1905,8 @@ generate_suffix (spnt, dbx_type) VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG); Lpnt = 0; VMS_Def_Struct (struct_number); - for (i = 0; i < 4; i++) - Local[Lpnt++] = 0; + COPY_LONG(&Local[Lpnt], 0L); + Lpnt += 4; VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG); Lpnt = 0; } @@ -1864,8 +1918,82 @@ generate_suffix (spnt, dbx_type) Lpnt = 0; } -/* This routine generates a symbol definition for a C sybmol for the debugger. - * It takes a psect and offset for global symbols - if psect < 0, then this is + /* "novel length" type doesn't work for simple atomic types */ +#define USE_BITSTRING_DESCRIPTOR(t) ((t)->advanced == BASIC) +#undef SETUP_BASIC_TYPES + +static void +bitfield_suffix (spnt, width) + struct VMS_DBG_Symbol *spnt; + int width; +{ + Local[Lpnt++] = 13; /* rec.len==13 */ + Local[Lpnt++] = DST_K_TYPSPEC; /* a type specification record */ + Local[Lpnt++] = 0; /* not named */ + COPY_SHORT(&Local[Lpnt], 9); /* typ.len==9 */ + Lpnt += 2; + Local[Lpnt++] = DST_K_TS_NOV_LENG; /* This type is a "novel length" + incarnation of some other type. */ + COPY_LONG(&Local[Lpnt], width); /* size in bits == novel length */ + Lpnt += 4; + VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG); + Lpnt = 0; + /* assert( spnt->struc_numb > 0 ); */ + VMS_Store_Struct (spnt->struc_numb); /* output 4 more bytes */ +} + +/* Formally define a builtin type, so that it can serve as the target of + an indirect reference. It makes bitfield_suffix() easier by avoiding + the need to use a forward reference for the first occurrence of each + type used in a bitfield. */ +static void +setup_basic_type (spnt) + struct VMS_DBG_Symbol *spnt; +{ +#ifdef SETUP_BASIC_TYPES + /* This would be very useful if "novel length" fields actually worked + with basic types like they do with enumerated types. However, + they do not, so this isn't worth doing just so that you can use + EXAMINE/TYPE=(__long_long_int) instead of EXAMINE/QUAD. */ + char *p; +#ifndef SETUP_SYNONYM_TYPES + /* This determines whether compatible things like `int' and `long int' + ought to have distinct type records rather than sharing one. */ + struct VMS_DBG_Symbol *spnt2; + + /* first check whether this type has already been seen by another name */ + for (spnt2 = VMS_Symbol_type_list; spnt2; spnt2 = spnt2->next) + if (spnt2 != spnt && spnt2->VMS_type == spnt->VMS_type) + { + spnt->struc_numb = spnt2->struc_numb; + return; + } +#endif + + /* `structure number' doesn't really mean `structure'; it means an index + into a linker maintained set of saved locations which can be referenced + again later. */ + spnt->struc_numb = ++structure_count; + VMS_Def_Struct (spnt->struc_numb); /* remember where this type lives */ + /* define the simple scalar type */ + Local[Lpnt++] = 6 + strlen (symbol_name) + 2; /* rec.len */ + Local[Lpnt++] = DST_K_TYPSPEC; /* rec.typ==type specification */ + Local[Lpnt++] = strlen (symbol_name) + 2; + Local[Lpnt++] = '_'; /* prefix name with "__" */ + Local[Lpnt++] = '_'; + for (p = symbol_name; *p; p++) + Local[Lpnt++] = *p == ' ' ? '_' : *p; + COPY_SHORT(&Local[Lpnt], 2); /* typ.len==2 */ + Lpnt += 2; + Local[Lpnt++] = DST_K_TS_ATOM; /* typ.kind is simple type */ + Local[Lpnt++] = spnt->VMS_type; /* typ.type */ + VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG); + Lpnt = 0; +#endif /* SETUP_BASIC_TYPES */ +} + +/* This routine generates a symbol definition for a C symbol for the debugger. + * It takes a psect and offset for global symbols; if psect < 0, then this is * a local variable and the offset is relative to FP. In this case it can * be either a variable (Offset < 0) or a parameter (Offset > 0). */ @@ -1879,32 +2007,29 @@ VMS_DBG_record (spnt, Psect, Offset, Name) char *pnt; char *Name_pnt; int j; - int maxlen; + int len; int i = 0; + Name_pnt = fix_name (Name); /* if there are bad characters in name, convert them */ + len = strlen(Name_pnt); if (Psect < 0) { /* this is a local variable, referenced to SP */ - maxlen = 7 + strlen (Name_pnt); - Local[i++] = maxlen; + Local[i++] = 7 + len; Local[i++] = spnt->VMS_type; - if (Offset > 0) - Local[i++] = DBG_S_C_FUNCTION_PARAMETER; - else - Local[i++] = DBG_S_C_LOCAL_SYM; + Local[i++] = (Offset > 0) ? DBG_C_FUNCTION_PARAM : DBG_C_LOCAL_SYM; COPY_LONG (&Local[i], Offset); i += 4; } else { - maxlen = 7 + strlen (Name_pnt); /* symbols fixed in memory */ - Local[i++] = 7 + strlen (Name_pnt); + Local[i++] = 7 + len; Local[i++] = spnt->VMS_type; - Local[i++] = 1; + Local[i++] = DST_K_VALKIND_ADDR; VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); i = 0; VMS_Set_Data (Psect, Offset, OBJ_S_C_DBG, 0); } - Local[i++] = strlen (Name_pnt); + Local[i++] = len; while (*Name_pnt != '\0') Local[i++] = *Name_pnt++; VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); @@ -1926,7 +2051,6 @@ VMS_local_stab_Parse (sp) struct VMS_DBG_Symbol *spnt; struct VMS_Symbol *vsp; int dbx_type; - int VMS_type; dbx_type = 0; str = S_GET_NAME (sp); pnt = (char *) strchr (str, ':'); @@ -1977,7 +2101,7 @@ VMS_local_stab_Parse (sp) } /* p block */ pnt = cvt_integer (pnt, &dbx_type); spnt = find_symbol (dbx_type); - if (spnt == (struct VMS_DBG_Symbol *) NULL) + if (!spnt) return 0; /*Dunno what this is*/ *pnt1 = '\0'; VMS_DBG_record (spnt, -1, S_GET_VALUE (sp), str); @@ -2010,7 +2134,6 @@ VMS_stab_parse (sp, expected_type, type1, type2, Text_Psect) struct VMS_DBG_Symbol *spnt; struct VMS_Symbol *vsp; int dbx_type; - int VMS_type; dbx_type = 0; str = S_GET_NAME (sp); pnt = (char *) strchr (str, ':'); @@ -2132,12 +2255,13 @@ VMS_RSYM_Parse (sp, Current_Routine, Text_Psect) int dbx_type; struct VMS_DBG_Symbol *spnt; int j; - int maxlen; + int len; int i = 0; int bcnt = 0; int Min_Offset = -1; /* min PC of validity */ int Max_Offset = 0; /* max PC of validity */ symbolS *symbolP; + for (symbolP = sp; symbolP; symbolP = symbol_next (symbolP)) { /* @@ -2205,35 +2329,31 @@ VMS_RSYM_Parse (sp, Current_Routine, Text_Psect) return 0; pnt = cvt_integer (pnt + 1, &dbx_type); spnt = find_symbol (dbx_type); - if (spnt == (struct VMS_DBG_Symbol *) NULL) + if (!spnt) return 0; /*Dunno what this is yet*/ *pnt1 = '\0'; pnt = fix_name (S_GET_NAME (sp)); /* if there are bad characters in name, convert them */ - maxlen = 25 + strlen (pnt); - Local[i++] = maxlen; + len = strlen(pnt); + Local[i++] = 25 + len; Local[i++] = spnt->VMS_type; - Local[i++] = 0xfb; - Local[i++] = strlen (pnt) + 1; - Local[i++] = 0x00; - Local[i++] = 0x00; - Local[i++] = 0x00; - Local[i++] = strlen (pnt); + Local[i++] = DST_K_VFLAGS_TVS; /* trailing value specified */ + COPY_LONG(&Local[i], 1 + len); /* relative offset, beyond name */ + i += 4; + Local[i++] = len; /* name length (ascic prefix) */ while (*pnt != '\0') Local[i++] = *pnt++; - Local[i++] = 0xfd; - Local[i++] = 0x0f; - Local[i++] = 0x00; - Local[i++] = 0x03; - Local[i++] = 0x01; + Local[i++] = DST_K_VS_FOLLOWS; /* value specification follows */ + COPY_SHORT(&Local[i], 15); /* length of rest of record */ + i += 2; + Local[i++] = DST_K_VS_ALLOC_SPLIT; /* split lifetime */ + Local[i++] = 1; /* one binding follows */ VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); i = 0; VMS_Set_Data (Text_Psect, Min_Offset, OBJ_S_C_DBG, 1); VMS_Set_Data (Text_Psect, Max_Offset, OBJ_S_C_DBG, 1); - Local[i++] = 0x03; - Local[i++] = S_GET_VALUE (sp); - Local[i++] = 0x00; - Local[i++] = 0x00; - Local[i++] = 0x00; + Local[i++] = DST_K_VALKIND_REG; /* nested value spec */ + COPY_LONG(&Local[i], S_GET_VALUE (sp)); + i += 4; VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); *pnt1 = ':'; if (spnt->VMS_type == DBG_S_C_ADVANCED_TYPE) @@ -2283,19 +2403,17 @@ forward_reference (pnt) static int final_forward_reference (spnt) - struct VMS_DBG_Symbol * spnt; + struct VMS_DBG_Symbol *spnt; { - struct VMS_DBG_Symbol * spnt1; - if(spnt != (struct VMS_DBG_Symbol*) NULL) { - while((spnt->advanced == POINTER) || (spnt->advanced == ARRAY)){ - spnt1 = find_symbol(spnt->type2); - if((spnt->advanced == ARRAY) && - (spnt1 == (struct VMS_DBG_Symbol*) NULL))return 1; - if(spnt1 == (struct VMS_DBG_Symbol*) NULL) break; - spnt=spnt1; - } - } - return 0; /* no forward refences found */ + struct VMS_DBG_Symbol *spnt1; + + while (spnt && (spnt->advanced == POINTER || spnt->advanced == ARRAY)) + { + spnt1 = find_symbol(spnt->type2); + if (spnt->advanced == ARRAY && !spnt1) return 1; + spnt = spnt1; + } + return 0; /* no forward refences found */ } /* This routine parses the stabs directives to find any definitions of dbx type @@ -2324,10 +2442,11 @@ VMS_typedef_parse (str) int i; int dtype; struct forward_ref *fpnt; - int i1, i2, i3; + int i1, i2, i3, len; int convert_integer; struct VMS_DBG_Symbol *spnt; struct VMS_DBG_Symbol *spnt1; + /* check for any nested def's */ pnt = (char *) strchr (str + 1, '='); if ((pnt != (char *) NULL) && (*(str + 1) != '*') @@ -2347,12 +2466,14 @@ VMS_typedef_parse (str) cvt_integer (pnt, &i1); spnt = find_symbol (i1); /* first we see if this has been defined already, due to a forward reference*/ - if (spnt == (struct VMS_DBG_Symbol *) NULL) + if (!spnt) { spnt = (struct VMS_DBG_Symbol *) xmalloc (sizeof (struct VMS_DBG_Symbol)); spnt->next = VMS_Symbol_type_list; VMS_Symbol_type_list = spnt; spnt->dbx_type = i1; /* and save the type */ + spnt->type2 = spnt->VMS_type = spnt->data_size = 0; + spnt->index_min = spnt->index_max = spnt->struc_numb = 0; } /* for structs and unions, do a partial parse, otherwise we sometimes get * circular definitions that are impossible to resolve. We read enough info @@ -2371,7 +2492,7 @@ VMS_typedef_parse (str) return 0; } if (type_check ("unknown type")) - { /* this is the void symbol */ + { *str = '\0'; spnt->advanced = UNKNOWN; return 0; @@ -2446,14 +2567,13 @@ VMS_typedef_parse (str) } else if (type_check ("double")) { - /* caveat: this assumes D_float, and is not correct for G_float */ - spnt->VMS_type = DBG_S_C_REAL8; + spnt->VMS_type = vax_g_doubles ? DBG_S_C_REAL8_G : DBG_S_C_REAL8; spnt->data_size = 8; } else if (type_check ("long double")) { /* same as double, at least for now */ - spnt->VMS_type = DBG_S_C_REAL8; + spnt->VMS_type = vax_g_doubles ? DBG_S_C_REAL8_G : DBG_S_C_REAL8; spnt->data_size = 8; } else if (type_check ("long long int")) @@ -2473,14 +2593,13 @@ VMS_typedef_parse (str) } else if (type_check ("complex double")) { - /* caveat: this assumes D_float, and is not correct for G_float */ - spnt->VMS_type = DBG_S_C_COMPLX8; + spnt->VMS_type = vax_g_doubles ? DBG_S_C_COMPLX8_G : DBG_S_C_COMPLX8; spnt->data_size = 2 * 8; } else if (type_check ("complex long double")) { /* same as complex double, at least for now */ - spnt->VMS_type = DBG_S_C_COMPLX8; + spnt->VMS_type = vax_g_doubles ? DBG_S_C_COMPLX8_G : DBG_S_C_COMPLX8; spnt->data_size = 2 * 8; } else @@ -2492,14 +2611,13 @@ VMS_typedef_parse (str) spnt->VMS_type = 0; spnt->data_size = 0; } + if (spnt->VMS_type != 0) + setup_basic_type(spnt); pnt1 = (char *) strchr (str, ';') + 1; break; case 's': case 'u': - if (*pnt == 's') - spnt->advanced = STRUCT; - else - spnt->advanced = UNION; + spnt->advanced = (*pnt == 's') ? STRUCT : UNION; spnt->VMS_type = DBG_S_C_ADVANCED_TYPE; pnt1 = cvt_integer (pnt + 1, &spnt->data_size); if (!final_pass && forward_reference(pnt)) @@ -2511,24 +2629,23 @@ VMS_typedef_parse (str) pnt1--; pnt = get_struct_name (str); VMS_Def_Struct (spnt->struc_numb); - fpnt = f_ref_root; - while (fpnt != (struct forward_ref *) NULL) - { - if (fpnt->dbx_type == spnt->dbx_type) - { - fpnt->resolved = 'Y'; - VMS_Set_Struct (fpnt->struc_numb); - VMS_Store_Struct (spnt->struc_numb); - } - fpnt = fpnt->next; - } - VMS_Set_Struct (spnt->struc_numb); + i = 0; + for (fpnt = f_ref_root; fpnt; fpnt = fpnt->next) + if (fpnt->dbx_type == spnt->dbx_type) + { + fpnt->resolved = 'Y'; + VMS_Set_Struct (fpnt->struc_numb); + VMS_Store_Struct (spnt->struc_numb); + i++; + } + if (i > 0) + VMS_Set_Struct (spnt->struc_numb); i = 0; Local[i++] = 11 + strlen (pnt); Local[i++] = DBG_S_C_STRUCT_START; - Local[i++] = 0x80; - for (i1 = 0; i1 < 4; i1++) - Local[i++] = 0x00; + Local[i++] = DST_K_VFLAGS_NOVAL; /* structure definition only */ + COPY_LONG(&Local[i], 0L); /* hence value is unused */ + i += 4; Local[i++] = strlen (pnt); pnt2 = pnt; while (*pnt2 != '\0') @@ -2551,47 +2668,76 @@ VMS_typedef_parse (str) pnt1 = cvt_integer (pnt + 1, &dtype); pnt1 = cvt_integer (pnt1 + 1, &i2); pnt1 = cvt_integer (pnt1 + 1, &i3); - if ((dtype == 1) && (i3 != 32)) + spnt1 = find_symbol (dtype); + len = strlen (pnt2); + if (spnt1 && (spnt1->advanced == BASIC || spnt1->advanced == ENUM) + && ((i3 != spnt1->data_size * 8) || (i2 % 8 != 0))) { /* bitfield */ - Apoint = 0; - push (19 + strlen (pnt2), 1); - push (0xfa22, 2); - push (1 + strlen (pnt2), 4); - push (strlen (pnt2), 1); - while (*pnt2 != '\0') - push (*pnt2++, 1); - push (i3, 2); /* size of bitfield */ - push (0x0d22, 2); - push (0x00, 4); - push (i2, 4); /* start position */ - VMS_Store_Immediate_Data (Asuffix, Apoint, OBJ_S_C_DBG); - Apoint = 0; + if (USE_BITSTRING_DESCRIPTOR (spnt1)) + { + /* This uses a type descriptor, which doesn't work if + the enclosing structure has been placed in a register. + Also, enum bitfields degenerate to simple integers. */ + int unsigned_type = (spnt1->VMS_type == DBG_S_C_ULINT + || spnt1->VMS_type == DBG_S_C_USINT + || spnt1->VMS_type == DBG_S_C_UCHAR + || spnt1->VMS_type == DBG_S_C_UQUAD + || spnt1->advanced == ENUM); /* (approximate) */ + Apoint = 0; + push (19 + len, 1); + push (unsigned_type ? DBG_S_C_UBITU : DBG_S_C_SBITU, 1); + push (DST_K_VFLAGS_DSC, 1); /* specified by descriptor */ + push (1 + len, 4); /* relative offset to descriptor */ + push (len, 1); /* length byte (ascic prefix) */ + while (*pnt2 != '\0') /* name bytes */ + push (*pnt2++, 1); + push (i3, 2); /* dsc length == size of bitfield */ + /* dsc type == un?signed bitfield */ + push (unsigned_type ? DBG_S_C_UBITU : DBG_S_C_SBITU, 1); + push (DSC_K_CLASS_UBS, 1); /* dsc class == unaligned bitstring */ + push (0x00, 4); /* dsc pointer == zeroes */ + push (i2, 4); /* start position */ + VMS_Store_Immediate_Data (Asuffix, Apoint, OBJ_S_C_DBG); + Apoint = 0; + } + else + { + /* Use a "novel length" type specification, which works + right for register structures and for enum bitfields + but results in larger object modules. */ + Local[i++] = 7 + len; + Local[i++] = DBG_S_C_ADVANCED_TYPE; /* type spec follows */ + Local[i++] = DBG_S_C_STRUCT_ITEM; /* value is a bit offset */ + COPY_LONG (&Local[i], i2); /* bit offset */ + i += 4; + Local[i++] = strlen (pnt2); + while (*pnt2 != '\0') + Local[i++] = *pnt2++; + VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); + i = 0; + bitfield_suffix (spnt1, i3); + } } else - { - Local[i++] = 7 + strlen (pnt2); - spnt1 = find_symbol (dtype); + { /* not a bitfield */ /* check if this is a forward reference */ if(final_pass && final_forward_reference(spnt1)) { printf("gcc-as warning(debugger output):"); - printf("structure element %s has undefined type\n",pnt2); - i--; + printf("structure element `%s' has undefined type\n",pnt2); continue; } - if (spnt1 != (struct VMS_DBG_Symbol *) NULL) - Local[i++] = spnt1->VMS_type; - else - Local[i++] = DBG_S_C_ADVANCED_TYPE; + Local[i++] = 7 + len; + Local[i++] = spnt1 ? spnt1->VMS_type : DBG_S_C_ADVANCED_TYPE; Local[i++] = DBG_S_C_STRUCT_ITEM; - COPY_LONG (&Local[i], i2); + COPY_LONG (&Local[i], i2); /* bit offset */ i += 4; Local[i++] = strlen (pnt2); while (*pnt2 != '\0') Local[i++] = *pnt2++; VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG); i = 0; - if (spnt1 == (struct VMS_DBG_Symbol *) NULL) + if (!spnt1) generate_suffix (spnt1, dtype); else if (spnt1->VMS_type == DBG_S_C_ADVANCED_TYPE) generate_suffix (spnt1, 0); @@ -2609,23 +2755,23 @@ VMS_typedef_parse (str) spnt->struc_numb = ++structure_count; spnt->data_size = 4; VMS_Def_Struct (spnt->struc_numb); - fpnt = f_ref_root; - while (fpnt != (struct forward_ref *) NULL) - { - if (fpnt->dbx_type == spnt->dbx_type) - { - fpnt->resolved = 'Y'; - VMS_Set_Struct (fpnt->struc_numb); - VMS_Store_Struct (spnt->struc_numb); - } - fpnt = fpnt->next; - } - VMS_Set_Struct (spnt->struc_numb); i = 0; - Local[i++] = 3 + strlen (symbol_name); + for (fpnt = f_ref_root; fpnt; fpnt = fpnt->next) + if (fpnt->dbx_type == spnt->dbx_type) + { + fpnt->resolved = 'Y'; + VMS_Set_Struct (fpnt->struc_numb); + VMS_Store_Struct (spnt->struc_numb); + i++; + } + if (i > 0) + VMS_Set_Struct (spnt->struc_numb); + i = 0; + len = strlen (symbol_name); + Local[i++] = 3 + len; Local[i++] = DBG_S_C_ENUM_START; - Local[i++] = 0x20; - Local[i++] = strlen (symbol_name); + Local[i++] = 4 * 8; /* enum values are 32 bits */ + Local[i++] = len; pnt2 = symbol_name; while (*pnt2 != '\0') Local[i++] = *pnt2++; @@ -2636,12 +2782,13 @@ VMS_typedef_parse (str) pnt1 = (char *) strchr (pnt, ':'); *pnt1++ = '\0'; pnt1 = cvt_integer (pnt1, &i1); - Local[i++] = 7 + strlen (pnt); + len = strlen (pnt); + Local[i++] = 7 + len; Local[i++] = DBG_S_C_ENUM_ITEM; - Local[i++] = 0x00; + Local[i++] = DST_K_VALKIND_LITERAL; COPY_LONG (&Local[i], i1); i += 4; - Local[i++] = strlen (pnt); + Local[i++] = len; pnt2 = pnt; while (*pnt != '\0') Local[i++] = *pnt++; @@ -4399,10 +4546,10 @@ VMS_Check_For_Main () * JSB instruction. */ symbolP = (symbolS *) xmalloc (sizeof (*symbolP)); - S_GET_NAME (symbolP) = "_c$main_args"; + S_SET_NAME (symbolP, "_C$MAIN_ARGS"); S_SET_TYPE (symbolP, N_UNDF); - S_GET_OTHER (symbolP) = 0; - S_GET_DESC (symbolP) = 0; + S_SET_OTHER (symbolP, 0); + S_SET_DESC (symbolP, 0); S_SET_VALUE (symbolP, 0); symbolP->sy_name_offset = 0; symbolP->sy_number = 0; @@ -4577,7 +4724,7 @@ VMS_write_object_file (text_siz, data_siz, bss_siz, text_frag_root, if (strncmp (S_GET_NAME (sp),"__vt.",5) == 0) { S_GET_RAW_TYPE (sp) = N_UNDF | N_EXT; - S_GET_OTHER (sp) = 1; + S_SET_OTHER (sp, 1); /* Is this warning still needed? It sounds like it describes a compiler bug. Does it? If not, let's dump it. */ as_warn("g++ wrote an extern reference to %s as a routine.", @@ -4619,18 +4766,11 @@ VMS_write_object_file (text_siz, data_siz, bss_siz, text_frag_root, /* * Make the psect for this data */ - if (S_GET_OTHER (sp)) - Globalref = VMS_Psect_Spec ( - S_GET_NAME (sp), - vsp->Size, - "CONST", - vsp); - else - Globalref = VMS_Psect_Spec ( - S_GET_NAME (sp), - vsp->Size, - "COMMON", - vsp); + Globalref = VMS_Psect_Spec ( + S_GET_NAME (sp), + vsp->Size, + S_GET_OTHER (sp) ? "CONST" : "COMMON", + vsp); if (Globalref) Psect_Number--; @@ -4695,18 +4835,11 @@ VMS_write_object_file (text_siz, data_siz, bss_siz, text_frag_root, /* * Make its psect */ - if (S_GET_OTHER (sp)) - Globalref = VMS_Psect_Spec ( - S_GET_NAME (sp), - vsp->Size, - "CONST", - vsp); - else - Globalref = VMS_Psect_Spec ( - S_GET_NAME (sp), - vsp->Size, - "COMMON", - vsp); + Globalref = VMS_Psect_Spec ( + S_GET_NAME (sp), + vsp->Size, + S_GET_OTHER (sp) ? "CONST" : "COMMON", + vsp); if (Globalref) Psect_Number--; @@ -5303,6 +5436,13 @@ VMS_write_object_file (text_siz, data_siz, bss_siz, text_frag_root, */ VMS_TBT_Routine_End (text_siz, Current_Routine); } + /* + * Check for & skip dummy labels like "gcc_compiled.". + * They're identified by the IN_DEFAULT_SECTION flag. + */ + if ((S_GET_OTHER (symbolP) & IN_DEFAULT_SECTION) != 0 && + (S_GET_VALUE (symbolP) == 0)) + continue; /* * Store the routine begin traceback info */ diff --git a/gas/config/obj-vms.h b/gas/config/obj-vms.h index 8470d270b76..059287cb32e 100644 --- a/gas/config/obj-vms.h +++ b/gas/config/obj-vms.h @@ -1,5 +1,5 @@ /* VMS object file format - Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc. + Copyright (C) 1989, 1990, 1991, 1994 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -37,6 +37,17 @@ to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ extern char const_flag; +/* This is overloaded onto const_flag, for convenience. It's used to flag + dummy labels like "gcc2_compiled." which occur before the first .text + or .data section directive. */ + +#define IN_DEFAULT_SECTION 0x80 + +/* Compiler-generated label "__vax_g_doubles" is used to augment .stabs. */ + +#define tc_frob_label(X) vms_check_for_special_label(X) +extern void vms_check_for_special_label(); + /* These are defined in obj-vms.c. */ extern const short seg_N_TYPE[]; extern const segT N_TYPE_seg[]; @@ -373,7 +384,8 @@ extern int vms_resolve_symbol_redef (); * machine-readable version seems * to be available. */ -#define DST_S_C_C 7 /* Language == "C" */ +#define DST_S_C_C 7 /* Language == "C" */ +#define DST_S_C_CXX 15 /* Language == "C++" */ #define DST_S_C_VERSION 153 #define DST_S_C_SOURCE 155 /* Source file */ #define DST_S_C_PROLOG 162 @@ -434,26 +446,73 @@ extern int vms_resolve_symbol_redef (); #define DBG_S_C_COMPLX8_G 0x1d /* 2xG_float complex double */ #define DBG_S_C_FUNCTION_ADDR 0x17 #define DBG_S_C_ADVANCED_TYPE 0xa3 +/* Some of these are just for future reference. [pr] + */ +#define DBG_S_C_UBITA 0x01 /* unsigned, aligned bit field */ +#define DBG_S_C_UBITU 0x22 /* unsigned, unaligned bit field */ +#define DBG_S_C_SBITA 0x29 /* signed, aligned bit field */ +#define DBG_S_C_SBITU 0x2a /* signed, unaligned bit field */ +#define DBG_S_C_CSTRING 0x2e /* asciz ('\0' terminated) string */ +#define DBG_S_C_WCHAR 0x38 /* wchar_t */ +/* These are descriptor class codes. + */ +#define DSC_K_CLASS_S 0x01 /* static (fixed length) */ +#define DSC_K_CLASS_D 0x02 /* dynamic string (not via malloc!) */ +#define DSC_K_CLASS_A 0x04 /* array */ +#define DSC_K_CLASS_UBS 0x0d /* unaligned bit string */ /* These are the codes that are used to generate the definitions of struct * union and enum records */ -#define DBG_S_C_ENUM_ITEM 0xa4 +#define DBG_S_C_ENUM_ITEM 0xa4 #define DBG_S_C_ENUM_START 0xa5 -#define DBG_S_C_ENUM_END 0xa6 +#define DBG_S_C_ENUM_END 0xa6 +#define DBG_S_C_STRUCT_ITEM DST_K_VFLAGS_BITOFFS /* 0xff */ #define DBG_S_C_STRUCT_START 0xab -#define DBG_S_C_STRUCT_ITEM 0xff #define DBG_S_C_STRUCT_END 0xac +#define DST_K_TYPSPEC 0xaf /* type specification */ +/* These codes are used in the generation of the symbol definition records + */ +#define DST_K_VFLAGS_NOVAL 0x80 /* struct definition only */ +#define DST_K_VFLAGS_DSC 0xfa /* descriptor used */ +#define DST_K_VFLAGS_TVS 0xfb /* trailing value specified */ +#define DST_K_VS_FOLLOWS 0xfd /* value spec follows */ +#define DST_K_VFLAGS_BITOFFS 0xff /* value contains bit offset */ +#define DST_K_VALKIND_LITERAL 0 +#define DST_K_VALKIND_ADDR 1 +#define DST_K_VALKIND_DESC 2 +#define DST_K_VALKIND_REG 3 +#define DST_K_REG_VAX_AP 0x0c /* R12 */ +#define DST_K_REG_VAX_FP 0x0d /* R13 */ +#define DST_K_REG_VAX_SP 0x0e /* R14 */ +#define DST_V_VALKIND 0 /* offset of valkind field */ +#define DST_V_INDIRECT 2 /* offset to indirect bit */ +#define DST_V_DISP 3 /* offset to displacement bit */ +#define DST_V_REGNUM 4 /* offset to register number */ +#define DST_M_INDIRECT (1<