optim.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 845 行 · 第 1/2 页

C
845
字号
		s2->prev->next = s1;	else		firstslot = s1;	s1->prev = s2->prev;	s2->prev = s1;	}else	{	s1->prev = lastslot;	lastslot->next = s1;	lastslot = s1;	}s1->next = s2;++numslots;}/* *  deletes the specified slot from the code buffer */delslot (sl)Slotp	sl;{removeslot (sl);if (sl->ctlinfo)	free ((charptr) sl->ctlinfo);frexpr (sl->expr);free ((charptr) sl);numslots--;}/* *  inserts a slot before the specified slot; if given NULL, it is *  inserted at the end of the buffer */Slotp optinsert (type,p,l,c,currslot)int	type;expptr	p;int	l;int	*c;Slotp	currslot;{Slotp	savelast,new;savelast = lastslot;if (currslot)	lastslot = currslot->prev;new = optbuff (type,p,l,c);new->next = currslot;if (currslot)	currslot->prev = new;new->lineno = -1;	/* who knows what the line number should be ??!! */if (currslot)	lastslot = savelast;return (new);}/* *  buffers the FRTEMP slots which have been waiting */frtempbuff (){chainp ht;register Slotp sp;for (ht = holdtemps; ht; ht = ht->nextp)	{	sp = newslot();		/* this slot actually belongs to some previous source line */	sp->lineno = sp->lineno - 1;	sp->type = SKFRTEMP;	sp->expr = (expptr) ht->datap;	sp->label = 0;	sp->ctlinfo = NULL;	}holdtemps = NULL;}/* *  puts the given information into a slot at the end of the code buffer */Slotp optbuff (type,p,l,c)int	type;expptr	p;int	l;int	*c;{register Slotp sp;if (debugflag[1])	{	fprintf (diagfile,"-----optbuff-----"); showslottype (type);	showexpr (p,0); fprintf (diagfile,"\n");	}p = expand (p);sp = newslot();sp->type = type;sp->expr = p;sp->label = l;sp->ctlinfo = NULL;switch (type)	{	case SKCMGOTO:		sp->ctlinfo = (int*) cplabarr (l, (struct Labelblock**) c);		break;	case SKARIF:		sp->ctlinfo = (int*) cplabarr (3, (struct Labelblock**) c);		break;	case SKDOHEAD:	case SKENDDO:		sp->ctlinfo = (int*) cpframe ((struct Ctlframe*) c);		break;	default:		break;	}frtempbuff ();return (sp);}/* *  expands the given expression, if possible (e.g., concat, min, max, etc.); *  also frees temporaries when they are indicated as being the last use */#define APPEND(z)	\	res = res->exprblock.rightp = mkexpr (OPCOMMA, z, newtemp)LOCAL expptr expand (p)tagptr p;{Addrp t;expptr q;expptr buffmnmx(), buffpower();if (!p)	return (ENULL);switch (p->tag)	{	case TEXPR:		switch (p->exprblock.opcode)			{			case OPASSIGN: /* handle a = b // c */				if (p->exprblock.vtype != TYCHAR)					goto standard;				q = p->exprblock.rightp;				if (!(q->tag == TEXPR &&				      q->exprblock.opcode == OPCONCAT))					goto standard;				t = (Addrp) expand(p->exprblock.leftp);				frexpr(p->exprblock.vleng);				free( (charptr) p );				p = (tagptr) q;				goto cat;			case OPCONCAT:				t = mktemp (TYCHAR, ICON(lencat(p)));			cat:				q = (expptr) cpexpr (p->exprblock.vleng);				buffcat (cpexpr(t),p);				frexpr (t->vleng);				t->vleng = q;				p = (tagptr) t;				break;			case OPMIN:			case OPMAX:				p = (tagptr) buffmnmx (p);				break;			case OPPOWER:				p = (tagptr) buffpower (p);				break;			default:			standard:				p->exprblock.leftp =					expand (p->exprblock.leftp);				if (p->exprblock.rightp)					p->exprblock.rightp =						expand (p->exprblock.rightp);				break;			}		break;	case TLIST:		{		chainp t;		for (t = p->listblock.listp; t; t = t->nextp)			t->datap = (tagptr) expand (t->datap);		}		break;	case TTEMP:		if (p->tempblock.istemp)			frtemp(p);		break;	case TADDR:		p->addrblock.memoffset = expand( p->addrblock.memoffset );		break;	default:		break;	}return ((expptr) p);}/* *  local version of routine putcat in putpcc.c, called by expand */LOCAL buffcat(lhs, rhs)register Addrp lhs;register expptr rhs;{int n;Addrp lp, cp;n = ncat(rhs);lp = (Addrp) mkaltmpn(n, TYLENG, PNULL);cp = (Addrp) mkaltmpn(n, TYADDR, PNULL);n = 0;buffct1(rhs, lp, cp, &n);optbuff (SKCALL, call4(TYSUBR, "s_cat", lhs, cp, lp, mkconv(TYLONG, ICON(n))),	0, 0);}/* *  local version of routine putct1 in putpcc.c, called by expand */LOCAL buffct1(q, lp, cp, ip)register expptr q;register Addrp lp, cp;int *ip;{int i;Addrp lp1, cp1;if(q->tag==TEXPR && q->exprblock.opcode==OPCONCAT)	{	buffct1(q->exprblock.leftp, lp, cp, ip);	buffct1(q->exprblock.rightp, lp, cp, ip);	frexpr(q->exprblock.vleng);	free( (charptr) q );	}else	{	i = (*ip)++;	lp1 = (Addrp) cpexpr(lp);	lp1->memoffset = mkexpr(OPPLUS,lp1->memoffset, ICON(i*SZLENG));	cp1 = (Addrp) cpexpr(cp);	cp1->memoffset = mkexpr(OPPLUS, cp1->memoffset, ICON(i*SZADDR));	optbuff (SKEQ, (mkexpr(OPASSIGN, lp1, cpexpr(q->headblock.vleng))),		0,0);	optbuff (SKEQ, (mkexpr(OPASSIGN, cp1, addrof(expand (q)))), 0, 0);	}}/* *  local version of routine putmnmx in putpcc.c, called by expand */LOCAL expptr buffmnmx(p)register expptr p;{int op, type;expptr qp;chainp p0, p1;Addrp sp, tp;Addrp newtemp;expptr result, res;if(p->tag != TEXPR)	badtag("buffmnmx", p->tag);type = p->exprblock.vtype;op = (p->exprblock.opcode==OPMIN ? OPLT : OPGT );qp = expand(p->exprblock.leftp);if(qp->tag != TLIST)	badtag("buffmnmx list", qp->tag);p0 = qp->listblock.listp;free( (charptr) qp );free( (charptr) p );sp = mktemp(type, PNULL);tp = mktemp(type, PNULL);qp = mkexpr(OPCOLON, cpexpr(tp), cpexpr(sp));qp = mkexpr(OPQUEST, mkexpr(op, cpexpr(tp),cpexpr(sp)), qp);qp = fixexpr(qp);newtemp = mktemp (type,PNULL);result = res = mkexpr (OPCOMMA,	mkexpr( OPASSIGN, cpexpr(sp), p0->datap ), cpexpr(newtemp));for(p1 = p0->nextp ; p1 ; p1 = p1->nextp)	{	APPEND (mkexpr( OPASSIGN, cpexpr(tp), p1->datap ));	if(p1->nextp)		APPEND (mkexpr (OPASSIGN, cpexpr(sp), cpexpr(qp)) );	else		APPEND (mkexpr (OPASSIGN, cpexpr(newtemp), qp));	}frtemp(sp);frtemp(tp);frtemp(newtemp);frchain( &p0 );return (result);}/* * Called by expand() to eliminate exponentiations to integer constants. */LOCAL expptr buffpower( p )	expptr p;{	expptr base;	Addrp newtemp;	expptr storetemp = ENULL;	expptr powtree();	expptr result;	ftnint exp;	if ( ! ISICON( p->exprblock.rightp ) )		fatal( "buffpower: bad non-integer exponent" );	base = expand(p->exprblock.leftp);	exp = p->exprblock.rightp->constblock.const.ci;	if ( exp < 2 )		fatal( "buffpower: bad exponent less than 2" );	if ( exp > 64 ) {		/*		 * Let's be reasonable, here...  Let putpower() do the job.		 */		p->exprblock.leftp = base;		return ( p );	}	/*	 * If the base is not a simple variable, evaluate it and copy the	 *	result into a temporary.	 */	if ( ! (base->tag == TADDR && ISCONST( base->addrblock.memoffset )) ) {		newtemp = mktemp( base->headblock.vtype, PNULL );		storetemp = mkexpr( OPASSIGN,			      cpexpr( (expptr) newtemp ),			      cpexpr( base ) );		base = (expptr) newtemp;	}	result = powtree( base, exp );	if ( storetemp != ENULL )		result = mkexpr( OPCOMMA, storetemp, result );	frexpr( p );	return ( result );}/* * powtree( base, exp ) -- Create a tree of multiplications which computes *	base ** exp.  The tree is built so that CSE will compact it if *	possible.  The routine works by creating subtrees that compute *	exponents which are powers of two, then multiplying these *	together to get the result; this gives a log2( exp ) tree depth *	and lots of subexpressions which can be eliminated. */LOCAL expptr powtree( base, exp )	expptr base;	register ftnint exp;{	register expptr r = ENULL, r1;	register int i;	for ( i = 0; exp; ++i, exp >>= 1 )		if ( exp & 1 )			if ( i == 0 )				r = (expptr) cpexpr( base );			else {				r1 = powtree( base, 1 << (i - 1) );				r1 = mkexpr( OPSTAR, r1, cpexpr( r1 ) );				r = (r ? mkexpr( OPSTAR, r1, r ) : r1);			}	return ( r );}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?