307a8b996e
If the ncg table uses reglap, then regvar($1, reg_float) would have two sizes of registers. An error from ncgg would happen if regvar() was in a token that allows only one size. Now one can pick a size with regvar_w() for word size or regvar_d() for double-word size. Add regvar_d and regvar_w as keywords in ncgg. Modify EX_REGVAR to include the register size. In ncg, add some checks for the register size. In tables without reglap, regvar() works as before, and ncg ignores the register size in EX_REGVAR.
723 lines
15 KiB
C
723 lines
15 KiB
C
#ifndef NORCSID
|
|
static char rcsid[] = "$Id$";
|
|
#endif
|
|
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "assert.h"
|
|
#include "param.h"
|
|
#include "tables.h"
|
|
#include "types.h"
|
|
#include <cgg_cg.h>
|
|
#include "data.h"
|
|
#include "result.h"
|
|
#include "extern.h"
|
|
#ifdef REGVARS
|
|
#include "regvar.h"
|
|
#endif
|
|
|
|
/*
|
|
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
|
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
|
*
|
|
* Author: Hans van Staveren
|
|
*/
|
|
|
|
string myalloc();
|
|
unsigned codegen();
|
|
|
|
match(tp,tep,optexp) register token_p tp; register set_p tep; {
|
|
register bitno;
|
|
token_p ct;
|
|
result_t result;
|
|
|
|
if (tp->t_token == -1) { /* register frame */
|
|
bitno = tp->t_att[0].ar;
|
|
if (tep->set_val[bitno>>4]&(1<<(bitno&017)))
|
|
if (tep->set_val[0]&1 || getrefcount(bitno, FALSE)<=1)
|
|
goto oklabel;
|
|
return(0);
|
|
} else { /* token frame */
|
|
bitno = tp->t_token+NREGS;
|
|
if ((tep->set_val[bitno>>4]&(1<<(bitno&017)))==0)
|
|
return(0);
|
|
}
|
|
oklabel:
|
|
if (optexp==0)
|
|
return(1);
|
|
ct=curtoken;
|
|
curtoken=tp;
|
|
compute(&enodes[optexp], &result);
|
|
curtoken=ct;
|
|
return(result.e_v.e_con);
|
|
}
|
|
|
|
void
|
|
instance(instno,token) register token_p token; {
|
|
register inst_p inp;
|
|
int i;
|
|
register token_p tp;
|
|
#if MAXMEMBERS != 0
|
|
struct reginfo *rp;
|
|
#endif
|
|
int regno;
|
|
result_t result;
|
|
|
|
if (instno==0) {
|
|
token->t_token = 0;
|
|
for (i=TOKENSIZE-1;i>=0;i--)
|
|
token->t_att[i].aw=0;
|
|
return;
|
|
}
|
|
inp= &tokeninstances[instno];
|
|
switch(inp->in_which) {
|
|
default:
|
|
assert(FALSE);
|
|
case IN_COPY:
|
|
if (inp->in_info[0] == 0)
|
|
if (curtoken) tp = curtoken;
|
|
else tp = &fakestack[stackheight-1];
|
|
else tp= &fakestack[stackheight-inp->in_info[0]];
|
|
if (inp->in_info[1]==0) {
|
|
*token = *tp;
|
|
} else {
|
|
token->t_token= -1;
|
|
#if MAXMEMBERS!=0
|
|
assert(tp->t_token == -1);
|
|
rp = &machregs[tp->t_att[0].ar];
|
|
token->t_att[0].ar=rp->r_members[inp->in_info[1]-1];
|
|
#else
|
|
assert(FALSE);
|
|
#endif
|
|
}
|
|
return;
|
|
case IN_MEMB:
|
|
if (inp->in_info[0] == 0)
|
|
if (curtoken) tp = curtoken;
|
|
else tp = &fakestack[stackheight-1];
|
|
else tp= &fakestack[stackheight-inp->in_info[0]];
|
|
assert(inp->in_info[1]!=0);
|
|
assert(tp->t_token>0);
|
|
token->t_token= -1;
|
|
assert(tokens[tp->t_token].t_type[inp->in_info[1]-1] == EV_REG);
|
|
token->t_att[0].ar=tp->t_att[inp->in_info[1]-1].ar;
|
|
return;
|
|
case IN_RIDENT:
|
|
token->t_token= -1;
|
|
token->t_att[0].ar= inp->in_info[0];
|
|
return;
|
|
case IN_ALLOC:
|
|
token->t_token= -1;
|
|
regno=allreg[inp->in_info[0]];
|
|
#if MAXMEMBERS!=0
|
|
if (inp->in_info[1])
|
|
regno=machregs[regno].r_members[inp->in_info[1]-1];
|
|
#endif
|
|
token->t_att[0].ar = regno;
|
|
return;
|
|
#ifdef REGVARS
|
|
case IN_S_DESCR:
|
|
case IN_D_DESCR:
|
|
compute(&enodes[inp->in_info[1]], &result);
|
|
assert(result.e_typ==EV_INT);
|
|
regno = isregvar_size(result.e_v.e_con,
|
|
tokens[inp->in_info[0]].t_size);
|
|
if (regno > 0) {
|
|
token->t_token = -1;
|
|
token->t_att[0].ar = regno;
|
|
for (i=TOKENSIZE-1;i>0;i--)
|
|
token->t_att[i].aw = 0;
|
|
return;
|
|
}
|
|
/* fall through */
|
|
#endif
|
|
case IN_DESCR:
|
|
token->t_token=inp->in_info[0];
|
|
for (i=0;i<TOKENSIZE;i++)
|
|
if (inp->in_info[i+1]==0) {
|
|
assert(tokens[token->t_token].t_type[i]==0);
|
|
token->t_att[i].aw=0;
|
|
} else {
|
|
compute(&enodes[inp->in_info[i+1]], &result);
|
|
assert(tokens[token->t_token].t_type[i]==result.e_typ);
|
|
if (result.e_typ==EV_INT)
|
|
token->t_att[i].aw=result.e_v.e_con;
|
|
else if (result.e_typ==EV_ADDR)
|
|
token->t_att[i].aa= result.e_v.e_addr;
|
|
else
|
|
token->t_att[i].ar=result.e_v.e_reg;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
void
|
|
cinstance(instno,token,tp,regno) register token_p token,tp; {
|
|
register inst_p inp;
|
|
int i;
|
|
#if MAXMEMBERS != 0
|
|
struct reginfo *rp;
|
|
#endif
|
|
result_t result;
|
|
int sh; /* saved stackheight */
|
|
|
|
assert(instno!=0);
|
|
inp= &tokeninstances[instno];
|
|
switch(inp->in_which) {
|
|
default:
|
|
assert(FALSE);
|
|
case IN_COPY:
|
|
assert(inp->in_info[0] <= 1);
|
|
if (inp->in_info[1]==0) {
|
|
*token = *tp;
|
|
} else {
|
|
token->t_token= -1;
|
|
#if MAXMEMBERS!=0
|
|
assert(tp->t_token == -1);
|
|
rp = &machregs[tp->t_att[0].ar];
|
|
token->t_att[0].ar=rp->r_members[inp->in_info[1]-1];
|
|
#else
|
|
assert(FALSE);
|
|
#endif
|
|
}
|
|
return;
|
|
case IN_MEMB:
|
|
assert(inp->in_info[0] <= 1);
|
|
token->t_token= -1;
|
|
assert(tp->t_token>0);
|
|
assert(tokens[tp->t_token].t_type[inp->in_info[1]-1] == EV_REG);
|
|
token->t_att[0].ar=tp->t_att[inp->in_info[1]-1].ar;
|
|
return;
|
|
case IN_RIDENT:
|
|
token->t_token= -1;
|
|
token->t_att[0].ar= inp->in_info[0];
|
|
return;
|
|
case IN_ALLOC:
|
|
token->t_token= -1;
|
|
assert(inp->in_info[0]==0);
|
|
#if MAXMEMBERS!=0
|
|
if (inp->in_info[1])
|
|
regno=machregs[regno].r_members[inp->in_info[1]-1];
|
|
#endif
|
|
token->t_att[0].ar = regno;
|
|
return;
|
|
#ifdef REGVARS
|
|
case IN_S_DESCR:
|
|
case IN_D_DESCR:
|
|
{ token_p ct = curtoken;
|
|
|
|
curtoken = tp;
|
|
compute(&enodes[inp->in_info[1]], &result);
|
|
curtoken = ct;
|
|
assert(result.e_typ==EV_INT);
|
|
regno = isregvar_size(result.e_v.e_con,
|
|
tokens[inp->in_info[0]].t_size);
|
|
if (regno > 0) {
|
|
token->t_token = -1;
|
|
token->t_att[0].ar = regno;
|
|
for (i=TOKENSIZE-1;i>0;i--)
|
|
token->t_att[i].aw = 0;
|
|
return;
|
|
}
|
|
}
|
|
/* fall through */
|
|
#endif
|
|
case IN_DESCR:
|
|
sh = stackheight;
|
|
stackheight = tp - fakestack + 1;
|
|
token->t_token=inp->in_info[0];
|
|
for (i=0;i<TOKENSIZE;i++)
|
|
if (inp->in_info[i+1]==0) {
|
|
assert(tokens[token->t_token].t_type[i]==0);
|
|
token->t_att[i].aw=0;
|
|
} else {
|
|
token_p ct = curtoken;
|
|
|
|
curtoken = tp;
|
|
compute(&enodes[inp->in_info[i+1]], &result);
|
|
curtoken = ct;
|
|
assert(tokens[token->t_token].t_type[i]==result.e_typ);
|
|
if (result.e_typ==EV_INT)
|
|
token->t_att[i].aw=result.e_v.e_con;
|
|
else if (result.e_typ==EV_ADDR)
|
|
token->t_att[i].aa= result.e_v.e_addr;
|
|
else
|
|
token->t_att[i].ar=result.e_v.e_reg;
|
|
}
|
|
stackheight = sh;
|
|
return;
|
|
}
|
|
}
|
|
|
|
eqtoken(tp1,tp2) token_p tp1,tp2; {
|
|
register i;
|
|
register tkdef_p tdp;
|
|
|
|
if (tp1->t_token!=tp2->t_token)
|
|
return(0);
|
|
if (tp1->t_token==0)
|
|
return(1);
|
|
if (tp1->t_token==-1) {
|
|
if (tp1->t_att[0].ar!=tp2->t_att[0].ar)
|
|
return(0);
|
|
return(1);
|
|
}
|
|
tdp = &tokens[tp1->t_token];
|
|
for (i=0;i<TOKENSIZE;i++)
|
|
switch(tdp->t_type[i]) {
|
|
default:
|
|
return(1);
|
|
case EV_INT:
|
|
if (tp1->t_att[i].aw != tp2->t_att[i].aw)
|
|
return(0);
|
|
break;
|
|
case EV_REG:
|
|
if (tp1->t_att[i].ar != tp2->t_att[i].ar)
|
|
return(0);
|
|
break;
|
|
case EV_ADDR:
|
|
if (strcmp(tp1->t_att[i].aa.ea_str, tp2->t_att[i].aa.ea_str))
|
|
return(0);
|
|
if (tp1->t_att[i].aa.ea_off!=tp2->t_att[i].aa.ea_off)
|
|
return(0);
|
|
break;
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
distance(cindex) {
|
|
register char *bp;
|
|
register i;
|
|
register token_p tp;
|
|
int tokexp,tpl;
|
|
int expsize,toksize,exact;
|
|
int xsekt=0;
|
|
int fromstackneeded=0;
|
|
|
|
bp = &coderules[cindex];
|
|
#ifndef NDEBUG
|
|
if (*bp==DO_DLINE) {
|
|
++bp;
|
|
getint(i,bp);
|
|
}
|
|
#endif
|
|
switch( (*bp)&037 ) {
|
|
default:
|
|
return(stackheight==0 ? 0 : 100);
|
|
case DO_MATCH:
|
|
break;
|
|
case DO_XXMATCH:
|
|
xsekt++;
|
|
case DO_XMATCH:
|
|
xsekt++;
|
|
break;
|
|
}
|
|
tpl= ((*bp++)>>5)&07;
|
|
if (stackheight < tpl) {
|
|
if (xsekt)
|
|
return(MAXINT);
|
|
fromstackneeded = tpl - stackheight;
|
|
tpl = stackheight;
|
|
} else
|
|
if (stackheight != tpl && xsekt==2)
|
|
return(MAXINT);
|
|
exact=0;
|
|
tp= &fakestack[stackheight-1];
|
|
for (i=0;i<tpl;i++,tp--) {
|
|
getint(tokexp,bp);
|
|
if (!match(tp, &machsets[tokexp], 0)) {
|
|
if (xsekt)
|
|
return(MAXINT);
|
|
expsize = ssize(tokexp);
|
|
toksize = tsize(tp);
|
|
if (expsize>toksize)
|
|
return(100);
|
|
if (expsize<toksize)
|
|
return(99-i);
|
|
|
|
/* Now we have a match in size, but it is not exact.
|
|
Therefore, make sure that we can at least
|
|
create it from the stack!
|
|
*/
|
|
if (! from_stack(&machsets[tokexp])) {
|
|
return MAXINT;
|
|
}
|
|
} else
|
|
exact++;
|
|
}
|
|
for (;i<tpl+fromstackneeded;i++) {
|
|
/* Make sure that any pattern we pick can be
|
|
made from the stack
|
|
*/
|
|
getint(tokexp,bp);
|
|
if (! from_stack(&machsets[tokexp])) {
|
|
return(MAXINT);
|
|
}
|
|
}
|
|
if (exact==tpl && ! fromstackneeded) {
|
|
if (xsekt)
|
|
return(0);
|
|
return(10-exact);
|
|
}
|
|
return(20-2*exact+fromstackneeded);
|
|
}
|
|
|
|
extern set_t unstackset;
|
|
|
|
int from_stack(s1)
|
|
register set_p s1;
|
|
{
|
|
register set_p s2 = &unstackset;
|
|
register int i;
|
|
for (i = 0; i < SETSIZE; i++) {
|
|
if ((s1->set_val[i] & s2->set_val[i]) != 0) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
unsigned costcalc(cost) cost_t cost; {
|
|
extern unsigned cc1,cc2,cc3,cc4;
|
|
|
|
return(cost.ct_space*cc1/cc2 + cost.ct_time*cc3/cc4);
|
|
}
|
|
|
|
ssize(tokexpno) {
|
|
|
|
return(machsets[tokexpno].set_size);
|
|
}
|
|
|
|
tsize(tp) register token_p tp; {
|
|
|
|
if (tp->t_token==-1)
|
|
return(machregs[tp->t_att[0].ar].r_size);
|
|
return(tokens[tp->t_token].t_size);
|
|
}
|
|
|
|
#ifdef MAXSPLIT
|
|
instsize(tinstno,tp) token_p tp; {
|
|
inst_p inp;
|
|
struct reginfo *rp;
|
|
|
|
inp = &tokeninstances[tinstno];
|
|
switch(inp->in_which) {
|
|
default:
|
|
assert(FALSE);
|
|
case IN_COPY:
|
|
assert(inp->in_info[0]<=1);
|
|
#if MAXMEMBERS!=0
|
|
if (inp->in_info[1]==0)
|
|
#endif
|
|
return(tsize(tp));
|
|
#if MAXMEMBERS!=0
|
|
else {
|
|
assert(tp->t_token == -1);
|
|
rp = &machregs[tp->t_att[0].ar];
|
|
return(machregs[rp->r_members[inp->in_info[1]-1]].r_size);
|
|
}
|
|
#endif
|
|
case IN_RIDENT:
|
|
return(machregs[inp->in_info[0]].r_size);
|
|
case IN_ALLOC:
|
|
assert(FALSE); /* cannot occur in splitting coercion */
|
|
case IN_DESCR:
|
|
case IN_S_DESCR:
|
|
case IN_D_DESCR:
|
|
return(tokens[inp->in_info[0]].t_size);
|
|
}
|
|
}
|
|
#endif /* MAXSPLIT */
|
|
|
|
tref(tp,amount) register token_p tp; {
|
|
register i;
|
|
register byte *tdpb;
|
|
|
|
if (tp->t_token==-1)
|
|
chrefcount(tp->t_att[0].ar,amount,FALSE);
|
|
else {
|
|
tdpb= &tokens[tp->t_token].t_type[0];
|
|
for(i=0;i<TOKENSIZE;i++)
|
|
if (*tdpb++==EV_REG)
|
|
chrefcount(tp->t_att[i].ar,amount,FALSE);
|
|
}
|
|
}
|
|
|
|
#define MAXSAVE 10
|
|
/* A few routines to save the top of the current stack,
|
|
restore it and check whether a certain register is present in the
|
|
saved stack
|
|
*/
|
|
token_t aside[MAXSAVE] ;
|
|
int aside_length = -1 ;
|
|
|
|
save_stack(tp) register token_p tp ; {
|
|
int i ;
|
|
token_p tmp = &fakestack[stackheight - 1];
|
|
|
|
/*aside_length = &fakestack[stackheight-1] -tp;
|
|
This did not compile on Xenix V3.2: CODE GENERATION ERROR!
|
|
*/
|
|
aside_length = tmp - tp;
|
|
assert(aside_length<=MAXSAVE);
|
|
#ifndef NDEBUG
|
|
if (aside_length!=0 && Debug>1)
|
|
fprintf(stderr,"Saving %d items from fakestack\n",aside_length);
|
|
#endif
|
|
for (i=1;i<=aside_length;i++)
|
|
aside[i-1] = tp[i];
|
|
stackheight -= aside_length;
|
|
}
|
|
|
|
in_stack(reg) {
|
|
register token_p tp ;
|
|
register i ;
|
|
register tkdef_p tdp ;
|
|
|
|
for ( i=0, tp=aside ; i<aside_length ; i++, tp++ )
|
|
if (tp->t_token==-1) {
|
|
if(tp->t_att[0].ar==reg)
|
|
goto gotone ;
|
|
} else {
|
|
tdp = &tokens[tp->t_token];
|
|
for(i=0;i<TOKENSIZE;i++)
|
|
if (tdp->t_type[i]==EV_REG &&
|
|
tp->t_att[i].ar==reg)
|
|
goto gotone ;
|
|
}
|
|
return 0 ;
|
|
gotone:
|
|
#ifndef NDEBUG
|
|
if ( Debug>2 )
|
|
fprintf(stderr,"Register %d present on non-visible stack\n",
|
|
reg ) ;
|
|
#endif
|
|
return 1 ;
|
|
}
|
|
|
|
rest_stack() {
|
|
register int i ;
|
|
|
|
assert(aside_length!= -1);
|
|
#ifndef NDEBUG
|
|
if (aside_length!=0 && Debug>1)
|
|
fprintf(stderr,"Restoring %d items to fakestack(%d)\n",
|
|
aside_length,stackheight);
|
|
#endif
|
|
for (i=0;i<aside_length;i++)
|
|
fakestack[stackheight++] = aside[i];
|
|
aside_length= -1 ;
|
|
}
|
|
|
|
#ifdef MAXSPLIT
|
|
split(tp,ip,ply,toplevel) token_p tp; register int *ip; {
|
|
register c2_p cp;
|
|
token_t savestack[MAXSAVE];
|
|
int ok;
|
|
register i;
|
|
int diff;
|
|
token_p stp;
|
|
int tpl;
|
|
|
|
for (cp=c2coercs;cp->c2_texpno>=0; cp++) {
|
|
if (!match(tp,&machsets[cp->c2_texpno],0))
|
|
continue;
|
|
ok=1;
|
|
for (i=0; ok && i<cp->c2_nsplit;i++) {
|
|
if (ip[i]==0)
|
|
goto found;
|
|
if (instsize(cp->c2_repl[i],tp) != ssize(ip[i]))
|
|
ok=0;
|
|
}
|
|
goto found;
|
|
}
|
|
return(0);
|
|
found:
|
|
assert(stackheight+cp->c2_nsplit-1<MAXFSTACK);
|
|
save_stack(tp);
|
|
tpl = tokpatlen;
|
|
tokpatlen = 1;
|
|
codegen(&coderules[cp->c2_codep],ply,toplevel,MAXINT,0);
|
|
tokpatlen = tpl;
|
|
rest_stack();
|
|
return(cp->c2_nsplit);
|
|
}
|
|
#endif /* MAXSPLIT */
|
|
|
|
unsigned docoerc(tp,cp,ply,toplevel,forced) token_p tp; register c3_p cp; {
|
|
unsigned cost;
|
|
int tpl; /* saved tokpatlen */
|
|
|
|
save_stack(tp) ;
|
|
tpl = tokpatlen;
|
|
tokpatlen = 1;
|
|
cost = codegen(&coderules[cp->c3_codep],ply,toplevel,MAXINT,forced);
|
|
tokpatlen = tpl;
|
|
rest_stack() ;
|
|
nallreg = 0;
|
|
return(cost);
|
|
}
|
|
|
|
unsigned stackupto(limit,ply,toplevel) token_p limit; {
|
|
token_t savestack[MAXFSTACK];
|
|
token_p stp;
|
|
int i,diff;
|
|
int tpl; /* saved tokpatlen */
|
|
int nareg; /* saved nareg */
|
|
int areg[MAXALLREG];
|
|
register c1_p cp;
|
|
register token_p tp;
|
|
unsigned totalcost=0;
|
|
struct reginfo *rp,**rpp;
|
|
|
|
for (tp=fakestack;tp<=limit;limit--) {
|
|
for (cp=c1coercs;cp->c1_texpno>=0; cp++) {
|
|
if (match(tp,&machsets[cp->c1_texpno],cp->c1_expr)) {
|
|
if (cp->c1_prop>=0) {
|
|
for (rpp=reglist[cp->c1_prop];
|
|
(rp = *rpp)!=0 &&
|
|
getrefcount((int)(rp-machregs), TRUE)!=0;
|
|
rpp++)
|
|
;
|
|
if (rp==0)
|
|
continue;
|
|
/* look for other possibility */
|
|
}
|
|
stp = &fakestack[stackheight-1];
|
|
diff = stp -tp;
|
|
assert(diff<=MAXFSTACK);
|
|
for (i=1;i<=diff;i++)
|
|
savestack[i-1] = tp[i];
|
|
stackheight -= diff;
|
|
tpl = tokpatlen;
|
|
tokpatlen = 1;
|
|
nareg = nallreg;
|
|
for (i=0;i<nareg;i++)
|
|
areg[i] = allreg[i];
|
|
if (cp->c1_prop>=0) {
|
|
nallreg=1; allreg[0] = rp-machregs;
|
|
chrefcount(allreg[0],1,FALSE);
|
|
} else
|
|
nallreg=0;
|
|
totalcost+= codegen(&coderules[cp->c1_codep],ply,toplevel,MAXINT,0);
|
|
tokpatlen = tpl;
|
|
for (i=0;i<diff;i++) {
|
|
fakestack[stackheight] = savestack[i];
|
|
stackheight++;
|
|
/* not cobmined in one statement;
|
|
this poor Xenix C compiler sometimes
|
|
gets failed assertions when you do
|
|
that!
|
|
*/
|
|
}
|
|
nallreg=nareg;
|
|
for (i=0;i<nareg;i++)
|
|
allreg[i] = areg[i];
|
|
goto contin;
|
|
}
|
|
}
|
|
assert(FALSE);
|
|
contin: ;
|
|
}
|
|
return(totalcost);
|
|
}
|
|
|
|
c3_p findcoerc(tp,tep) token_p tp; set_p tep; {
|
|
register c3_p cp;
|
|
token_t rtoken;
|
|
register i;
|
|
register struct reginfo **rpp;
|
|
|
|
for (cp=c3coercs;cp->c3_texpno>=0; cp++) {
|
|
if (tp!=(token_p) 0) {
|
|
if (cp->c3_texpno==0)
|
|
continue;
|
|
if (!match(tp,&machsets[cp->c3_texpno],cp->c3_expr))
|
|
continue;
|
|
} else {
|
|
if (cp->c3_texpno!=0)
|
|
continue;
|
|
}
|
|
if (cp->c3_prop<0) { /* no reg needed */
|
|
cinstance(cp->c3_repl,&rtoken,tp,0);
|
|
if (match(&rtoken,tep,0))
|
|
return(cp);
|
|
} else {
|
|
curreglist = (rl_p) myalloc(sizeof (rl_t));
|
|
curreglist->rl_n = 0;
|
|
for (rpp=reglist[cp->c3_prop];*rpp;rpp++) {
|
|
i = *rpp - machregs;
|
|
cinstance(cp->c3_repl,&rtoken,tp,i);
|
|
if (match(&rtoken,tep,0))
|
|
curreglist->rl_list[curreglist->rl_n++] = i;
|
|
}
|
|
if (curreglist->rl_n != 0)
|
|
return(cp);
|
|
myfree((string)curreglist);
|
|
}
|
|
}
|
|
return(0); /* nothing found */
|
|
}
|
|
|
|
itokcost() {
|
|
register tkdef_p tdp;
|
|
|
|
for(tdp=tokens+1;tdp->t_size!=0;tdp++)
|
|
tdp->t_cost.ct_space = costcalc(tdp->t_cost);
|
|
}
|
|
|
|
void error(const char *s, ...) {
|
|
va_list ap;
|
|
|
|
va_start(ap,s);
|
|
fprintf(stderr,"Error: ");
|
|
vfprintf(stderr,s,ap);
|
|
fprintf(stderr,"\n");
|
|
#ifdef TABLEDEBUG
|
|
ruletrace();
|
|
#endif
|
|
out_finish();
|
|
exit(-1);
|
|
}
|
|
|
|
void fatal(const char *s, ...) {
|
|
va_list ap;
|
|
|
|
va_start(ap,s);
|
|
fprintf(stderr,"Fatal: ");
|
|
vfprintf(stderr,s,ap);
|
|
fprintf(stderr,"\n");
|
|
#ifdef TABLEDEBUG
|
|
ruletrace();
|
|
#endif
|
|
out_finish();
|
|
abort();
|
|
exit(-1);
|
|
}
|
|
|
|
#ifdef TABLEDEBUG
|
|
|
|
ruletrace() {
|
|
register i;
|
|
extern int tablelines[MAXTDBUG];
|
|
extern int ntableline;
|
|
extern char *tablename;
|
|
|
|
fprintf(stderr,"Last code rules used\n");
|
|
i=ntableline-1;
|
|
while(i!=ntableline) {
|
|
if (i<0)
|
|
i += MAXTDBUG;
|
|
if (tablelines[i]!=0)
|
|
fprintf(stderr,"\%d: \"%s\", line %d\n",i,tablename,tablelines[i]);
|
|
i--;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifndef NDEBUG
|
|
badassertion(asstr,file,line) char *asstr, *file; {
|
|
|
|
fatal("\"%s\", line %d:Assertion \"%s\" failed",file,line,asstr);
|
|
}
|
|
#endif
|