From: Ian Lance Taylor Date: Wed, 24 Jan 1996 19:40:21 +0000 (+0000) Subject: * ieee.c: Various changes to write out types for functions and X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=2466210755c857114fe94a9395c689a77a14c349;p=binutils-gdb.git * ieee.c: Various changes to write out types for functions and references, and to not write out unnecessary function types. --- diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 6050888777b..286485978ab 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,5 +1,8 @@ Wed Jan 24 12:06:05 1996 Ian Lance Taylor + * 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 822aa7d63dd..6b409852fa3 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; }