2008-06-04 15:37:38 -06:00
|
|
|
// Inferno utils/cc/scon.c
|
|
|
|
// http://code.google.com/p/inferno-os/source/browse/utils/cc/scon.c
|
|
|
|
//
|
|
|
|
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
|
|
|
|
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
|
|
|
|
// Portions Copyright © 1997-1999 Vita Nuova Limited
|
|
|
|
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
|
|
|
|
// Portions Copyright © 2004,2006 Bruce Ellis
|
|
|
|
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
|
|
|
|
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
|
|
|
|
// Portions Copyright © 2009 The Go Authors. All rights reserved.
|
|
|
|
//
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
|
|
// in the Software without restriction, including without limitation the rights
|
|
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
|
|
// furnished to do so, subject to the following conditions:
|
|
|
|
//
|
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
// all copies or substantial portions of the Software.
|
|
|
|
//
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
// THE SOFTWARE.
|
|
|
|
|
2011-07-01 07:50:24 -06:00
|
|
|
#include <u.h>
|
2008-06-04 15:37:38 -06:00
|
|
|
#include "cc.h"
|
|
|
|
|
|
|
|
static Node*
|
|
|
|
acast(Type *t, Node *n)
|
|
|
|
{
|
|
|
|
if(n->type->etype != t->etype || n->op == OBIT) {
|
|
|
|
n = new1(OCAST, n, Z);
|
|
|
|
if(nocast(n->left->type, t))
|
|
|
|
*n = *n->left;
|
|
|
|
n->type = t;
|
|
|
|
}
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
evconst(Node *n)
|
|
|
|
{
|
|
|
|
Node *l, *r;
|
|
|
|
int et, isf;
|
|
|
|
vlong v;
|
|
|
|
double d;
|
|
|
|
|
|
|
|
if(n == Z || n->type == T)
|
|
|
|
return;
|
|
|
|
|
|
|
|
et = n->type->etype;
|
|
|
|
isf = typefd[et];
|
|
|
|
|
|
|
|
l = n->left;
|
|
|
|
r = n->right;
|
|
|
|
|
|
|
|
d = 0;
|
|
|
|
v = 0;
|
|
|
|
|
|
|
|
switch(n->op) {
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
|
|
|
|
case ONEG:
|
|
|
|
if(isf)
|
|
|
|
d = -l->fconst;
|
|
|
|
else
|
|
|
|
v = -l->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCOM:
|
|
|
|
v = ~l->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCAST:
|
|
|
|
if(et == TVOID)
|
|
|
|
return;
|
|
|
|
et = l->type->etype;
|
|
|
|
if(isf) {
|
|
|
|
if(typefd[et])
|
|
|
|
d = l->fconst;
|
|
|
|
else
|
|
|
|
d = l->vconst;
|
|
|
|
} else {
|
|
|
|
if(typefd[et])
|
|
|
|
v = l->fconst;
|
|
|
|
else
|
|
|
|
v = convvtox(l->vconst, n->type->etype);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OCONST:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OADD:
|
|
|
|
if(isf)
|
|
|
|
d = l->fconst + r->fconst;
|
|
|
|
else {
|
|
|
|
v = l->vconst + r->vconst;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OSUB:
|
|
|
|
if(isf)
|
|
|
|
d = l->fconst - r->fconst;
|
|
|
|
else
|
|
|
|
v = l->vconst - r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OMUL:
|
|
|
|
if(isf)
|
|
|
|
d = l->fconst * r->fconst;
|
|
|
|
else {
|
|
|
|
v = l->vconst * r->vconst;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OLMUL:
|
|
|
|
v = (uvlong)l->vconst * (uvlong)r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case ODIV:
|
|
|
|
if(vconst(r) == 0) {
|
|
|
|
warn(n, "divide by zero");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(isf)
|
|
|
|
d = l->fconst / r->fconst;
|
|
|
|
else
|
|
|
|
v = l->vconst / r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OLDIV:
|
|
|
|
if(vconst(r) == 0) {
|
|
|
|
warn(n, "divide by zero");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
v = (uvlong)l->vconst / (uvlong)r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OMOD:
|
|
|
|
if(vconst(r) == 0) {
|
|
|
|
warn(n, "modulo by zero");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
v = l->vconst % r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OLMOD:
|
|
|
|
if(vconst(r) == 0) {
|
|
|
|
warn(n, "modulo by zero");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
v = (uvlong)l->vconst % (uvlong)r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OAND:
|
|
|
|
v = l->vconst & r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OOR:
|
|
|
|
v = l->vconst | r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OXOR:
|
|
|
|
v = l->vconst ^ r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OLSHR:
|
|
|
|
v = (uvlong)l->vconst >> r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OASHR:
|
|
|
|
v = l->vconst >> r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OASHL:
|
|
|
|
v = l->vconst << r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OLO:
|
|
|
|
v = (uvlong)l->vconst < (uvlong)r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OLT:
|
|
|
|
if(typefd[l->type->etype])
|
|
|
|
v = l->fconst < r->fconst;
|
|
|
|
else
|
|
|
|
v = l->vconst < r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OHI:
|
|
|
|
v = (uvlong)l->vconst > (uvlong)r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OGT:
|
|
|
|
if(typefd[l->type->etype])
|
|
|
|
v = l->fconst > r->fconst;
|
|
|
|
else
|
|
|
|
v = l->vconst > r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OLS:
|
|
|
|
v = (uvlong)l->vconst <= (uvlong)r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OLE:
|
|
|
|
if(typefd[l->type->etype])
|
|
|
|
v = l->fconst <= r->fconst;
|
|
|
|
else
|
|
|
|
v = l->vconst <= r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OHS:
|
|
|
|
v = (uvlong)l->vconst >= (uvlong)r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OGE:
|
|
|
|
if(typefd[l->type->etype])
|
|
|
|
v = l->fconst >= r->fconst;
|
|
|
|
else
|
|
|
|
v = l->vconst >= r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OEQ:
|
|
|
|
if(typefd[l->type->etype])
|
|
|
|
v = l->fconst == r->fconst;
|
|
|
|
else
|
|
|
|
v = l->vconst == r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ONE:
|
|
|
|
if(typefd[l->type->etype])
|
|
|
|
v = l->fconst != r->fconst;
|
|
|
|
else
|
|
|
|
v = l->vconst != r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ONOT:
|
|
|
|
if(typefd[l->type->etype])
|
|
|
|
v = !l->fconst;
|
|
|
|
else
|
|
|
|
v = !l->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OANDAND:
|
|
|
|
if(typefd[l->type->etype])
|
|
|
|
v = l->fconst && r->fconst;
|
|
|
|
else
|
|
|
|
v = l->vconst && r->vconst;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OOROR:
|
|
|
|
if(typefd[l->type->etype])
|
|
|
|
v = l->fconst || r->fconst;
|
|
|
|
else
|
|
|
|
v = l->vconst || r->vconst;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(isf) {
|
|
|
|
n->fconst = d;
|
|
|
|
} else {
|
|
|
|
n->vconst = convvtox(v, n->type->etype);
|
|
|
|
}
|
|
|
|
n->oldop = n->op;
|
|
|
|
n->op = OCONST;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
acom(Node *n)
|
|
|
|
{
|
|
|
|
Type *t;
|
|
|
|
Node *l, *r;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
switch(n->op)
|
|
|
|
{
|
|
|
|
|
|
|
|
case ONAME:
|
|
|
|
case OCONST:
|
|
|
|
case OSTRING:
|
|
|
|
case OINDREG:
|
|
|
|
case OREGISTER:
|
|
|
|
return;
|
|
|
|
|
|
|
|
case ONEG:
|
|
|
|
l = n->left;
|
|
|
|
if(addo(n) && addo(l))
|
|
|
|
break;
|
|
|
|
acom(l);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case OADD:
|
|
|
|
case OSUB:
|
|
|
|
case OMUL:
|
|
|
|
l = n->left;
|
|
|
|
r = n->right;
|
|
|
|
if(addo(n)) {
|
|
|
|
if(addo(r))
|
|
|
|
break;
|
|
|
|
if(addo(l))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
acom(l);
|
|
|
|
acom(r);
|
|
|
|
return;
|
|
|
|
|
|
|
|
default:
|
|
|
|
l = n->left;
|
|
|
|
r = n->right;
|
|
|
|
if(l != Z)
|
|
|
|
acom(l);
|
|
|
|
if(r != Z)
|
|
|
|
acom(r);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* bust terms out */
|
|
|
|
t = n->type;
|
|
|
|
term[0].mult = 0;
|
|
|
|
term[0].node = Z;
|
|
|
|
nterm = 1;
|
|
|
|
acom1(1, n);
|
|
|
|
if(debug['m'])
|
|
|
|
for(i=0; i<nterm; i++) {
|
|
|
|
print("%d %3lld ", i, term[i].mult);
|
|
|
|
prtree1(term[i].node, 1, 0);
|
|
|
|
}
|
|
|
|
if(nterm < NTERM)
|
|
|
|
acom2(n, t);
|
|
|
|
n->type = t;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
acomcmp1(const void *a1, const void *a2)
|
|
|
|
{
|
|
|
|
vlong c1, c2;
|
|
|
|
Term *t1, *t2;
|
|
|
|
|
|
|
|
t1 = (Term*)a1;
|
|
|
|
t2 = (Term*)a2;
|
|
|
|
c1 = t1->mult;
|
|
|
|
if(c1 < 0)
|
|
|
|
c1 = -c1;
|
|
|
|
c2 = t2->mult;
|
|
|
|
if(c2 < 0)
|
|
|
|
c2 = -c2;
|
|
|
|
if(c1 > c2)
|
|
|
|
return 1;
|
|
|
|
if(c1 < c2)
|
|
|
|
return -1;
|
|
|
|
c1 = 1;
|
|
|
|
if(t1->mult < 0)
|
|
|
|
c1 = 0;
|
|
|
|
c2 = 1;
|
|
|
|
if(t2->mult < 0)
|
|
|
|
c2 = 0;
|
|
|
|
if(c2 -= c1)
|
|
|
|
return c2;
|
|
|
|
if(t2 > t1)
|
|
|
|
return 1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
acomcmp2(const void *a1, const void *a2)
|
|
|
|
{
|
|
|
|
vlong c1, c2;
|
|
|
|
Term *t1, *t2;
|
|
|
|
|
|
|
|
t1 = (Term*)a1;
|
|
|
|
t2 = (Term*)a2;
|
|
|
|
c1 = t1->mult;
|
|
|
|
c2 = t2->mult;
|
|
|
|
if(c1 > c2)
|
|
|
|
return 1;
|
|
|
|
if(c1 < c2)
|
|
|
|
return -1;
|
|
|
|
if(t2 > t1)
|
|
|
|
return 1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
acom2(Node *n, Type *t)
|
|
|
|
{
|
|
|
|
Node *l, *r;
|
|
|
|
Term trm[NTERM];
|
|
|
|
int et, nt, i, j;
|
|
|
|
vlong c1, c2;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* copy into automatic
|
|
|
|
*/
|
|
|
|
c2 = 0;
|
|
|
|
nt = nterm;
|
|
|
|
for(i=0; i<nt; i++)
|
|
|
|
trm[i] = term[i];
|
|
|
|
/*
|
|
|
|
* recur on subtrees
|
|
|
|
*/
|
|
|
|
j = 0;
|
|
|
|
for(i=1; i<nt; i++) {
|
|
|
|
c1 = trm[i].mult;
|
|
|
|
if(c1 == 0)
|
|
|
|
continue;
|
|
|
|
l = trm[i].node;
|
|
|
|
if(l != Z) {
|
|
|
|
j = 1;
|
|
|
|
acom(l);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
c1 = trm[0].mult;
|
|
|
|
if(j == 0) {
|
|
|
|
n->oldop = n->op;
|
|
|
|
n->op = OCONST;
|
|
|
|
n->vconst = c1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
et = t->etype;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* prepare constant term,
|
|
|
|
* combine it with an addressing term
|
|
|
|
*/
|
|
|
|
if(c1 != 0) {
|
|
|
|
l = new1(OCONST, Z, Z);
|
|
|
|
l->type = t;
|
|
|
|
l->vconst = c1;
|
|
|
|
trm[0].mult = 1;
|
|
|
|
for(i=1; i<nt; i++) {
|
|
|
|
if(trm[i].mult != 1)
|
|
|
|
continue;
|
|
|
|
r = trm[i].node;
|
|
|
|
if(r->op != OADDR)
|
|
|
|
continue;
|
|
|
|
r->type = t;
|
|
|
|
l = new1(OADD, r, l);
|
|
|
|
l->type = t;
|
|
|
|
trm[i].mult = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
trm[0].node = l;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* look for factorable terms
|
|
|
|
* c1*i + c1*c2*j -> c1*(i + c2*j)
|
|
|
|
*/
|
|
|
|
qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp1);
|
|
|
|
for(i=nt-1; i>=0; i--) {
|
|
|
|
c1 = trm[i].mult;
|
|
|
|
if(c1 < 0)
|
|
|
|
c1 = -c1;
|
|
|
|
if(c1 <= 1)
|
|
|
|
continue;
|
|
|
|
for(j=i+1; j<nt; j++) {
|
|
|
|
c2 = trm[j].mult;
|
|
|
|
if(c2 < 0)
|
|
|
|
c2 = -c2;
|
|
|
|
if(c2 <= 1)
|
|
|
|
continue;
|
|
|
|
if(c2 % c1)
|
|
|
|
continue;
|
|
|
|
r = trm[j].node;
|
|
|
|
if(r->type->etype != et)
|
|
|
|
r = acast(t, r);
|
|
|
|
c2 = trm[j].mult/trm[i].mult;
|
|
|
|
if(c2 != 1 && c2 != -1) {
|
|
|
|
r = new1(OMUL, r, new(OCONST, Z, Z));
|
|
|
|
r->type = t;
|
|
|
|
r->right->type = t;
|
|
|
|
r->right->vconst = c2;
|
|
|
|
}
|
|
|
|
l = trm[i].node;
|
|
|
|
if(l->type->etype != et)
|
|
|
|
l = acast(t, l);
|
|
|
|
r = new1(OADD, l, r);
|
|
|
|
r->type = t;
|
|
|
|
if(c2 == -1)
|
|
|
|
r->op = OSUB;
|
|
|
|
trm[i].node = r;
|
|
|
|
trm[j].mult = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(debug['m']) {
|
|
|
|
print("\n");
|
|
|
|
for(i=0; i<nt; i++) {
|
|
|
|
print("%d %3lld ", i, trm[i].mult);
|
|
|
|
prtree1(trm[i].node, 1, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* put it all back together
|
|
|
|
*/
|
|
|
|
qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp2);
|
|
|
|
l = Z;
|
|
|
|
for(i=nt-1; i>=0; i--) {
|
|
|
|
c1 = trm[i].mult;
|
|
|
|
if(c1 == 0)
|
|
|
|
continue;
|
|
|
|
r = trm[i].node;
|
|
|
|
if(r->type->etype != et || r->op == OBIT)
|
|
|
|
r = acast(t, r);
|
|
|
|
if(c1 != 1 && c1 != -1) {
|
|
|
|
r = new1(OMUL, r, new(OCONST, Z, Z));
|
|
|
|
r->type = t;
|
|
|
|
r->right->type = t;
|
|
|
|
if(c1 < 0) {
|
|
|
|
r->right->vconst = -c1;
|
|
|
|
c1 = -1;
|
|
|
|
} else {
|
|
|
|
r->right->vconst = c1;
|
|
|
|
c1 = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(l == Z) {
|
|
|
|
l = r;
|
|
|
|
c2 = c1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if(c1 < 0)
|
|
|
|
if(c2 < 0)
|
|
|
|
l = new1(OADD, l, r);
|
|
|
|
else
|
|
|
|
l = new1(OSUB, l, r);
|
|
|
|
else
|
|
|
|
if(c2 < 0) {
|
|
|
|
l = new1(OSUB, r, l);
|
|
|
|
c2 = 1;
|
|
|
|
} else
|
|
|
|
l = new1(OADD, l, r);
|
|
|
|
l->type = t;
|
|
|
|
}
|
|
|
|
if(c2 < 0) {
|
|
|
|
r = new1(OCONST, 0, 0);
|
|
|
|
r->vconst = 0;
|
|
|
|
r->type = t;
|
|
|
|
l = new1(OSUB, r, l);
|
|
|
|
l->type = t;
|
|
|
|
}
|
|
|
|
*n = *l;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
acom1(vlong v, Node *n)
|
|
|
|
{
|
|
|
|
Node *l, *r;
|
|
|
|
|
|
|
|
if(v == 0 || nterm >= NTERM)
|
|
|
|
return;
|
|
|
|
if(!addo(n)) {
|
|
|
|
if(n->op == OCONST)
|
|
|
|
if(!typefd[n->type->etype]) {
|
|
|
|
term[0].mult += v*n->vconst;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
term[nterm].mult = v;
|
|
|
|
term[nterm].node = n;
|
|
|
|
nterm++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
switch(n->op) {
|
|
|
|
|
|
|
|
case OCAST:
|
|
|
|
acom1(v, n->left);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ONEG:
|
|
|
|
acom1(-v, n->left);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OADD:
|
|
|
|
acom1(v, n->left);
|
|
|
|
acom1(v, n->right);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OSUB:
|
|
|
|
acom1(v, n->left);
|
|
|
|
acom1(-v, n->right);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OMUL:
|
|
|
|
l = n->left;
|
|
|
|
r = n->right;
|
|
|
|
if(l->op == OCONST)
|
|
|
|
if(!typefd[n->type->etype]) {
|
|
|
|
acom1(v*l->vconst, r);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(r->op == OCONST)
|
|
|
|
if(!typefd[n->type->etype]) {
|
|
|
|
acom1(v*r->vconst, l);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
diag(n, "not addo");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
addo(Node *n)
|
|
|
|
{
|
|
|
|
|
|
|
|
if(n != Z)
|
|
|
|
if(!typefd[n->type->etype])
|
|
|
|
if(!typev[n->type->etype] || ewidth[TVLONG] == ewidth[TIND])
|
|
|
|
switch(n->op) {
|
|
|
|
|
|
|
|
case OCAST:
|
|
|
|
if(nilcast(n->left->type, n->type))
|
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ONEG:
|
|
|
|
case OADD:
|
|
|
|
case OSUB:
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
case OMUL:
|
|
|
|
if(n->left->op == OCONST)
|
|
|
|
return 1;
|
|
|
|
if(n->right->op == OCONST)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|