|
|
1.1 root 1: /* C compiler: tree simplification and constant folding */
2:
3: #include "c.h"
4:
5: int needconst; /* >=1 if parsing a constant expression */
6:
7: dclproto(static int add,(double, double, double, double, int));
8: dclproto(static Tree addrnode,(Symbol, int, Type));
9: dclproto(static int div,(double, double, double, double, int));
10: dclproto(static int mul,(double, double, double, double, int));
11: dclproto(static int sub,(double, double, double, double, int));
12:
13: /* add - return 1 if min <= x+y <= max, 0 otherwise */
14: static int add(x, y, min, max, needconst) double x, y, min, max; {
15: int cond = x == 0 || y == 0
16: || x < 0 && y < 0 && x >= min - y
17: || x < 0 && y > 0
18: || x > 0 && y < 0
19: || x > 0 && y > 0 && x <= max - y;
20: if (!cond && needconst) {
21: warning("overflow in constant expression\n");
22: cond = 1;
23: }
24: return cond;
25: }
26:
27: /* addrnode - create a tree for addressing expression p+n, type ty */
28: static Tree addrnode(p, n, ty) Symbol p; Type ty; {
29: Symbol q = (Symbol)talloc(sizeof *q);
30: Tree e;
31: static struct symbol z;
32:
33: *q = z;
34: q->name = stringd(genlabel(1));
35: q->sclass = p->sclass;
36: q->scope = p->scope;
37: q->type = ty;
38: q->defined = 1;
39: q->temporary = p->temporary;
40: q->generated = p->generated;
41: q->computed = 1;
42: q->addressed = p->addressed;
43: q->ref = 1;
44: if (p->scope == GLOBAL || p->sclass == STATIC || p->sclass == EXTERN) {
45: q->sclass = p->sclass == AUTO ? STATIC : p->sclass;
46: (*IR->address)(q, p, n);
47: e = tree(ADDRG+P, ty, 0, 0);
48: } else {
49: Code cp;
50: if (!p->defined)
51: addlocal(p);
52: cp = code(Address);
53: cp->u.addr.sym = q;
54: cp->u.addr.base = p;
55: cp->u.addr.offset = n;
56: e = tree(p->scope == PARAM ? ADDRF+P : ADDRL+P, ty, 0, 0);
57: }
58: e->u.sym = q;
59: return e;
60: }
61:
62: /* div - return 1 if min <= x/y <= max, 0 otherwise */
63: static int div(x, y, min, max, needconst) double x, y, min, max; {
64: int cond;
65:
66: if (x < 0) x = -x;
67: if (y < 0) y = -y;
68: cond = y != 0 && (y > 1 || x <= max*y);
69: if (!cond && y != 0 && needconst) {
70: warning("overflow in constant expression\n");
71: cond = 1;
72: }
73: return cond;
74: }
75:
76: /* ispow2 - if u > 1 && u == 2^n, return n, otherwise return 0 */
77: int ispow2(u) unsigned u; {
78: int n;
79:
80: if (u > 1 && (u&(u-1)) == 0)
81: for (n = 0; u; u >>= 1, n++)
82: if (u&1)
83: return n;
84: return 0;
85: }
86:
87: /* mul - return 1 if min <= x*y <= max, 0 otherwise */
88: static int mul(x, y, min, max, needconst) double x, y, min, max; {
89: int cond = x > -1 && x <= 1 || y > -1 && y <= 1
90: || x < 0 && y < 0 && -x <= max/-y
91: || x < 0 && y > 0 && x >= min/y
92: || x > 0 && y < 0 && x >= min/y
93: || x > 0 && y > 0 && x <= max/y;
94: if (!cond && needconst) {
95: warning("overflow in constant expression\n");
96: cond = 1;
97: }
98: return cond;
99: }
100:
101: #define xcvtcnst(FTYPE,TTYPE,EXP,VAR,MIN,MAX) \
102: if (l->op == CNST+FTYPE) { \
103: if (needconst && (VAR < MIN || VAR > MAX)) \
104: warning("overflow in constant expression\n"); \
105: if (needconst || VAR >= MIN && VAR <= MAX) { \
106: p = tree(CNST+ttob(TTYPE), TTYPE, 0, 0); EXP; return p; } }
107: #define cvtcnst(FTYPE,TTYPE,EXP) \
108: if (l->op == CNST+FTYPE) { \
109: p = tree(CNST+ttob(TTYPE), TTYPE, 0, 0); EXP; return p; }
110: #define commute(L,R) \
111: if (generic(R->op) == CNST && generic(L->op) != CNST) { \
112: Tree t = L; L = R; R = t; }
113: #define zerofield(OP,TYPE,VAR) \
114: if (l->op == FIELD && r->op == CNST+TYPE && r->u.v.VAR == 0) \
115: return eqnode(OP, bitnode(BAND, l->kids[0], \
116: constnode(fieldmask(l->u.field)<<fieldright(l->u.field), \
117: unsignedtype)), r);
118: #define ufoldcnst(TYPE,EXP) if (l->op == CNST+TYPE) return EXP
119: #define xfoldcnst(TYPE,VAR,OP,RTYPE,FUNC,MIN,MAX,needconst) \
120: if (l->op == CNST+TYPE && r->op == CNST+TYPE \
121: && FUNC((double)l->u.v.VAR,(double)r->u.v.VAR,(double)MIN,(double)MAX, needconst)) { \
122: p = tree(CNST+ttob(RTYPE), RTYPE, 0, 0); \
123: p->u.v.VAR = l->u.v.VAR OP r->u.v.VAR; return p; }
124: #define foldcnst(TYPE,VAR,OP,RTYPE) \
125: if (l->op == CNST+TYPE && r->op == CNST+TYPE) { \
126: p = tree(CNST+ttob(RTYPE), RTYPE, 0, 0); \
127: p->u.v.VAR = l->u.v.VAR OP r->u.v.VAR; return p; }
128: #define cfoldcnst(TYPE,VAR,OP,RTYPE) \
129: if (l->op == CNST+TYPE && r->op == CNST+TYPE) { \
130: p = tree(CNST+ttob(RTYPE), RTYPE, 0, 0); \
131: p->u.v.i = l->u.v.VAR OP r->u.v.VAR; return p; }
132: #define sfoldcnst(TYPE,VAR,OP,RTYPE) \
133: if (l->op == CNST+TYPE && r->op == CNST+I \
134: && r->u.v.i >= 0 && r->u.v.i < 8*l->type->size) { \
135: p = tree(CNST+ttob(RTYPE), RTYPE, 0, 0); \
136: p->u.v.VAR = l->u.v.VAR OP r->u.v.i; return p; }
137: #define foldaddp(L,R,RTYPE,VAR) \
138: if (L->op == CNST+P && R->op == CNST+RTYPE) { \
139: p = tree(CNST+P, ty, 0, 0); \
140: p->u.v.p = L->u.v.p + R->u.v.VAR; return p; }
141: #define geu(L,R,V) \
142: if (R->op == CNST+U && R->u.v.u == 0) { \
143: warning("result of unsigned comparison is constant\n"); \
144: return tree(RIGHT, inttype, root(L), constnode(V, inttype)); }
145: #define idempotent(OP) if (l->op == OP) return l->kids[0];
146: #define identity(X,Y,TYPE,VAR,VAL) if (X->op == CNST+TYPE && X->u.v.VAR == VAL) return Y
147:
148: /* simplify - build node for op, simplifying and folding constants, if possible */
149: Tree simplify(op, ty, l, r) Type ty; Tree l, r; {
150: int n;
151: Tree p;
152:
153: if (optype(op) == 0)
154: op += ttob(ty);
155: switch (op) {
156: case ADD+D:
157: xfoldcnst(D,d,+,doubletype,add,-DBL_MAX,DBL_MAX,0);
158: commute(r,l);
159: break;
160: case ADD+F:
161: xfoldcnst(F,f,+,floattype,add,-FLT_MAX,FLT_MAX,0);
162: commute(r,l);
163: break;
164: case ADD+I:
165: xfoldcnst(I,i,+,inttype,add,INT_MIN,INT_MAX,needconst);
166: commute(r,l);
167: break;
168: case ADD+P:
169: foldaddp(l,r,I,i);
170: foldaddp(l,r,U,u);
171: foldaddp(r,l,I,i);
172: foldaddp(r,l,U,u);
173: commute(r,l);
174: identity(r,retype(l,ty),I,i,0);
175: identity(r,retype(l,ty),U,u,0);
176: if (isaddrop(l->op) && (r->op == CNST+I || r->op == CNST+U))
177: /* l + c => l+c, where l is a symbolic address */
178: return addrnode(l->u.sym, r->op == CNST+I ? r->u.v.i : r->u.v.u, ty);
179: if ((l->op == ADD+I || l->op == SUB+I)
180: && l->kids[1]->op == CNST+I && isaddrop(r->op))
181: /* (x +- c) + r => x + r+-c, where r is a symbolic address */
182: return simplify(ADD+P, ty, l->kids[0],
183: simplify(l->op == ADD+I ? ADD+P : SUB+P, ty, r, l->kids[1]));
184: if (l->op == ADD+P && isaddrop(l->kids[1]->op)
185: && (r->op == CNST+I || r->op == CNST+U))
186: /* (x + a) + r => x + a+r */
187: return simplify(ADD+P, ty, l->kids[0],
188: addrnode(l->kids[1]->u.sym, r->op == CNST+I ? r->u.v.i : r->u.v.u, ty));
189: if (l->op == ADD+P && generic(l->kids[1]->op) == CNST && generic(r->op) == CNST)
190: /* (x + c) + r => x + c+r */
191: return simplify(ADD+P, ty, l->kids[0], (*opnode['+'])(ADD, l->kids[1], r));
192: if (l->op == ADD+I && generic(l->kids[1]->op) == CNST
193: && r->op == ADD+P && generic(r->kids[1]->op) == CNST)
194: /* (x + c1) + (y + c2) => x + (y + c1+c2) */
195: return simplify(ADD+P, ty, l->kids[0],
196: simplify(ADD+P, ty, r->kids[0],
197: (*opnode['+'])(ADD, l->kids[1], r->kids[1])));
198: if (l->op == RIGHT && isstruct(l->type)) /* f().x */
199: return tree(RIGHT, ty, l->kids[0],
200: simplify(ADD+P, ty, l->kids[1], r));
201: if (l->op == RIGHT)
202: if (l->kids[1])
203: return tree(RIGHT, ty, l->kids[0],
204: simplify(ADD+P, ty, l->kids[1], r));
205: else
206: return tree(RIGHT, ty,
207: simplify(ADD+P, ty, l->kids[0], r), 0);
208: break;
209: case ADD+U:
210: foldcnst(U,u,+,unsignedtype);
211: commute(r,l);
212: break;
213: case AND+I:
214: op = AND;
215: ufoldcnst(I,l->u.v.i ? cond(r) : l); /* 0&&r => 0, 1&&r => r */
216: break;
217: case OR+I:
218: op = OR;
219: /* 0||r => r, 1||r => 1 */
220: ufoldcnst(I,l->u.v.i ? constnode(1, inttype) : cond(r));
221: break;
222: case BAND+U:
223: foldcnst(U,u,&,unsignedtype);
224: commute(r,l);
225: identity(r,l,U,u,(~0));
226: if (r->op == CNST+U && r->u.v.u == 0) /* l&0 => (l,0) */
227: return tree(RIGHT, unsignedtype, root(l),
228: constnode(0, unsignedtype));
229: break;
230: case BCOM+I:
231: ufoldcnst(I,constnode(~l->u.v.i, inttype));
232: idempotent(BCOM+U);
233: op = BCOM+U;
234: break;
235: case BCOM+U:
236: ufoldcnst(U,constnode(~l->u.v.u, unsignedtype));
237: idempotent(BCOM+U);
238: break;
239: case BOR+U:
240: foldcnst(U,u,|,unsignedtype);
241: commute(r,l);
242: identity(r,l,U,u,0);
243: break;
244: case BXOR+U:
245: foldcnst(U,u,^,unsignedtype);
246: commute(r,l);
247: identity(r,l,U,u,0);
248: break;
249: case CVC+I: cvtcnst(C, inttype,p->u.v.i = (l->u.v.sc&0200 ? (~0<<8) : 0)|(l->u.v.sc&0377)); break;
250: case CVC+U: cvtcnst(C, unsignedtype,p->u.v.u = l->u.v.uc); break;
251: case CVD+F: xcvtcnst(D, floattype,p->u.v.f = l->u.v.d,l->u.v.d,-FLT_MAX,FLT_MAX); break;
252: case CVD+I: xcvtcnst(D, inttype,p->u.v.i = l->u.v.d,l->u.v.d,INT_MIN,INT_MAX); break;
253: case CVF+D: cvtcnst(F, doubletype,p->u.v.d = l->u.v.f); break;
254: case CVI+C: xcvtcnst(I, chartype,p->u.v.sc = l->u.v.i,l->u.v.i,SCHAR_MIN,SCHAR_MAX); break;
255: case CVI+D: cvtcnst(I, doubletype,p->u.v.d = l->u.v.i); break;
256: case CVI+S: xcvtcnst(I, shorttype,p->u.v.ss = l->u.v.i,l->u.v.i,SHRT_MIN,SHRT_MAX); break;
257: case CVI+U: cvtcnst(I, unsignedtype,p->u.v.u = l->u.v.i); break;
258: case CVP+U: cvtcnst(P, unsignedtype,p->u.v.u = (unsigned)l->u.v.p); break;
259: case CVS+I: cvtcnst(S, inttype,p->u.v.i = l->u.v.ss); break;
260: case CVS+U: cvtcnst(S, unsignedtype,p->u.v.u = l->u.v.us); break;
261: case CVU+C: cvtcnst(U, unsignedchar,p->u.v.uc = l->u.v.u); break;
262: case CVU+D: cvtcnst(U, doubletype,p->u.v.d = utod(l->u.v.u)); break;
263: case CVU+I:
264: if (needconst && l->u.v.u > INT_MAX)
265: warning("overflow in constant expression\n");
266: if (needconst || l->u.v.u <= INT_MAX)
267: cvtcnst(U, inttype,p->u.v.i = l->u.v.u);
268: break;
269: case CVU+P: cvtcnst(U, voidptype,p->u.v.p = (char *)l->u.v.u); break;
270: case CVU+S: cvtcnst(U,unsignedshort,p->u.v.us = l->u.v.u); break;
271: case DIV+D:
272: xfoldcnst(D,d,/,doubletype,div,-DBL_MAX,DBL_MAX,0);
273: break;
274: case DIV+F:
275: xfoldcnst(F,f,/,floattype,div,-FLT_MAX,FLT_MAX,0);
276: break;
277: case DIV+I:
278: identity(r,l,I,i,1);
279: #ifdef mips
280: if (l->op == CNST+I && r->op == CNST+I && r->u.v.i == -1
281: && !div((double)l->u.v.i, (double)r->u.v.i, (double)INT_MIN, (double)INT_MAX, 0))
282: break;
283: #endif
284: xfoldcnst(I,i,/,inttype,div,INT_MIN,INT_MAX,needconst);
285: break;
286: case DIV+U:
287: identity(r,l,U,u,1);
288: if (r->op == CNST+U && r->u.v.u == 0)
289: break;
290: if (r->op == CNST+U && (n = ispow2(r->u.v.u)))
291: return simplify(RSH+U, unsignedtype, l, constnode(n, inttype));
292: foldcnst(U,u,/,unsignedtype);
293: break;
294: case EQ+D:
295: cfoldcnst(D,d,==,inttype);
296: commute(r,l);
297: break;
298: case EQ+F:
299: cfoldcnst(F,f,==,inttype);
300: commute(r,l);
301: break;
302: case EQ+I:
303: cfoldcnst(I,i,==,inttype);
304: commute(r,l);
305: zerofield(EQ,I,i);
306: break;
307: case EQ+U:
308: cfoldcnst(U,u,==,inttype);
309: commute(r,l);
310: zerofield(EQ,U,u);
311: op = EQ+I;
312: break;
313: case GE+D: cfoldcnst(D,d,>=,inttype); break;
314: case GE+F: cfoldcnst(F,f,>=,inttype); break;
315: case GE+I: cfoldcnst(I,i,>=,inttype); break;
316: case GE+U:
317: geu(l,r,1); /* l >= 0 => (l,1) */
318: cfoldcnst(U,u,>=,inttype);
319: if (l->op == CNST+U && l->u.v.u == 0) /* 0 >= r => 0 == r */
320: return tree(EQ+I, ty, l, r);
321: break;
322: case GT+D: cfoldcnst(D,d, >,inttype); break;
323: case GT+F: cfoldcnst(F,f, >,inttype); break;
324: case GT+I: cfoldcnst(I,i, >,inttype); break;
325: case GT+U:
326: geu(r,l,0); /* 0 > r => (r,0) */
327: cfoldcnst(U,u, >,inttype);
328: if (r->op == CNST+U && r->u.v.u == 0) /* l > 0 => l != 0 */
329: return tree(NE+I, ty, l, r);
330: break;
331: case LE+D: cfoldcnst(D,d,<=,inttype); break;
332: case LE+F: cfoldcnst(F,f,<=,inttype); break;
333: case LE+I: cfoldcnst(I,i,<=,inttype); break;
334: case LE+U:
335: geu(r,l,1); /* 0 <= r => (r,1) */
336: cfoldcnst(U,u,<=,inttype);
337: if (r->op == CNST+U && r->u.v.u == 0) /* l <= 0 => l == 0 */
338: return tree(EQ+I, ty, l, r);
339: break;
340: case LSH+I:
341: identity(r,l,I,i,0);
342: if (l->op == CNST+I && r->op == CNST+I
343: && r->u.v.i >= 0 && r->u.v.i < 8*l->type->size
344: && mul((double)l->u.v.i, (double)(1<<r->u.v.i), (double)INT_MIN, (double)INT_MAX, needconst))
345: return constnode(l->u.v.i<<r->u.v.i, inttype);
346: break;
347: case LSH+U:
348: identity(r,l,I,i,0);
349: sfoldcnst(U,u,<<,unsignedtype);
350: break;
351: case LT+D: cfoldcnst(D,d, <,inttype); break;
352: case LT+F: cfoldcnst(F,f, <,inttype); break;
353: case LT+I: cfoldcnst(I,i, <,inttype); break;
354: case LT+U:
355: geu(l,r,0); /* l < 0 => (l,0) */
356: cfoldcnst(U,u, <,inttype);
357: if (l->op == CNST+U && l->u.v.u == 0) /* 0 < r => 0 != r */
358: return tree(NE+I, ty, l, r);
359: break;
360: case MOD+I:
361: if (r->op == CNST+I && r->u.v.i == 1) /* l%1 => (l,0) */
362: return tree(RIGHT, inttype, root(l), constnode(0, inttype));
363: if (r->op == CNST+I && r->u.v.i == 0)
364: break;
365: #ifdef mips
366: if (l->op == CNST+I && r->op == CNST+I && r->u.v.i == -1
367: && !div((double)l->u.v.i, (double)r->u.v.i, (double)INT_MIN, (double)INT_MAX, 0))
368: break;
369: #endif
370: xfoldcnst(I,i,%,inttype,div,INT_MIN,INT_MAX,needconst);
371: break;
372: case MOD+U:
373: if (r->op == CNST+U && ispow2(r->u.v.u)) /* l%2^n => l&(2^n-1) */
374: return bitnode(BAND, l,
375: constnode(r->u.v.u - 1, unsignedtype));
376: if (r->op == CNST+U && r->u.v.u == 0)
377: break;
378: foldcnst(U,u,%,unsignedtype);
379: break;
380: case MUL+D:
381: xfoldcnst(D,d,*,doubletype,mul,-DBL_MAX,DBL_MAX,0);
382: commute(l,r);
383: break;
384: case MUL+F:
385: xfoldcnst(F,f,*,floattype,mul,-FLT_MAX,FLT_MAX,0);
386: commute(l,r);
387: break;
388: case MUL+I:
389: commute(l,r);
390: if (l->op == CNST+I && r->op == ADD+I && r->kids[1]->op == CNST+I)
391: /* c1*(x + c2) => c1*x + c1*c2 */
392: return simplify(ADD+I, inttype, simplify(MUL+I, inttype, l, r->kids[0]),
393: simplify(MUL+I, inttype, l, r->kids[1]));
394: if (l->op == CNST+I && r->op == SUB+I && r->kids[1]->op == CNST+I)
395: /* c1*(x - c2) => c1*x - c1*c2 */
396: return simplify(SUB+I, inttype, simplify(MUL+I, inttype, l, r->kids[0]),
397: simplify(MUL+I, inttype, l, r->kids[1]));
398: if (l->op == CNST+I && l->u.v.i > 0 && (n = ispow2(l->u.v.i)))
399: /* 2^n * r => r<<n */
400: return simplify(LSH+I, inttype, r, constnode(n, inttype));
401: xfoldcnst(I,i,*,inttype,mul,INT_MIN,INT_MAX,needconst);
402: break;
403: case MUL+U:
404: commute(l,r);
405: if (l->op == CNST+U && (n = ispow2(l->u.v.u)))
406: /* 2^n * r => r<<n */
407: return simplify(LSH+U, unsignedtype, r, constnode(n, inttype));
408: foldcnst(U,u,*,unsignedtype);
409: break;
410: case NE+D:
411: foldcnst(D,d,!=,inttype);
412: commute(r,l);
413: break;
414: case NE+F:
415: cfoldcnst(F,f,!=,inttype);
416: commute(r,l);
417: break;
418: case NE+I:
419: cfoldcnst(I,i,!=,inttype);
420: commute(r,l);
421: zerofield(NE,I,i);
422: break;
423: case NE+U:
424: cfoldcnst(U,u,!=,inttype);
425: commute(r,l);
426: zerofield(NE,U,u);
427: op = NE+I;
428: break;
429: case NEG+D:
430: ufoldcnst(D,(p = tree(CNST+D, doubletype, 0, 0), p->u.v.d = -l->u.v.d, p));
431: idempotent(NEG+D);
432: break;
433: case NEG+F:
434: ufoldcnst(F,(p = tree(CNST+F, floattype, 0, 0), p->u.v.f = -l->u.v.f, p));
435: idempotent(NEG+F);
436: break;
437: case NEG+I:
438: if (l->op == CNST+I) {
439: if (needconst && l->u.v.i == INT_MIN)
440: warning("overflow in constant expression\n");
441: if (needconst || l->u.v.i != INT_MIN)
442: return constnode(-l->u.v.i, inttype);
443: }
444: idempotent(NEG+I);
445: break;
446: case NOT+I:
447: op = NOT;
448: ufoldcnst(I,constnode(!l->u.v.i, inttype));
449: break;
450: case RSH+I:
451: identity(r,l,I,i,0);
452: if (l->op == CNST+I && r->op == CNST+I
453: && r->u.v.i >= 0 && r->u.v.i < 8*l->type->size) {
454: int n = l->u.v.i>>r->u.v.i;
455: if (l->u.v.i < 0)
456: n |= ~0<<(8*l->type->size - r->u.v.i);
457: return constnode(n, inttype);
458: }
459: break;
460: case RSH+U:
461: identity(r,l,I,i,0);
462: sfoldcnst(U,u,>>,unsignedtype);
463: break;
464: case SUB+D:
465: xfoldcnst(D,d,-,doubletype,sub,-DBL_MAX,DBL_MAX,0);
466: break;
467: case SUB+F:
468: xfoldcnst(F,f,-,floattype,sub,-FLT_MAX,FLT_MAX,0);
469: break;
470: case SUB+I:
471: xfoldcnst(I,i,-,inttype,sub,INT_MIN,INT_MAX,needconst);
472: break;
473: case SUB+U:
474: foldcnst(U,u,-,unsignedtype);
475: break;
476: case SUB+P:
477: if (l->op == CNST+P && r->op == CNST+P)
478: return constnode(l->u.v.p - r->u.v.p, inttype);
479: if (r->op == CNST+I || r->op == CNST+U)
480: return simplify(ADD+P, ty, l,
481: constnode(r->op == CNST+I ? -r->u.v.i : -(int)r->u.v.u, inttype));
482: if (isaddrop(l->op) && r->op == ADD+I && r->kids[1]->op == CNST+I)
483: /* l - (x + c) => l-c - x */
484: return simplify(SUB+P, ty,
485: simplify(SUB+P, ty, l, r->kids[1]), r->kids[0]);
486: break;
487: default:assert(0);
488: }
489: return tree(op, ty, l, r);
490: }
491:
492: /* sub - return 1 if min <= x-y <= max, 0 otherwise */
493: static int sub(x, y, min, max, needconst) double x, y, min, max; {
494: return add(x, -y, min, max, needconst);
495: }
496:
497: /* vtoa - return string for the constant v of type ty */
498: char *vtoa(ty, v) Type ty; Value v; {
499: char buf[50];
500:
501: ty = unqual(ty);
502: switch (ty->op) {
503: case CHAR:
504: return stringf("%d", v.uc);
505: case SHORT:
506: return stringf("%d", v.ss);
507: case INT:
508: return stringf("%d", v.i);
509: case UNSIGNED:
510: if ((v.u&~0x7fff) == 0)
511: return stringf("%d", v.u);
512: else
513: return stringf("0x%x", v.u);
514: case FLOAT:
515: if (v.f == 0.0)
516: return "0";
517: sprintf(buf, "%.*g", 8, v.f);
518: return string(buf);
519: case DOUBLE:
520: if (v.d == 0.0)
521: return "0";
522: sprintf(buf, "%.*g", 18, v.d);
523: return string(buf);
524: case ARRAY:
525: if (ty->type->op == CHAR)
526: return v.p;
527: /* else fall thru */
528: case POINTER: case FUNCTION:
529: if (((unsigned)v.p&~0x7fff) == 0)
530: return stringf("%d", v.p);
531: else
532: return stringf("0x%x", v.p);
533: default:assert(0);
534: }
535: return 0;
536: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.