5ef8e284631484077b69ce63bb183814a6f11f79
[ghc-hetmet.git] / ghc / interpreter / codegen.c
1
2 /* --------------------------------------------------------------------------
3  * Code generator
4  *
5  * Copyright (c) The University of Nottingham and Yale University, 1994-1997.
6  * All rights reserved. See NOTICE for details and conditions of use etc...
7  * Hugs version 1.4, December 1997
8  *
9  * $RCSfile: codegen.c,v $
10  * $Revision: 1.4 $
11  * $Date: 1999/03/01 14:46:42 $
12  * ------------------------------------------------------------------------*/
13
14 #include "prelude.h"
15 #include "storage.h"
16 #include "backend.h"
17 #include "connect.h"
18 #include "errors.h"
19 #include "Assembler.h"
20 #include "link.h"
21
22 #include "Rts.h"    /* IF_DEBUG */
23 #include "RtsFlags.h"
24
25 /* --------------------------------------------------------------------------
26  * Local function prototypes:
27  * ------------------------------------------------------------------------*/
28
29 #define getPos(v)     intOf(stgVarInfo(v))
30 #define setPos(v,sp)  stgVarInfo(v) = mkInt(sp)
31 #define getObj(v)     ptrOf(stgVarInfo(v))
32 #define setObj(v,obj) stgVarInfo(v) = mkPtr(obj)
33
34 #define repOf(x)      charOf(stgVarRep(x))
35
36 static void  cgBind        ( AsmBCO bco, StgVar v );
37 static Void  pushVar       ( AsmBCO bco, StgVar v );
38 static Void  pushAtom      ( AsmBCO bco, StgAtom atom );
39 static Void  alloc         ( AsmBCO bco, StgRhs rhs );
40 static Void  build         ( AsmBCO bco, StgRhs rhs );
41 static Void  cgExpr        ( AsmBCO bco, AsmSp root, StgExpr e );
42              
43 static AsmBCO cgAlts       ( AsmSp root, AsmSp sp, List alts );
44 static void   testPrimPats ( AsmBCO bco, AsmSp root, List pats, StgExpr e );
45 //static void   cgPrimAlt    ( AsmBCO bco, AsmSp root, List vs, StgExpr e );
46 static AsmBCO cgLambda     ( StgExpr e );
47 static AsmBCO cgRhs        ( StgRhs rhs );
48 static void   beginTop     ( StgVar v );
49 static void   endTop       ( StgVar v );
50
51 /* --------------------------------------------------------------------------
52  * 
53  * ------------------------------------------------------------------------*/
54
55 static Bool varHasClosure( StgVar v )
56 {
57     return asmObjectHasClosure((AsmClosure*)ptrOf(stgVarInfo(v)));
58 }
59
60 /* should be AsmClosure* */
61 void* closureOfVar( StgVar v )
62 {
63     return asmClosureOfObject((AsmClosure*)ptrOf(stgVarInfo(v)));
64 }
65
66 char* lookupHugsName( void* closure )
67 {
68     extern Name nameHw;
69     Name nm;
70     for( nm=NAMEMIN; nm<nameHw; ++nm ) {
71         StgVar v  = name(nm).stgVar;
72         if (isStgVar(v) 
73             && isPtr(stgVarInfo(v)) 
74             && varHasClosure(v)
75             && closureOfVar(v) == closure) {
76             return textToStr(name(nm).text);
77         }
78     }
79     return 0;
80 }
81
82 /* called at the start of GC */
83 void markHugsObjects( void )
84 {
85     extern Name nameHw;
86     Name nm;
87     for( nm=NAMEMIN; nm<nameHw; ++nm ) {
88         StgVar v  = name(nm).stgVar;
89         if (isStgVar(v) && isPtr(stgVarInfo(v))) {
90             asmMarkObject((AsmClosure*)ptrOf(stgVarInfo(v)));
91         }
92     }
93 }
94
95 static void cgBindRep( AsmBCO bco, StgVar v, AsmRep rep )
96 {
97     setPos(v,asmBind(bco,rep));
98 }
99
100 static void cgBind( AsmBCO bco, StgVar v )
101 {
102     cgBindRep(bco,v,repOf(v));
103 }
104
105 static Void pushVar( AsmBCO bco, StgVar v )
106 {
107     Cell info = stgVarInfo(v);
108     //    if (!isStgVar(v)) {
109     //printf("\n\nprefail\n");
110     //print(v,1000);
111        assert(isStgVar(v));
112     //}
113     if (isPtr(info)) {
114         asmClosure(bco,ptrOf(info));
115     } else if (isInt(info)) {
116         asmVar(bco,intOf(info),repOf(v));
117     } else {
118         internal("pushVar");
119     }        
120 }
121
122 static Void pushAtom( AsmBCO bco, StgAtom e )
123 {
124     switch (whatIs(e)) {
125     case STGVAR: 
126             pushVar(bco,e);
127             break;
128     case NAME: 
129             pushVar(bco,name(e).stgVar);
130             break;
131     case CHARCELL: 
132             asmConstChar(bco,charOf(e));
133             break;
134     case INTCELL: 
135             asmConstInt(bco,intOf(e));
136             break;
137 #if BIGNUM_IS_INTEGER
138     case BIGCELL:
139             asmConstInteger(bco,bignumToString(e)); 
140             break;
141 #elif BIGNUM_IS_INT64
142     case BIGCELL:
143             asmConstInt64(bco,bignumOf(e)); 
144             break;
145 #else
146 #warning What is BIGNUM?
147 #endif
148     case FLOATCELL: 
149 #if 0
150             asmConstFloat(bco,e); /* ToDo: support both float and double! */
151 #else
152             asmConstDouble(bco,floatOf(e));
153 #endif
154             break;
155 #if DOUBLES
156     case DOUBLECELL: 
157             asmConstDouble(bco,doubleOf(e));
158             break;
159 #endif
160     case STRCELL: 
161 #if USE_ADDR_FOR_STRINGS
162             asmConstAddr(bco,textToStr(textOf(e)));
163 #else
164             asmClosure(bco,asmStringObj(textToStr(textOf(e))));
165 #endif
166             break;
167     case PTRCELL: 
168             asmConstAddr(bco,ptrOf(e));
169             break;
170     default: 
171             fprintf(stderr,"\nYoiks: "); printExp(stderr,e);
172             internal("pushAtom");
173     }
174 }
175
176 static AsmBCO cgAlts( AsmSp root, AsmSp sp, List alts )
177 {
178     AsmBCO bco = asmBeginContinuation(sp,alts);
179     /* ppStgAlts(alts); */
180     for(; nonNull(alts); alts=tl(alts)) {
181         StgCaseAlt alt  = hd(alts);
182         StgPat     pat  = stgCaseAltPat(alt);
183         StgExpr    body = stgCaseAltBody(alt);
184         if (isDefaultPat(pat)) {
185             //AsmSp      begin = asmBeginAlt(bco);
186             cgBind(bco,pat);
187             cgExpr(bco,root,body);
188             asmEndContinuation(bco);
189             return bco; /* ignore any further alternatives */
190         } else {
191             StgDiscr con = stgPatDiscr(pat);
192             List     vs  = stgPatVars(pat);
193             AsmSp    begin = asmBeginAlt(bco);
194             AsmPc    fix = asmTest(bco,stgDiscrTag(con)); /* ToDo: omit in single constructor types! */
195             cgBind(bco,pat);
196             if (isBoxingCon(con)) {
197                 setPos(hd(vs),asmUnbox(bco,boxingConRep(con)));
198             } else {
199                 asmBeginUnpack(bco);
200                 map1Proc(cgBind,bco,reverse(vs));
201                 asmEndUnpack(bco);
202             }
203             cgExpr(bco,root,body);
204             asmEndAlt(bco,begin);
205             asmFixBranch(bco,fix);
206         }
207     }
208     /* if we got this far and didn't match, panic! */
209     asmPanic(bco);
210     asmEndContinuation(bco);
211     return bco;
212 }
213
214 static void testPrimPats( AsmBCO bco, AsmSp root, List pats, StgExpr e )
215 {
216     if (isNull(pats)) {
217         cgExpr(bco,root,e);
218     } else {
219         StgPrimPat pat = hd(pats);
220         if (isInt(stgVarBody(pat))) {
221             /* asmTestInt leaves stack unchanged - so no need to adjust it */
222             AsmPc tst = asmTestInt(bco,getPos(pat),intOf(stgVarBody(pat)));
223             assert(repOf(pat) == INT_REP);
224             testPrimPats(bco,root,tl(pats),e);
225             asmFixBranch(bco,tst);
226         } else {
227             testPrimPats(bco,root,tl(pats),e);
228         }
229     }
230 }
231
232 #if 0  /* appears to be unused */
233 static void cgPrimAlt( AsmBCO bco, AsmSp root, List vs, StgExpr e )
234 {
235     assert(0); /* ToDo: test for patterns */
236     map1Proc(cgBind,bco,vs); /* ToDo: are these in right order? */
237     cgExpr(bco,root,e);
238 }
239 #endif
240
241
242 static AsmBCO cgLambda( StgExpr e )
243 {
244     AsmBCO bco = asmBeginBCO(e);
245
246     AsmSp root = asmBeginArgCheck(bco);
247     map1Proc(cgBind,bco,reverse(stgLambdaArgs(e)));
248     asmEndArgCheck(bco,root);
249
250     /* ppStgExpr(e); */
251     cgExpr(bco,root,stgLambdaBody(e));
252
253     asmEndBCO(bco);
254     return bco;
255 }
256
257 static AsmBCO cgRhs( StgRhs rhs )
258 {
259     AsmBCO bco = asmBeginBCO(rhs );
260
261     AsmSp root = asmBeginArgCheck(bco);
262     asmEndArgCheck(bco,root);
263
264     /* ppStgExpr(rhs); */
265     cgExpr(bco,root,rhs);
266
267     asmEndBCO(bco);
268     return bco;
269 }
270
271
272 static Void cgExpr( AsmBCO bco, AsmSp root, StgExpr e )
273 {
274   //printf("cgExpr:");ppStgExpr(e);printf("\n");
275     switch (whatIs(e)) {
276     case LETREC:
277         {
278             List binds = stgLetBinds(e);
279             map1Proc(alloc,bco,binds);
280             map1Proc(build,bco,binds);
281             cgExpr(bco,root,stgLetBody(e));
282             break;
283         }
284     case LAMBDA:
285         {
286             AsmSp begin = asmBeginEnter(bco);
287             asmClosure(bco,cgLambda(e));
288             asmEndEnter(bco,begin,root);
289             break;
290         }
291     case CASE:
292         {
293             List  alts     = stgCaseAlts(e);
294             AsmSp sp       = asmBeginCase(bco);
295             AsmSp caseroot = asmContinuation(bco,cgAlts(root,sp,alts));
296             cgExpr(bco,caseroot,stgCaseScrut(e));
297             asmEndCase(bco);
298             break;
299         }
300     case PRIMCASE:
301         {
302             StgExpr scrut = stgPrimCaseScrut(e);
303             List alts = stgPrimCaseAlts(e);
304             if (whatIs(scrut) == STGPRIM) {  /* this is an optimisation */
305
306                 /* No need to use return address or to Slide */
307                 AsmSp beginPrim = asmBeginPrim(bco);
308                 map1Proc(pushAtom,bco,reverse(stgPrimArgs(scrut)));
309                 asmEndPrim(bco,(AsmPrim*)name(stgPrimOp(scrut)).primop,beginPrim);
310
311                 for(; nonNull(alts); alts=tl(alts)) {
312                     StgPrimAlt alt = hd(alts);
313                     List    pats = stgPrimAltPats(alt);
314                     StgExpr body = stgPrimAltBody(alt);
315                     AsmSp altBegin = asmBeginAlt(bco);
316                     map1Proc(cgBind,bco,reverse(pats));
317                     testPrimPats(bco,root,pats,body);
318                     asmEndAlt(bco,altBegin);
319                 }
320                 /* if we got this far and didn't match, panic! */
321                 asmPanic(bco);
322                 
323             } else if (whatIs(scrut) == STGVAR) { /* another optimisation */
324
325                 /* No need to use return address or to Slide */
326
327                 /* only part different from primop code... todo */
328                 AsmSp beginCase = asmBeginCase(bco);
329                 pushVar(bco,scrut);
330                 asmEndAlt(bco,beginCase); /* hack, hack -  */
331
332                 for(; nonNull(alts); alts=tl(alts)) {
333                     StgPrimAlt alt = hd(alts);
334                     List    pats = stgPrimAltPats(alt);
335                     StgExpr body = stgPrimAltBody(alt);
336                     AsmSp altBegin = asmBeginAlt(bco);
337                     map1Proc(cgBind,bco,pats);
338                     testPrimPats(bco,root,pats,body);
339                     asmEndAlt(bco,altBegin);
340                 }
341                 /* if we got this far and didn't match, panic! */
342                 asmPanic(bco);
343                                 
344             } else {
345                 /* ToDo: implement this code...  */
346                 assert(0);
347                 /* asmPushRet(bco,delayPrimAlt( stgPrimCaseVars(e), stgPrimCaseBody(e))); */
348                 /* cgExpr( bco,root,scrut ); */
349             }
350             break;
351         }
352     case STGAPP: /* Tail call */
353         {
354             AsmSp env = asmBeginEnter(bco);
355             map1Proc(pushAtom,bco,reverse(stgAppArgs(e)));
356             pushAtom(bco,stgAppFun(e));
357             asmEndEnter(bco,env,root);
358             break;
359         }
360     case NAME: /* Tail call (with no args) */
361         {
362             AsmSp env = asmBeginEnter(bco);
363             pushVar(bco,name(e).stgVar);
364             asmEndEnter(bco,env,root);
365             break;
366         }
367     case STGVAR: /* Tail call (with no args), plus unboxed return */
368             switch (repOf(e)) {
369             case PTR_REP:
370             case ALPHA_REP:
371             case BETA_REP:
372                 {
373                     AsmSp env = asmBeginEnter(bco);
374                     pushVar(bco,e);
375                     asmEndEnter(bco,env,root);
376                     break;
377                 }
378             case INT_REP:
379                     assert(0);
380                     /* cgTailCall(bco,singleton(e)); */
381                     /* asmReturnInt(bco); */
382                     break;
383             default:
384                     internal("cgExpr StgVar");
385             }
386             break;
387     case STGPRIM: /* Tail call again */
388         {
389             AsmSp beginPrim = asmBeginPrim(bco);
390             map1Proc(pushAtom,bco,reverse(stgPrimArgs(e)));
391             asmEndPrim(bco,(AsmPrim*)name(e).primop,beginPrim);
392             /* map1Proc(cgBind,bco,rs_vars); */
393             assert(0); /* asmReturn_retty(); */
394             break;
395         }
396     default:
397             fprintf(stderr,"\nYoiks: "); printExp(stderr,e);
398             internal("cgExpr");
399     }
400 }
401
402 void* itblNames[1000];
403 int   nItblNames = 0;
404
405 /* allocate space for top level variable
406  * any change requires a corresponding change in 'build'.
407  */
408 static Void alloc( AsmBCO bco, StgVar v )
409 {
410     StgRhs rhs = stgVarBody(v);
411     assert(isStgVar(v));
412     switch (whatIs(rhs)) {
413     case STGCON:
414         {
415             StgDiscr con  = stgConCon(rhs);
416             List     args = stgConArgs(rhs);
417             if (isBoxingCon(con)) {
418                 pushAtom(bco,hd(args));
419                 setPos(v,asmBox(bco,boxingConRep(con)));
420             } else {
421
422                 void* vv = stgConInfo(con);
423                 assert (nItblNames < (1000-2));
424                 if (isName(con)) {
425                    itblNames[nItblNames++] = vv;
426                    itblNames[nItblNames++] = textToStr(name(con).text);
427                 } else
428                 if (isTuple(con)) {
429                    char* cc = malloc(10);
430                    assert(cc);
431                    sprintf(cc, "Tuple%d", tupleOf(con) );
432                    itblNames[nItblNames++] = vv;
433                    itblNames[nItblNames++] = cc;
434                 } else
435                 assert ( /* cant identify constructor name */ 0 );
436
437                 setPos(v,asmAllocCONSTR(bco, vv));
438             }
439             break;
440         }
441     case STGAPP: 
442             setPos(v,asmAllocAP(bco,length(stgAppArgs(rhs))));
443             break;
444     case LAMBDA: /* optimisation */
445             setObj(v,cgLambda(rhs));
446             break;
447     default: 
448             setPos(v,asmAllocAP(bco,0));
449             break;
450     }
451 }
452
453 static Void build( AsmBCO bco, StgVar v )
454 {
455     StgRhs rhs = stgVarBody(v);
456     assert(isStgVar(v));
457
458     switch (whatIs(rhs)) {
459     case STGCON:
460         {
461             StgDiscr con  = stgConCon(rhs);
462             List     args = stgConArgs(rhs);
463             if (isBoxingCon(con)) {
464                 doNothing();  /* already done in alloc */
465             } else {
466                 AsmSp start = asmBeginPack(bco);
467                 map1Proc(pushAtom,bco,reverse(args));
468                 asmEndPack(bco,getPos(v),start,stgConInfo(con));
469             }
470             return;
471         }
472     case STGAPP: 
473         {
474             StgVar fun  = stgAppFun(rhs);
475             List   args = stgAppArgs(rhs);
476             if (isName(fun)) {
477                 fun = name(fun).stgVar;
478             }
479             if (nonNull(stgVarBody(fun))
480                 && whatIs(stgVarBody(fun)) == LAMBDA 
481                 && length(stgLambdaArgs(stgVarBody(fun))) > length(args)) {
482                 AsmSp  start = asmBeginMkPAP(bco);
483                 map1Proc(pushAtom,bco,reverse(args));
484                 pushAtom(bco,fun);
485                 asmEndMkPAP(bco,getPos(v),start); /* optimisation */
486             } else {
487                 AsmSp  start = asmBeginMkAP(bco);
488                 map1Proc(pushAtom,bco,reverse(args));
489                 pushAtom(bco,fun);
490                 asmEndMkAP(bco,getPos(v),start);
491             }
492             return;
493         }
494     case LAMBDA: /* optimisation */
495             doNothing(); /* already pushed in alloc */
496             break;
497
498     /* These two cases look almost identical to the default but they're really
499      * special cases of STGAPP.  The essential thing here is that we can't call
500      * cgRhs(rhs) because that expects the rhs to have no free variables when, 
501      * in fact, the rhs is _always_ a free variable.
502      *
503      * ToDo: a simple optimiser would eliminate all examples
504      * of this except "let x = x in ..."
505      */
506     case NAME:
507             rhs = name(rhs).stgVar;
508     case STGVAR:
509         {
510             AsmSp  start = asmBeginMkAP(bco);
511             pushAtom(bco,rhs);
512             asmEndMkAP(bco,getPos(v),start);
513         }
514         return;
515     default:
516         {
517             AsmSp start = asmBeginMkAP(bco);   /* make it updateable! */
518             asmClosure(bco,cgRhs(rhs));
519             asmEndMkAP(bco,getPos(v),start);
520             return;
521         }
522     }
523 }
524
525 /* --------------------------------------------------------------------------
526  * Top level variables
527  *
528  * ToDo: these should be handled by allocating a dynamic unentered CAF
529  * for each top level variable - this should be simpler!
530  * ------------------------------------------------------------------------*/
531
532 #if 0   /* appears to be unused */
533 static void cgAddVar( AsmObject obj, StgAtom v )
534 {
535     if (isName(v)) {
536         v = name(v).stgVar;
537     }
538     assert(isStgVar(v));
539     asmAddPtr(obj,getObj(v));
540 }
541 #endif
542
543
544 /* allocate AsmObject for top level variables
545  * any change requires a corresponding change in endTop
546  */
547 static void beginTop( StgVar v )
548 {
549     StgRhs rhs;
550     assert(isStgVar(v));
551     rhs = stgVarBody(v);
552     switch (whatIs(rhs)) {
553     case STGCON:
554         {
555             //List as = stgConArgs(rhs);
556             setObj(v,asmBeginCon(stgConInfo(stgConCon(rhs))));
557             break;
558         }
559     case LAMBDA:
560             setObj(v,asmBeginBCO(rhs));
561             break;
562     default:
563             setObj(v,asmBeginCAF());
564             break;
565     }
566 }
567
568 static void endTop( StgVar v )
569 {
570     StgRhs rhs = stgVarBody(v);
571     //ppStgRhs(rhs);
572     switch (whatIs(rhs)) {
573     case STGCON:
574         {
575             List as = stgConArgs(rhs);
576             AsmCon con = (AsmCon)getObj(v);
577             for( ; nonNull(as); as=tl(as)) {
578                 StgAtom a = hd(as);
579                 switch (whatIs(a)) {
580                 case STGVAR: 
581                         /* should be a delayed combinator! */
582                         asmAddPtr(con,(AsmObject)getObj(a));
583                         break;
584                 case NAME: 
585                     {
586                         StgVar var = name(a).stgVar;
587                         assert(var);
588                         asmAddPtr(con,(AsmObject)getObj(a));
589                         break;
590                     }
591 #if !USE_ADDR_FOR_STRINGS
592                 case STRCELL:
593                         asmAddPtr(con,asmStringObj(textToStr(textOf(a))));
594                         break;
595 #endif
596                 default: 
597                         /* asmAddPtr(con,??); */
598                         assert(0);
599                         break;
600                 }
601             }
602             asmEndCon(con);
603             break;
604         }
605     case LAMBDA: /* optimisation */
606         {
607             /* ToDo: merge this code with cgLambda */
608             AsmBCO bco = (AsmBCO)getObj(v);
609             AsmSp root = asmBeginArgCheck(bco);
610             map1Proc(cgBind,bco,reverse(stgLambdaArgs(rhs)));
611             asmEndArgCheck(bco,root);
612             
613             cgExpr(bco,root,stgLambdaBody(rhs));
614             
615             asmEndBCO(bco);
616             break;
617         }
618     default:   /* updateable caf */
619         {
620             AsmCAF caf = (AsmCAF)getObj(v);
621             asmEndCAF(caf,cgRhs(rhs));
622             break;
623         }
624     }
625 }
626
627 static void zap( StgVar v )
628 {
629   // ToDo: reinstate
630   //    stgVarBody(v) = NIL;
631 }
632
633 /* external entry point */
634 Void cgBinds( List binds )
635 {
636     List b;
637     int i;
638
639     //if (lastModule() != modulePrelude) {
640     //    printf("\n\ncgBinds: before ll\n\n" );
641     //    for (b=binds; nonNull(b); b=tl(b)) {
642     //       printStg ( stdout, hd(b) ); printf("\n\n");
643     //    }
644     //}
645
646     binds = liftBinds(binds);
647
648     //if (lastModule() != modulePrelude) {
649     //    printf("\n\ncgBinds: after ll\n\n" );
650     //    for (b=binds; nonNull(b); b=tl(b)) {
651     //       printStg ( stdout, hd(b) ); printf("\n\n");
652     //    }
653     //}
654
655
656     //mapProc(beginTop,binds);
657     for (b=binds,i=0; nonNull(b); b=tl(b),i++) {
658       //printf("beginTop %d\n", i);
659        beginTop(hd(b));
660     }
661
662     //mapProc(endTop,binds);
663     for (b=binds,i=0; nonNull(b); b=tl(b),i++) {
664        endTop(hd(b));
665        //if (lastModule() != modulePrelude) {
666        //    printStg ( stdout, hd(b) ); printf("\n\n");
667        //}
668     }
669
670     //mapProc(zap,binds);
671 }
672
673 /* --------------------------------------------------------------------------
674  * Code Generator control:
675  * ------------------------------------------------------------------------*/
676
677 Void codegen(what)
678 Int what; {
679     switch (what) {
680     case INSTALL:
681             /* deliberate fall though */
682     case RESET: 
683             break;
684     case MARK: 
685             break;
686     }
687     liftControl(what);
688 }
689
690 /*-------------------------------------------------------------------------*/