Pristine Ack-5.5
[Ack-5.5.git] / mach / proto / ncg / subr.c
1 #ifndef NORCSID
2 static char rcsid[] = "$Id: subr.c,v 0.19 1994/06/24 13:28:18 ceriel Exp $";
3 #endif
4
5 #include "assert.h"
6 #include <stdio.h>
7 #include "param.h"
8 #include "tables.h"
9 #include "types.h"
10 #include <cgg_cg.h>
11 #include "data.h"
12 #include "result.h"
13 #include "extern.h"
14
15 /*
16  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
17  * See the copyright notice in the ACK home directory, in the file "Copyright".
18  *
19  * Author: Hans van Staveren
20  */
21
22 string myalloc();
23 unsigned codegen();
24
25 match(tp,tep,optexp) register token_p tp; register set_p tep; {
26         register bitno;
27         token_p ct;
28         result_t result;
29
30         if (tp->t_token == -1) {        /* register frame */
31                 bitno = tp->t_att[0].ar;
32                 if (tep->set_val[bitno>>4]&(1<<(bitno&017)))
33                         if (tep->set_val[0]&1 || getrefcount(bitno, FALSE)<=1)
34                                 goto oklabel;
35                 return(0);
36         } else {                /* token frame */
37                 bitno = tp->t_token+NREGS;
38                 if ((tep->set_val[bitno>>4]&(1<<(bitno&017)))==0)
39                         return(0);
40         }
41     oklabel:
42         if (optexp==0)
43                 return(1);
44         ct=curtoken;
45         curtoken=tp;
46         compute(&enodes[optexp], &result);
47         curtoken=ct;
48         return(result.e_v.e_con);
49 }
50
51 instance(instno,token) register token_p token; {
52         register inst_p inp;
53         int i;
54         register token_p tp;
55 #if MAXMEMBERS != 0
56         struct reginfo *rp;
57 #endif
58         int regno;
59         result_t result;
60
61         if (instno==0) {
62                 token->t_token = 0;
63                 for (i=TOKENSIZE-1;i>=0;i--)
64                         token->t_att[i].aw=0;
65                 return;
66         }
67         inp= &tokeninstances[instno];
68         switch(inp->in_which) {
69         default:
70                 assert(FALSE);
71         case IN_COPY:
72                 if (inp->in_info[0] == 0)
73                         if (curtoken) tp = curtoken;
74                         else tp = &fakestack[stackheight-1];
75                 else    tp= &fakestack[stackheight-inp->in_info[0]];
76                 if (inp->in_info[1]==0) {
77                         *token = *tp;
78                 } else {
79                         token->t_token= -1;
80 #if MAXMEMBERS!=0
81                         assert(tp->t_token == -1);
82                         rp = &machregs[tp->t_att[0].ar];
83                         token->t_att[0].ar=rp->r_members[inp->in_info[1]-1];
84 #else
85                         assert(FALSE);
86 #endif
87                 }
88                 return;
89         case IN_MEMB:
90                 if (inp->in_info[0] == 0)
91                         if (curtoken) tp = curtoken;
92                         else tp = &fakestack[stackheight-1];
93                 else    tp= &fakestack[stackheight-inp->in_info[0]];
94                 assert(inp->in_info[1]!=0);
95                 assert(tp->t_token>0);
96                 token->t_token= -1;
97                 assert(tokens[tp->t_token].t_type[inp->in_info[1]-1] == EV_REG);
98                 token->t_att[0].ar=tp->t_att[inp->in_info[1]-1].ar;
99                 return;
100         case IN_RIDENT:
101                 token->t_token= -1;
102                 token->t_att[0].ar= inp->in_info[0];
103                 return;
104         case IN_ALLOC:
105                 token->t_token= -1;
106                 regno=allreg[inp->in_info[0]];
107 #if MAXMEMBERS!=0
108                 if (inp->in_info[1])
109                         regno=machregs[regno].r_members[inp->in_info[1]-1];
110 #endif
111                 token->t_att[0].ar = regno;
112                 return;
113 #ifdef REGVARS
114         case IN_S_DESCR:
115         case IN_D_DESCR:
116                 compute(&enodes[inp->in_info[1]], &result);
117                 assert(result.e_typ==EV_INT);
118                 if ((regno=isregvar(result.e_v.e_con)) > 0) {
119                         token->t_token = -1;
120                         token->t_att[0].ar = regno;
121                         for (i=TOKENSIZE-1;i>0;i--)
122                                 token->t_att[i].aw = 0;
123                         return;
124                 }
125                 /* fall through */
126 #endif
127         case IN_DESCR:
128                 token->t_token=inp->in_info[0];
129                 for (i=0;i<TOKENSIZE;i++)
130                         if (inp->in_info[i+1]==0) {
131                                 assert(tokens[token->t_token].t_type[i]==0);
132                                 token->t_att[i].aw=0;
133                         } else {
134                                 compute(&enodes[inp->in_info[i+1]], &result);
135                                 assert(tokens[token->t_token].t_type[i]==result.e_typ);
136                                 if (result.e_typ==EV_INT)
137                                         token->t_att[i].aw=result.e_v.e_con;
138                                 else if (result.e_typ==EV_ADDR)
139                                         token->t_att[i].aa= result.e_v.e_addr;
140                                 else
141                                         token->t_att[i].ar=result.e_v.e_reg;
142                         }
143                 return;
144         }
145 }
146
147 cinstance(instno,token,tp,regno) register token_p token,tp; {
148         register inst_p inp;
149         int i;
150 #if MAXMEMBERS != 0
151         struct reginfo *rp;
152 #endif
153         result_t result;
154         int sh; /* saved stackheight */
155
156         assert(instno!=0);
157         inp= &tokeninstances[instno];
158         switch(inp->in_which) {
159         default:
160                 assert(FALSE);
161         case IN_COPY:
162                 assert(inp->in_info[0] <= 1);
163                 if (inp->in_info[1]==0) {
164                         *token = *tp;
165                 } else {
166                         token->t_token= -1;
167 #if MAXMEMBERS!=0
168                         assert(tp->t_token == -1);
169                         rp = &machregs[tp->t_att[0].ar];
170                         token->t_att[0].ar=rp->r_members[inp->in_info[1]-1];
171 #else
172                         assert(FALSE);
173 #endif
174                 }
175                 return;
176         case IN_MEMB:
177                 assert(inp->in_info[0] <= 1);
178                 token->t_token= -1;
179                 assert(tp->t_token>0);
180                 assert(tokens[tp->t_token].t_type[inp->in_info[1]-1] == EV_REG);
181                 token->t_att[0].ar=tp->t_att[inp->in_info[1]-1].ar;
182                 return;
183         case IN_RIDENT:
184                 token->t_token= -1;
185                 token->t_att[0].ar= inp->in_info[0];
186                 return;
187         case IN_ALLOC:
188                 token->t_token= -1;
189                 assert(inp->in_info[0]==0);
190 #if MAXMEMBERS!=0
191                 if (inp->in_info[1])
192                         regno=machregs[regno].r_members[inp->in_info[1]-1];
193 #endif
194                 token->t_att[0].ar = regno;
195                 return;
196 #ifdef REGVARS
197         case IN_S_DESCR:
198         case IN_D_DESCR:
199                 {       token_p ct = curtoken;
200
201                         curtoken = tp;
202                         compute(&enodes[inp->in_info[1]], &result);
203                         curtoken = ct;
204                         assert(result.e_typ==EV_INT);
205                         if ((regno=isregvar(result.e_v.e_con)) > 0) {
206                                 token->t_token = -1;
207                                 token->t_att[0].ar = regno;
208                                 for (i=TOKENSIZE-1;i>0;i--)
209                                         token->t_att[i].aw = 0;
210                                 return;
211                         }
212                 }
213                 /* fall through */
214 #endif
215         case IN_DESCR:
216                 sh = stackheight;
217                 stackheight = tp - fakestack + 1;
218                 token->t_token=inp->in_info[0];
219                 for (i=0;i<TOKENSIZE;i++)
220                         if (inp->in_info[i+1]==0) {
221                                 assert(tokens[token->t_token].t_type[i]==0);
222                                 token->t_att[i].aw=0;
223                         } else {
224                                 token_p ct = curtoken;
225
226                                 curtoken = tp;
227                                 compute(&enodes[inp->in_info[i+1]], &result);
228                                 curtoken = ct;
229                                 assert(tokens[token->t_token].t_type[i]==result.e_typ);
230                                 if (result.e_typ==EV_INT)
231                                         token->t_att[i].aw=result.e_v.e_con;
232                                 else if (result.e_typ==EV_ADDR)
233                                         token->t_att[i].aa= result.e_v.e_addr;
234                                 else
235                                         token->t_att[i].ar=result.e_v.e_reg;
236                         }
237                 stackheight = sh;
238                 return;
239         }
240 }
241
242 eqtoken(tp1,tp2) token_p tp1,tp2; {
243         register i;
244         register tkdef_p tdp;
245
246         if (tp1->t_token!=tp2->t_token)
247                 return(0);
248         if (tp1->t_token==0)
249                 return(1);
250         if (tp1->t_token==-1) {
251                 if (tp1->t_att[0].ar!=tp2->t_att[0].ar)
252                         return(0);
253                 return(1);
254         }
255         tdp = &tokens[tp1->t_token];
256         for (i=0;i<TOKENSIZE;i++)
257                 switch(tdp->t_type[i]) {
258                 default:
259                         return(1);
260                 case EV_INT:
261                         if (tp1->t_att[i].aw != tp2->t_att[i].aw)
262                                 return(0);
263                         break;
264                 case EV_REG:
265                         if (tp1->t_att[i].ar != tp2->t_att[i].ar)
266                                 return(0);
267                         break;
268                 case EV_ADDR:
269                         if (strcmp(tp1->t_att[i].aa.ea_str, tp2->t_att[i].aa.ea_str))
270                                 return(0);
271                         if (tp1->t_att[i].aa.ea_off!=tp2->t_att[i].aa.ea_off)
272                                 return(0);
273                         break;
274                 }
275         return(1);
276 }
277
278 distance(cindex) {
279         register char *bp;
280         register i;
281         register token_p tp;
282         int tokexp,tpl;
283         int expsize,toksize,exact;
284         int xsekt=0;
285         int fromstackneeded=0;
286
287         bp = &coderules[cindex];
288 #ifndef NDEBUG
289         if (*bp==DO_DLINE) {
290                 ++bp;
291                 getint(i,bp);
292         }
293 #endif
294         switch( (*bp)&037 ) {
295         default:
296                 return(stackheight==0 ? 0 : 100);
297         case DO_MATCH:
298                 break;
299         case DO_XXMATCH:
300                 xsekt++;
301         case DO_XMATCH:
302                 xsekt++;
303                 break;
304         }
305         tpl= ((*bp++)>>5)&07;
306         if (stackheight < tpl) {
307                 if (xsekt)
308                         return(MAXINT);
309                 fromstackneeded = tpl - stackheight;
310                 tpl = stackheight;
311         } else
312                 if (stackheight != tpl && xsekt==2)
313                         return(MAXINT);
314         exact=0;
315         tp= &fakestack[stackheight-1];
316         for (i=0;i<tpl;i++,tp--) {
317                 getint(tokexp,bp);
318                 if (!match(tp, &machsets[tokexp], 0)) {
319                         if (xsekt)
320                                 return(MAXINT);
321                         expsize = ssize(tokexp);
322                         toksize = tsize(tp);
323                         if (expsize>toksize)
324                                 return(100);
325                         if (expsize<toksize)
326                                 return(99-i);
327
328                         /* Now we have a match in size, but it is not exact.
329                            Therefore, make sure that we can at least
330                            create it from the stack!
331                         */
332                         if (! from_stack(&machsets[tokexp])) {
333                                 return MAXINT;
334                         }
335                 } else
336                         exact++;
337         }
338         for (;i<tpl+fromstackneeded;i++) {
339                 /*      Make sure that any pattern we pick can be
340                         made from the stack
341                 */
342                 getint(tokexp,bp);
343                 if (! from_stack(&machsets[tokexp])) {
344                         return(MAXINT);
345                 }
346         }
347         if (exact==tpl && ! fromstackneeded) {
348                 if (xsekt)
349                         return(0);
350                 return(10-exact);
351         }
352         return(20-2*exact+fromstackneeded);
353 }
354
355 extern set_t unstackset;
356
357 int from_stack(s1)
358         register set_p s1;
359 {
360         register set_p s2 = &unstackset;
361         register int i;
362         for (i = 0; i < SETSIZE; i++) {
363                 if ((s1->set_val[i] & s2->set_val[i]) != 0) return 1;
364         }
365         return 0;
366 }
367
368 unsigned costcalc(cost) cost_t cost; {
369         extern unsigned cc1,cc2,cc3,cc4;
370
371         return(cost.ct_space*cc1/cc2 + cost.ct_time*cc3/cc4);
372 }
373
374 ssize(tokexpno) {
375
376         return(machsets[tokexpno].set_size);
377 }
378
379 tsize(tp) register token_p tp; {
380
381         if (tp->t_token==-1)
382                 return(machregs[tp->t_att[0].ar].r_size);
383         return(tokens[tp->t_token].t_size);
384 }
385
386 #ifdef MAXSPLIT
387 instsize(tinstno,tp) token_p tp; {
388         inst_p inp;
389         struct reginfo *rp;
390
391         inp = &tokeninstances[tinstno];
392         switch(inp->in_which) {
393         default:
394                 assert(FALSE);
395         case IN_COPY:
396                 assert(inp->in_info[0]<=1);
397 #if MAXMEMBERS!=0
398                 if (inp->in_info[1]==0)
399 #endif
400                         return(tsize(tp));
401 #if MAXMEMBERS!=0
402                 else {
403                         assert(tp->t_token == -1);
404                         rp = &machregs[tp->t_att[0].ar];
405                         return(machregs[rp->r_members[inp->in_info[1]-1]].r_size);
406                 }
407 #endif
408         case IN_RIDENT:
409                 return(machregs[inp->in_info[0]].r_size);
410         case IN_ALLOC:
411                 assert(FALSE);  /* cannot occur in splitting coercion */
412         case IN_DESCR:
413         case IN_S_DESCR:
414         case IN_D_DESCR:
415                 return(tokens[inp->in_info[0]].t_size);
416         }
417 }
418 #endif /* MAXSPLIT */
419
420 tref(tp,amount) register token_p tp; {
421         register i;
422         register byte *tdpb;
423
424         if (tp->t_token==-1)
425                 chrefcount(tp->t_att[0].ar,amount,FALSE);
426         else {
427                 tdpb= &tokens[tp->t_token].t_type[0];
428                 for(i=0;i<TOKENSIZE;i++)
429                         if (*tdpb++==EV_REG)
430                                 chrefcount(tp->t_att[i].ar,amount,FALSE);
431         }
432 }
433
434 #define MAXSAVE 10
435 /* A few routines to save the top of the current stack,
436    restore it and check whether a certain register is present in the
437    saved stack
438 */
439 token_t aside[MAXSAVE] ;
440 int     aside_length = -1 ;
441
442 save_stack(tp) register token_p tp ; {
443         int i ;
444         token_p tmp = &fakestack[stackheight - 1];
445
446         /*aside_length = &fakestack[stackheight-1] -tp;
447           This did not compile on Xenix V3.2: CODE GENERATION ERROR!
448         */
449         aside_length = tmp - tp;
450         assert(aside_length<=MAXSAVE);
451 #ifndef NDEBUG
452         if (aside_length!=0 && Debug>1)
453                 fprintf(stderr,"Saving %d items from fakestack\n",aside_length);
454 #endif
455         for (i=1;i<=aside_length;i++)
456                 aside[i-1] = tp[i];
457         stackheight -= aside_length;
458 }
459
460 in_stack(reg) {
461         register token_p tp ;
462         register i ;
463         register tkdef_p tdp ;
464
465         for ( i=0, tp=aside ; i<aside_length ; i++, tp++ )
466                 if (tp->t_token==-1) {
467                         if(tp->t_att[0].ar==reg)
468                                 goto gotone ;
469                 } else {
470                         tdp = &tokens[tp->t_token];
471                         for(i=0;i<TOKENSIZE;i++)
472                                 if (tdp->t_type[i]==EV_REG &&
473                                     tp->t_att[i].ar==reg)
474                                         goto gotone ;
475                 }
476         return 0 ;
477 gotone:
478 #ifndef NDEBUG
479         if ( Debug>2 )
480                 fprintf(stderr,"Register %d present on non-visible stack\n",
481                         reg ) ;
482 #endif
483         return 1 ;
484 }
485
486 rest_stack() {
487         register int i ;
488
489         assert(aside_length!= -1); 
490 #ifndef NDEBUG
491         if (aside_length!=0 && Debug>1)
492                 fprintf(stderr,"Restoring %d items to fakestack(%d)\n",
493                         aside_length,stackheight);
494 #endif
495         for (i=0;i<aside_length;i++)
496                 fakestack[stackheight++] = aside[i];
497         aside_length= -1 ;
498 }
499
500 #ifdef MAXSPLIT
501 split(tp,ip,ply,toplevel) token_p tp; register int *ip; {
502         register c2_p cp;
503         token_t savestack[MAXSAVE];
504         int ok;
505         register i;
506         int diff;
507         token_p stp;
508         int tpl;
509
510         for (cp=c2coercs;cp->c2_texpno>=0; cp++) {
511                 if (!match(tp,&machsets[cp->c2_texpno],0))
512                         continue;
513                 ok=1;
514                 for (i=0; ok && i<cp->c2_nsplit;i++) {
515                         if (ip[i]==0)
516                                 goto found;
517                         if (instsize(cp->c2_repl[i],tp) != ssize(ip[i]))
518                                 ok=0;
519                 }
520                 goto found;
521         }
522         return(0);
523 found:
524         assert(stackheight+cp->c2_nsplit-1<MAXFSTACK);
525         save_stack(tp);
526         tpl = tokpatlen;
527         tokpatlen = 1;
528         codegen(&coderules[cp->c2_codep],ply,toplevel,MAXINT,0);
529         tokpatlen = tpl;
530         rest_stack();
531         return(cp->c2_nsplit);
532 }
533 #endif /* MAXSPLIT */
534
535 unsigned docoerc(tp,cp,ply,toplevel,forced) token_p tp; register c3_p cp; {
536         unsigned cost;
537         int tpl;        /* saved tokpatlen */
538
539         save_stack(tp) ;
540         tpl = tokpatlen;
541         tokpatlen = 1;
542         cost = codegen(&coderules[cp->c3_codep],ply,toplevel,MAXINT,forced);
543         tokpatlen = tpl;
544         rest_stack() ;
545         nallreg = 0;
546         return(cost);
547 }
548
549 unsigned stackupto(limit,ply,toplevel) token_p limit; {
550         token_t savestack[MAXFSTACK];
551         token_p stp;
552         int i,diff;
553         int tpl;        /* saved tokpatlen */
554         int nareg;      /* saved nareg */
555         int areg[MAXALLREG];
556         register c1_p cp;
557         register token_p tp;
558         unsigned totalcost=0;
559         struct reginfo *rp,**rpp;
560
561         for (tp=fakestack;tp<=limit;limit--) {
562                 for (cp=c1coercs;cp->c1_texpno>=0; cp++) {
563                         if (match(tp,&machsets[cp->c1_texpno],cp->c1_expr)) {
564                                 if (cp->c1_prop>=0) {
565                                         for (rpp=reglist[cp->c1_prop];
566                                                (rp = *rpp)!=0 &&
567                                                getrefcount((int)(rp-machregs), TRUE)!=0;
568                                                   rpp++)
569                                                 ;
570                                         if (rp==0)
571                                                 continue;
572                                                 /* look for other possibility */
573                                 }
574                                 stp = &fakestack[stackheight-1];
575                                 diff = stp -tp;
576                                 assert(diff<=MAXFSTACK);
577                                 for (i=1;i<=diff;i++)
578                                         savestack[i-1] = tp[i];
579                                 stackheight -= diff;
580                                 tpl = tokpatlen;
581                                 tokpatlen = 1;
582                                 nareg = nallreg;
583                                 for (i=0;i<nareg;i++)
584                                         areg[i] = allreg[i];
585                                 if (cp->c1_prop>=0) {
586                                         nallreg=1; allreg[0] = rp-machregs;
587                                         chrefcount(allreg[0],1,FALSE);
588                                 } else 
589                                         nallreg=0;
590                                 totalcost+= codegen(&coderules[cp->c1_codep],ply,toplevel,MAXINT,0);
591                                 tokpatlen = tpl;
592                                 for (i=0;i<diff;i++) {
593                                         fakestack[stackheight] = savestack[i];
594                                         stackheight++;
595                                         /* not cobmined in one statement;
596                                            this poor Xenix C compiler sometimes
597                                            gets failed assertions when you do
598                                            that!
599                                         */
600                                 }
601                                 nallreg=nareg;
602                                 for (i=0;i<nareg;i++)
603                                         allreg[i] = areg[i];
604                                 goto contin;
605                         }
606                 }
607                 assert(FALSE);
608         contin: ;
609         }
610         return(totalcost);
611 }
612
613 c3_p findcoerc(tp,tep) token_p tp; set_p tep; {
614         register c3_p cp;
615         token_t rtoken;
616         register i;
617         register struct reginfo **rpp;
618
619         for (cp=c3coercs;cp->c3_texpno>=0; cp++) {
620                 if (tp!=(token_p) 0) {
621                         if (cp->c3_texpno==0)
622                                 continue;
623                         if (!match(tp,&machsets[cp->c3_texpno],cp->c3_expr))
624                                 continue;
625                 } else {
626                         if (cp->c3_texpno!=0)
627                                 continue;
628                 }
629                 if (cp->c3_prop<0) {   /* no reg needed */
630                         cinstance(cp->c3_repl,&rtoken,tp,0);
631                         if (match(&rtoken,tep,0))
632                                 return(cp);
633                 } else {
634                         curreglist = (rl_p) myalloc(sizeof (rl_t));
635                         curreglist->rl_n = 0;
636                         for (rpp=reglist[cp->c3_prop];*rpp;rpp++) {
637                                 i = *rpp - machregs;
638                                 cinstance(cp->c3_repl,&rtoken,tp,i);
639                                 if (match(&rtoken,tep,0))
640                                         curreglist->rl_list[curreglist->rl_n++] = i;
641                         }
642                         if (curreglist->rl_n != 0)
643                                 return(cp);
644                         myfree((string)curreglist);
645                 }
646         }
647         return(0);      /* nothing found */
648 }
649
650 itokcost() {
651         register tkdef_p tdp;
652
653         for(tdp=tokens+1;tdp->t_size!=0;tdp++)
654                 tdp->t_cost.ct_space = costcalc(tdp->t_cost);
655 }
656
657 /*VARARGS1*/
658 error(s,a1,a2,a3,a4,a5,a6,a7,a8) char *s; {
659
660         fprintf(stderr,"Error: ");
661         fprintf(stderr,s,a1,a2,a3,a4,a5,a6,a7,a8);
662         fprintf(stderr,"\n");
663 #ifdef TABLEDEBUG
664         ruletrace();
665 #endif
666         out_finish();
667         exit(-1);
668 }
669
670 /*VARARGS1*/
671 fatal(s,a1,a2,a3,a4,a5,a6,a7,a8) char *s; {
672
673         fprintf(stderr,"Fatal: ");
674         fprintf(stderr,s,a1,a2,a3,a4,a5,a6,a7,a8);
675         fprintf(stderr,"\n");
676 #ifdef TABLEDEBUG
677         ruletrace();
678 #endif
679         out_finish();
680         abort();
681         exit(-1);
682 }
683
684 #ifdef TABLEDEBUG
685
686 ruletrace() {
687         register i;
688         extern int tablelines[MAXTDBUG];
689         extern int ntableline;
690         extern char *tablename;
691
692         fprintf(stderr,"Last code rules used\n");
693         i=ntableline-1;
694         while(i!=ntableline) {
695                 if (i<0)
696                         i += MAXTDBUG;
697                 if (tablelines[i]!=0)
698                         fprintf(stderr,"\%d: \"%s\", line %d\n",i,tablename,tablelines[i]);
699                 i--;
700         }
701 }
702 #endif
703
704 #ifndef NDEBUG
705 badassertion(asstr,file,line) char *asstr, *file; {
706
707         fatal("\"%s\", line %d:Assertion \"%s\" failed",file,line,asstr);
708 }
709 #endif