aboutsummaryrefslogtreecommitdiff
path: root/binutils
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1996-01-24 19:40:21 +0000
committerIan Lance Taylor <ian@airs.com>1996-01-24 19:40:21 +0000
commit2466210755c857114fe94a9395c689a77a14c349 (patch)
tree8dc43dcfb40173eea0e0164585c1c09c3b12f280 /binutils
parenta837b8fc9692536b38fe435f8f3f52d2749b3527 (diff)
downloadgdb-2466210755c857114fe94a9395c689a77a14c349.zip
gdb-2466210755c857114fe94a9395c689a77a14c349.tar.gz
gdb-2466210755c857114fe94a9395c689a77a14c349.tar.bz2
* ieee.c: Various changes to write out types for functions and
references, and to not write out unnecessary function types.
Diffstat (limited to 'binutils')
-rw-r--r--binutils/ChangeLog3
-rw-r--r--binutils/ieee.c633
2 files changed, 474 insertions, 162 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 6050888..2864859 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,5 +1,8 @@
Wed Jan 24 12:06:05 1996 Ian Lance Taylor <ian@cygnus.com>
+ * ieee.c: Various changes to write out types for functions and
+ references, and to not write out unnecessary function types.
+
* ieee.c (struct ieee_var): Remove variable field. Add kind
field, and define some enum constants for it.
(parse_ieee_ty): Set kind field of variable for 'x' and 'X' types.
diff --git a/binutils/ieee.c b/binutils/ieee.c
index 822aa7d..6b40985 100644
--- a/binutils/ieee.c
+++ b/binutils/ieee.c
@@ -3505,6 +3505,8 @@ struct ieee_type_class
bfd_vma voffset;
/* The current method. */
const char *method;
+ /* Additional pmisc records used to record fields of reference type. */
+ struct ieee_buf *refs;
};
/* This is how we store types for the writing routines. Most types
@@ -3516,6 +3518,9 @@ struct ieee_write_type
unsigned int indx;
/* The size of the type, if known. */
unsigned int size;
+ /* If this is a function or method type, we build the type here, and
+ only add it to the output buffers if we need it. */
+ struct ieee_buf *fndef;
/* If this is a struct, this is where the struct definition is
built. */
struct ieee_buf *strdef;
@@ -3566,6 +3571,8 @@ struct ieee_pending_parm
const char *name;
/* Type index. */
unsigned int type;
+ /* Whether the type is a reference. */
+ boolean referencep;
/* Kind. */
enum debug_parm_kind kind;
/* Value. */
@@ -3613,6 +3620,16 @@ struct ieee_handle
/* The depth of block nesting. This is 0 outside a function, and 1
just after start_function is called. */
unsigned int block_depth;
+ /* The name of the current function. */
+ const char *fnname;
+ /* List of buffers for the type of the function we are currently
+ writing out. */
+ struct ieee_buf *fntype;
+ /* List of buffers for the parameters of the function we are
+ currently writing out. */
+ struct ieee_buf *fnargs;
+ /* Number of arguments written to fnargs. */
+ unsigned int fnargcount;
/* Pending function parameters. */
struct ieee_pending_parm *pending_parms;
/* Current line number filename. */
@@ -3625,13 +3642,6 @@ struct ieee_handle
static boolean ieee_change_buffer
PARAMS ((struct ieee_handle *, struct ieee_buf **));
-static boolean ieee_push_type
- PARAMS ((struct ieee_handle *, unsigned int, unsigned int, boolean));
-static unsigned int ieee_pop_type PARAMS ((struct ieee_handle *));
-static boolean ieee_add_range
- PARAMS ((struct ieee_handle *, bfd_vma, bfd_vma));
-static boolean ieee_start_range PARAMS ((struct ieee_handle *, bfd_vma));
-static boolean ieee_end_range PARAMS ((struct ieee_handle *, bfd_vma));
static boolean ieee_real_write_byte PARAMS ((struct ieee_handle *, int));
static boolean ieee_write_2bytes PARAMS ((struct ieee_handle *, int));
static boolean ieee_write_number PARAMS ((struct ieee_handle *, bfd_vma));
@@ -3640,6 +3650,16 @@ static boolean ieee_write_asn
PARAMS ((struct ieee_handle *, unsigned int, bfd_vma));
static boolean ieee_write_atn65
PARAMS ((struct ieee_handle *, unsigned int, const char *));
+static boolean ieee_push_type
+ PARAMS ((struct ieee_handle *, unsigned int, unsigned int, boolean));
+static unsigned int ieee_pop_type PARAMS ((struct ieee_handle *));
+static void ieee_pop_unused_type PARAMS ((struct ieee_handle *));
+static unsigned int ieee_pop_type_used
+ PARAMS ((struct ieee_handle *, boolean));
+static boolean ieee_add_range
+ PARAMS ((struct ieee_handle *, bfd_vma, bfd_vma));
+static boolean ieee_start_range PARAMS ((struct ieee_handle *, bfd_vma));
+static boolean ieee_end_range PARAMS ((struct ieee_handle *, bfd_vma));
static boolean ieee_define_type
PARAMS ((struct ieee_handle *, unsigned int, boolean));
static boolean ieee_define_named_type
@@ -3786,135 +3806,6 @@ ieee_change_buffer (info, ppbuf)
return true;
}
-/* Push a type index onto the type stack. */
-
-static boolean
-ieee_push_type (info, indx, size, unsignedp)
- struct ieee_handle *info;
- unsigned int indx;
- unsigned int size;
- boolean unsignedp;
-{
- struct ieee_type_stack *ts;
-
- ts = (struct ieee_type_stack *) xmalloc (sizeof *ts);
- memset (ts, 0, sizeof *ts);
-
- ts->type.indx = indx;
- ts->type.size = size;
- ts->type.unsignedp = unsignedp;
-
- ts->next = info->type_stack;
- info->type_stack = ts;
-
- return true;
-}
-
-/* Pop a type index off the type stack. */
-
-static unsigned int
-ieee_pop_type (info)
- struct ieee_handle *info;
-{
- struct ieee_type_stack *ts;
- unsigned int ret;
-
- ts = info->type_stack;
- assert (ts != NULL);
- ret = ts->type.indx;
- info->type_stack = ts->next;
- free (ts);
- return ret;
-}
-
-/* Add a range of bytes included in the current compilation unit. */
-
-static boolean
-ieee_add_range (info, low, high)
- struct ieee_handle *info;
- bfd_vma low;
- bfd_vma high;
-{
- struct ieee_range *r, **pr;
-
- if (low == (bfd_vma) -1 || high == (bfd_vma) -1)
- return true;
-
- for (r = info->ranges; r != NULL; r = r->next)
- {
- if (high >= r->low && low <= r->high)
- {
- /* The new range overlaps r. */
- if (low < r->low)
- r->low = low;
- if (high > r->high)
- r->high = high;
- pr = &r->next;
- while (*pr != NULL && (*pr)->low <= r->high)
- {
- struct ieee_range *n;
-
- if ((*pr)->high > r->high)
- r->high = (*pr)->high;
- n = (*pr)->next;
- free (*pr);
- *pr = n;
- }
- return true;
- }
- }
-
- r = (struct ieee_range *) xmalloc (sizeof *r);
- memset (r, 0, sizeof *r);
-
- r->low = low;
- r->high = high;
-
- /* Store the ranges sorted by address. */
- for (pr = &info->ranges; *pr != NULL; pr = &(*pr)->next)
- if ((*pr)->next != NULL && (*pr)->next->low > high)
- break;
- r->next = *pr;
- *pr = r;
-
- return true;
-}
-
-/* Start a new range for which we only have the low address. */
-
-static boolean
-ieee_start_range (info, low)
- struct ieee_handle *info;
- bfd_vma low;
-{
- struct ieee_range *r;
-
- r = (struct ieee_range *) xmalloc (sizeof *r);
- memset (r, 0, sizeof *r);
- r->low = low;
- r->next = info->pending_ranges;
- info->pending_ranges = r;
- return true;
-}
-
-/* Finish a range started by ieee_start_range. */
-
-static boolean
-ieee_end_range (info, high)
- struct ieee_handle *info;
- bfd_vma high;
-{
- struct ieee_range *r;
- bfd_vma low;
-
- assert (info->pending_ranges != NULL);
- r = info->pending_ranges;
- low = r->low;
- info->pending_ranges = r->next;
- free (r);
- return ieee_add_range (info, low, high);
-}
-
/* Write a byte into the buffer. We use a macro for speed and a
function for the complex cases. */
@@ -4068,6 +3959,177 @@ ieee_write_atn65 (info, indx, s)
&& ieee_write_id (info, s));
}
+/* Push a type index onto the type stack. */
+
+static boolean
+ieee_push_type (info, indx, size, unsignedp)
+ struct ieee_handle *info;
+ unsigned int indx;
+ unsigned int size;
+ boolean unsignedp;
+{
+ struct ieee_type_stack *ts;
+
+ ts = (struct ieee_type_stack *) xmalloc (sizeof *ts);
+ memset (ts, 0, sizeof *ts);
+
+ ts->type.indx = indx;
+ ts->type.size = size;
+ ts->type.unsignedp = unsignedp;
+
+ ts->next = info->type_stack;
+ info->type_stack = ts;
+
+ return true;
+}
+
+/* Pop a type index off the type stack. */
+
+static unsigned int
+ieee_pop_type (info)
+ struct ieee_handle *info;
+{
+ return ieee_pop_type_used (info, true);
+}
+
+/* Pop an unused type index off the type stack. */
+
+static void
+ieee_pop_unused_type (info)
+ struct ieee_handle *info;
+{
+ (void) ieee_pop_type_used (info, false);
+}
+
+/* Pop a used or unused type index off the type stack. */
+
+static unsigned int
+ieee_pop_type_used (info, used)
+ struct ieee_handle *info;
+ boolean used;
+{
+ struct ieee_type_stack *ts;
+ unsigned int ret;
+
+ ts = info->type_stack;
+ assert (ts != NULL);
+
+ /* If this is a function type, and we need it, we need to append the
+ actual definition to the typedef block now. */
+ if (ts->type.fndef != NULL && used)
+ {
+ struct ieee_buf **pb;
+
+ /* Make sure we have started the types block. */
+ if (info->types == NULL)
+ {
+ if (! ieee_change_buffer (info, &info->types)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 1)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, info->modname))
+ return false;
+ }
+
+ for (pb = &info->types; *pb != NULL; pb = &(*pb)->next)
+ ;
+ *pb = ts->type.fndef;
+ }
+
+ ret = ts->type.indx;
+ info->type_stack = ts->next;
+ free (ts);
+ return ret;
+}
+
+/* Add a range of bytes included in the current compilation unit. */
+
+static boolean
+ieee_add_range (info, low, high)
+ struct ieee_handle *info;
+ bfd_vma low;
+ bfd_vma high;
+{
+ struct ieee_range *r, **pr;
+
+ if (low == (bfd_vma) -1 || high == (bfd_vma) -1)
+ return true;
+
+ for (r = info->ranges; r != NULL; r = r->next)
+ {
+ if (high >= r->low && low <= r->high)
+ {
+ /* The new range overlaps r. */
+ if (low < r->low)
+ r->low = low;
+ if (high > r->high)
+ r->high = high;
+ pr = &r->next;
+ while (*pr != NULL && (*pr)->low <= r->high)
+ {
+ struct ieee_range *n;
+
+ if ((*pr)->high > r->high)
+ r->high = (*pr)->high;
+ n = (*pr)->next;
+ free (*pr);
+ *pr = n;
+ }
+ return true;
+ }
+ }
+
+ r = (struct ieee_range *) xmalloc (sizeof *r);
+ memset (r, 0, sizeof *r);
+
+ r->low = low;
+ r->high = high;
+
+ /* Store the ranges sorted by address. */
+ for (pr = &info->ranges; *pr != NULL; pr = &(*pr)->next)
+ if ((*pr)->next != NULL && (*pr)->next->low > high)
+ break;
+ r->next = *pr;
+ *pr = r;
+
+ return true;
+}
+
+/* Start a new range for which we only have the low address. */
+
+static boolean
+ieee_start_range (info, low)
+ struct ieee_handle *info;
+ bfd_vma low;
+{
+ struct ieee_range *r;
+
+ r = (struct ieee_range *) xmalloc (sizeof *r);
+ memset (r, 0, sizeof *r);
+ r->low = low;
+ r->next = info->pending_ranges;
+ info->pending_ranges = r;
+ return true;
+}
+
+/* Finish a range started by ieee_start_range. */
+
+static boolean
+ieee_end_range (info, high)
+ struct ieee_handle *info;
+ bfd_vma high;
+{
+ struct ieee_range *r;
+ bfd_vma low;
+
+ assert (info->pending_ranges != NULL);
+ r = info->pending_ranges;
+ low = r->low;
+ info->pending_ranges = r->next;
+ free (r);
+ return ieee_add_range (info, low, high);
+}
+
/* Start defining a type. */
static boolean
@@ -4748,7 +4810,10 @@ ieee_pointer_type (p)
&& ieee_write_number (info, indx));
}
-/* Make a function type. */
+/* Make a function type. This will be called for a method, but we
+ don't want to actually add it to the type table in that case. We
+ handle this by defining the type in a private buffer, and only
+ adding that buffer to the typedef block if we are going to use it. */
static boolean
ieee_function_type (p, argcount, varargs)
@@ -4760,6 +4825,7 @@ ieee_function_type (p, argcount, varargs)
unsigned int *args = NULL;
int i;
unsigned int retindx;
+ struct ieee_buf *fndef;
if (argcount > 0)
{
@@ -4774,7 +4840,9 @@ ieee_function_type (p, argcount, varargs)
/* An attribute of 0x41 means that the frame and push mask are
unknown. */
- if (! ieee_define_type (info, 0, true)
+ fndef = NULL;
+ if (! ieee_define_named_type (info, (const char *) NULL, false, 0, 0,
+ true, &fndef)
|| ! ieee_write_number (info, 'x')
|| ! ieee_write_number (info, 0x41)
|| ! ieee_write_number (info, 0)
@@ -4797,7 +4865,14 @@ ieee_function_type (p, argcount, varargs)
return false;
}
- return ieee_write_number (info, 0);
+ if (! ieee_write_number (info, 0))
+ return false;
+
+ /* We wrote the information into fndef, in case we don't need it.
+ It will be appended to info->types by ieee_pop_type. */
+ info->type_stack->type.fndef = fndef;
+
+ return true;
}
/* Make a reference type. */
@@ -4831,7 +4906,7 @@ ieee_range_type (p, low, high)
size = info->type_stack->type.size;
unsignedp = info->type_stack->type.unsignedp;
- (void) ieee_pop_type (info);
+ ieee_pop_unused_type (info);
return (ieee_define_type (info, size, unsignedp)
&& ieee_write_number (info, 'R')
&& ieee_write_number (info, (bfd_vma) low)
@@ -4854,7 +4929,7 @@ ieee_array_type (p, low, high, stringp)
unsigned int eleindx;
/* IEEE does not store the range, so we just ignore it. */
- (void) ieee_pop_type (info);
+ ieee_pop_unused_type (info);
eleindx = ieee_pop_type (info);
if (! ieee_define_type (info, 0, false)
@@ -4928,7 +5003,7 @@ ieee_method_type (p, domain, argcount, varargs)
type. */
if (domain)
- (void) ieee_pop_type (info);
+ ieee_pop_unused_type (info);
return ieee_function_type (p, argcount, varargs);
}
@@ -5032,11 +5107,13 @@ ieee_struct_field (p, name, bitpos, bitsize, visibility)
struct ieee_handle *info = (struct ieee_handle *) p;
unsigned int size;
boolean unsignedp;
+ boolean referencep;
unsigned int indx;
bfd_vma offset;
size = info->type_stack->type.size;
unsignedp = info->type_stack->type.unsignedp;
+ referencep = info->type_stack->type.referencep;
indx = ieee_pop_type (info);
assert (info->type_stack != NULL && info->type_stack->type.strdef != NULL);
@@ -5059,6 +5136,37 @@ ieee_struct_field (p, name, bitpos, bitsize, visibility)
|| ! ieee_write_atn65 (info, nindx, name))
return false;
info->type_stack->type.classdef->pmisccount += 4;
+
+ if (referencep)
+ {
+ unsigned int nindx;
+
+ /* We need to output a record recording that this field is
+ really of reference type. We put this on the refs field
+ of classdef, so that it can be appended to the C++
+ records after the class is defined. */
+
+ nindx = info->name_indx;
+ ++info->name_indx;
+
+ if (! ieee_change_buffer (info,
+ &info->type_stack->type.classdef->refs)
+ || ! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 62)
+ || ! ieee_write_number (info, 80)
+ || ! ieee_write_number (info, 4)
+ || ! ieee_write_asn (info, nindx, 'R')
+ || ! ieee_write_asn (info, nindx, 3)
+ || ! ieee_write_atn65 (info, nindx,
+ info->type_stack->type.classdef->name)
+ || ! ieee_write_atn65 (info, nindx, name))
+ return false;
+ }
}
/* If the bitsize doesn't match the expected size, we need to output
@@ -5158,6 +5266,8 @@ ieee_start_class_type (p, tag, id, structp, size, vptr, ownvptr)
{
assert (info->type_stack->type.classdef != NULL);
vclass = info->type_stack->type.classdef->name;
+ /* We don't call ieee_pop_unused_type, since the class should
+ get defined. */
(void) ieee_pop_type (info);
}
@@ -5214,10 +5324,10 @@ ieee_class_static_member (p, name, physname, visibility)
unsigned int flags;
unsigned int nindx;
- /* We don't care about the type. Hopefully there will be a call
+ /* We don't care about the type. Hopefully there will be a call to
ieee_variable declaring the physical name and the type, since
that is where an IEEE consumer must get the type. */
- (void) ieee_pop_type (info);
+ ieee_pop_unused_type (info);
assert (info->type_stack != NULL
&& info->type_stack->type.classdef != NULL);
@@ -5345,12 +5455,12 @@ ieee_class_method_var (info, physname, visibility, staticp, constp,
/* We don't need the type of the method. An IEEE consumer which
wants the type must track down the function by the physical name
and get the type from that. */
- (void) ieee_pop_type (info);
+ ieee_pop_unused_type (info);
/* We don't use the context. FIXME: We probably ought to use it to
adjust the voffset somehow, but I don't really know how. */
if (context)
- (void) ieee_pop_type (info);
+ ieee_pop_unused_type (info);
assert (info->type_stack != NULL
&& info->type_stack->type.classdef != NULL
@@ -5518,6 +5628,12 @@ ieee_end_class_type (p)
for (pb = &info->cxx; *pb != NULL; pb = &(*pb)->next)
;
*pb = info->type_stack->type.classdef->pmiscbuf;
+ if (info->type_stack->type.classdef->refs != NULL)
+ {
+ for (; *pb != NULL; pb = &(*pb)->next)
+ ;
+ *pb = info->type_stack->type.classdef->refs;
+ }
return ieee_end_struct_type (p);
}
@@ -5790,7 +5906,9 @@ ieee_typdef (p, name)
|| ! ieee_write_number (info, indx))
return false;
- /* Remove the type we just added to the type stack. */
+ /* Remove the type we just added to the type stack. This should not
+ be ieee_pop_unused_type, since the type is used, we just don't
+ need it now. */
(void) ieee_pop_type (info);
return true;
@@ -5805,6 +5923,8 @@ ieee_tag (p, name)
{
struct ieee_handle *info = (struct ieee_handle *) p;
+ /* This should not be ieee_pop_unused_type, since we want the type
+ to be defined. */
(void) ieee_pop_type (info);
return true;
}
@@ -5844,7 +5964,7 @@ ieee_typed_constant (p, name, val)
struct ieee_handle *info = (struct ieee_handle *) p;
/* FIXME. */
- (void) ieee_pop_type (info);
+ ieee_pop_unused_type (info);
return true;
}
@@ -5860,8 +5980,14 @@ ieee_variable (p, name, kind, val)
struct ieee_handle *info = (struct ieee_handle *) p;
unsigned int name_indx;
unsigned int size;
+ boolean referencep;
unsigned int type_indx;
boolean asn;
+ int refflag;
+
+ size = info->type_stack->type.size;
+ referencep = info->type_stack->type.referencep;
+ type_indx = ieee_pop_type (info);
/* Make sure the variable section is started. */
if (info->vars != NULL)
@@ -5882,9 +6008,6 @@ ieee_variable (p, name, kind, val)
name_indx = info->name_indx;
++info->name_indx;
- size = info->type_stack->type.size;
- type_indx = ieee_pop_type (info);
-
/* Write out an NN and an ATN record for this variable. */
if (! ieee_write_byte (info, (int) ieee_nn_record)
|| ! ieee_write_number (info, name_indx)
@@ -5902,19 +6025,28 @@ ieee_variable (p, name, kind, val)
if (! ieee_write_number (info, 8)
|| ! ieee_add_range (info, val, val + size))
return false;
+ refflag = 0;
asn = true;
break;
case DEBUG_STATIC:
+ if (! ieee_write_number (info, 3)
+ || ! ieee_add_range (info, val, val + size))
+ return false;
+ refflag = 1;
+ asn = true;
+ break;
case DEBUG_LOCAL_STATIC:
if (! ieee_write_number (info, 3)
|| ! ieee_add_range (info, val, val + size))
return false;
+ refflag = 2;
asn = true;
break;
case DEBUG_LOCAL:
if (! ieee_write_number (info, 1)
|| ! ieee_write_number (info, val))
return false;
+ refflag = 2;
asn = false;
break;
case DEBUG_REGISTER:
@@ -5922,6 +6054,7 @@ ieee_variable (p, name, kind, val)
|| ! ieee_write_number (info,
ieee_genreg_to_regno (info->abfd, val)))
return false;
+ refflag = 2;
asn = false;
break;
}
@@ -5932,6 +6065,41 @@ ieee_variable (p, name, kind, val)
return false;
}
+ /* If this is really a reference type, then we just output it with
+ pointer type, and must now output a C++ record indicating that it
+ is really reference type. */
+ if (referencep)
+ {
+ unsigned int nindx;
+
+ nindx = info->name_indx;
+ ++info->name_indx;
+
+ /* If this is a global variable, we want to output the misc
+ record in the C++ misc record block. Otherwise, we want to
+ output it just after the variable definition, which is where
+ the current buffer is. */
+ if (refflag != 2)
+ {
+ if (! ieee_change_buffer (info, &info->cxx))
+ return false;
+ }
+
+ if (! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 62)
+ || ! ieee_write_number (info, 80)
+ || ! ieee_write_number (info, 3)
+ || ! ieee_write_asn (info, nindx, 'R')
+ || ! ieee_write_asn (info, nindx, refflag)
+ || ! ieee_write_atn65 (info, nindx, name))
+ return false;
+ }
+
return true;
}
@@ -5944,7 +6112,63 @@ ieee_start_function (p, name, global)
boolean global;
{
struct ieee_handle *info = (struct ieee_handle *) p;
- unsigned int indx;
+ boolean referencep;
+ unsigned int retindx, typeindx;
+
+ referencep = info->type_stack->type.referencep;
+ retindx = ieee_pop_type (info);
+
+ /* Besides recording a BB4 or BB6 block, we record the type of the
+ function in the BB1 typedef block. We can't write out the full
+ type until we have seen all the parameters, so we accumulate it
+ in info->fntype and info->fnargs. */
+ if (info->fntype != NULL)
+ {
+ /* FIXME: This might happen someday if we support nested
+ functions. */
+ abort ();
+ }
+
+ info->fnname = name;
+
+ /* An attribute of 0x41 means that the frame and push mask are
+ unknown. */
+ if (! ieee_define_named_type (info, name, false, 0, 0, false, &info->fntype)
+ || ! ieee_write_number (info, 'x')
+ || ! ieee_write_number (info, 0x41)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, retindx))
+ return false;
+
+ typeindx = ieee_pop_type (info);
+
+ info->fnargs = NULL;
+ info->fnargcount = 0;
+
+ /* If the function return value is actually a reference type, we
+ must add a record indicating that. */
+ if (referencep)
+ {
+ unsigned int nindx;
+
+ nindx = info->name_indx;
+ ++info->name_indx;
+ if (! ieee_change_buffer (info, &info->cxx)
+ || ! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 62)
+ || ! ieee_write_number (info, 80)
+ || ! ieee_write_number (info, 3)
+ || ! ieee_write_asn (info, nindx, 'R')
+ || ! ieee_write_asn (info, nindx, global ? 0 : 1)
+ || ! ieee_write_atn65 (info, nindx, name))
+ return false;
+ }
/* Make sure the variable section is started. */
if (info->vars != NULL)
@@ -5962,8 +6186,6 @@ ieee_start_function (p, name, global)
return false;
}
- indx = ieee_pop_type (info);
-
/* The address is written out as the first block. */
++info->block_depth;
@@ -5973,7 +6195,7 @@ ieee_start_function (p, name, global)
&& ieee_write_number (info, 0)
&& ieee_write_id (info, name)
&& ieee_write_number (info, 0)
- && ieee_write_number (info, indx));
+ && ieee_write_number (info, typeindx));
}
/* Add a function parameter. This will normally be called before the
@@ -5996,6 +6218,7 @@ ieee_function_parameter (p, name, kind, val)
m->next = NULL;
m->name = name;
+ m->referencep = info->type_stack->type.referencep;
m->type = ieee_pop_type (info);
m->kind = kind;
m->val = val;
@@ -6004,6 +6227,12 @@ ieee_function_parameter (p, name, kind, val)
;
*pm = m;
+ /* Add the type to the fnargs list. */
+ if (! ieee_change_buffer (info, &info->fnargs)
+ || ! ieee_write_number (info, m->type))
+ return false;
+ ++info->fnargcount;
+
return true;
}
@@ -6014,11 +6243,11 @@ ieee_output_pending_parms (info)
struct ieee_handle *info;
{
struct ieee_pending_parm *m;
+ unsigned int refcount;
- m = info->pending_parms;
- while (m != NULL)
+ refcount = 0;
+ for (m = info->pending_parms; m != NULL; m = m->next)
{
- struct ieee_pending_parm *next;
enum debug_var_kind vkind;
switch (m->kind)
@@ -6036,17 +6265,61 @@ ieee_output_pending_parms (info)
break;
}
- if (! ieee_push_type (info, m->type, 0, false)
- || ! ieee_variable ((PTR) info, m->name, vkind, m->val))
+ if (! ieee_push_type (info, m->type, 0, false))
+ return false;
+ info->type_stack->type.referencep = m->referencep;
+ if (m->referencep)
+ ++refcount;
+ if (! ieee_variable ((PTR) info, m->name, vkind, m->val))
+ return false;
+ }
+
+ /* If there are any reference parameters, we need to output a
+ miscellaneous record indicating them. */
+ if (refcount > 0)
+ {
+ unsigned int nindx, varindx;
+
+ /* FIXME: The MRI compiler outputs the demangled function name
+ here, but we are outputting the mangled name. */
+ nindx = info->name_indx;
+ ++info->name_indx;
+ if (! ieee_change_buffer (info, &info->vars)
+ || ! ieee_write_byte (info, (int) ieee_nn_record)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_id (info, "")
+ || ! ieee_write_2bytes (info, (int) ieee_atn_record_enum)
+ || ! ieee_write_number (info, nindx)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_number (info, 62)
+ || ! ieee_write_number (info, 80)
+ || ! ieee_write_number (info, refcount + 3)
+ || ! ieee_write_asn (info, nindx, 'B')
+ || ! ieee_write_atn65 (info, nindx, info->fnname)
+ || ! ieee_write_asn (info, nindx, 0))
return false;
+ for (m = info->pending_parms, varindx = 1;
+ m != NULL;
+ m = m->next, varindx++)
+ {
+ if (m->referencep)
+ {
+ if (! ieee_write_asn (info, nindx, varindx))
+ return false;
+ }
+ }
+ }
- /* FIXME: We should output a pmisc note here for reference
- parameters. */
+ m = info->pending_parms;
+ while (m != NULL)
+ {
+ struct ieee_pending_parm *next;
next = m->next;
free (m);
m = next;
}
+
info->pending_parms = NULL;
return true;
@@ -6123,11 +6396,47 @@ ieee_end_function (p)
PTR p;
{
struct ieee_handle *info = (struct ieee_handle *) p;
+ struct ieee_buf **pb;
assert (info->block_depth == 1);
--info->block_depth;
+ /* Now we can finish up fntype, and add it to the typdef section.
+ At this point, fntype is the 'x' type up to the argument count,
+ and fnargs is the argument types. We must add the argument
+ count, and we must add the level. FIXME: We don't record varargs
+ functions correctly. In fact, stabs debugging does not give us
+ enough information to do so. */
+ if (! ieee_change_buffer (info, &info->fntype)
+ || ! ieee_write_number (info, info->fnargcount)
+ || ! ieee_change_buffer (info, &info->fnargs)
+ || ! ieee_write_number (info, 0))
+ return false;
+
+ /* Make sure the typdef block has been started. */
+ if (info->types == NULL)
+ {
+ if (! ieee_change_buffer (info, &info->types)
+ || ! ieee_write_byte (info, (int) ieee_bb_record_enum)
+ || ! ieee_write_byte (info, 1)
+ || ! ieee_write_number (info, 0)
+ || ! ieee_write_id (info, info->modname))
+ return false;
+ }
+
+ for (pb = &info->types; *pb != NULL; pb = &(*pb)->next)
+ ;
+ *pb = info->fntype;
+ for (; *pb != NULL; pb = &(*pb)->next)
+ ;
+ *pb = info->fnargs;
+
+ info->fnname = NULL;
+ info->fntype = NULL;
+ info->fnargs = NULL;
+ info->fnargcount = 0;
+
return true;
}