Rev 6 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/*
* Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of The TenDRA Project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific, prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
* IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id$
*/
/*
Crown Copyright (c) 1997
This TenDRA(r) Computer Program is subject to Copyright
owned by the United Kingdom Secretary of State for Defence
acting through the Defence Evaluation and Research Agency
(DERA). It is made available to Recipients with a
royalty-free licence for its use, reproduction, transfer
to other parties and amendment for any purpose not excluding
product development provided that any such use et cetera
shall be deemed to be acceptance of the following conditions:-
(1) Its Recipients shall ensure that this Notice is
reproduced upon any copies or amended versions of it;
(2) Any amended version of it shall be clearly marked to
show both the nature of and the organisation responsible
for the relevant amendment or amendments;
(3) Its onward transfer from a recipient to another
party shall be deemed to be that party's acceptance of
these conditions;
(4) DERA gives no warranty or assurance as to its
quality or suitability for any purpose and DERA accepts
no liability whatsoever in relation to any use to which
it may be put.
*/
/**********************************************************************
$Author: pwe $
$Date: 1998/03/15 16:00:35 $
$Revision: 1.5 $
$Log: dw2_info.c,v $
* Revision 1.5 1998/03/15 16:00:35 pwe
* regtrack dwarf dagnostics added
*
* Revision 1.4 1998/03/11 11:03:43 pwe
* DWARF optimisation info
*
* Revision 1.3 1998/02/18 11:22:20 pwe
* test corrections
*
* Revision 1.2 1998/01/21 10:30:06 pwe
* labdiff change
*
* Revision 1.1.1.1 1998/01/17 15:55:48 release
* First version to be checked into rolling release.
*
* Revision 1.13 1998/01/09 09:31:32 pwe
* prep restructure
*
* Revision 1.12 1997/12/04 19:41:31 pwe
* ANDF-DE V1.9
*
* Revision 1.11 1997/11/06 09:22:14 pwe
* ANDF-DE V1.8
*
* Revision 1.10 1997/10/28 10:14:22 pwe
* local location corrections
*
* Revision 1.9 1997/10/23 09:27:40 pwe
* ANDF-DE v1.7, extra diags
*
* Revision 1.8 1997/10/10 18:18:38 pwe
* prep ANDF-DE revision
*
* Revision 1.7 1997/08/23 13:36:45 pwe
* initial ANDF-DE
*
* Revision 1.6 1997/06/25 13:05:39 pwe
* constant global floats as well as local
*
* Revision 1.5 1997/06/25 12:16:16 pwe
* constant floats supported, 4-byte only
*
* Revision 1.4 1997/04/17 11:50:25 pwe
* Sparc and 80x86 support
*
* Revision 1.3 1997/04/04 15:17:13 pwe
* another (long)
*
* Revision 1.2 1997/04/01 17:19:40 pwe
* diagnose pl_tests and locate -> platform specific
*
* Revision 1.1 1997/03/20 16:09:18 pwe
* first version
*
**********************************************************************/
#include "config.h"
#include "common_types.h"
#include "dg_aux.h"
#include "dw2_config.h"
#include "dw2_entries.h"
#include "dw2_codes.h"
#include "dw2_info.h"
#include "dw2_basic.h"
#include "dw2_types.h"
#include "dw2_lines.h"
#include "dw2_iface.h"
#include "tags.h"
#include "expmacs.h"
#include "shapemacs.h"
#include "basicread.h"
#include "flags.h"
#include "flpt.h"
#include "flpttypes.h"
#include "externs.h"
#include "xalloc.h"
#include "dg_globs.h"
#include "f64.h"
#include "dw2_locdata.h"
long dw2_scope_start = 0;
long dw2_scope_end = 0;
int dw_doing_branch_tests = 0;
static long local_var_place;
static int doing_abstract = 0;
static int doing_inline = 0; /* consistency check only */
static dg_info proc_dg_info = (dg_info)0;
static dg_type return_type = (dg_type)0;
static dg_default *default_span_list = (dg_default *)0;
static void
fail_unimplemented(void)
{
failer("unimplemented attribute");
return;
}
static exp
find_id(exp e)
{
if (name(e) == name_tag && !isdiscarded(e) && !isvar(son(e))) {
return son(e);
}
if (name(e) == cont_tag && name(son(e)) == name_tag &&
!isdiscarded(son(e)) && (isvar(son(son(e))) ||
isparam(son(son(e))))) {
return son(son(e));
}
return nilexp;
}
void
dw_out_const(exp e)
{
switch (name(e)) {
case real_tag: {
int sw = (shape_size(sh(e)) <= 32 ? 0 : 1);
/* DWARF cannot represent extended reals */
r2l real_parts;
real_parts = real2longs_IEEE(&flptnos[no(e)], sw);
dw_at_form((sw ? DW_FORM_data8 : DW_FORM_data4));
d_outnl();
dw_at_data(4, (long)(real_parts.i1));
if (sw) {
dw_at_data(4, (long)(real_parts.i2));
}
break;
}
case val_tag:
case null_tag:
if (isbigval(e)) {
flt64 x;
int ov;
x = flt_to_f64(no(e), is_signed(sh(e)), &ov);
dw_at_form(DW_FORM_data8);
d_outnl();
dw_at_data(4, (long)(x.small));
dw_at_data(4, (long)(x.big));
} else if (is_signed(sh(e))) {
dw_at_form(DW_FORM_sdata);
outs(", ");
sleb128((long)no(e));
d_outnl();
} else {
dw_at_form(DW_FORM_udata);
outs(", ");
uleb128((unsigned long)no(e));
d_outnl();
}
break;
default:
dw_at_form(DW_FORM_block1);
d_outnl();
dw2_locate_exp(e, 1, 0);
}
return;
}
void
dw_out_default(dg_default *d)
{
if (d->val && dw_is_const(son(d->val))) {
dw_out_const(son(d->val));
} else if (d->span.sp_key != SP_SPAN) {
dw_at_form(DW_FORM_flag);
d_outnl();
dw_at_flag(1);
} else {
if (!d->lab) {
d->lab = next_dwarf_label();
d->next = default_span_list;
default_span_list = d;
}
dw_at_form(DW_FORM_ref_addr);
d_outnl();
dw_at_address(d->lab);
}
return;
}
void
complete_defaults(void)
{
while (default_span_list) {
out_dwf_label(default_span_list->lab, 1);
IGNORE dw_entry(dwe_span, (long)0);
IGNORE dw_entry(dwe_span_strt, (long)0);
dw_at_decl(shorten_sourcepos(default_span_list->span));
IGNORE dw_entry(dwe_span_end, (long)0);
dw_at_decl(end_sourcepos(default_span_list->span));
dw_sibling_end();
default_span_list = default_span_list->next;
}
return;
}
/* Not certain this is needed! */
static void
out_refblock(objset *objs, int assgn)
{
int count = 0;
#ifdef NEEDS_DEBUG_ALIGN
long over_lab;
#endif
objset * p = objs;
while (p) {
if (p->ass == assgn) {
count++;
}
p = p->next;
}
out16();
#ifdef NEEDS_DEBUG_ALIGN
if (count) {
over_lab = next_dwarf_label();
out_dwf_label(over_lab, 0);
outs(" - . - 2");
} else
#endif
outn(count * 4);
d_outnl();
if (count) {
p = objs;
while (p) {
if (p->ass == assgn) {
dw_at_ext_address(p->tg);
}
p = p->next;
}
#ifdef NEEDS_DEBUG_ALIGN
out_dwf_label(over_lab, 1);
#endif
}
return;
}
static void
check_trivial(exp e)
{
#if 0
/* This is still far too strong; e may be anything with equivalent
already in a register! */
if (e && name(e) != val_tag && name(e) != name_tag &&
(name(e) != cont_tag || name(son(e)) != name_tag) &&
name(e) != goto_tag && name(e) != top_tag) {
if (name(e) == chvar_tag || name(e) == chfl_tag)
check_trivial(son(e));
else
failer("lost information?");
}
#endif
return;
}
static void output_detch(detch_info *dl);
static detch_info *sub_detch = (detch_info *)0;
static void
output_info(exp e, dg_info d)
{
/* within info section */
if (!d) {
exp t;
if (!e) {
if (sub_detch) {
output_detch(sub_detch);
}
return;
}
if (name(e) == name_tag || name(e) == env_size_tag ||
name(e) == env_offset_tag || (t = son(e), !t)) {
return;
}
for (;;) {
output_info(t, dgf(t));
if (last(t) || name(e) == case_tag) {
return;
}
t = bro(t);
}
}
switch (d->key) {
case DGA_COMP:
if (!(d->data.i_comp.lo_pc)) {
/* optimised away */
check_trivial(e);
output_info(e, d->more);
break;
}
if (d->data.i_comp.is_tag) {
IGNORE dw_entry(dwe_for_unit, (long)0);
dw_at_address(d->data.i_comp.lo_pc);
dw_at_address(d->data.i_comp.hi_pc);
dw_at_ext_address(d->data.i_comp.corl.comp_tag);
}
else {
IGNORE dw_entry(dwe_for_lang, (long)0);
dw_at_address(d->data.i_comp.lo_pc);
dw_at_address(d->data.i_comp.hi_pc);
dw_at_udata((unsigned long)d->data.i_comp.corl.comp_lang);
}
output_info(e, d->more);
break;
case DGA_PARAMS:
output_info(e, d->more);
break;
case DGA_SRC:
output_info(e, d->more);
break;
case DGA_SCOPE: {
long old_scope1 = dw2_scope_start;
long old_scope2 = dw2_scope_end;
long attr1 = 0, attr2;
char * lexname = d->data.i_scope.lexname;
if (!doing_abstract) {
if (!(d->data.i_scope.start)) {
/* optimised away */
check_trivial(e);
output_info(e, d->more);
break;
}
if (lexname && lexname[0]) {
attr1 |= (H_NM | H_XY);
}
attr1 |= H_PC;
if (d->data.i_scope.begin_st) {
if (d->data.i_scope.begin_st == (long)(-1)) {
/* old diags */
d->data.i_scope.begin_st = (long)0;
} else {
attr1 |= H_BG;
}
}
}
dw2_scope_start = d->data.i_scope.start;
dw2_scope_end = d->data.i_scope.end;
attr2 = dw_entry(dwe_scope, attr1);
if (attr2 & ~(H_NM|H_XY|H_PC|H_BG)) {
fail_unimplemented();
}
if (attr2 & H_NM) {
dw_at_string(lexname);
}
if (attr2 & H_XY) {
dw_at_decl(d->data.i_scope.lexpos);
}
if (attr2 & H_PC) {
dw_at_address(dw2_scope_start);
dw_at_address(dw2_scope_end);
}
if (attr2 & H_BG) {
dw_at_address(d->data.i_scope.begin_st);
}
output_info(e, d->more);
dw_sibling_end();
dw2_scope_start = old_scope1;
dw2_scope_end = old_scope2;
break;
}
case DGA_EXTRA: {
long old_scope1 = dw2_scope_start;
long old_scope2 = dw2_scope_end;
dw2_scope_start = d->data.i_scope.start;
dw2_scope_end = d->data.i_scope.end;
if (!doing_abstract) {
IGNORE dw_entry(dwe_fragment, (long)0);
dw_at_address(dw2_scope_start);
dw_at_address(dw2_scope_end);
}
output_info(e, d->more);
if (!doing_abstract) {
dw_sibling_end();
}
dw2_scope_start = old_scope1;
dw2_scope_end = old_scope2;
break;
}
case DGA_LAB:
if (!doing_abstract) {
if (d->data.i_scope.start) {
IGNORE dw_entry(dwe_label, (long)0);
dw_at_string(d->data.i_scope.lexname);
dw_at_decl(d->data.i_scope.lexpos);
dw_at_address(d->data.i_scope.start);
} else {
check_trivial(e);
}
}
output_info(e, d->more);
break;
case DGA_NAME:
local_var_place = d->data.i_nam.scope_start;
dw2_out_name(d->data.i_nam.dnam, (e ? LOCAL_NAME : DEAD_NAME));
output_info(e, d->more);
break;
case DGA_WITH:
if (!doing_abstract) {
if (!(d->data.i_with.lo_pc) || !e) {
/* optimised away */
check_trivial(e);
output_info(e, d->more);
break;
}
IGNORE dw_entry(dwe_with, (long)0);
dw_at_ext_lab(dw2_find_type_label(d->data.i_with.w_typ));
dw2_locate_exp(son(d->data.i_with.w_exp), 0, 0);
dw_at_address(d->data.i_with.lo_pc);
dw_at_address(d->data.i_with.hi_pc);
}
output_info(e, d->more);
if (!doing_abstract) {
dw_sibling_end();
}
break;
case DGA_CALL:
if (doing_abstract) {
output_info(e, d->more);
} else {
if (!(d->data.i_call.brk)) {
/* optimised away */
check_trivial(e);
output_info(e, d->more);
break;
}
IGNORE dw_entry(dwe_call, (long)0);
dw_at_string(d->data.i_call.clnam);
dw_at_decl(d->data.i_call.pos);
dw_at_udata((unsigned long)d->data.i_call.ck);
dw_at_address(d->data.i_call.brk);
dw2_locate_val(d->data.i_call.p);
output_info(e, d->more);
}
break;
case DGA_INL_CALL: {
int old_il = doing_inline;
dg_type old_res = return_type;
dg_name_list args = d->data.i_inl.args;
dg_name di;
dg_type p_t, res_t;
long brk = d->data.i_inl.lo_pc;
if (doing_abstract) {
/* no recursion */
break;
}
di = d->data.i_inl.proc->p.nam;
p_t = find_proc_type(di->data.n_proc.typ);
res_t = p_t->data.t_proc.res_type;
return_type = res_t;
if (brk) {
/* sometimes lo = hi */
IGNORE dw_entry(dwe_inl_call, (long)0);
dw_at_ext_address(d->data.i_inl.proc);
dw_at_address(d->data.i_inl.lo_pc);
dw_at_address(d->data.i_inl.hi_pc);
} else {
/* call compressed into operand, so no breakpoint */
check_trivial(e);
IGNORE dw_entry(dwe_inl_opnd, (long)0);
dw_at_ext_address(d->data.i_inl.proc);
}
doing_inline = 1;
while (args) {
dw2_out_name(args, INL_PARAM_NAME);
args = args->next;
}
if (extra_diags && brk) {
dg_info rets = d->data.i_inl.resref;
long attr1 = H_XY, attr2;
if (rets) {
attr1 |= H_PC;
if (res_t) {
attr1 |= H_LC;
}
}
do {
attr2 = dw_entry(dwe_return, attr1);
if (attr2 & ~(H_XY|H_PC|H_LC)) {
fail_unimplemented();
}
if (attr2 & H_XY) {
dw_at_decl(di->mor->end_pos);
}
if (attr2 & H_PC) {
dw_at_address(rets->data.i_res.brk);
}
if (attr2 & H_LC) {
dw2_locate_val(rets->data.i_res.res);
}
if (!rets) {
break;
}
rets = rets->data.i_res.next;
} while (rets);
}
output_info(e, d->more);
doing_inline = old_il;
dw_sibling_end();
return_type = old_res;
break;
}
case DGA_INL_RES:
output_info(e, d->more);
break;
case DGA_X_TRY:
if (!doing_abstract) {
if (!(d->data.i_try.lo_pc)) {
/* optimised away */
check_trivial(e);
output_info(e, d->more);
break;
}
IGNORE dw_entry(dwe_try, (long)0);
dw_at_address(d->data.i_try.lo_pc);
dw_at_address(d->data.i_try.hi_pc);
}
output_info(e, d->more);
if (!doing_abstract) {
dw_sibling_end();
}
break;
case DGA_X_CATCH:
if (!doing_abstract) {
if (!(d->data.i_catch.lo_pc)) {
/* optimised away */
check_trivial(e);
output_info(e, d->more);
break;
}
IGNORE dw_entry(dwe_catch, (long)0);
dw_at_address(d->data.i_catch.lo_pc);
dw_at_address(d->data.i_catch.hi_pc);
if (d->data.i_catch.ex) {
dw2_out_name(d->data.i_catch.ex, EXCEPT_NAME);
} else {
IGNORE dw_entry(dwe_opt_par, (long)0);
}
}
output_info(e, d->more);
if (!doing_abstract) {
dw_sibling_end();
}
break;
case DGA_X_RAISE:
if (!doing_abstract) {
long attr1 = H_XY, attr2;
if (d->data.i_raise.x_typ) {
attr1 |= H_TP;
}
if (d->data.i_raise.x_val) {
attr1 |=
(dw_is_const(son(d->data.i_raise.x_val)) ?
H_CV : H_LC);
}
attr2 = dw_entry(dwe_throw, attr1);
if (attr2 & ~(H_XY|H_TP|H_LC|H_CV)) {
fail_unimplemented();
}
if (attr2 & H_XY) {
dw_at_decl(d->data.i_raise.pos);
}
if (attr2 & H_TP) {
dw_at_ext_lab(dw2_find_type_label(d->data.i_raise.x_typ));
}
if (attr2 & H_LC) {
dw2_locate_exp(son(d->data.i_raise.x_val), 0,
0);
}
if (attr2 & H_CV) {
dw_out_const(son(d->data.i_raise.x_val));
}
}
output_info(e, d->more);
break;
case DGA_BRANCH:
if (doing_abstract) {
output_info(e, d->more);
} else {
long brk = d->data.i_brn.brk;
if (brk) {
IGNORE dw_entry(dwe_branch, (long)0);
dw_at_decl(d->data.i_brn.pos);
dw_at_address(brk);
dw_at_address(d->data.i_brn.cont);
trace_dw_branch_exits(e);
} else {
check_trivial(e);
IGNORE dw_entry(dwe_branch_0, (long)0);
dw_at_decl(d->data.i_brn.pos);
}
output_info(e, d->more);
if (brk) {
dw_sibling_end();
}
}
break;
case DGA_TEST:
if (doing_abstract) {
output_info(e, d->more);
} else {
long brk = d->data.i_tst.brk;
if (brk) {
IGNORE dw_entry(dwe_test, (long)0);
dw_at_decl(d->data.i_tst.pos);
dw_at_address(d->data.i_tst.brk);
dw_at_address(d->data.i_tst.cont);
dw_at_ext_lab(d->data.i_tst.jlab);
} else {
check_trivial(e);
IGNORE dw_entry(dwe_test_0, (long)0);
dw_at_decl(d->data.i_tst.pos);
}
output_info(e, d->more);
}
break;
case DGA_JUMP:
if (doing_abstract) {
output_info(e, d->more);
} else {
long brk = d->data.i_tst.brk;
if (brk) {
IGNORE dw_entry(dwe_jump, (long)0);
dw_at_decl(d->data.i_tst.pos);
dw_at_address(d->data.i_tst.brk);
dw_at_ext_lab(d->data.i_tst.jlab);
} else {
check_trivial(e);
IGNORE dw_entry(dwe_jump_0, (long)0);
dw_at_decl(d->data.i_tst.pos);
}
output_info(e, d->more);
}
break;
case DGA_LJ:
if (doing_abstract) {
output_info(e, d->more);
} else {
long brk = d->data.i_lj.brk;
if (brk) {
IGNORE dw_entry(dwe_lj, (long)0);
dw_at_decl(d->data.i_lj.pos);
dw_at_address(d->data.i_lj.brk);
dw2_locate_val(d->data.i_lj.j);
} else {
check_trivial(e);
IGNORE dw_entry(dwe_lj_0, (long)0);
dw_at_decl(d->data.i_lj.pos);
}
output_info(e, d->more);
}
break;
case DGA_DEST:
if (!doing_abstract) {
long attr1 = 0, attr2;
if (!(d->data.i_dest.brk)) {
/* optimised away */
check_trivial(e);
output_info(e, d->more);
break;
}
if (d->data.i_dest.val) {
attr1 |= H_TP;
attr1 |= (dw_is_const(son(d->data.i_dest.val)) ?
H_CV : H_LC);
}
attr2 = dw_entry(dwe_destruct, attr1);
if (attr2 & ~(H_XY|H_TP|H_LC|H_CV)) {
fail_unimplemented();
}
dw_at_decl(d->data.i_dest.pos);
dw_at_address(d->data.i_dest.brk);
if (attr2 & H_TP) {
dw_at_ext_lab(dw2_find_type_label(return_type));
}
if (attr2 & H_LC) {
dw2_locate_exp(son(d->data.i_dest.val), 0, 0);
}
if (attr2 & H_CV) {
dw_out_const(son(d->data.i_dest.val));
}
}
output_info(e, d->more);
if (!doing_abstract) {
dw_sibling_end();
}
break;
case DGA_RVS:
if (d->data.i_rvs.has_iv) {
/* inverse ref, so don't output here */
break;
}
if (!doing_abstract) {
abbrev_entry dwe;
int w_alt = 0, w_en = 0, w_kind = 0;
switch (d->data.i_rvs.rvs_key) {
case DGR_SEL:
dwe = (d->data.i_rvs.async ? dwe_asynchsel :
dwe_select);
break;
case DGR_ACC:
dwe = (d->data.i_rvs.n_code ? dwe_accept_c :
dwe_accept);
w_alt = w_en = 1;
break;
case DGR_RTS:
dwe = dwe_rts;
w_alt = w_kind = 1;
if (d->data.i_rvs.en) {
dwe = dwe_rts_en;
w_en = 1;
}
break;
case DGR_ALT:
dwe = (d->data.i_rvs.n_code ? dwe_sel_alt_c :
dwe_sel_alt);
w_kind = 1;
break;
case DGR_SGD:
dwe = dwe_sel_guard;
break;
case DGR_TRIG:
dwe = (d->data.i_rvs.n_code ? dwe_trigger_c :
dwe_trigger);
w_kind = 1;
break;
case DGR_ABTL:
dwe = (d->data.i_rvs.n_code ? dwe_abort_ptc :
dwe_abort_pt);
break;
case DGR_REQUE:
dwe = dwe_requeue;
w_en = 1;
break;
}
IGNORE dw_entry(dwe, (long)0);
dw_at_decl(d->data.i_rvs.pos);
if (d->data.i_rvs.n_code) {
dw_at_address(d->data.i_rvs.lo_pc);
if (d->data.i_rvs.n_code >= 2) {
dw_at_address(d->data.i_rvs.hi_pc);
}
}
if (w_alt) {
dw_at_flag(d->data.i_rvs.alt);
}
if (w_en) {
dw_at_ext_address(d->data.i_rvs.en);
}
if (w_kind) {
dw_at_udata((unsigned long)d->data.i_rvs.kind);
}
if (d->data.i_rvs.rvs_key == DGR_ALT) {
dw_out_const(d->data.i_rvs.u2.e);
}
if (d->data.i_rvs.rvs_key == DGR_REQUE) {
dw_at_flag(d->data.i_rvs.w_abort);
}
if (d->data.i_rvs.rvs_key == DGR_ACC &&
d->data.i_rvs.n_code) {
dg_name_list args = d->data.i_rvs.u2.p;
while (args) {
dw2_out_name(args, INL_PARAM_NAME);
args = args->next;
}
}
if (d->data.i_rvs.holder) {
dg_info inner = d->data.i_rvs.u.iv;
while (inner) {
if (!inner->data.i_rvs.has_iv) {
failer("bad RVS invert");
}
inner->data.i_rvs.has_iv = 0;
output_info(inner->data.i_rvs.info_e,
inner);
inner->data.i_rvs.has_iv = 1;
inner = inner->data.i_rvs.u.iv;
}
}
}
output_info(e, d->more);
if (!doing_abstract && d->data.i_rvs.rvs_key != DGR_RTS &&
(d->data.i_rvs.n_code ||
(d->data.i_rvs.rvs_key == DGR_ALT ||
d->data.i_rvs.rvs_key == DGR_TRIG))) {
dw_sibling_end();
}
break;
}
case DGA_DETCH:
if (d->data.i_detch.posn < 0) {
output_detch(d->data.i_detch.dl);
output_info(e, d->more);
}
else {
output_info(e, d->more);
output_detch(d->data.i_detch.dl);
}
break;
case DGA_MOVD:
case DGA_HOIST:
if (!doing_abstract) {
dg_tag tg = d->data.i_movd.tg;
if (d->this_tag) {
set_ext_address(d->this_tag);
}
if (d->data.i_movd.lo_pc) {
IGNORE dw_entry((tg ? dwe_moved_r : dwe_moved),
(long)0);
dw_at_udata((unsigned long)d->data.i_movd.reason);
if (tg) {
dw_at_ext_address(tg);
}
dw_at_address(d->data.i_movd.lo_pc);
dw_at_address(d->data.i_movd.hi_pc);
} else {
check_trivial(e);
IGNORE dw_entry((tg ? dwe_moved_xr :
dwe_moved_x), (long)0);
dw_at_udata((unsigned long)d->data.i_movd.reason);
if (tg) {
dw_at_ext_address(tg);
}
}
}
output_info(e, d->more);
if (!doing_abstract) {
dw_sibling_end();
}
break;
case DGA_OPTIM: {
if (!doing_abstract) {
if (d->this_tag) {
set_ext_address(d->this_tag);
}
if (d->data.i_optim.lo_pc) {
IGNORE dw_entry(dwe_optim, (long)0);
dw_at_udata((unsigned long)d->data.i_optim.reason);
dw_at_address(d->data.i_optim.lo_pc);
dw_at_address(d->data.i_optim.hi_pc);
/* unassigned refs */
out_refblock (d->data.i_optim.objs, 0);
/* assigned refs */
out_refblock (d->data.i_optim.objs, 1);
} else {
check_trivial(e);
IGNORE dw_entry(dwe_moved_x, (long)0);
dw_at_udata((unsigned long)d->data.i_movd.reason);
}
}
output_info(e, d->more);
if (!doing_abstract) {
dw_sibling_end();
}
break;
}
case DGA_REMVAL:
case DGA_BEG:
case DGA_BAR:
case DGA_NONE:
output_info(e, d->more);
break;
default:
failer("unexpected dg_info");
}
return;
}
static void
output_detch(detch_info *dl)
{
while (dl) {
int has_child = 0;
int has_dest = 0;
int reason = dl->why;
dg_info d_src = dl->info;
dg_info more_src = (dg_info)0;
dg_tag tg = dl->tg;
while (tg && tg->copy) {
tg = tg->copy;
}
if (tg && tg->p.info->key == DGA_MOVD) {
d_src = tg->p.info;
reason = d_src->data.i_movd.reason;
if (d_src->data.i_movd.lost) {
tg = d_src->data.i_movd.tg;
} else {
has_dest = 1;
}
d_src = d_src->more;
}
if (has_dest) {
if (d_src->key == DGA_SRC && !doing_abstract) {
IGNORE dw_entry(dwe_displ_x, (long)0);
dw_at_ext_address(tg);
dw_at_decl(d_src->data.i_src.startpos);
} else if (!doing_abstract &&
d_src->key != DGA_INL_RES &&
(d_src->key != DGA_RVS ||
!d_src->data.i_rvs.has_iv) &&
d_src->key != DGA_BEG &&
d_src->key != DGA_BAR) {
IGNORE dw_entry(dwe_displaced, (long)0);
dw_at_ext_address(tg);
}
} else {
if (d_src->key == DGA_SRC && !doing_abstract) {
IGNORE dw_entry((tg ? dwe_absent_xr :
dwe_absent_x), (long)0);
dw_at_udata((unsigned long)reason);
if (tg) {
dw_at_ext_address(tg);
}
dw_at_decl(d_src->data.i_src.startpos);
} else if (d_src->key == DGA_NAME) {
/* included when doing_abstract */
more_src = d_src;
} else if (!doing_abstract &&
d_src->key != DGA_INL_RES &&
(d_src->key != DGA_RVS ||
!d_src->data.i_rvs.has_iv) &&
d_src->key != DGA_BEG &&
d_src->key != DGA_BAR) {
has_child = 1;
more_src = d_src;
more_src->more = (dg_info)0;
IGNORE dw_entry((tg ? dwe_absent_r :
dwe_absent), (long)0);
dw_at_udata((unsigned long)reason);
if (tg) {
dw_at_ext_address(tg);
}
}
}
{
detch_info *old = sub_detch;
sub_detch = dl->sub;
output_info(nilexp, more_src);
sub_detch = old;
}
if (has_child) {
dw_sibling_end();
}
dl = dl->next;
}
return;
}
static void
out_param(dg_param p)
{
/* within debug_info */
/* used for declarations only */
long attr1 = (H_TP | H_VP), attr2;
if (p.pnam[0]) {
attr1 |= H_NM;
}
if (p.ppos.file) {
attr1 |= H_XY;
}
#ifdef H_DX
if (p.p_dflt) {
if (p.p_dflt->span.sp_key == SP_SPAN ||
(p.p_dflt->val && dw_is_const(son(p.p_dflt->val)))) {
attr1 |= H_DF;
} else {
attr1 |= H_DX;
}
}
#else
if (p.p_dflt) {
attr1 |= H_DF;
}
#endif
attr2 = dw_entry(dwe_param, attr1);
#ifdef H_DX
if (attr2 & ~(H_NM|H_XY|H_TP|H_VP|H_DF|H_DX)) {
#else
if (attr2 & ~(H_NM|H_XY|H_TP|H_VP|H_DF)) {
#endif
fail_unimplemented();
}
if (attr2 & H_NM) {
dw_at_string(p.pnam);
}
if (attr2 & H_XY) {
dw_at_decl(p.ppos);
}
if (attr2 & H_TP) {
dw_at_ext_lab(dw2_find_type_label(p.p_typ));
}
if (attr2 & H_VP) {
int vp = 0;
if (p.pmode == DG_OUT_MODE || p.pmode == DG_INOUT_MODE) {
vp = 1;
}
dw_at_flag(vp);
}
#ifdef H_DX
if (attr2 & H_DX) {
dw_at_flag((p.p_dflt && !(attr2 & H_DF))? 1 : 0);
}
#endif
if (attr2 & H_DF) {
dw_out_default(p.p_dflt);
}
return;
}
static void
dw2_out_proc(dg_name di)
{
/* within debug_info section */
int old_il = doing_inline;
int old_ab = doing_abstract;
long infolab = 0;
exp id;
dg_type p_t, res_t;
dg_type old_res = return_type;
long is_callable = DW_CC_normal;
char *nam;
char *gnam = "";
long attr1, attr2;
dg_instantn *generic = (dg_instantn *)0;
dg_info old_di = proc_dg_info;
proc_dg_info = (dg_info)0;
if (di->idnam.id_key == DG_ID_INST) {
generic = di->idnam.idd.instance;
if (generic->nam.id_key == DG_ID_ANON) {
nam = generic->spec.idd.nam;
} else {
nam = generic->nam.idd.nam;
gnam = generic->spec.idd.nam;
}
} else {
nam = di->idnam.idd.nam;
}
p_t = find_proc_type(di->data.n_proc.typ);
res_t = p_t->data.t_proc.res_type;
return_type = res_t;
id = di->data.n_proc.obtain_val;
if (id) {
exp p;
if (name(id) != hold_tag || name(son(id)) != name_tag) {
failer("wrong proc obtain_tag");
return;
}
id = son(son(id));
p = son(id);
if (p) {
exp t = son(p);
dw2_prepare_locate(id);
proc_dg_info = dgf(p);
if (proc_dg_info && proc_dg_info->key != DGA_PRC) {
failer("inconsistent proc info");
}
if (proc_has_vcallees(p)) {
is_callable = DW_CC_nocall;
}
while (name(t) == ident_tag && isparam(t) &&
name(son(t)) != formal_callee_tag) {
t = bro(son(t));
}
if (name(t) == ident_tag &&
name(son(t)) == formal_callee_tag) {
is_callable = DW_CC_nocall;
}
if (brog(id)->dec_u.dec_val.extnamed) {
infolab = next_dwarf_label();
exit_section();
enter_section("debug_pubnames");
out32();
out_dwf_labdiff(dw_info_start, infolab);
d_outnl();
out_string(nam);
exit_section();
enter_section("debug_info");
}
}
}
if (p_t->data.t_proc.prps & (f_untidy | f_var_callees)) {
is_callable = DW_CC_nocall;
}
if (di->mor && di->mor->refspec) {
attr1 = H_SP | H_XY;
} else {
attr1 = H_NM | H_XY;
if (res_t) {
attr1 |= H_TP;
}
switch (di->idnam.id_key) {
case DG_ID_EXT:
attr1 |= H_EX;
break;
case DG_ID_ARTFL:
attr1 |= H_AT;
break;
case DG_ID_INST:
if (gnam[0]) {
attr1 |= H_GN;
}
break;
default:
break;
}
if (p_t->data.t_proc.knowpro) {
attr1 |= H_PT;
}
if (p_t->data.t_proc.lang) {
attr1 |= H_LN;
}
if (p_t->data.t_proc.ccv) {
attr1 |= H_CC;
if (p_t->data.t_proc.ccv != DW_CC_normal) {
is_callable = p_t->data.t_proc.ccv;
}
}
}
if (is_callable |= DW_CC_normal) {
attr1 |= H_CC;
}
if (di->mor && di->mor->isspec) {
attr1 |= H_DC;
}
if (di->mor && di->mor->issep) {
attr1 |= H_SE;
}
if (di->mor && di->mor->acc) {
attr1 |= H_AC;
}
if (di->mor && di->mor->virt) {
attr1 |= H_VT;
}
if (di->mor && di->mor->vslot) {
attr1 |= H_VL;
}
if (di->mor && di->mor->repn) {
attr1 |= H_RP;
}
doing_abstract = 0;
if (di->mor && di->mor->this_tag) {
set_ext_address(di->mor->this_tag);
if (di->mor->this_tag->any_inl) {
doing_abstract = 1;
attr1 |= H_IL;
}
}
do {
if (!doing_abstract && proc_dg_info) {
if (infolab) {
out_dwf_label(infolab, 1);
}
attr1 |= H_PC;
if (proc_dg_info->data.i_prc.p &&
proc_dg_info->data.i_prc.p->data.i_param.o_env) {
attr1 |= H_SL;
}
if (di->mor && di->mor->elabn) {
attr1 |= H_EL;
}
}
attr2 = dw_entry(dwe_proc, attr1);
if (attr2 & ~(H_AO|H_SP|H_DC|H_NM|H_XY|H_EX|H_AT|H_AC|H_CC|
H_TP|H_PT|H_IL|H_VT|H_VL|H_PC|H_SL|H_EXTN)) {
fail_unimplemented();
}
if (attr2 & H_AO) {
dw_at_ext_address(di->mor->this_tag);
}
if (attr2 & H_SP) {
dw_at_ext_address(di->mor->refspec);
}
if (attr2 & H_DC) {
dw_at_flag((di->mor && di->mor->isspec ? 1 : 0));
}
if (attr2 & H_NM) {
dw_at_string(nam);
}
if (attr2 & H_XY) {
dw_at_decl(di->whence);
}
if (attr2 & H_EX) {
dw_at_flag((di->idnam.id_key == DG_ID_EXT ? 1 : 0));
}
if (attr2 & H_AT) {
dw_at_flag((di->idnam.id_key == DG_ID_ARTFL ? 1 : 0));
}
if (attr2 & H_AC) {
dw_at_data(1, (long)(di->mor ? di->mor->acc : 0));
}
if (attr2 & H_CC) {
dw_at_data(1, is_callable);
}
if (attr2 & H_TP) {
dw_at_ext_lab(dw2_find_type_label(res_t));
}
if (attr2 & H_PT) {
dw_at_flag(p_t->data.t_proc.yespro);
}
if (attr2 & H_IL) {
dw_at_data(1, (long)(di->mor->isinline ?
DW_INL_declared_inlined :
DW_INL_inlined));
}
if (attr2 & H_VT) {
dw_at_data(1, (long)(di->mor ? di->mor->virt : 0));
}
if (attr2 & H_VL) {
dw2_locate_exp(son(di->mor->vslot), 0, 0);
}
if (attr2 & H_PC) {
dw_at_address(proc_dg_info->data.i_prc.prc_start);
dw_at_address(proc_dg_info->data.i_prc.prc_end);
/* return address and frame_base */
dw_at_procdetails();
}
if (attr2 & H_SL) {
dw2_locate_exp(son(proc_dg_info->data.i_prc.p->data.i_param.o_env), 1, 0);
}
if (attr2 & H_EXTN) {
long block_end = next_dwarf_label();
attr1 &= ~attr2;
if (attr1 & ~(H_EL|H_GN|H_RP|H_LN|H_SE)) {
fail_unimplemented();
}
out16();
out_dwf_dist_to_label(block_end);
d_outnl();
if (attr1 & H_EL) {
set_attribute(DW_AT_DD_elaboration,
DW_FORM_ref_addr);
dw_at_ext_address(di->mor->elabn);
}
if (attr1 & H_GN) {
set_attribute(DW_AT_DD_generic_name,
DW_FORM_string);
dw_at_string(gnam);
}
if (attr1 & H_RP) {
set_attribute(DW_AT_DD_repn, 0);
dw_out_const(son(di->mor->repn));
}
if (attr1 & H_LN) {
set_attribute(DW_AT_language, DW_FORM_udata);
dw_at_udata((unsigned long)(p_t->data.t_proc.lang));
}
if (attr1 & H_SE) {
set_attribute(DW_AT_DD_separate, DW_FORM_flag);
dw_at_flag((di->mor && di->mor->issep ? 1 : 0));
}
set_attribute(0, 0);
out_dwf_label(block_end, 1);
}
if (!doing_abstract && generic) {
dw2_out_generic(generic->params);
}
if (!doing_abstract && !proc_dg_info &&
!di->data.n_proc.params) {
/* must be declaration only */
dg_param *el = p_t->data.t_proc.params.array;
int i;
for (i = 0; i < p_t->data.t_proc.params.len; i++) {
out_param(el[i]);
}
if (p_t->data.t_proc.prps & f_var_callers) {
IGNORE dw_entry(dwe_opt_par,(long)0);
}
if (di->mor && di->mor->en_family)
dw_out_dim(*(di->mor->en_family));
dw_sibling_end();
break; /* to return */
}
{
dg_name param = (dg_name)0;
dg_param *el = p_t->data.t_proc.params.array;
int w = 0;
if (proc_dg_info && proc_dg_info->data.i_prc.p) {
param = proc_dg_info->data.i_prc.p->data.i_param.args;
} else if (di->data.n_proc.params) {
param =
di->data.n_proc.params->data.i_param.args;
}
while (param) {
if (param->key == DGN_OBJECT) {
if (w < p_t->data.t_proc.params.len) {
param->data.n_obj.p = & (el[w]);
} else {
param->data.n_obj.p =
(dg_param *)0;
}
}
if (doing_abstract) {
if (!(param->mor) ||
!(param->mor->this_tag)) {
failer("param inlining error");
}
param->mor->inline_ref =
param->mor->this_tag;
}
dw2_out_name(param, PARAM_NAME);
param = param->next;
w++;
}
}
if (p_t->data.t_proc.prps & f_var_callers) {
IGNORE dw_entry(dwe_opt_par, (long)0);
}
if (!doing_abstract && di->mor && di->mor->exptns.len) {
dg_type *et = di->mor->exptns.array;
int i;
for (i = 0; i < di->mor->exptns.len; i++) {
IGNORE dw_entry(dwe_thrown_t, (long)0);
dw_at_ext_lab(dw2_find_type_label(et[i]));
}
}
if (di->mor && di->mor->en_family) {
dw_out_dim(*(di->mor->en_family));
}
if (proc_dg_info && proc_dg_info->data.i_prc.barrier) {
dg_info b = proc_dg_info->data.i_prc.barrier;
IGNORE dw_entry(dwe_barrier, (long)0);
dw_at_decl(b->data.i_bar.pos);
dw_at_address(b->data.i_bar.lo_pc);
dw_at_address(b->data.i_bar.hi_pc);
}
if (!doing_abstract && extra_diags && proc_dg_info) {
long atret1 = H_XY, atret2;
retrec *rets = proc_dg_info->data.i_prc.returns;
if (rets) {
atret1 |= H_PC;
if (res_t) {
atret1 |= H_LC;
}
}
do {
atret2 = dw_entry(dwe_return, atret1);
if (atret2 & ~(H_XY|H_PC|H_LC)) {
fail_unimplemented();
}
if (atret2 & H_XY) {
dw_at_decl(di->mor->end_pos);
}
if (atret2 & H_PC) {
dw_at_address(rets->lab);
}
if (atret2 & H_LC) {
dw2_locate_result(pt(son(id)));
}
if (!rets) {
break;
}
rets = rets->next;
}
while (rets);
}
if (id && (proc_dg_info || doing_abstract)) {
output_info(son(id), (proc_dg_info ?
dgf(son(id))->more :
dgf(son(id))));
}
dw_sibling_end();
if (doing_abstract) {
doing_abstract = 0;
doing_inline = 1;
attr1 = H_AO;
} else {
break;
}
} while (proc_dg_info);
doing_abstract = old_ab;
doing_inline = old_il;
proc_dg_info = old_di;
return_type = old_res;
return;
}
void
dw2_out_generic(dg_name_list p)
{
while (p) {
switch (p->key) {
case DGN_OBJECT:
IGNORE dw_entry(dwe_tmpl_val, (long)0);
dw_at_string(idname_chars(p->idnam));
dw_at_decl(p->whence);
dw_at_ext_lab(dw2_find_type_label(p->data.n_obj.typ));
dw_out_const(son(p->data.n_obj.obtain_val));
break;
case DGN_TYPE:
IGNORE dw_entry(dwe_tmpl_type, (long)0);
dw_at_string(idname_chars(p->idnam));
dw_at_decl(p->whence);
dw_at_ext_lab(dw2_find_type_label(p->data.n_typ.raw));
break;
case DGN_PROC:
IGNORE dw_entry(dwe_tmpl_proc, (long)0);
dw_at_string(idname_chars(p->idnam));
dw_at_decl(p->whence);
dw_at_ext_address(p->mor->refspec);
break;
case DGN_MODULE:
IGNORE dw_entry(dwe_tmpl_mod, (long)0);
dw_at_string(idname_chars(p->idnam));
dw_at_decl(p->whence);
dw_at_ext_address(p->mor->refspec);
break;
default:
break;
}
p = p->next;
}
return;
}
void
dw2_out_name(dg_name di, dg_nm_contex contex)
{
/* in debug_info section */
dg_tag inl_tag = (di->mor ? di->mor->inline_ref : (dg_tag)0);
if (di->mor && di->mor->this_tag && !di->mor->this_tag->outref.k) {
di->mor->this_tag->outref.k = LAB_D;
di->mor->this_tag->outref.u.l = next_dwarf_label();
}
/* EXCEPT_NAME, INSTANTN_NAME not done yet */
if ((contex == LOCAL_NAME || contex == DEAD_NAME) && !doing_abstract) {
if (!dw2_scope_start) {
failer("missing scope");
}
}
switch (di->key) {
case DGN_OBJECT: {
exp x = di->data.n_obj.obtain_val;
dg_type typ = di->data.n_obj.typ;
dg_param *ppar = (contex == PARAM_NAME ? di->data.n_obj.p :
(dg_param *)0);
char *nam = idname_chars(di->idnam);
long attr1 = 0, attr2;
long loclab = 0, loclabext = 0, infolab = 0;
abbrev_entry dwe;
if ((inl_tag && !doing_inline && !doing_abstract) ||
(!inl_tag && doing_inline)) {
failer("inline inconsistency");
}
if (contex == GLOBAL_NAME && di->idnam.id_key == DG_ID_EXT &&
x && find_id(son(x))) {
infolab = next_dwarf_label();
exit_section();
enter_section("debug_pubnames");
out32();
out_dwf_labdiff(dw_info_start, infolab);
d_outnl();
dw_at_string(nam);
exit_section();
enter_section("debug_info");
}
if (contex == PARAM_NAME || contex == INL_PARAM_NAME) {
dwe = dwe_param;
} else if (di->mor && di->mor->isconst) {
dwe = dwe_constant;
} else {
dwe = dwe_variable;
}
if (doing_inline) {
attr1 |= H_AO;
} else {
if (di->mor && di->mor->refspec) {
attr1 |= (H_SP | H_XY);
} else {
attr1 |= (H_NM | H_XY | H_TP);
if (contex == GLOBAL_NAME) {
attr1 |= H_EX;
}
if (di->idnam.id_key == DG_ID_ARTFL) {
attr1 |= H_AT;
}
}
if (di->mor && di->mor->isspec) {
attr1 |= H_DC;
}
if (di->mor && di->mor->acc) {
attr1 |= H_AC;
}
if (contex == PARAM_NAME) {
attr1 |= H_VP;
#ifdef H_DX
if (ppar && ppar->p_dflt) {
if (ppar->p_dflt->span.sp_key ==
SP_SPAN ||
(ppar->p_dflt->val &&
dw_is_const(son(ppar->p_dflt->val)))) {
attr1 |= H_DF;
} else {
attr1 |= H_DX;
}
}
#else
if (ppar && ppar->p_dflt) {
attr1 |= H_DF;
}
#endif
}
if (di->mor && di->mor->repn) {
attr1 |= H_RP;
}
}
if (!doing_abstract && !(attr1 & H_DC)) {
if (!x) {
failer("obtain_value missing");
}
if (contex == LOCAL_NAME || contex == DEAD_NAME) {
attr1 |= H_SS;
}
if (contex != DEAD_NAME && dw_is_const(son(x))) {
attr1 |= H_CV;
} else {
int ll = decide_ll_type(x);
if (!ll && contex == PARAM_NAME) {
ll = 1;
}
attr1 |= (ll ? H_LL : H_LC);
if (ll > 1) {
attr1 |= H_LE;
}
}
}
if (di->mor && di->mor->this_tag) {
if (doing_abstract) {
set_abstract_lab(di->mor->this_tag);
} else {
set_ext_address(di->mor->this_tag);
}
}
if (infolab) {
out_dwf_label(infolab, 1);
}
attr2 = dw_entry(dwe, attr1);
if (attr2 & ~(H_AO|H_SP|H_DC|H_NM|H_XY|H_EX|H_AT|H_AC|H_TP|H_VP|
#ifdef H_DX
H_SS|H_LC|H_LL|H_LE|H_CV|H_RP|H_DF|H_DX)) {
#else
H_SS|H_LC|H_LL|H_LE|H_CV|H_RP|H_DF)) {
#endif
fail_unimplemented();
}
if (attr2 & H_AO) {
dw_at_abstract_lab(inl_tag);
}
if (attr2 & H_SP) {
dw_at_ext_address(di->mor->refspec);
}
if (attr2 & H_DC) {
dw_at_flag((di->mor && di->mor->isspec ? 1 : 0));
}
if (attr2 & H_NM) {
dw_at_string(nam);
}
if (attr2 & H_XY) {
dw_at_decl(di->whence);
}
if (attr2 & H_EX) {
dw_at_flag((infolab ? 1 : 0));
}
if (attr2 & H_AT) {
dw_at_flag((di->idnam.id_key == DG_ID_ARTFL ? 1 : 0));
}
if (attr2 & H_AC) {
dw_at_data(1, (long)(di->mor ? di->mor->acc : 0));
}
if (attr2 & H_TP) {
dw_at_ext_lab(dw2_find_type_label(typ));
}
if (attr2 & H_VP) {
int vp = 0;
if (ppar && (ppar->pmode == DG_OUT_MODE ||
ppar->pmode == DG_INOUT_MODE)) {
vp = 1;
}
dw_at_flag(vp);
}
#ifdef H_DX
if (attr2 & H_DX) {
dw_at_flag((ppar && ppar->p_dflt &&
!(attr2 & H_DF)) ? 1 : 0);
}
#endif
if (attr2 & H_DF) {
dw_out_default(ppar->p_dflt);
}
if (attr2 & H_SS) {
dw_at_distance(dw2_scope_start, local_var_place);
}
if (attr2 & H_CV) {
dw_out_const(son(x));
}
if (attr2 & H_LC) {
if (contex == DEAD_NAME) {
dw_no_locate();
} else {
dw2_locate_exp(son(x), 0, 0);
}
}
if (attr2 & H_LL) {
dw_at_address(loclab = next_dwarf_label());
}
if (attr2 & H_LE) {
dw_at_address(loclabext = next_dwarf_label());
}
if (attr2 & H_RP) {
dw_out_const(son(di->mor->repn));
}
if (loclab) {
long lstart, lend;
#if 0
retrec * rets = proc_dg_info->data.i_prc.returns;
long rstart = proc_dg_info->data.i_prc.p->data.i_param.b_start, rend;
#endif
exit_section();
enter_section("debug_loc");
out_dwf_label(loclab, 1);
if (contex == PARAM_NAME) {
lstart = proc_dg_info->data.i_prc.prc_start;
out_loc_range(lstart, lstart, 1);
dw2_locate_exp(son(x), 0, 3);
lstart = proc_dg_info->data.i_prc.p->data.i_param.b_start;
lend = proc_dg_info->data.i_prc.prc_end;
} else {
lstart = dw2_scope_start;
lend = dw2_scope_end;
}
out_obj_loclist(lstart, lend, x);
#if 0
while (rets) {
if (rets->over) {
rend = rets->lab;
if (rend != rstart) {
out_loc_range(rstart, rend, 0);
dw2_locate_exp(son(x), 0, 1);
}
rstart = rets->over;
}
rets = rets->next;
}
rend = proc_dg_info->data.i_prc.prc_end;
if (rend != rstart) {
out_loc_range(rstart, rend, 0);
dw2_locate_exp(son(x), 0, 1);
}
#endif
out32();
outs("0, 0");
outnl_comment("loclist end");
if (loclabext) {
out_dwf_label(loclabext, 1);
out_obj_extloclist(lstart, lend, x);
out32();
outs("0, 0");
outnl_comment("extension end");
}
out_obj_shared_set(di);
exit_section();
enter_section("debug_info");
}
break;
}
case DGN_PROC:
dw2_out_proc(di);
break;
case DGN_MODULE:
case DGN_NSP: {
char *nam;
char *gnam = "";
long attr1 = 0, attr2;
abbrev_entry dwe;
int has_init_code = 0;
exp id = di->data.n_mod.init;
dg_instantn *generic = (dg_instantn *)0;
dg_name mem;
if (id && name(id) == hold_tag && name(son(id)) == name_tag) {
id = son(son(id));
if (son(id) &&
(name(son(id)) == apply_tag ||
name(son(id)) == apply_general_tag)) {
dw2_prepare_locate(id);
if (dgf(son(id))) {
has_init_code = 1;
}
}
}
if (di->key == DGN_MODULE) {
dwe = dwe_module;
} else {
dwe = dwe_namespace;
}
if (di->idnam.id_key == DG_ID_INST) {
generic = di->idnam.idd.instance;
if (generic->nam.id_key == DG_ID_ANON) {
nam = generic->spec.idd.nam;
} else {
nam = generic->nam.idd.nam;
gnam = generic->spec.idd.nam;
}
} else {
nam = di->idnam.idd.nam;
}
if (doing_inline) {
attr1 |= H_AO;
} else {
if (di->mor && di->mor->refspec) {
attr1 = H_SP | H_XY;
} else {
attr1 = H_NM | H_XY;
switch (di->idnam.id_key) {
case DG_ID_ARTFL:
attr1 |= H_AT;
break;
case DG_ID_INST:
if (gnam[0]) {
attr1 |= H_GN;
}
break;
default:
break;
}
}
if (di->mor && di->mor->isspec) {
attr1 |= H_DC;
}
if (di->mor && di->mor->issep) {
attr1 |= H_SE;
}
}
if (!doing_abstract) {
if (has_init_code) {
attr1 |= H_PC;
}
if (di->mor && di->mor->elabn) {
attr1 |= H_EL;
}
}
if (di->mor && di->mor->this_tag) {
if (doing_abstract) {
set_abstract_lab(di->mor->this_tag);
} else {
set_ext_address(di->mor->this_tag);
}
}
attr2 = dw_entry(dwe, attr1);
if (attr2 & ~(H_AO|H_SP|H_DC|H_NM|H_XY|H_AT|H_AC|H_PC|H_EXTN)) {
fail_unimplemented();
}
if (attr2 & H_AO) {
dw_at_abstract_lab(inl_tag);
}
if (attr2 & H_SP) {
dw_at_ext_address(di->mor->refspec);
}
if (attr2 & H_DC) {
dw_at_flag((di->mor && di->mor->isspec ? 1 : 0));
}
if (attr2 & H_NM) {
dw_at_string(nam);
}
if (attr2 & H_XY) {
dw_at_decl(di->whence);
}
if (attr2 & H_AT) {
dw_at_flag((di->idnam.id_key == DG_ID_ARTFL ? 1 : 0));
}
if (attr2 & H_AC) {
dw_at_data(1, (long)(di->mor ? di->mor->acc : 0));
}
if (attr2 & H_PC) {
dg_info pd = dgf(son(id));
if (pd->key != DGA_PRC) {
failer("inconsistent proc info");
}
dw_at_address(pd->data.i_prc.prc_start);
dw_at_address(pd->data.i_prc.prc_end);
}
if (attr2 & H_EXTN) {
long block_end = next_dwarf_label();
attr1 &= ~attr2;
if (attr1 & ~(H_EL|H_GN|H_SE)) {
fail_unimplemented();
}
out16();
out_dwf_dist_to_label(block_end);
d_outnl();
if (attr1 & H_EL) {
set_attribute(DW_AT_DD_elaboration,
DW_FORM_ref_addr);
dw_at_ext_address(di->mor->elabn);
}
if (attr1 & H_GN) {
set_attribute(DW_AT_DD_generic_name,
DW_FORM_string);
dw_at_string(gnam);
}
if (attr1 & H_SE) {
set_attribute(DW_AT_DD_separate, DW_FORM_flag);
dw_at_flag((di->mor && di->mor->issep ? 1 : 0));
}
set_attribute(0, 0);
out_dwf_label(block_end, 1);
}
if (!doing_abstract && generic) {
dw2_out_generic(generic->params);
}
mem = di->data.n_mod.members;
while (mem) {
dw2_out_name(mem, contex);
mem = mem->next;
}
dw_sibling_end();
break;
}
case DGN_SUBUNIT: {
abbrev_entry dwe;
if (di->data.n_sub.child) {
dwe = (di->data.n_sub.acc ? dwe_child_acc :
dwe_childunit);
} else {
dwe = dwe_subunit;
}
dw_at_ext_address(di->data.n_sub.parent);
if (di->data.n_sub.child) {
if (di->data.n_sub.acc) {
dw_at_data(1, (long)(di->data.n_sub.acc));
}
} else {
dw_at_flag(di->data.n_sub.split);
}
dw2_out_name(di->data.n_sub.sub, contex);
dw_sibling_end();
break;
}
case DGN_IMPORT: {
long attr1 = 0, attr2;
char *nam = idname_chars(di->idnam);
dg_type p_t = di->data.n_imp.i_typ;
int params = (p_t && p_t->key == DGT_PROC);
if (nam[0]) {
attr1 |= H_NM;
}
if (di->whence.file) {
attr1 |= H_XY;
}
if (di->mor && di->mor->acc) {
attr1 |= H_AC;
}
if (contex == LOCAL_NAME && !doing_abstract) {
attr1 |= H_SS;
}
attr2 = dw_entry((params ? dwe_import_p : dwe_import), attr1);
if (attr2 & ~(H_NM|H_XY|H_AC|H_SS)) {
fail_unimplemented();
}
if (attr2 & H_NM) {
dw_at_string(nam);
}
if (attr2 & H_XY) {
dw_at_decl(di->whence);
}
if (attr2 & H_AC) {
dw_at_data(1, (long)(di->mor ? di->mor->acc : 0));
}
dw_at_ext_address(di->data.n_imp.import);
dw_at_udata((unsigned long)(di->data.n_imp.ik));
if (attr2 & H_SS) {
dw_at_distance(dw2_scope_start, local_var_place);
}
if (params) {
dg_param *el = p_t->data.t_proc.params.array;
int i;
for (i = 0; i < p_t->data.t_proc.params.len; i++) {
out_param(el[i]);
}
if (p_t->data.t_proc.prps & f_var_callers) {
IGNORE dw_entry(dwe_opt_par, (long)0);
}
dw_sibling_end();
}
break;
}
case DGN_TYPE: {
long attr1 = 0, attr2;
int ada_derived = 0;
char * nam = idname_chars(di->idnam);
if (doing_inline && inl_tag) {
attr1 |= H_AO;
} else {
if (di->mor && di->mor->refspec) {
attr1 = H_SP;
}
if (di->mor && di->mor->isspec) {
attr1 |= H_DC;
}
if (nam[0]) {
attr1 |= H_NM;
}
if (di->whence.file) {
attr1 |= H_XY;
}
if (di->idnam.id_key == DG_ID_ARTFL) {
attr1 |= H_AT;
}
if (di->mor && di->mor->acc) {
attr1 |= H_AC;
}
if (di->data.n_typ.raw) {
attr1 |= H_TP;
}
if (di->mor && di->mor->isnew) {
attr1 |= H_NW;
}
if (di->mor && di->mor->aderiv) {
attr1 |= H_AD;
ada_derived = 1;
}
}
if ((attr1 == H_TP ||
(!nam[0] && !(di->mor && di->mor->this_tag))) &&
!(di->data.n_typ.raw->outref.u.l) &&
!di->data.n_typ.constraints) {
if (di->mor && di->mor->this_tag) {
di->data.n_typ.raw->outref =
di->mor->this_tag->outref;
} else {
di->data.n_typ.raw->outref.u.l =
next_dwarf_label();
di->data.n_typ.raw->outref.k = LAB_D;
}
dw_out_type(di->data.n_typ.raw);
} else {
if (di->mor && di->mor->this_tag) {
if (doing_abstract) {
set_abstract_lab(di->mor->this_tag);
} else if (!(di->mor->this_tag->done)) {
set_ext_address(di->mor->this_tag);
di->mor->this_tag->done = 1;
}
}
attr2 = dw_entry((di->data.n_typ.constraints ?
dwe_typecon :
dwe_typedef), attr1);
if (attr2 & ~(H_AO|H_SP|H_DC|H_NM|H_XY|H_AT|H_AC|H_TP|
H_NW|H_AD)) {
fail_unimplemented();
}
if (attr2 & H_AO) {
dw_at_abstract_lab(inl_tag);
}
if (attr2 & H_SP) {
dw_at_ext_address(di->mor->refspec);
}
if (attr2 & H_DC) {
dw_at_flag((di->mor &&
di->mor->isspec ? 1 : 0));
}
if (attr2 & H_NM) {
dw_at_string(nam);
}
if (attr2 & H_XY) {
dw_at_decl(di->whence);
}
if (attr2 & H_AT) {
dw_at_flag((di->idnam.id_key ==
DG_ID_ARTFL ? 1 : 0));
}
if (attr2 & H_AC) {
dw_at_data(1, (long)(di->mor ?
di->mor->acc : 0));
}
if (attr2 & H_TP) {
dw_at_ext_lab(dw2_find_type_label(di->data.n_typ.raw));
}
if (attr2 & H_NW) {
dw_at_flag((di->mor &&
di->mor->isnew ? 1 : ada_derived));
}
if (attr2 & H_AD) {
dw_at_flag(ada_derived);
}
}
if (di->data.n_typ.constraints) {
dg_constraint c = di->data.n_typ.constraints;
while (c) {
attr1 = (c->is_val ? H_CV : H_TP);
if (c->refmem) {
attr1 |= H_RM;
}
attr2 = dw_entry(dwe_cnstraint, attr1);
if (attr2 & ~(H_RM|H_CV|H_TP)) {
fail_unimplemented();
}
if (attr2 & H_RM) {
dw_at_ext_address(c->refmem);
}
if (attr2 & H_CV) {
dw_out_const(son(c->u.val));
}
if (attr2 & H_TP) {
dw_at_ext_lab(dw2_find_type_label(c->u.typ));
}
c = c->next;
}
dw_sibling_end();
}
break;
}
case DGN_ENTRY: {
long attr1 = 0, attr2;
char *nam = idname_chars(di->idnam);
dg_type p_t = find_proc_type(di->data.n_proc.typ);
dg_type res_t = p_t->data.t_proc.res_type;
dg_param *el = p_t->data.t_proc.params.array;
int i;
attr1 = H_NM | H_XY;
if (di->mor && di->mor->acc) {
attr1 |= H_AC;
}
if (res_t) {
attr1 |= H_TP;
}
if (di->mor && di->mor->repn) {
attr1 |= H_RP;
}
if (di->mor && di->mor->this_tag) {
set_ext_address(di->mor->this_tag);
}
attr2 = dw_entry(dwe_entry, attr1);
if (attr2 & ~(H_NM|H_XY|H_AC|H_TP|H_RP)) {
fail_unimplemented();
}
if (attr2 & H_NM) {
dw_at_string(nam);
}
if (attr2 & H_XY) {
dw_at_decl(di->whence);
}
if (attr2 & H_AC) {
dw_at_data(1, (long)(di->mor ? di->mor->acc : 0));
}
if (attr2 & H_TP) {
dw_at_ext_lab(dw2_find_type_label(res_t));
}
if (attr2 & H_RP) {
dw_out_const(son(di->mor->repn));
}
for (i = 0; i < p_t->data.t_proc.params.len; i++) {
out_param(el[i]);
}
if (di->mor && di->mor->en_family) {
dw_out_dim(*(di->mor->en_family));
}
dw_sibling_end();
break;
}
default:
failer("unexpected dg_name");
}
if (di->mor && di->mor->this_tag) {
di->mor->this_tag->done = 1;
}
return;
}
static retrec **returns_list;
void
dw2_proc_start(exp p, dg_name d)
{
if (dgf(p)) {
failer("unexpected diag info for proc");
}
proc_dg_info = dgf(p) = new_dg_info(DGA_PRC);
proc_dg_info->data.i_prc.prc_start = set_dw_text_label();
proc_dg_info->data.i_prc.prc_end = 0;
proc_dg_info->data.i_prc.returns = (retrec *)0;
returns_list = &(proc_dg_info->data.i_prc.returns);
proc_dg_info->data.i_prc.p = proc_dg_info->data.i_prc.barrier =
(dg_info)0;
if (d) {
dw2_source_mark(d->whence, 0);
}
return;
}
void
dw2_return_pos(long over)
{
retrec *rec = (retrec *)xmalloc(sizeof(retrec));
rec->lab = set_dw_text_label();
rec->over = over;
rec->next = (retrec *)0;
*returns_list = rec;
returns_list = &(rec->next);
if (over) {
set_obj_rets(rec);
}
return;
}
void
dw2_proc_end(exp p)
{
dgf(p)->data.i_prc.prc_end = set_dw_text_label();
proc_dg_info = (dg_info)0;
return;
}
static void
prepare_detch(detch_info *dl)
{
while (dl) {
int reason = dl->why;
dg_info d = dl->info;
dg_tag found_tg;
if (reason >= DGD_MOVD) {
found_tg = dl->tg;
while (found_tg->copy) {
found_tg = found_tg->copy;
}
d = found_tg->p.info;
reason = d->data.i_movd.reason;
d = d->more;
}
if (reason < DGD_MOVD) {
switch (d->key) {
case DGA_NAME:
d->data.i_nam.scope_start = set_dw_text_label();
break;
case DGA_SCOPE:
d->data.i_scope.start = set_dw_text_label();
d->data.i_scope.end = set_dw_text_label();
break;
case DGA_REMVAL:
d->data.i_remval.lo_pc = set_dw_text_label();
set_remval_object(d);
break;
default:
break;
}
}
if (dl->sub) {
prepare_detch(dl->sub);
}
dl = dl->next;
}
return;
}
void
dw2_code_info(dg_info d, void(*mcode)(void *), void *args)
{
if (d == nildiag) {
(*mcode)(args);
return;
}
switch (d->key) {
case DGA_PARAMS: {
obj_list hold_pars;
hold_pars.obj = d->data.i_param.args;
hold_pars.islist = 1;
hold_pars.next = (obj_list *)0;
local_objects = &hold_pars;
set_locdata(hold_pars);
if (proc_dg_info) {
proc_dg_info->data.i_prc.p = d;
}
d->data.i_param.b_start = set_dw_text_label();
dw2_code_info(d->more, mcode, args);
close_locdata(hold_pars);
local_objects = (obj_list *)0;
break;
}
case DGA_COMP:
dw2_code_info(d->more, mcode, args);
break;
case DGA_SRC:
if (d->data.i_src.startpos.file) {
dw2_source_mark(d->data.i_src.startpos,
d->data.i_src.is_stmt);
}
dw2_code_info(d->more, mcode, args);
if (d->data.i_src.endpos.file) {
dw2_source_mark(d->data.i_src.endpos, 0);
}
break;
case DGA_SCOPE:
case DGA_EXTRA:
d->data.i_scope.start = set_dw_text_label();
dw2_code_info(d->more, mcode, args);
d->data.i_scope.end = set_dw_text_label();
break;
case DGA_LAB:
d->data.i_scope.start = set_dw_text_label();
dw2_code_info(d->more, mcode, args);
break;
case DGA_NAME: {
obj_list hold_obj;
hold_obj.obj = d->data.i_nam.dnam;
hold_obj.islist = 0;
hold_obj.next = local_objects;
local_objects = &hold_obj;
set_locdata(hold_obj);
d->data.i_nam.scope_start = set_dw_text_label();
dw2_code_info(d->more, mcode, args);
close_locdata(hold_obj);
local_objects = hold_obj.next;
break;
}
case DGA_WITH:
d->data.i_with.lo_pc = set_dw_text_label();
dw2_code_info(d->more, mcode, args);
d->data.i_with.hi_pc = set_dw_text_label();
break;
case DGA_CALL: {
dg_info old = current_dg_info;
current_dg_info = d;
dw2_code_info(d->more, mcode, args);
current_dg_info = old;
break;
}
case DGA_INL_CALL: {
obj_list hold_pars;
hold_pars.obj = d->data.i_inl.args;
hold_pars.islist = 1;
hold_pars.next = local_objects;
local_objects = &hold_pars;
set_locdata(hold_pars);
d->data.i_inl.lo_pc = set_dw_text_label();
dw2_code_info(d->more, mcode, args);
d->data.i_inl.hi_pc = set_dw_text_label();
close_locdata(hold_pars);
local_objects = hold_pars.next;
break;
}
case DGA_INL_RES:
dw2_code_info(d->more, mcode, args);
d->data.i_res.brk = set_dw_text_label();
d->data.i_res.res = find_diag_res(args);
{
dg_tag cr = d->data.i_res.call;
dg_info *dl;
if (cr->key != DGK_INFO ||
cr->p.info->key != DGA_INL_CALL) {
failer("inline result ref?");
}
dl = &(cr->p.info->data.i_inl.resref);
while (*dl) {
if ((*dl) ==d) {
failer("impossible cycle");
return;
}
dl = &((*dl)->data.i_res.next);
}
*dl = d;
}
break;
case DGA_X_TRY:
d->data.i_try.lo_pc = set_dw_text_label();
dw2_code_info(d->more, mcode, args);
d->data.i_try.hi_pc = set_dw_text_label();
break;
case DGA_X_CATCH: {
obj_list hold_obj;
hold_obj.obj = d->data.i_catch.ex;
hold_obj.islist = 0;
hold_obj.next = local_objects;
local_objects = &hold_obj;
set_locdata(hold_obj);
d->data.i_catch.lo_pc = set_dw_text_label();
dw2_code_info(d->more, mcode, args);
d->data.i_catch.hi_pc = set_dw_text_label();
close_locdata(hold_obj);
local_objects = hold_obj.next;
break;
}
case DGA_X_RAISE:
dw2_code_info(d->more, mcode, args);
break;
case DGA_BRANCH: {
int old_db = dw_doing_branch_tests;
dw_doing_branch_tests = 1;
d->data.i_brn.brk = set_dw_text_label();
dw2_code_info(d->more, mcode, args);
d->data.i_brn.cont = set_dw_text_label();
dw_doing_branch_tests = old_db;
break;
}
case DGA_TEST:
case DGA_JUMP:
case DGA_LJ: {
dg_info old = current_dg_info;
current_dg_info = d;
dw2_code_info(d->more, mcode, args);
current_dg_info = old;
break;
}
case DGA_BEG: {
dg_tag tg = d->data.i_tg;
if (tg->key != DGK_INFO || tg->p.info->key != DGA_SCOPE)
failer("statement_part_dg?");
tg->p.info->data.i_scope.begin_st = set_dw_text_label();
dw2_code_info(d->more, mcode, args);
break;
}
case DGA_DEST:
d->data.i_dest.brk = set_dw_text_label();
dw2_code_info(d->more, mcode, args);
break;
case DGA_RVS: {
obj_list hold_pars;
hold_pars.next = local_objects;
if (d->data.i_rvs.rvs_key == DGR_ACC && d->data.i_rvs.n_code) {
hold_pars.obj = d->data.i_rvs.u2.p;
hold_pars.islist = 1;
local_objects = &hold_pars;
set_locdata(hold_pars);
}
if (d->data.i_rvs.n_code) {
d->data.i_rvs.lo_pc = set_dw_text_label();
}
if (d->data.i_rvs.u.tg) {
dg_info h;
if (d->data.i_rvs.u.tg->key != DGK_INFO ||
(h = d->data.i_rvs.u.tg->p.info,
h->key != DGA_RVS)) {
failer("incompatible rendezvous sequence");
}
d->data.i_rvs.u.iv = h->data.i_rvs.u.iv;
h->data.i_rvs.u.iv = d;
h->data.i_rvs.holder = 1;
d->data.i_rvs.info_e = current_dg_exp;
d->data.i_rvs.has_iv = 1;
}
dw2_code_info(d->more, mcode, args);
if ((unsigned int)d->data.i_rvs.n_code >= 2) {
d->data.i_rvs.hi_pc = set_dw_text_label();
}
if (d->data.i_rvs.rvs_key == DGR_ACC && d->data.i_rvs.n_code) {
close_locdata(hold_pars);
}
local_objects = hold_pars.next;
break;
}
case DGA_BAR:
d->data.i_bar.lo_pc = set_dw_text_label();
if (proc_dg_info) {
proc_dg_info->data.i_prc.barrier = d;
}
dw2_code_info(d->more, mcode, args);
d->data.i_bar.hi_pc = set_dw_text_label();
break;
case DGA_DETCH:
if (d->data.i_detch.posn < 0) {
prepare_detch(d->data.i_detch.dl);
dw2_code_info(d->more, mcode, args);
} else {
dw2_code_info(d->more, mcode, args);
prepare_detch(d->data.i_detch.dl);
}
break;
case DGA_MOVD:
case DGA_HOIST:
d->data.i_movd.lo_pc = set_dw_text_label();
dw2_code_info(d->more, mcode, args);
d->data.i_movd.hi_pc = set_dw_text_label();
break;
case DGA_OPTIM:
d->data.i_optim.lo_pc = set_dw_text_label();
set_optim_objects(d, 1);
dw2_code_info(d->more, mcode, args);
d->data.i_optim.hi_pc = set_dw_text_label();
set_optim_objects(d, 0);
break;
default:
failer("unexpected dg_info");
}
return;
}