|
|
1.1 root 1: /*
2: * This file contains the machine-specific parts of the parser.
3: * It is used in both the SMALL and the LARGE models of segmentation.
4: */
5: #ifdef vax
6: #include "INC$LIB:cc0.h"
7: #else
8: #include "cc0.h"
9: #endif
10:
11: typedef struct locals {
12: struct locals *l_lstp;
13: int l_lofs;
14: int l_mask;
15: } LOCALS;
16:
17: LOCALS *clstp; /* Local stack */
18: int clofs; /* Current local offset */
19: int cmask; /* Current mask */
20: int llofs; /* Last local offset reported */
21: int lmask; /* Last register mask reported */
22: int lastword = T_PTR; /* Last 16 bit type */
23: char inbtr[] = "identifier \"%s\" not bound to register";
24:
25: /*
26: * This table is indexed by C type to obtain the size
27: * in bytes of a machine object.
28: * The T_PTR entry is 2; this is for ONLYSMALL.
29: * The entry is patched based on the model.
30: */
31: int mysizes[] = {
32: 0,
33: 1, 1,
34: 2, 2,
35: 2, 2,
36: 2,
37: 4, 4,
38: 4, 8,
39: 0,
40: 0, 0,
41: 0, 0,
42: 0, 0
43: };
44:
45: /*
46: * This table is indexed by C type to obtain the machine type,
47: * as defined in 'mch.h'.
48: */
49: char mytypes[] = {
50: 0,
51: S8, U8,
52: S16, U16,
53: S16, U16,
54: SPTR,
55: S32, U32,
56: F32, F64,
57: S16,
58: BLK, 0,
59: BLK, 0,
60: 0, 0
61: };
62:
63: /*
64: * main() calls this routine to perform machine-dependent setup.
65: * On the i8086, it changes the size of a pointer and some other things
66: * that alter the allocation of register variables.
67: */
68: vinit()
69: {
70: #if !ONLYSMALL
71: lastword = T_PTR;
72: mysizes[T_PTR] = 2;
73: mytypes[T_PTR] = SPTR;
74: if (notvariant(VSMALL)) {
75: lastword = T_UINT;
76: mysizes[T_PTR] = 4;
77: mytypes[T_PTR] = LPTR;
78: }
79: #endif
80: }
81:
82: /*
83: * Empty the local binding stack and mark the registers usable
84: * for register variables (SI and DI) as available.
85: */
86: initlocals()
87: {
88: clstp = NULL;
89: clofs = 0;
90: cmask = BCS|BSS|BSP|BBP;
91: llofs = 0;
92: lmask = BCS|BSS|BSP|BBP;
93: bput(AUTOS);
94: iput((ival_t)clofs);
95: iput((ival_t)cmask);
96: }
97:
98: /*
99: * Save the current state of the local bindings.
100: */
101: savelocals()
102: {
103: register LOCALS *lstp;
104:
105: lstp = (LOCALS *) new(sizeof(LOCALS));
106: lstp->l_lstp = clstp;
107: lstp->l_lofs = clofs;
108: lstp->l_mask = cmask;
109: clstp = lstp;
110: }
111:
112: /*
113: * Restore locals. Tell the code generator if it changes.
114: */
115: restlocals()
116: {
117: register LOCALS *lstp;
118:
119: if ((lstp=clstp) == NULL)
120: cbotch("restlocals");
121: clstp = lstp->l_lstp;
122: clofs = lstp->l_lofs;
123: cmask = lstp->l_mask;
124: putautos();
125: free((char *) lstp);
126: }
127:
128: /*
129: * Bind locals to the correct place on the stack frame.
130: * Where things end up is a function of the model of compilation.
131: */
132: bindlocal(sp)
133: register SYM *sp;
134: {
135: register int c, regno;
136:
137: if ((c=sp->s_class) == C_REG) {
138: if ((regno=grabreg(sp)) >= 0) {
139: sp->s_value = regno;
140: return;
141: }
142: sp->s_class = C_AUTO;
143: if (isvariant(VSNREG))
144: cstrict(inbtr, sp->s_id);
145: }
146: if (c==C_AUTO || c==C_REG) {
147: clofs -= ssize(sp);
148: #if OMF286
149: /*
150: * The 80287 does not function properly for arguments
151: * on odd boundaries.
152: * The OMF286 compiler therefore rounds up the offsets
153: * of autos to keep them on even boundaries;
154: * however, char and unsigned char autos are not word-aligned.
155: * The compiler driver must also setvariant(VALIGN) to keep
156: * the stack word-aligned.
157: * fieldalign() should also keep structure members
158: * on word boundaries within the struct, but it does not;
159: * this is a kludge to maintain compatability with PL/M-286,
160: * which does not word-align structure members.
161: * The UDI interface routines fail if structure members
162: * are forced to word boundaries.
163: */
164: if (ssize(sp) != 1 && (clofs & 1) != 0)
165: --clofs;
166: #endif
167: sp->s_value = clofs;
168: if (clofs >= 0)
169: cerror("auto \"%s\" is not addressable", sp->s_id);
170: }
171: }
172:
173: /*
174: * Attempt to get a register for symbol 'sp'.
175: * Only word things go in registers;
176: * this includes pointers in SMALL model.
177: */
178: grabreg(sp)
179: register SYM *sp;
180: {
181: register DIM *dp;
182: register int type;
183:
184: if ((dp=sp->s_dp) != NULL) {
185: #if !ONLYSMALL
186: if (isvariant(VSMALL)) {
187: #endif
188: if (dp->d_type == D_PTR) {
189: if ((cmask&BSI) == 0) {
190: cmask |= BSI;
191: return (SI);
192: }
193: if ((cmask&BDI) == 0) {
194: cmask |= BDI;
195: return (DI);
196: }
197: }
198: #if !ONLYSMALL
199: }
200: #endif
201: return (-1);
202: }
203: type = sp->s_type;
204: if (type>=T_SHORT && type<=lastword) {
205: if ((cmask&BSI) == 0) {
206: cmask |= BSI;
207: return (SI);
208: }
209: if ((cmask&BDI) == 0) {
210: cmask |= BDI;
211: return (DI);
212: }
213: }
214: return (-1);
215: }
216:
217: /*
218: * Bind arguments.
219: */
220: bindargs()
221: {
222: register SYM *sp;
223: register int i;
224: register sizeof_t offset;
225:
226: #if !ONLYSMALL
227: if (isvariant(VSMALL))
228: offset = 8;
229: else
230: offset = 10;
231: #else
232: offset = 8;
233: #endif
234: for (i=0; i<nargs; ++i) {
235: sp = args[i];
236: if (sp->s_class != C_PREG)
237: sp->s_class = C_PAUTO;
238: sp->s_value = offset;
239: offset += ssize(sp);
240: if (isvariant(VALIGN) && (offset & 1) != 0)
241: ++offset;
242: if ((short)offset != offset)
243: cerror("parameter \"%s\" is not addressible", sp->s_id);
244: }
245: }
246:
247: /*
248: * Copy register arguments from the stack into the register.
249: * Change class of the argument to plain register.
250: * Note that bindargs() has put the stack displacement
251: * into the 's_value' field of the argument symbol.
252: */
253: loadargs()
254: {
255: register SYM *sp;
256: register int i, r, v;
257:
258: for (i=0; i<nargs; ++i) {
259: sp = args[i];
260: if (sp->s_class == C_PREG) {
261: if ((r=grabreg(sp)) >= 0) {
262: v = sp->s_value;
263: sp->s_class = C_REG;
264: sp->s_value = r;
265: loadreg(sp, v);
266: continue;
267: }
268: sp->s_class = C_PAUTO;
269: if (isvariant(VSNREG))
270: cstrict(inbtr, sp->s_id);
271: }
272: }
273: }
274:
275: /*
276: * Load symbol 'sp' from offset 'offset' in the frame.
277: * Since register variables are always words,
278: * the type can always be setup to T_INT.
279: */
280: loadreg(sp, offset)
281: SYM *sp;
282: {
283: register TREE *lp, *rp, *tp;
284:
285: newtree(sizeof(TREE));
286: lp = talloc();
287: lp->t_op = REG;
288: lp->t_type = T_INT;
289: lp->t_reg = sp->s_value;
290: rp = talloc();
291: rp->t_op = PID;
292: rp->t_type = T_INT;
293: rp->t_offs = offset;
294: tp = build(ASSIGN, lp, rp);
295: putautos();
296: tput(EEXPR, 0, tp);
297: }
298:
299: /*
300: * Inform the code generator (and perhaps the optimizer)
301: * about the current automatic variable allocation.
302: * Keep the stack word-aligned if isvariant(VALIGN).
303: */
304: putautos()
305: {
306: if (clofs != llofs || cmask != lmask) {
307: if (isvariant(VALIGN) && (clofs & 1) != 0)
308: --clofs;
309: llofs = clofs;
310: lmask = cmask;
311: bput(AUTOS);
312: iput((ival_t)-clofs);
313: iput((ival_t)cmask);
314: }
315: }
316:
317: /*
318: * Look at type 't', DIM list 'dp' and field width 'w' (0 for non fields)
319: * and return the bit offset of the base of the structure member.
320: * The 'offset' argument is the current bit offset in the structure or union.
321: * Check for fields that are too wide, bad field base types, and arrange
322: * that the byte or word that spans the field can be grabbed in one grab.
323: * See comments in bindlocal() above concerning reals and bitfield alignment.
324: */
325: long
326: fieldalign(t, dp, ip, w, offset)
327: register DIM *dp;
328: INFO *ip;
329: register int w;
330: long offset;
331: {
332: register int maxwidth;
333:
334: if (w != 0) { /* nonzero width */
335: if (dp != 0)
336: cerror("non scalar field");
337: if ((maxwidth=8*mysizes[t]) > 16) /* 8 for char, 16 for int */
338: cerror("bad base type for field");
339: if (w > maxwidth)
340: cerror("field too wide");
341: if ((offset&7)+w > maxwidth)
342: offset = (offset+7) & ~7L;
343: } else { /* zero width */
344: offset = (offset+7) & ~7L;
345: }
346: return (offset);
347: }
348:
349: /*
350: * Convert a tree into its low level form.
351: * Fill in the machine type byte looking at the C type
352: * and the segment information.
353: */
354: TREE *
355: transform(tp, why, above)
356: register TREE *tp;
357: {
358: register TREE *lp;
359: register int t;
360: register int wd;
361:
362: /*
363: * The way that this code looks at the DIM lists to decide
364: * what type of conversion is inserted makes me sick.
365: * The correct type of conversion node (MUL, DIV, etc.)
366: * should really be inserted when the tree is constructed,
367: * guided by a table.
368: */
369: if (tp->t_op == CONVERT) {
370: lp = tp->t_lp;
371: if (tp->t_dp!=NULL && lp->t_dp==NULL
372: && why!=REXPR) {
373: tp->t_op = MUL;
374: tp->t_dp = NULL;
375: if (lp->t_type != T_INT)
376: tp->t_lp = bconvert(lp, T_INT, NULL,NULL,NULL);
377: tp->t_type = T_INT;
378: } else if (tp->t_dp==NULL && lp->t_dp!=NULL && tp->t_rp!=NULL) {
379: tp->t_op = DIV;
380: lp->t_dp = NULL;
381: lp->t_type = T_INT;
382: }
383: }
384: /* Fixup any remaining ZCON's */
385: if (tp->t_op == ZCON) {
386: tp->t_op = ICON;
387: if (tp->t_zval > 0xFFFFL)
388: cwarn("sizeof truncated to unsigned");
389: if (tp->t_zval < 0x8000L)
390: tp->t_type = T_INT;
391: tp->t_ival = tp->t_zval;
392: }
393: if (tp->t_dp != NULL)
394: tp->t_type = mytypes[T_PTR];
395: else if ((t=tp->t_type)==T_FSTRUCT || t==T_FUNION || t==T_FENUM) {
396: unksize(t, tp->t_ip);
397: tp->t_type = S16;
398: } else {
399: if (t == T_ENUM)
400: t = tp->t_ip->i_type;
401: tp->t_type = mytypes[t];
402: }
403: if (tp->t_op >= MIOBASE) {
404: wd = why;
405: if (why == REXPR)
406: wd = EEXPR;
407: tp->t_lp = transform(tp->t_lp, wd, tp->t_op);
408: if (tp->t_op!=FIELD && tp->t_rp!=NULL)
409: tp->t_rp = transform(tp->t_rp, wd, -1);
410: if (tp->t_op==CONVERT && tp->t_rp==NULL) {
411: lp = tp->t_lp;
412: if (tp->t_type == lp->t_type)
413: tp = lp;
414: }
415: }
416: return (tp);
417: }
418:
419: /*
420: * Check if the operator 'op', when applied to C types 'lt' and 'rt'
421: * (which are outputs from tltype(), which means that all pointers
422: * have been converted to type T_PTR), involves no conversions.
423: * What this means is that the code generator
424: * has to be prepared to deal with the type mismatch.
425: * This code has been edited too many times; I am really
426: * quite ashamed of the number of bugs that have been
427: * tracked down to this code. It is no longer amusing.
428: */
429: noconvert(op, lt, rt)
430: register int op;
431: register int lt;
432: register int rt;
433: {
434: if (op==ASSIGN || op==CAST || (op>=EQ && op<=ULT)) {
435: if ((lt>=T_CHAR && lt<=T_UCHAR)
436: && (rt>=T_CHAR && rt<=T_UCHAR))
437: return(1);
438: if ((lt>=T_SHORT && lt<=T_UINT)
439: && (rt>=T_SHORT && rt<=T_UINT))
440: return (1);
441: if ((lt>=T_LONG && lt<=T_ULONG)
442: && (rt>=T_LONG && rt<=T_ULONG))
443: return (1);
444: if (lt==T_PTR && rt==T_PTR)
445: return (1);
446: #if !ONLYSMALL
447: if (notvariant(VSMALL)
448: && op != CAST) {
449: if ((lt>=T_SHORT && lt<=T_ULONG)
450: && (rt>=T_SHORT && rt<=T_ULONG)
451: && (lt==T_PTR || rt==T_PTR))
452: return (1);
453: } else if (isvariant(VSMALL)) {
454: #endif
455: if ((lt>=T_SHORT && lt<=T_PTR)
456: && (rt>=T_SHORT && rt<=T_PTR))
457: return (1);
458: #if !ONLYSMALL
459: }
460: #endif
461: if (op==CAST && lt==T_FLOAT && rt==T_DOUBLE)
462: return (1);
463: }
464: return (0);
465: }
466:
467: /*
468: * Put out an ALIGN object of the correct flavor to align
469: * the location counter well enough for the object to which 'sp' points.
470: * On the i8086 there is only one type of alignment,
471: * so the argument is unused.
472: */
473: align(sp)
474: SYM *sp;
475: {
476: bput(ALIGN);
477: bput(0);
478: }
479:
480: /*
481: * Check object sizes for overflow.
482: */
483: sizeof_t szcheck(n, a, s) sizeof_t n; int a; char *s;
484: {
485: if (n < 0x10000L)
486: return n;
487: if (a == 0 || (n & ~MAXUV) != 0) {
488: cerror("size of %s too large", s);
489: return(0);
490: }
491: if (isvariant(VSLCON))
492: cstrict("size of %s overflows fsize_t", s);
493: return (n);
494: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.