585 lines
13 KiB
C
585 lines
13 KiB
C
/* debug.c -- symbol table output routines for common assembler */
|
|
|
|
#include <signal.h>
|
|
#include "mfile1.h"
|
|
#include "macdefs.h"
|
|
#include <storclass.h>
|
|
|
|
static FILE * outfile = stdout; /* static now, maybe global later */
|
|
|
|
#define LINENO (lineno-startln+1) /* local line number */
|
|
|
|
static int startln; /* editor line number of opening { */
|
|
static int oldln; /* last line number printed */
|
|
int gdebug; /* -g flag */
|
|
static char startfn[100]; /* file name of the opening { */
|
|
static char fncname[BUFSIZ+1]; /* name of current function */
|
|
static int bb_flags[BCSZ]; /* remember whether or not bb
|
|
** is needed
|
|
*/
|
|
|
|
fixdef(p) struct symtab *p; {
|
|
|
|
/* print debugging info
|
|
*
|
|
* don't do params, externs, structure names or members
|
|
* at this time; they are delayed until more information
|
|
* is known about them
|
|
*/
|
|
|
|
switch( p->sclass ) {
|
|
|
|
case USTATIC:
|
|
case EXTERN:
|
|
case EXTDEF:
|
|
case STNAME:
|
|
case UNAME:
|
|
case ENAME:
|
|
case MOS:
|
|
case MOE:
|
|
case MOU:
|
|
return;
|
|
default:
|
|
if( p->sclass & FIELD ) return;
|
|
}
|
|
|
|
/* parameters */
|
|
if( p->slevel == 1 ) return;
|
|
|
|
/* static externs */
|
|
if( p->sclass == STATIC && p->slevel == 0 ) return;
|
|
|
|
prdef(p,0);
|
|
}
|
|
|
|
prdims( p ) struct symtab *p; {
|
|
/* print debugging info for dimensions
|
|
*/
|
|
int temp, dtemp, dflag;
|
|
OFFSZ tsize();
|
|
|
|
dflag = 0; /* need to print dim */
|
|
dtemp = p->dimoff;
|
|
|
|
for( temp=p->stype; temp&TMASK; temp = DECREF(temp) ) {
|
|
/* put out a dimension for each instance of ARY in type word */
|
|
|
|
if( ISARY(temp) ) {
|
|
if( !dflag ) {
|
|
fprintf( outfile, " dim %ld", dimtab[dtemp++] );
|
|
dflag = 1;
|
|
}
|
|
else
|
|
fprintf( outfile, ",%ld", dimtab[dtemp++] );
|
|
}
|
|
}
|
|
|
|
if( dflag ) {
|
|
fputs( ";\tsize\t", outfile );
|
|
fprintf( outfile, /*CONFMT*/"%ld", tsize(p->stype, p->dimoff, p->sizoff ) / SZCHAR );
|
|
putc( ';', outfile );
|
|
}
|
|
}
|
|
|
|
/* local table of fakes for un-names structures
|
|
* sizoff for ~ifake is stored in mystrtab[i]
|
|
*/
|
|
#define FAKENM 99 /* maximum number of fakenames */
|
|
int mystrtab[FAKENM], ifake = 0;
|
|
struct symtab mytable;
|
|
char tagname[BUFSIZ] = "";
|
|
|
|
prdef(p,dsflg) struct symtab *p; int dsflg; {
|
|
/* print symbol definition pseudos
|
|
*/
|
|
TWORD pty, bpty;
|
|
TWORD chgtype();
|
|
char *strname();
|
|
int sclass;
|
|
int saveloc;
|
|
|
|
if ( dsflg || !gdebug )
|
|
return;
|
|
|
|
/* translate storage class */
|
|
|
|
switch( p->sclass ){
|
|
case AUTO: sclass = C_AUTO; break;
|
|
case EXTDEF:
|
|
case EXTERN: sclass = C_EXT; break;
|
|
case STATIC: sclass = C_STAT; break;
|
|
case REGISTER: sclass = blevel==1 ? C_REGPARM : C_REG; break;
|
|
case ULABEL:
|
|
case LABEL: sclass = C_LABEL; break;
|
|
case MOS: sclass = C_MOS; break;
|
|
case PARAM: sclass = C_ARG; break;
|
|
case STNAME: sclass = C_STRTAG; break;
|
|
case MOU: sclass = C_MOU; break;
|
|
case UNAME: sclass = C_UNTAG; break;
|
|
case TYPEDEF: sclass = C_TPDEF; break;
|
|
case ENAME: sclass = C_ENTAG; break;
|
|
case MOE: sclass = C_MOE; break;
|
|
default: if( p->sclass & FIELD )
|
|
sclass = C_FIELD;
|
|
else
|
|
cerror( "bad storage class %d", p->sclass );
|
|
break;
|
|
}
|
|
|
|
/* print a bb symbol if this is the first symbol in the block */
|
|
|
|
if( blevel > 2 && !bb_flags[blevel] && sclass != C_LABEL ) {
|
|
fprintf( outfile, " def ~bb; val ~; scl %d; line %d; endef\n", C_BLOCK, LINENO );
|
|
bb_flags[blevel] = 1; /* don't let another bb print */
|
|
}
|
|
|
|
/* make sure that defs in functions are in text section */
|
|
if( blevel > 1 )
|
|
saveloc = locctr( PROG );
|
|
|
|
fprintf( outfile, " def %s;", exname( p->sname ) );
|
|
|
|
switch( sclass ) { /* print val based on storage class */
|
|
|
|
case C_AUTO:
|
|
/* offset in bytes plus savearea */
|
|
fprintf( outfile, " val %ld+S%%%d;",
|
|
p->offset/SZCHAR, ftnno );
|
|
break;
|
|
|
|
case C_MOS:
|
|
case C_MOU:
|
|
case C_ARG:
|
|
/* offset in bytes */
|
|
fprintf( outfile, " val %ld;", p->offset/SZCHAR );
|
|
break;
|
|
|
|
case C_FIELD:
|
|
case C_MOE:
|
|
/* offset in bits, or internal value of enum symbol */
|
|
fprintf( outfile, " val %ld;", p->offset );
|
|
break;
|
|
|
|
case C_REGPARM:
|
|
case C_REG:
|
|
/* offset in bytes in savearea for reg vars */
|
|
/* actual offset determination is deferred to the asembler */
|
|
/* pointer vars in %aN indicated by adding 8 */
|
|
fprintf( outfile, " val %ld;", OUTREGNO(p));
|
|
break;
|
|
|
|
case C_STAT:
|
|
case C_LABEL:
|
|
case C_EXT:
|
|
/* actual or hidden name, depending on scope */
|
|
if( p->slevel != 0 )
|
|
{
|
|
fprintf( outfile, " val ");
|
|
fprintf( outfile, LABFMT, (int)p->offset );
|
|
putc( ';', outfile);
|
|
}
|
|
else
|
|
fprintf( outfile, " val %s;",
|
|
exname( p->sname ) );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
pty = chgtype(p->stype); /* change type word from new style
|
|
** to old
|
|
*/
|
|
bpty = BTYPE(p->stype);
|
|
fprintf( outfile, " scl %d; type 0%o;", sclass, pty );
|
|
|
|
/* print tag and size info, size only for tags themselves;
|
|
* don't print if size not known
|
|
*/
|
|
|
|
if (dimtab[p->sizoff] > 0)
|
|
switch( sclass ) {
|
|
|
|
case C_STRTAG:
|
|
case C_UNTAG:
|
|
case C_ENTAG:
|
|
fprintf( outfile, " size %ld;", dimtab[p->sizoff] / SZCHAR );
|
|
break;
|
|
|
|
default: /* bpty is base type */
|
|
if( (bpty == STRTY || bpty == UNIONTY || bpty == ENUMTY) && gdebug ) {
|
|
char buf[BUFSIZ];
|
|
|
|
(void) strcpy( buf, strname( p->sizoff ) );
|
|
if ( buf[0] == '$' )
|
|
buf[0] = '_';
|
|
fprintf( outfile, " tag %s;",
|
|
exname( buf ) );
|
|
fprintf( outfile, " size %ld;",
|
|
dimtab[p->sizoff] / SZCHAR );
|
|
}
|
|
break;
|
|
}
|
|
|
|
#ifdef FOOBARBLETCH
|
|
/* print line for block symbols */
|
|
|
|
if( p->slevel > 2 )
|
|
fprintf( outfile, " line %d;", LINENO );
|
|
#endif FOOBARBLETCH
|
|
|
|
/* look for dimensions to print */
|
|
|
|
if( sclass != C_LABEL && gdebug )
|
|
prdims( p );
|
|
|
|
/* size of field is its length in bits */
|
|
|
|
if( sclass == C_FIELD )
|
|
fprintf( outfile, " size %d;", p->sclass & FLDSIZ );
|
|
|
|
fputs( "\tendef\n", outfile );
|
|
if( blevel > 1 )
|
|
locctr( saveloc );
|
|
}
|
|
|
|
strend( dimst ) int dimst; {
|
|
/* called at the end of a structure declaration
|
|
* this routine puts out the structure tag, its members
|
|
* and an eos. dimst is the index in dimtab of the
|
|
* structure description
|
|
*/
|
|
int member;
|
|
OFFSZ size;
|
|
int saveloc;
|
|
struct symtab *memptr, *tagnm, *strfind();
|
|
|
|
if( !gdebug ) return;
|
|
|
|
/* set locctr to text */
|
|
saveloc = locctr( PROG );
|
|
|
|
/* set up tagname */
|
|
member = dimtab[dimst + 1];
|
|
tagnm = strfind(dimst);
|
|
|
|
if( tagnm == NULL ) {
|
|
/* create a fake if there is no tagname */
|
|
/* use the local symbol table */
|
|
tagnm = &mytable;
|
|
if( ifake == FAKENM )
|
|
cerror( "fakename table overflow" );
|
|
|
|
/* generate the fake name and enter into the fake table */
|
|
{
|
|
char buf[BUFSIZ];
|
|
|
|
sprintf( buf, "~%dfake", ifake );
|
|
mytable.sname = savestr( buf ); /* lives forever! */
|
|
}
|
|
mystrtab[ifake++] = dimst;
|
|
memptr = &stab[dimtab[member]];
|
|
|
|
/* fix up the fake's class, type, and sizoff based on class of its members */
|
|
switch( memptr->sclass ) {
|
|
case MOS:
|
|
tagnm->sclass = STNAME;
|
|
tagnm->stype = STRTY;
|
|
break;
|
|
case MOE:
|
|
tagnm->sclass = ENAME;
|
|
tagnm->stype = ENUMTY;
|
|
break;
|
|
case MOU:
|
|
tagnm->sclass = UNAME;
|
|
tagnm->stype = UNIONTY;
|
|
break;
|
|
default:
|
|
if( memptr->sclass & FIELD ){
|
|
tagnm->sclass = STNAME;
|
|
tagnm->stype = STRTY;
|
|
}
|
|
else
|
|
cerror( "can't identify type of fake tagname" );
|
|
}
|
|
tagnm->slevel = 0;;
|
|
tagnm->sizoff = dimst;
|
|
}
|
|
|
|
/* print out the structure header */
|
|
{
|
|
char buf[BUFSIZ], *saveit;
|
|
|
|
saveit = tagnm->sname;
|
|
(void) strncpy( buf, saveit, BUFSIZ - 1 );
|
|
buf[BUFSIZ - 1] = '\0';
|
|
tagnm->sname = buf;
|
|
if ( buf[0] == '$' )
|
|
buf[0] = '_';
|
|
prdef( tagnm, 0 );
|
|
tagnm->sname = saveit;
|
|
}
|
|
|
|
/* print out members */
|
|
while( dimtab[member] >= 0 ) {
|
|
memptr = &stab[dimtab[member++]];
|
|
{
|
|
char buf[BUFSIZ], *saveit;
|
|
|
|
saveit = memptr->sname;
|
|
(void) strncpy( buf, saveit, BUFSIZ - 1 );
|
|
buf[BUFSIZ - 1] = '\0';
|
|
memptr->sname = buf;
|
|
if ( buf[0] == '$' )
|
|
buf[0] = '_';
|
|
prdef( memptr, 0 );
|
|
memptr->sname = saveit;
|
|
}
|
|
}
|
|
|
|
/* print eos */
|
|
size = dimtab[dimst] / SZCHAR;
|
|
fprintf( outfile, " def ~eos; val %ld; scl %d;", size, C_EOS );
|
|
fprintf( outfile, " tag %s; size %ld; endef\n",
|
|
exname( tagnm->sname ), size );
|
|
|
|
/* return to old locctr */
|
|
locctr( saveloc );
|
|
}
|
|
|
|
struct symtab *
|
|
strfind( key ) int key; {
|
|
/* find the structure tag in the symbol table, 0 == not found
|
|
*/
|
|
struct symtab *sptr;
|
|
char spc;
|
|
for( sptr = stab; sptr < stab + SYMTSZ; ++sptr ) {
|
|
spc = sptr->sclass;
|
|
if( (spc == STNAME || spc == ENAME || spc == UNAME ) && sptr->sizoff == key && sptr->stype != TNULL )
|
|
return( sptr );
|
|
}
|
|
/* not found */
|
|
return( NULL );
|
|
}
|
|
|
|
char *
|
|
strname( key ) int key; {
|
|
/* return a pointer to the tagname,
|
|
* the fake table is used if not found by strfind
|
|
*/
|
|
int i;
|
|
struct symtab *tagnm, *strfind();
|
|
tagnm = strfind( key );
|
|
if( tagnm != NULL )
|
|
return( tagnm->sname );
|
|
|
|
for( i = 0; i < FAKENM; ++i )
|
|
if( mystrtab[i] == key ) {
|
|
sprintf( tagname, "~%dfake", i );
|
|
return( tagname );
|
|
}
|
|
|
|
cerror( "structure tagname not found" );
|
|
return(NULL);
|
|
}
|
|
|
|
/* chgtype -- change type word from pcc2 internal type to
|
|
** old style type for symbol table utilities.
|
|
**
|
|
** The old and new types are sufficiently similar to obtain the
|
|
** old from the new by extracting the basic type, shifting the
|
|
** remaining bits right 1, then OR-ing them back with the basic
|
|
** type. That will probably not continue to be true.
|
|
*/
|
|
|
|
/* Define old types */
|
|
|
|
#define O_TNULL 020
|
|
#define O_TVOID 040
|
|
#define O_UNDEF 00
|
|
#define O_FARG 01
|
|
#define O_CHAR 02
|
|
#define O_SHORT 03
|
|
#define O_INT 04
|
|
#define O_LONG 05
|
|
#define O_FLOAT 06
|
|
#define O_DOUBLE 07
|
|
#define O_STRTY 010
|
|
#define O_UNIONTY 011
|
|
#define O_ENUMTY 012
|
|
#define O_MOETY 013
|
|
#define O_UCHAR 014
|
|
#define O_USHORT 015
|
|
#define O_UNSIGNED 016
|
|
#define O_ULONG 017
|
|
|
|
TWORD
|
|
chgtype(ntype)
|
|
TWORD ntype; /* new type */
|
|
{
|
|
TWORD btype = BTYPE(ntype); /* get basic type */
|
|
TWORD other = ntype & ~((TWORD) BTMASK);
|
|
/* get remaining bits */
|
|
|
|
TWORD newtype; /* derived "new" (i.e., old-style) type */
|
|
|
|
switch ( btype ) /* convert basic type */
|
|
{
|
|
case TNULL: newtype = O_TNULL; break;
|
|
case FARG: newtype = O_FARG; break;
|
|
case CHAR: newtype = O_CHAR; break;
|
|
case SHORT: newtype = O_SHORT; break;
|
|
case INT: newtype = O_INT; break;
|
|
case LONG: newtype = O_LONG; break;
|
|
case FLOAT: newtype = O_FLOAT; break;
|
|
case DOUBLE: newtype = O_DOUBLE; break;
|
|
case STRTY: newtype = O_STRTY; break;
|
|
case UNIONTY: newtype = O_UNIONTY; break;
|
|
case ENUMTY: newtype = O_ENUMTY; break;
|
|
case MOETY: newtype = O_MOETY; break;
|
|
case UCHAR: newtype = O_UCHAR; break;
|
|
case USHORT: newtype = O_USHORT; break;
|
|
case UNSIGNED: newtype = O_UNSIGNED; break;
|
|
case ULONG: newtype = O_ULONG; break;
|
|
case VOID: newtype = O_TVOID; break;
|
|
case UNDEF: newtype = O_UNDEF; break;
|
|
default: cerror("Unknown basic type\n");
|
|
}
|
|
return( (other >> 1) | newtype ); /* return changed type */
|
|
}
|
|
|
|
|
|
beg_file(){
|
|
/* called as the very first thing by the parser to do machine
|
|
* dependent stuff
|
|
*/
|
|
register char * p;
|
|
register char * s;
|
|
extern fpe_catch();
|
|
|
|
/* note: double quotes already in ftitle... */
|
|
p = ftitle + strlen( ftitle ) - 2;
|
|
*(p+1) = '\"';
|
|
s = p - 14; /* max name length */
|
|
while ( p > s && *p != '"' && *p != '/' )
|
|
--p;
|
|
fprintf( outfile, ".line 1 \"%.15s\n", p + 1 );
|
|
fprintf( outfile, "\t.seg\n\tfp := r13\n\tFP := rr12\n");
|
|
fprintf( outfile, "\tsp := r15\n\tSP := rr14\n");
|
|
|
|
/*
|
|
* Catch floating exceptions generated by the constant
|
|
* folding code.
|
|
*/
|
|
(void) signal( SIGFPE, fpe_catch );
|
|
}
|
|
|
|
fpe_catch() {
|
|
/*
|
|
* Floating exception generated by constant folding.
|
|
*/
|
|
/* "floating point constant folding causes exception" */
|
|
uerror( "floating point constant folding causes exception" );
|
|
exit(2);
|
|
}
|
|
|
|
sdbline()
|
|
{
|
|
if ( gdebug && lineno != oldln )
|
|
{
|
|
oldln = lineno; /* remember last line no. output */
|
|
if ( curloc == PROG && strcmp( startfn, ftitle ) == 0 )
|
|
fprintf( outfile, " ln %d\n", LINENO );
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
aobeg(){
|
|
/* called before removing automatics from stab
|
|
*/
|
|
}
|
|
|
|
aocode(p) struct symtab *p; {
|
|
/* called when automatic p removed from stab
|
|
*/
|
|
}
|
|
|
|
aoend(){
|
|
/* called after removing all automatics from stab
|
|
* print eb here if bb printed for this block
|
|
*/
|
|
# ifndef NOSYMB
|
|
if( gdebug && bb_flags[blevel+1] ) {
|
|
fprintf( outfile, " def ~eb; val ~; scl %d; line %d; endef\n", C_BLOCK, LINENO );
|
|
bb_flags[blevel+1] = 0;
|
|
}
|
|
# endif
|
|
}
|
|
|
|
|
|
bfdebug( a, n )
|
|
int a[];
|
|
int n;
|
|
{
|
|
register i;
|
|
register struct symtab *p;
|
|
|
|
/* remember name of current function */
|
|
|
|
(void) strcpy( fncname, stab[curftn].sname );
|
|
|
|
/* initialize line number counters */
|
|
|
|
oldln = startln = lineno;
|
|
strcpy( startfn, ftitle );
|
|
|
|
/* do ~bf symbol and defs for parameters
|
|
* parameters are delayed to here to two reasons:
|
|
* 1: they appear inside the ~bf - ~ef
|
|
* 2: the true declarations have been seen
|
|
*/
|
|
if ( gdebug ) {
|
|
int line;
|
|
|
|
fprintf( outfile, " ln 1\n");
|
|
line = lineno; /* line number information for sdb */
|
|
fprintf( outfile, " def ~bf; val ~; scl %d; line %d; endef\n", C_FCN ,line );
|
|
for( i=0; i<n; ++i ) {
|
|
p = &stab[a[i]];
|
|
prdef(p,0);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* output end of function debugging information */
|
|
|
|
efdebug()
|
|
{
|
|
/* print end-of-function pseudo and its line number */
|
|
|
|
if ( gdebug )
|
|
{
|
|
fprintf( outfile, " def ~ef; val ~; scl %d; line %d; endef\n", C_FCN, LINENO );
|
|
if( LINENO > 1 )
|
|
fprintf( outfile, " ln %d\n", LINENO );
|
|
}
|
|
}
|
|
|
|
eobl2dbg()
|
|
{
|
|
/* print debug information at lexical end of function */
|
|
|
|
if ( gdebug )
|
|
{
|
|
fprintf( outfile, "\tdef %s; val ~; scl -1; endef\n", fncname);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
/* called at end of job to output debug information */
|
|
ejsdb()
|
|
{
|
|
}
|