446 lines
8.6 KiB
C
446 lines
8.6 KiB
C
#ifndef NORCSID
|
|
static char rcsid[] = "$Header$";
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include "param.h"
|
|
#include "types.h"
|
|
#include "assert.h"
|
|
#include "alloc.h"
|
|
#include "line.h"
|
|
#include "lookup.h"
|
|
#include "proinf.h"
|
|
|
|
/*
|
|
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
|
*
|
|
* This product is part of the Amsterdam Compiler Kit.
|
|
*
|
|
* Permission to use, sell, duplicate or disclose this software must be
|
|
* obtained in writing. Requests for such permissions may be sent to
|
|
*
|
|
* Dr. Andrew S. Tanenbaum
|
|
* Wiskundig Seminarium
|
|
* Vrije Universiteit
|
|
* Postbox 7161
|
|
* 1007 MC Amsterdam
|
|
* The Netherlands
|
|
*
|
|
* Author: Hans van Staveren
|
|
*/
|
|
|
|
#ifdef USEMALLOC
|
|
|
|
short * myalloc();
|
|
|
|
#define newcore(size) myalloc(size)
|
|
#define oldcore(p,size) free(p)
|
|
|
|
#else
|
|
|
|
/* #define CORECHECK /* if defined tests are made to insure
|
|
each block occurs at most once */
|
|
|
|
#define CCHUNK 1024 /* number of shorts asked from system */
|
|
|
|
short *newcore(),*freshcore();
|
|
extern char *sbrk();
|
|
|
|
#ifdef COREDEBUG
|
|
int shortsasked=0;
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/*
|
|
* The following two sizetables contain the sizes of the various kinds
|
|
* of line and argument structures.
|
|
* Care has been taken to make this table implementation independent,
|
|
* but if you think very hard you might find a compiler failing the
|
|
* assumptions made.
|
|
* A wasteful but safe approach is to replace every line of them by
|
|
* sizeof(line_t)
|
|
* and
|
|
* sizeof(arg_t)
|
|
* respectively.
|
|
*/
|
|
|
|
#define LBASE (sizeof(line_t)-sizeof(un_l_a))
|
|
|
|
int lsizetab[] = {
|
|
LBASE,
|
|
LBASE+sizeof(short),
|
|
LBASE+sizeof(offset),
|
|
LBASE+sizeof(num_p),
|
|
LBASE+sizeof(sym_p),
|
|
LBASE+sizeof(s_la_sval),
|
|
LBASE+sizeof(s_la_lval),
|
|
LBASE+sizeof(arg_p),
|
|
LBASE
|
|
};
|
|
|
|
#define ABASE (sizeof(arg_t)-sizeof(un_a_a))
|
|
|
|
int asizetab[] = {
|
|
ABASE+sizeof(offset),
|
|
ABASE+sizeof(num_p),
|
|
ABASE+sizeof(sym_p),
|
|
ABASE+sizeof(s_a_val),
|
|
ABASE+sizeof(argb_t),
|
|
ABASE+sizeof(s_a_con),
|
|
ABASE+sizeof(s_a_con),
|
|
ABASE+sizeof(s_a_con),
|
|
};
|
|
|
|
/*
|
|
* alloc routines:
|
|
* Two parts:
|
|
* 1) typed alloc and free routines
|
|
* 2) untyped raw core allocation
|
|
*/
|
|
|
|
/*
|
|
* PART 1
|
|
*/
|
|
|
|
line_p newline(optyp) int optyp; {
|
|
register line_p lnp;
|
|
register kind=optyp;
|
|
|
|
if (kind>OPMINI)
|
|
kind = OPMINI;
|
|
lnp = (line_p) newcore(lsizetab[kind]);
|
|
lnp->l_optyp = optyp;
|
|
return(lnp);
|
|
}
|
|
|
|
oldline(lnp) register line_p lnp; {
|
|
register kind=lnp->l_optyp&BMASK;
|
|
|
|
if (kind>OPMINI)
|
|
kind = OPMINI;
|
|
if (kind == OPLIST)
|
|
oldargs(lnp->l_a.la_arg);
|
|
oldcore((short *) lnp,lsizetab[kind]);
|
|
}
|
|
|
|
arg_p newarg(kind) int kind; {
|
|
register arg_p ap;
|
|
|
|
ap = (arg_p) newcore(asizetab[kind]);
|
|
ap->a_typ = kind;
|
|
return(ap);
|
|
}
|
|
|
|
oldargs(ap) register arg_p ap; {
|
|
register arg_p next;
|
|
|
|
while (ap != (arg_p) 0) {
|
|
next = ap->a_next;
|
|
switch(ap->a_typ) {
|
|
case ARGSTR:
|
|
oldargb(ap->a_a.a_string.ab_next);
|
|
break;
|
|
case ARGICN:
|
|
case ARGUCN:
|
|
case ARGFCN:
|
|
oldargb(ap->a_a.a_con.ac_con.ab_next);
|
|
break;
|
|
}
|
|
oldcore((short *) ap,asizetab[ap->a_typ]);
|
|
ap = next;
|
|
}
|
|
}
|
|
|
|
oldargb(abp) register argb_p abp; {
|
|
register argb_p next;
|
|
|
|
while (abp != (argb_p) 0) {
|
|
next = abp->ab_next;
|
|
oldcore((short *) abp,sizeof (argb_t));
|
|
abp = next;
|
|
}
|
|
}
|
|
|
|
reg_p newreg() {
|
|
|
|
return((reg_p) newcore(sizeof(reg_t)));
|
|
}
|
|
|
|
oldreg(rp) reg_p rp; {
|
|
|
|
oldcore((short *) rp,sizeof(reg_t));
|
|
}
|
|
|
|
num_p newnum() {
|
|
|
|
return((num_p) newcore(sizeof(num_t)));
|
|
}
|
|
|
|
oldnum(lp) num_p lp; {
|
|
|
|
oldcore((short *) lp,sizeof(num_t));
|
|
}
|
|
|
|
offset *newrom() {
|
|
|
|
return((offset *) newcore(MAXROM*sizeof(offset)));
|
|
}
|
|
|
|
sym_p newsym() {
|
|
|
|
return((sym_p) newcore(sizeof(sym_t)));
|
|
}
|
|
|
|
argb_p newargb() {
|
|
|
|
return((argb_p) newcore(sizeof(argb_t)));
|
|
}
|
|
|
|
#ifndef USEMALLOC
|
|
|
|
/******************************************************************/
|
|
/****** Start of raw core management package *****************/
|
|
/******************************************************************/
|
|
|
|
#define MAXSHORT 30 /* Maximum number of shorts one can ask for */
|
|
|
|
short *freelist[MAXSHORT];
|
|
|
|
typedef struct coreblock {
|
|
struct coreblock *co_next;
|
|
short co_size;
|
|
} core_t,*core_p;
|
|
|
|
#define SINC (sizeof(core_t)/sizeof(short))
|
|
#ifdef COREDEBUG
|
|
coreverbose() {
|
|
register size;
|
|
register short *p;
|
|
register sum;
|
|
|
|
sum = 0;
|
|
for(size=1;size<MAXSHORT;size++)
|
|
for (p=freelist[size];p!=0;p = *(short **) p)
|
|
sum += size;
|
|
fprintf(stderr,"Used core %u\n",(shortsasked-sum)*sizeof(short));
|
|
}
|
|
#endif
|
|
|
|
#ifdef SEPID
|
|
|
|
compactcore() {
|
|
register core_p corelist=0,tp,cl;
|
|
int size;
|
|
|
|
#ifdef COREDEBUG
|
|
fprintf(stderr,"Almost out of core\n");
|
|
#endif
|
|
for(size=SINC;size<MAXSHORT;size++) {
|
|
while ((tp = (core_p) freelist[size]) != (core_p) 0) {
|
|
freelist[size] = (short *) tp->co_next;
|
|
tp->co_size = size;
|
|
if (corelist==0 || tp<corelist) {
|
|
tp->co_next = corelist;
|
|
corelist = tp;
|
|
} else {
|
|
for(cl=corelist;cl->co_next != 0 && tp>cl->co_next;
|
|
cl = cl->co_next)
|
|
;
|
|
tp->co_next = cl->co_next;
|
|
cl->co_next = tp;
|
|
}
|
|
}
|
|
}
|
|
while (corelist != 0) {
|
|
while ((short *) corelist->co_next ==
|
|
(short *) corelist + corelist->co_size) {
|
|
corelist->co_size += corelist->co_next->co_size;
|
|
corelist->co_next = corelist->co_next->co_next;
|
|
}
|
|
assert(corelist->co_next==0 ||
|
|
(short *) corelist->co_next >
|
|
(short *) corelist + corelist->co_size);
|
|
while (corelist->co_size >= MAXSHORT+SINC) {
|
|
oldcore((short *) corelist + corelist->co_size-(MAXSHORT-1),
|
|
sizeof(short)*(MAXSHORT-1));
|
|
corelist->co_size -= MAXSHORT;
|
|
}
|
|
if (corelist->co_size >= MAXSHORT) {
|
|
oldcore((short *) corelist + corelist->co_size-SINC,
|
|
sizeof(short)*SINC);
|
|
corelist->co_size -= SINC;
|
|
}
|
|
cl = corelist->co_next;
|
|
oldcore((short *) corelist, sizeof(short)*corelist->co_size);
|
|
corelist = cl;
|
|
}
|
|
}
|
|
|
|
short *grabcore(size) int size; {
|
|
register short *p;
|
|
register trysize;
|
|
|
|
/*
|
|
* Desperate situation, can't get more core from system.
|
|
* Postpone giving up just a little bit by splitting up
|
|
* larger free blocks if possible.
|
|
* Algorithm is worst fit.
|
|
*/
|
|
|
|
assert(size<2*MAXSHORT);
|
|
for(trysize=2*MAXSHORT-2; trysize>size; trysize -= 2) {
|
|
p = freelist[trysize/sizeof(short)];
|
|
if ( p != (short *) 0) {
|
|
freelist[trysize/sizeof(short)] = *(short **) p;
|
|
oldcore(p+size/sizeof(short),trysize-size);
|
|
return(p);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Can't get more core from the biggies, try to combine the
|
|
* little ones. This is expensive but probably better than
|
|
* giving up.
|
|
*/
|
|
|
|
compactcore();
|
|
if ((p=freelist[size/sizeof(short)]) != 0) {
|
|
freelist[size/sizeof(short)] = * (short **) p;
|
|
return(p);
|
|
}
|
|
for(trysize=2*MAXSHORT-2; trysize>size; trysize -= 2) {
|
|
p = freelist[trysize/sizeof(short)];
|
|
if ( p != (short *) 0) {
|
|
freelist[trysize/sizeof(short)] = *(short **) p;
|
|
oldcore(p+size/sizeof(short),trysize-size);
|
|
return(p);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* That's it then. Finished.
|
|
*/
|
|
|
|
return(0);
|
|
}
|
|
#endif /* SEPID */
|
|
|
|
short *newcore(size) int size; {
|
|
register short *p,*q;
|
|
|
|
if( size < 2*MAXSHORT ) {
|
|
if ((p=freelist[size/sizeof(short)]) != (short *) 0)
|
|
freelist[size/sizeof(short)] = *(short **) p;
|
|
else {
|
|
p = freshcore(size);
|
|
#ifdef SEPID
|
|
if (p == (short *) 0)
|
|
p = grabcore(size);
|
|
#endif
|
|
}
|
|
} else
|
|
p = freshcore(size);
|
|
if (p == 0)
|
|
error("out of memory");
|
|
for (q=p; size > 0 ; size -= sizeof(short))
|
|
*q++ = 0;
|
|
return(p);
|
|
}
|
|
|
|
#ifdef NOMALLOC
|
|
|
|
/*
|
|
* stdio uses malloc and free.
|
|
* you can use these as substitutes
|
|
*/
|
|
|
|
char *malloc(size) int size; {
|
|
|
|
/*
|
|
* malloc(III) is called by stdio,
|
|
* this routine is a substitute.
|
|
*/
|
|
|
|
return( (char *) newcore(size));
|
|
}
|
|
|
|
free() {
|
|
|
|
}
|
|
#endif
|
|
|
|
oldcore(p,size) short *p; int size; {
|
|
#ifdef CORECHECK
|
|
register short *cp;
|
|
#endif
|
|
|
|
assert(size<2*MAXSHORT);
|
|
#ifdef CORECHECK
|
|
for (cp=freelist[size/sizeof(short)]; cp != (short *) 0;
|
|
cp = (short *) *cp)
|
|
assert(cp != p);
|
|
#endif
|
|
*(short **) p = freelist[size/sizeof(short)];
|
|
freelist[size/sizeof(short)] = p;
|
|
}
|
|
|
|
short *ccur,*cend;
|
|
|
|
coreinit(p1,p2) short *p1,*p2; {
|
|
|
|
/*
|
|
* coreinit is called with the boundaries of a piece of
|
|
* memory that can be used for starters.
|
|
*/
|
|
|
|
ccur = p1;
|
|
cend = p2;
|
|
}
|
|
|
|
short *freshcore(size) int size; {
|
|
register short *temp;
|
|
static int cchunk=CCHUNK;
|
|
|
|
while(&ccur[size/sizeof(short)] >= cend && cchunk>0) {
|
|
do {
|
|
temp = (short *) sbrk(cchunk*sizeof(short));
|
|
if (temp == (short *) -1)
|
|
cchunk >>= 1;
|
|
else if (temp != cend)
|
|
ccur = cend = temp;
|
|
} while (temp == (short *) -1 && cchunk>0);
|
|
cend += cchunk;
|
|
#ifdef COREDEBUG
|
|
shortsasked += cchunk;
|
|
#endif
|
|
}
|
|
if (cchunk==0)
|
|
return(0);
|
|
temp = ccur;
|
|
ccur = &ccur[size/sizeof(short)];
|
|
return(temp);
|
|
}
|
|
|
|
#else /* USEMALLOC */
|
|
|
|
coreinit() {
|
|
|
|
/*
|
|
* Empty function, no initialization needed
|
|
*/
|
|
}
|
|
|
|
short *myalloc(size) register size; {
|
|
register short *p,*q;
|
|
extern char *malloc();
|
|
|
|
p = (short *)malloc(size);
|
|
if (p == 0)
|
|
error("out of memory");
|
|
for(q=p;size>0;size -= sizeof(short))
|
|
*q++ = 0;
|
|
return(p);
|
|
}
|
|
#endif
|