/* 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.
*/
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
* use with VMS.
*/
-char const_flag = 0;
+char const_flag = IN_DEFAULT_SECTION;
void
s_const ()
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);
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_<name>" and possibly "__vax_<type>_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 ()
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))
{
{
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
*/
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);
}
/* 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 *
{
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;
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)
{
/* 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)
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;
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:
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);
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",
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;
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
{
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
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;
}
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).
*/
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);
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, ':');
} /* 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);
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, ':');
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))
{
/*
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)
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
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) != '*')
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
return 0;
}
if (type_check ("unknown type"))
- { /* this is the void symbol */
+ {
*str = '\0';
spnt->advanced = UNKNOWN;
return 0;
}
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"))
}
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
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))
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')
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);
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++;
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++;
* 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;
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.",
/*
* 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--;
/*
* 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--;
*/
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
*/
/* 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.
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[];
* 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
#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<<DST_V_INDIRECT)
+#define DST_M_DISP (1<<DST_V_DISP)
+#define DBG_C_FUNCTION_PARAM /* 0xc9 */ \
+ (DST_K_VALKIND_ADDR|DST_M_DISP|(DST_K_REG_VAX_AP<<DST_V_REGNUM))
+#define DBG_C_LOCAL_SYM /* 0xd9 */ \
+ (DST_K_VALKIND_ADDR|DST_M_DISP|(DST_K_REG_VAX_FP<<DST_V_REGNUM))
+/* Kinds of value specifications
+ */
+#define DST_K_VS_ALLOC_SPLIT 3 /* split lifetime */
+/* Kinds of type specifications
+ */
+#define DST_K_TS_ATOM 0x01 /* atomic type specification */
+#define DST_K_TS_DSC 0x02 /* descriptor type spec */
+#define DST_K_TS_IND 0x03 /* indirect type specification */
+#define DST_K_TS_TPTR 0x04 /* typed pointer type spec */
+#define DST_K_TS_PTR 0x05 /* pointer type spec */
+#define DST_K_TS_ARRAY 0x07 /* array type spec */
+#define DST_K_TS_NOV_LENG 0x0e /* novel length type spec */
/* These are the codes that are used in the suffix records to determine the
* actual data type
*/
-#define DBG_S_C_BASIC 0x01
-#define DBG_S_C_BASIC_ARRAY 0x02
-#define DBG_S_C_STRUCT 0x03
-#define DBG_S_C_POINTER 0x04
-#define DBG_S_C_VOID 0x05
-#define DBG_S_C_COMPLEX_ARRAY 0x07
-/* These codes are used in the generation of the symbol definition records
- */
-#define DBG_S_C_FUNCTION_PARAMETER 0xc9
-#define DBG_S_C_LOCAL_SYM 0xd9
+#define DBG_S_C_BASIC DST_K_TS_ATOM
+#define DBG_S_C_BASIC_ARRAY DST_K_TS_DSC
+#define DBG_S_C_STRUCT DST_K_TS_IND
+#define DBG_S_C_POINTER DST_K_TS_TPTR
+#define DBG_S_C_VOID DST_K_TS_PTR
+#define DBG_S_C_COMPLEX_ARRAY DST_K_TS_ARRAY
/* end of obj-vms.h */