Commit | Line | Data |
---|---|---|
f1525c23 WH |
1 | /**************************************************************** |
2 | Copyright 1990, 1991, 1993 by AT&T Bell Laboratories and Bellcore. | |
3 | ||
4 | Permission to use, copy, modify, and distribute this software | |
5 | and its documentation for any purpose and without fee is hereby | |
6 | granted, provided that the above copyright notice appear in all | |
7 | copies and that both that the copyright notice and this | |
8 | permission notice and warranty disclaimer appear in supporting | |
9 | documentation, and that the names of AT&T Bell Laboratories or | |
10 | Bellcore or any of their entities not be used in advertising or | |
11 | publicity pertaining to distribution of the software without | |
12 | specific, written prior permission. | |
13 | ||
14 | AT&T and Bellcore disclaim all warranties with regard to this | |
15 | software, including all implied warranties of merchantability | |
16 | and fitness. In no event shall AT&T or Bellcore be liable for | |
17 | any special, indirect or consequential damages or any damages | |
18 | whatsoever resulting from loss of use, data or profits, whether | |
19 | in an action of contract, negligence or other tortious action, | |
20 | arising out of or in connection with the use or performance of | |
21 | this software. | |
22 | ****************************************************************/ | |
23 | ||
24 | /* | |
25 | * INTERMEDIATE CODE GENERATION PROCEDURES COMMON TO BOTH | |
26 | * JOHNSON (PORTABLE) AND RITCHIE FAMILIES OF SECOND PASSES | |
27 | */ | |
28 | ||
29 | #include "defs.h" | |
30 | #include "names.h" /* For LOCAL_CONST_NAME */ | |
31 | #include "pccdefs.h" | |
32 | #include "p1defs.h" | |
33 | ||
34 | /* Definitions for putconst() */ | |
35 | ||
36 | #define LIT_CHAR 1 | |
37 | #define LIT_FLOAT 2 | |
38 | #define LIT_INT 3 | |
39 | ||
40 | ||
41 | /* | |
42 | char *ops [ ] = | |
43 | { | |
44 | "??", "+", "-", "*", "/", "**", "-", | |
45 | "OR", "AND", "EQV", "NEQV", "NOT", | |
46 | "CONCAT", | |
47 | "<", "==", ">", "<=", "!=", ">=", | |
48 | " of ", " ofC ", " = ", " += ", " *= ", " CONV ", " << ", " % ", | |
49 | " , ", " ? ", " : " | |
50 | " abs ", " min ", " max ", " addr ", " indirect ", | |
51 | " bitor ", " bitand ", " bitxor ", " bitnot ", " >> ", | |
52 | }; | |
53 | */ | |
54 | ||
55 | /* Each of these values is defined in pccdefs */ | |
56 | ||
57 | int ops2 [ ] = | |
58 | { | |
59 | P2BAD, P2PLUS, P2MINUS, P2STAR, P2SLASH, P2BAD, P2NEG, | |
60 | P2OROR, P2ANDAND, P2EQ, P2NE, P2NOT, | |
61 | P2BAD, | |
62 | P2LT, P2EQ, P2GT, P2LE, P2NE, P2GE, | |
63 | P2CALL, P2CALL, P2ASSIGN, P2PLUSEQ, P2STAREQ, P2CONV, P2LSHIFT, P2MOD, | |
64 | P2COMOP, P2QUEST, P2COLON, | |
65 | 1, P2BAD, P2BAD, P2BAD, P2BAD, | |
66 | P2BITOR, P2BITAND, P2BITXOR, P2BITNOT, P2RSHIFT, | |
67 | P2BAD, P2BAD, P2BAD, P2BAD, P2BAD, P2BAD, P2BAD, P2BAD, P2BAD, | |
68 | P2BAD, P2BAD, P2BAD, P2BAD, | |
69 | 1,1,1,1,1, /* OPNEG1, OPDMIN, OPDMAX, OPASSIGNI, OPIDENTITY */ | |
70 | 1,1,1,1 /* OPCHARCAST, OPDABS, OPMIN2, OPMAX2 */ | |
71 | }; | |
72 | ||
73 | ||
74 | setlog() | |
75 | { | |
76 | typesize[TYLOGICAL] = typesize[tylogical]; | |
77 | typealign[TYLOGICAL] = typealign[tylogical]; | |
78 | } | |
79 | ||
80 | ||
81 | putexpr(p) | |
82 | expptr p; | |
83 | { | |
84 | /* Write the expression to the p1 file */ | |
85 | ||
86 | p = (expptr) putx (fixtype (p)); | |
87 | p1_expr (p); | |
88 | } | |
89 | ||
90 | ||
91 | ||
92 | ||
93 | ||
94 | expptr putassign(lp, rp) | |
95 | expptr lp, rp; | |
96 | { | |
97 | return putx(fixexpr((Exprp)mkexpr(OPASSIGN, lp, rp))); | |
98 | } | |
99 | ||
100 | ||
101 | ||
102 | ||
103 | void puteq(lp, rp) | |
104 | expptr lp, rp; | |
105 | { | |
106 | putexpr(mkexpr(OPASSIGN, lp, rp) ); | |
107 | } | |
108 | ||
109 | ||
110 | ||
111 | ||
112 | /* put code for a *= b */ | |
113 | ||
114 | expptr putsteq(a, b) | |
115 | Addrp a, b; | |
116 | { | |
117 | return putx( fixexpr((Exprp) | |
118 | mkexpr(OPSTAREQ, cpexpr((expptr)a), cpexpr((expptr)b)))); | |
119 | } | |
120 | ||
121 | ||
122 | ||
123 | ||
124 | Addrp mkfield(res, f, ty) | |
125 | register Addrp res; | |
126 | char *f; | |
127 | int ty; | |
128 | { | |
129 | res -> vtype = ty; | |
130 | res -> Field = f; | |
131 | return res; | |
132 | } /* mkfield */ | |
133 | ||
134 | ||
135 | Addrp realpart(p) | |
136 | register Addrp p; | |
137 | { | |
138 | register Addrp q; | |
139 | expptr mkrealcon(); | |
140 | ||
141 | if (p->tag == TADDR | |
142 | && p->uname_tag == UNAM_CONST | |
143 | && ISCOMPLEX (p->vtype)) | |
144 | return (Addrp)mkrealcon (p -> vtype + TYREAL - TYCOMPLEX, | |
145 | p->user.kludge.vstg1 ? p->user.Const.cds[0] | |
146 | : cds(dtos(p->user.Const.cd[0]),CNULL)); | |
147 | ||
148 | q = (Addrp) cpexpr((expptr) p); | |
149 | if( ISCOMPLEX(p->vtype) ) | |
150 | q = mkfield (q, "r", p -> vtype + TYREAL - TYCOMPLEX); | |
151 | ||
152 | return(q); | |
153 | } | |
154 | ||
155 | ||
156 | ||
157 | ||
158 | expptr imagpart(p) | |
159 | register Addrp p; | |
160 | { | |
161 | register Addrp q; | |
162 | expptr mkrealcon(); | |
163 | ||
164 | if( ISCOMPLEX(p->vtype) ) | |
165 | { | |
166 | if (p->tag == TADDR && p->uname_tag == UNAM_CONST) | |
167 | return mkrealcon (p -> vtype + TYREAL - TYCOMPLEX, | |
168 | p->user.kludge.vstg1 ? p->user.Const.cds[1] | |
169 | : cds(dtos(p->user.Const.cd[1]),CNULL)); | |
170 | q = (Addrp) cpexpr((expptr) p); | |
171 | q = mkfield (q, "i", p -> vtype + TYREAL - TYCOMPLEX); | |
172 | return( (expptr) q ); | |
173 | } | |
174 | else | |
175 | ||
176 | /* Cast an integer type onto a Double Real type */ | |
177 | ||
178 | return( mkrealcon( ISINT(p->vtype) ? TYDREAL : p->vtype , "0")); | |
179 | } | |
180 | ||
181 | ||
182 | ||
183 | ||
184 | ||
185 | /* ncat -- computes the number of adjacent concatenation operations */ | |
186 | ||
187 | ncat(p) | |
188 | register expptr p; | |
189 | { | |
190 | if(p->tag==TEXPR && p->exprblock.opcode==OPCONCAT) | |
191 | return( ncat(p->exprblock.leftp) + ncat(p->exprblock.rightp) ); | |
192 | else return(1); | |
193 | } | |
194 | ||
195 | ||
196 | ||
197 | ||
198 | /* lencat -- returns the length of the concatenated string. Each | |
199 | substring must have a static (i.e. compile-time) fixed length */ | |
200 | ||
201 | ftnint lencat(p) | |
202 | register expptr p; | |
203 | { | |
204 | if(p->tag==TEXPR && p->exprblock.opcode==OPCONCAT) | |
205 | return( lencat(p->exprblock.leftp) + lencat(p->exprblock.rightp) ); | |
206 | else if( p->headblock.vleng!=NULL && ISICON(p->headblock.vleng) ) | |
207 | return(p->headblock.vleng->constblock.Const.ci); | |
208 | else if(p->tag==TADDR && p->addrblock.varleng!=0) | |
209 | return(p->addrblock.varleng); | |
210 | else | |
211 | { | |
212 | err("impossible element in concatenation"); | |
213 | return(0); | |
214 | } | |
215 | } | |
216 | ||
217 | /* putconst -- Creates a new Addrp value which maps onto the input | |
218 | constant value. The Addrp doesn't retain the value of the constant, | |
219 | instead that value is copied into a table of constants (called | |
220 | litpool, for pool of literal values). The only way to retrieve the | |
221 | actual value of the constant is to look at the memno field of the | |
222 | Addrp result. You know that the associated literal is the one referred | |
223 | to by q when (q -> memno == litp -> litnum). | |
224 | */ | |
225 | ||
226 | Addrp putconst(p) | |
227 | register Constp p; | |
228 | { | |
229 | register Addrp q; | |
230 | struct Literal *litp, *lastlit; | |
231 | int k, len, type; | |
232 | int litflavor; | |
233 | double cd[2]; | |
234 | ftnint nblanks; | |
235 | char *strp; | |
236 | char cdsbuf0[64], cdsbuf1[64], *ds[2]; | |
237 | ||
238 | if (p->tag != TCONST) | |
239 | badtag("putconst", p->tag); | |
240 | ||
241 | q = ALLOC(Addrblock); | |
242 | q->tag = TADDR; | |
243 | type = p->vtype; | |
244 | q->vtype = ( type==TYADDR ? tyint : type ); | |
245 | q->vleng = (expptr) cpexpr(p->vleng); | |
246 | q->vstg = STGCONST; | |
247 | ||
248 | /* Create the new label for the constant. This is wasteful of labels | |
249 | because when the constant value already exists in the literal pool, | |
250 | this label gets thrown away and is never reclaimed. It might be | |
251 | cleaner to move this down past the first switch() statement below */ | |
252 | ||
253 | q->memno = newlabel(); | |
254 | q->memoffset = ICON(0); | |
255 | q -> uname_tag = UNAM_CONST; | |
256 | ||
257 | /* Copy the constant info into the Addrblock; do this by copying the | |
258 | largest storage elts */ | |
259 | ||
260 | q -> user.Const = p -> Const; | |
261 | q->user.kludge.vstg1 = p->vstg; /* distinguish string from binary fp */ | |
262 | ||
263 | /* check for value in literal pool, and update pool if necessary */ | |
264 | ||
265 | k = 1; | |
266 | switch(type) | |
267 | { | |
268 | case TYCHAR: | |
269 | if (halign) { | |
270 | strp = p->Const.ccp; | |
271 | nblanks = p->Const.ccp1.blanks; | |
272 | len = p->vleng->constblock.Const.ci; | |
273 | litflavor = LIT_CHAR; | |
274 | goto loop; | |
275 | } | |
276 | else | |
277 | q->memno = BAD_MEMNO; | |
278 | break; | |
279 | case TYCOMPLEX: | |
280 | case TYDCOMPLEX: | |
281 | k = 2; | |
282 | if (p->vstg) | |
283 | cd[1] = atof(ds[1] = p->Const.cds[1]); | |
284 | else | |
285 | ds[1] = cds(dtos(cd[1] = p->Const.cd[1]), cdsbuf1); | |
286 | case TYREAL: | |
287 | case TYDREAL: | |
288 | litflavor = LIT_FLOAT; | |
289 | if (p->vstg) | |
290 | cd[0] = atof(ds[0] = p->Const.cds[0]); | |
291 | else | |
292 | ds[0] = cds(dtos(cd[0] = p->Const.cd[0]), cdsbuf0); | |
293 | goto loop; | |
294 | ||
295 | case TYLOGICAL1: | |
296 | case TYLOGICAL2: | |
297 | case TYLOGICAL: | |
298 | type = tylogical; | |
299 | goto lit_int_flavor; | |
300 | case TYLONG: | |
301 | type = tyint; | |
302 | case TYSHORT: | |
303 | case TYINT1: | |
304 | #ifdef TYQUAD | |
305 | case TYQUAD: | |
306 | #endif | |
307 | lit_int_flavor: | |
308 | litflavor = LIT_INT; | |
309 | ||
310 | /* Scan the literal pool for this constant value. If this same constant | |
311 | has been assigned before, use the same label. Note that this routine | |
312 | does NOT consider two differently-typed constants with the same bit | |
313 | pattern to be the same constant */ | |
314 | ||
315 | loop: | |
316 | lastlit = litpool + nliterals; | |
317 | for(litp = litpool ; litp<lastlit ; ++litp) | |
318 | ||
319 | /* Remove this type checking to ensure that all bit patterns are reused */ | |
320 | ||
321 | if(type == litp->littype) switch(litflavor) | |
322 | { | |
323 | case LIT_CHAR: | |
324 | if (len == (int)litp->litval.litival2[0] | |
325 | && nblanks == litp->litval.litival2[1] | |
326 | && !memcmp(strp, litp->cds[0], len)) { | |
327 | q->memno = litp->litnum; | |
328 | frexpr((expptr)p); | |
329 | q->user.Const.ccp1.ccp0 = litp->cds[0]; | |
330 | return(q); | |
331 | } | |
332 | break; | |
333 | case LIT_FLOAT: | |
334 | if(cd[0] == litp->litval.litdval[0] | |
335 | && !strcmp(ds[0], litp->cds[0]) | |
336 | && (k == 1 || | |
337 | cd[1] == litp->litval.litdval[1] | |
338 | && !strcmp(ds[1], litp->cds[1]))) { | |
339 | ret: | |
340 | q->memno = litp->litnum; | |
341 | frexpr((expptr)p); | |
342 | return(q); | |
343 | } | |
344 | break; | |
345 | ||
346 | case LIT_INT: | |
347 | if(p->Const.ci == litp->litval.litival) | |
348 | goto ret; | |
349 | break; | |
350 | } | |
351 | ||
352 | /* If there's room in the literal pool, add this new value to the pool */ | |
353 | ||
354 | if(nliterals < maxliterals) | |
355 | { | |
356 | ++nliterals; | |
357 | ||
358 | /* litp now points to the next free elt */ | |
359 | ||
360 | litp->littype = type; | |
361 | litp->litnum = q->memno; | |
362 | switch(litflavor) | |
363 | { | |
364 | case LIT_CHAR: | |
365 | litp->litval.litival2[0] = len; | |
366 | litp->litval.litival2[1] = nblanks; | |
367 | q->user.Const.ccp = litp->cds[0] = | |
368 | memcpy(gmem(len,0), strp, len); | |
369 | break; | |
370 | ||
371 | case LIT_FLOAT: | |
372 | litp->litval.litdval[0] = cd[0]; | |
373 | litp->cds[0] = copys(ds[0]); | |
374 | if (k == 2) { | |
375 | litp->litval.litdval[1] = cd[1]; | |
376 | litp->cds[1] = copys(ds[1]); | |
377 | } | |
378 | break; | |
379 | ||
380 | case LIT_INT: | |
381 | litp->litval.litival = p->Const.ci; | |
382 | break; | |
383 | } /* switch (litflavor) */ | |
384 | } | |
385 | else | |
386 | many("literal constants", 'L', maxliterals); | |
387 | ||
388 | break; | |
389 | case TYADDR: | |
390 | break; | |
391 | default: | |
392 | badtype ("putconst", p -> vtype); | |
393 | break; | |
394 | } /* switch */ | |
395 | ||
396 | if (type != TYCHAR || halign) | |
397 | frexpr((expptr)p); | |
398 | return( q ); | |
399 | } |