/* $Header$ */
/*
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 */
/*
 *   R E G I S T E R    A L L O C A T I O N
 *
 */

/* TEMPORARY: should be put in ../../../h/em_mes.h: */
#define ms_liv 9
#define ms_ded 10

#define INFINITE	10000
#define NRREGTYPES	(reg_float+1)

extern int nrinstrs;  /* number of instructions of current procedure */
extern line_p *instrmap; 
/* Dynamic array: instrmap[i] points to i'th instruction */

extern cond_p alocaltab[NRREGTYPES][NRREGTYPES],
	alocaddrtab[NRREGTYPES][NRREGTYPES], aconsttab,
	adconsttab,aglobaltab,aproctab;
extern cond_p olocaltab[NRREGTYPES],olocaddrtab[NRREGTYPES],
	oconsttab,odconsttab,oglobaltab,oproctab;
extern cond_p regsav_cost;

/* Register Allocation */
typedef struct item *item_p;
typedef struct allocation *alloc_p;
typedef struct interval *interv_p;
typedef struct time *time_p;




extern short regs_available[];  /* contains #registers of every type */
extern short use_any_as_pointer;/* indicates whether general registers
				   can be used as pointers
				*/


/* A thing that can be put in a register is called an "item". The are several
 * types of items: a local variable, the address of a local variable,
 * the address of a global variable, the address of a procedure,
 * a word-size constant and a doubleword- size constant.
 */

#define LOCALVAR	0
#define LOCAL_ADDR	1
#define GLOBL_ADDR	2
#define PROC_ADDR	3
#define CONST		4
#define DCONST		5

#define NO_ITEM		6
#define NRITEMTYPES	6

struct item {
	item_p	  it_next;	/* link to next item is list		*/
	short	  it_type;	/* its type; see above			*/
	short	  it_regtype;	/* preferred type of register		*/
	short	  it_size;	/* its size (in bytes)			*/
	short	  it_lastlive;	/* temporary, used to build livetime	*/
	lset	  it_usage;	/* all points in text where item is used*/
	interv_p  it_lives;	/* intervals during which item is live	*/
	bool	  it_desirable; /* should this item be put in reg.?	*/
	union {
		obj_p	it_obj;		/* for GLOBL_ADDR 		*/
		proc_p	it_proc;	/* for PROC_ADDR		*/
		offset	it_off;		/* for others	  		*/
	} i_t;
};


/* A 'point in time' is defined by a (line,basic block) pair */

struct time {
	line_p	  t_line;	/* point in EM text			*/
	bblock_p  t_bblock;	/* its basic block			*/
};


struct interval {
	short	 i_start;	/* number of first instruction		*/
	short	 i_stop;	/* number of last instruction		*/
	interv_p i_next;
};


/* An item may be put in a register for the duration of a whole procedure
 * or part of a procedure (e.g. a loop). So a possible "allocation" looks
 * like: put item X in a register during the timespan T (which is a subset
 * of the timespan of the entire procedure). The packing process deals
 * with allocations, rather than items. One item may be part of several
 * possible allocations.
 */

struct allocation {
	item_p	  al_item;	/* the item to be put in a register	  */
	short	  al_id;	/* unique identifying number		  */
	short	  al_regtype;	/* the register type to be used		  */
	interv_p  al_timespan;	/* timespan during which item is in reg.  */
	short	  al_profits;	/* gains of putting item in register	  */
	cset	  al_rivals;	/* set of allocations competing with it	  */
	short	  al_susecount;	/* #usages during timespan (statically)   */
	short	  al_dusecount;	/* #usages (dynamically, estimate)	  */
	lset	  al_inits;	/* points where reg. must be initialized  */
	interv_p  al_busy;	/* used to compute rivals		  */
	short	  al_regnr;	/* register nr.,if it is granted a reg.   */
	offset	  al_dummy;	/* dummy local variable,if granted a reg  */
	alloc_p	  al_mates;	/* link to allocations packed in same reg */
	alloc_p	  al_wholeproc;	/* alloc. for whole proc as timespan  	  */
	short	  al_cntrivals; /* # unpacked rivals ; used for cost estim. */
	bool	  al_isloop;	/* true if timespan consists of loop	  */
	bool	  al_iswholeproc;/*true if timespan consists of whole proc*/
	alloc_p	  al_next;	/* link to next one in a list		  */
};

extern short alloc_id;  /* last al_id used for current procedure */

#define LP_BLOCKS	lp_extend->lpx_ra.lpx_blocks
#define LP_HEADER	lp_extend->lpx_ra.lpx_header
#define B_BEGIN		b_extend->bx_ra.bx_begin
#define B_END		b_extend->bx_ra.bx_end

#define DLINK(l1,l2)	l1->l_next=l2; l2->l_prev=l1

struct item_descr {
	int	id_type;
	int	id_replindex;
} ;

extern struct item_descr itemtab[];

#define newalloc()	(alloc_p) newstruct(allocation)
#define  oldalloc(a)	oldstruct(allocation,a)
#define newitem()	(item_p) newstruct(item)
#define olditem(i)	oldstruct(item,i)
#define newtime()	(time_p) newstruct(time)
#define oldtime(t)	oldstruct(time,t)
#define newinterval()	(interv_p) newstruct(interval)
#define oldinterval(i)	oldstruct(interval,i)