2 /* --------------------------------------------------------------------------
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
9 * $RCSfile: codegen.c,v $
11 * $Date: 1999/06/07 17:22:53 $
12 * ------------------------------------------------------------------------*/
19 #include "Assembler.h"
22 #include "Rts.h" /* IF_DEBUG */
25 /* --------------------------------------------------------------------------
26 * Local function prototypes:
27 * ------------------------------------------------------------------------*/
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)
34 #define repOf(x) charOf(stgVarRep(x))
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 );
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 );
51 static StgVar currentTop;
53 /* --------------------------------------------------------------------------
55 * ------------------------------------------------------------------------*/
57 static Bool varHasClosure( StgVar v )
59 return asmObjectHasClosure((AsmClosure*)ptrOf(stgVarInfo(v)));
62 /* should be AsmClosure* */
63 void* closureOfVar( StgVar v )
65 return asmClosureOfObject((AsmClosure*)ptrOf(stgVarInfo(v)));
68 char* lookupHugsName( void* closure )
72 for( nm=NAMEMIN; nm<nameHw; ++nm ) {
73 StgVar v = name(nm).stgVar;
75 && isPtr(stgVarInfo(v))
77 && closureOfVar(v) == closure) {
78 return textToStr(name(nm).text);
84 /* called at the start of GC */
85 void markHugsObjects( void )
89 for( nm=NAMEMIN; nm<nameHw; ++nm ) {
90 StgVar v = name(nm).stgVar;
91 if (isStgVar(v) && isPtr(stgVarInfo(v))) {
92 asmMarkObject((AsmClosure*)ptrOf(stgVarInfo(v)));
97 static void cgBindRep( AsmBCO bco, StgVar v, AsmRep rep )
99 setPos(v,asmBind(bco,rep));
102 static void cgBind( AsmBCO bco, StgVar v )
104 cgBindRep(bco,v,repOf(v));
107 static Void pushVar( AsmBCO bco, StgVar v )
113 fprintf ( stderr, "push cptr %p\n", (void*)cptrOf(v) );
115 info = stgVarInfo(v);
117 asmClosure(bco,ptrOf(info));
118 } else if (isInt(info)) {
119 asmVar(bco,intOf(info),repOf(v));
126 static Void pushAtom( AsmBCO bco, StgAtom e )
133 pushVar(bco,name(e).stgVar);
136 asmConstChar(bco,charOf(e));
139 asmConstInt(bco,intOf(e));
142 asmConstInteger(bco,bignumToString(e));
146 asmConstFloat(bco,e); /* ToDo: support both float and double! */
148 asmConstDouble(bco,floatOf(e));
153 asmConstDouble(bco,doubleOf(e));
157 #if USE_ADDR_FOR_STRINGS
158 asmConstAddr(bco,textToStr(textOf(e)));
160 asmClosure(bco,asmStringObj(textToStr(textOf(e))));
164 asmConstWord(bco,cptrOf(e));
167 asmConstAddr(bco,ptrOf(e));
170 fprintf(stderr,"\nYoiks: "); printExp(stderr,e);
171 internal("pushAtom");
175 static AsmBCO cgAlts( AsmSp root, AsmSp sp, List alts )
177 #ifdef CRUDE_PROFILING
178 AsmBCO bco = asmBeginContinuation(sp, currentTop + 1000000000);
180 AsmBCO bco = asmBeginContinuation(sp, alts);
182 /* ppStgAlts(alts); */
183 for(; nonNull(alts); alts=tl(alts)) {
184 StgCaseAlt alt = hd(alts);
185 if (isDefaultAlt(alt)) {
186 cgBind(bco,stgDefaultVar(alt));
187 cgExpr(bco,root,stgDefaultBody(alt));
188 asmEndContinuation(bco);
189 return bco; /* ignore any further alternatives */
191 StgDiscr con = stgCaseAltCon(alt);
192 List vs = stgCaseAltVars(alt);
193 AsmSp begin = asmBeginAlt(bco);
194 AsmPc fix = asmTest(bco,stgDiscrTag(con));
195 /* ToDo: omit in single constructor types! */
196 asmBind(bco,PTR_REP); /* Adjust simulated sp to acct for return value */
197 if (isBoxingCon(con)) {
198 setPos(hd(vs),asmUnbox(bco,boxingConRep(con)));
201 map1Proc(cgBind,bco,reverse(vs));
204 cgExpr(bco,root,stgCaseAltBody(alt));
205 asmEndAlt(bco,begin);
206 asmFixBranch(bco,fix);
209 /* if we got this far and didn't match, panic! */
211 asmEndContinuation(bco);
215 static void testPrimPats( AsmBCO bco, AsmSp root, List pats, StgExpr e )
220 StgVar pat = hd(pats);
221 if (isInt(stgVarBody(pat))) {
222 /* asmTestInt leaves stack unchanged - so no need to adjust it */
223 AsmPc tst = asmTestInt(bco,getPos(pat),intOf(stgVarBody(pat)));
224 assert(repOf(pat) == INT_REP);
225 testPrimPats(bco,root,tl(pats),e);
226 asmFixBranch(bco,tst);
228 testPrimPats(bco,root,tl(pats),e);
233 #if 0 /* appears to be unused */
234 static void cgPrimAlt( AsmBCO bco, AsmSp root, List vs, StgExpr e )
236 assert(0); /* ToDo: test for patterns */
237 map1Proc(cgBind,bco,vs); /* ToDo: are these in right order? */
243 static AsmBCO cgLambda( StgExpr e )
245 AsmBCO bco = asmBeginBCO(e);
247 AsmSp root = asmBeginArgCheck(bco);
248 map1Proc(cgBind,bco,reverse(stgLambdaArgs(e)));
249 asmEndArgCheck(bco,root);
252 cgExpr(bco,root,stgLambdaBody(e));
258 static AsmBCO cgRhs( StgRhs rhs )
260 AsmBCO bco = asmBeginBCO(rhs );
262 AsmSp root = asmBeginArgCheck(bco);
263 asmEndArgCheck(bco,root);
265 /* ppStgExpr(rhs); */
266 cgExpr(bco,root,rhs);
273 static Void cgExpr( AsmBCO bco, AsmSp root, StgExpr e )
275 //printf("cgExpr:");ppStgExpr(e);printf("\n");
279 List binds = stgLetBinds(e);
280 map1Proc(alloc,bco,binds);
281 map1Proc(build,bco,binds);
282 cgExpr(bco,root,stgLetBody(e));
287 AsmSp begin = asmBeginEnter(bco);
288 asmClosure(bco,cgLambda(e));
289 asmEndEnter(bco,begin,root);
294 List alts = stgCaseAlts(e);
295 AsmSp sp = asmBeginCase(bco);
296 AsmSp caseroot = asmContinuation(bco,cgAlts(root,sp,alts));
297 cgExpr(bco,caseroot,stgCaseScrut(e));
303 StgExpr scrut = stgPrimCaseScrut(e);
304 List alts = stgPrimCaseAlts(e);
305 if (whatIs(scrut) == STGPRIM) { /* this is an optimisation */
307 /* No need to use return address or to Slide */
308 AsmSp beginPrim = asmBeginPrim(bco);
309 map1Proc(pushAtom,bco,reverse(stgPrimArgs(scrut)));
310 asmEndPrim(bco,(AsmPrim*)name(stgPrimOp(scrut)).primop,beginPrim);
312 for(; nonNull(alts); alts=tl(alts)) {
313 StgPrimAlt alt = hd(alts);
314 List pats = stgPrimAltVars(alt);
315 StgExpr body = stgPrimAltBody(alt);
316 AsmSp altBegin = asmBeginAlt(bco);
317 map1Proc(cgBind,bco,reverse(pats));
318 testPrimPats(bco,root,pats,body);
319 asmEndAlt(bco,altBegin);
321 /* if we got this far and didn't match, panic! */
324 } else if (whatIs(scrut) == STGVAR) { /* another optimisation */
326 /* No need to use return address or to Slide */
328 /* only part different from primop code... todo */
329 AsmSp beginCase = asmBeginCase(bco);
331 asmEndAlt(bco,beginCase); /* hack, hack - */
333 for(; nonNull(alts); alts=tl(alts)) {
334 StgPrimAlt alt = hd(alts);
335 List pats = stgPrimAltVars(alt);
336 StgExpr body = stgPrimAltBody(alt);
337 AsmSp altBegin = asmBeginAlt(bco);
338 map1Proc(cgBind,bco,pats);
339 testPrimPats(bco,root,pats,body);
340 asmEndAlt(bco,altBegin);
342 /* if we got this far and didn't match, panic! */
346 /* ToDo: implement this code... */
348 /* asmPushRet(bco,delayPrimAlt( stgPrimCaseVars(e), stgPrimCaseBody(e))); */
349 /* cgExpr( bco,root,scrut ); */
353 case STGAPP: /* Tail call */
355 AsmSp env = asmBeginEnter(bco);
356 map1Proc(pushAtom,bco,reverse(stgAppArgs(e)));
357 pushAtom(bco,stgAppFun(e));
358 asmEndEnter(bco,env,root);
361 case NAME: /* Tail call (with no args) */
363 AsmSp env = asmBeginEnter(bco);
364 pushVar(bco,name(e).stgVar);
365 asmEndEnter(bco,env,root);
368 case STGVAR: /* Tail call (with no args), plus unboxed return */
374 AsmSp env = asmBeginEnter(bco);
376 asmEndEnter(bco,env,root);
381 /* cgTailCall(bco,singleton(e)); */
382 /* asmReturnInt(bco); */
385 internal("cgExpr StgVar");
388 case STGPRIM: /* Tail call again */
390 AsmSp beginPrim = asmBeginPrim(bco);
391 map1Proc(pushAtom,bco,reverse(stgPrimArgs(e)));
392 asmEndPrim(bco,(AsmPrim*)name(e).primop,beginPrim);
393 /* map1Proc(cgBind,bco,rs_vars); */
394 assert(0); /* asmReturn_retty(); */
398 fprintf(stderr,"\nYoiks: "); printExp(stderr,e);
403 #define M_ITBLNAMES 35000
405 void* itblNames[M_ITBLNAMES];
408 /* allocate space for top level variable
409 * any change requires a corresponding change in 'build'.
411 static Void alloc( AsmBCO bco, StgVar v )
413 StgRhs rhs = stgVarBody(v);
415 switch (whatIs(rhs)) {
418 StgDiscr con = stgConCon(rhs);
419 List args = stgConArgs(rhs);
420 if (isBoxingCon(con)) {
421 pushAtom(bco,hd(args));
422 setPos(v,asmBox(bco,boxingConRep(con)));
425 void* vv = stgConInfo(con);
426 if (!(nItblNames < (M_ITBLNAMES-2)))
427 internal("alloc -- M_ITBLNAMES too small");
429 itblNames[nItblNames++] = vv;
430 itblNames[nItblNames++] = textToStr(name(con).text);
433 char* cc = malloc(10);
435 sprintf(cc, "Tuple%d", tupleOf(con) );
436 itblNames[nItblNames++] = vv;
437 itblNames[nItblNames++] = cc;
439 assert ( /* cant identify constructor name */ 0 );
441 setPos(v,asmAllocCONSTR(bco, vv));
447 List bs = stgAppArgs(rhs);
448 for (; nonNull(bs); bs=tl(bs)) {
449 if (isName(hd(bs))) {
452 ASSERT(whatIs(hd(bs))==STGVAR);
453 totSizeW += asmRepSizeW( charOf(stgVarRep(hd(bs))) );
456 setPos(v,asmAllocAP(bco,totSizeW));
457 //ORIGINALLY:setPos(v,asmAllocAP(bco,length(stgAppArgs(rhs))));
460 case LAMBDA: /* optimisation */
461 setObj(v,cgLambda(rhs));
464 setPos(v,asmAllocAP(bco,0));
469 static Void build( AsmBCO bco, StgVar v )
471 StgRhs rhs = stgVarBody(v);
474 switch (whatIs(rhs)) {
477 StgDiscr con = stgConCon(rhs);
478 List args = stgConArgs(rhs);
479 if (isBoxingCon(con)) {
480 doNothing(); /* already done in alloc */
482 AsmSp start = asmBeginPack(bco);
483 map1Proc(pushAtom,bco,reverse(args));
484 asmEndPack(bco,getPos(v),start,stgConInfo(con));
490 StgVar fun = stgAppFun(rhs);
491 List args = stgAppArgs(rhs);
493 fun = name(fun).stgVar;
497 (nonNull(stgVarBody(fun))
498 && whatIs(stgVarBody(fun)) == LAMBDA
499 && length(stgLambdaArgs(stgVarBody(fun))) > length(args)
502 AsmSp start = asmBeginMkPAP(bco);
503 map1Proc(pushAtom,bco,reverse(args));
505 asmEndMkPAP(bco,getPos(v),start); /* optimisation */
507 AsmSp start = asmBeginMkAP(bco);
508 map1Proc(pushAtom,bco,reverse(args));
510 asmEndMkAP(bco,getPos(v),start);
514 case LAMBDA: /* optimisation */
515 doNothing(); /* already pushed in alloc */
518 /* These two cases look almost identical to the default but they're really
519 * special cases of STGAPP. The essential thing here is that we can't call
520 * cgRhs(rhs) because that expects the rhs to have no free variables when,
521 * in fact, the rhs is _always_ a free variable.
523 * ToDo: a simple optimiser would eliminate all examples
524 * of this except "let x = x in ..."
527 rhs = name(rhs).stgVar;
530 AsmSp start = asmBeginMkAP(bco);
532 asmEndMkAP(bco,getPos(v),start);
537 AsmSp start = asmBeginMkAP(bco); /* make it updateable! */
538 asmClosure(bco,cgRhs(rhs));
539 asmEndMkAP(bco,getPos(v),start);
545 /* --------------------------------------------------------------------------
546 * Top level variables
548 * ToDo: these should be handled by allocating a dynamic unentered CAF
549 * for each top level variable - this should be simpler!
550 * ------------------------------------------------------------------------*/
552 #if 0 /* appears to be unused */
553 static void cgAddVar( AsmObject obj, StgAtom v )
559 asmAddPtr(obj,getObj(v));
564 /* allocate AsmObject for top level variables
565 * any change requires a corresponding change in endTop
567 static void beginTop( StgVar v )
573 switch (whatIs(rhs)) {
576 //List as = stgConArgs(rhs);
577 setObj(v,asmBeginCon(stgConInfo(stgConCon(rhs))));
581 #ifdef CRUDE_PROFILING
582 setObj(v,asmBeginBCO(currentTop));
584 setObj(v,asmBeginBCO(rhs));
588 setObj(v,asmBeginCAF());
593 static void endTop( StgVar v )
595 StgRhs rhs = stgVarBody(v);
597 switch (whatIs(rhs)) {
600 List as = stgConArgs(rhs);
601 AsmCon con = (AsmCon)getObj(v);
602 for( ; nonNull(as); as=tl(as)) {
606 /* should be a delayed combinator! */
607 asmAddPtr(con,(AsmObject)getObj(a));
611 StgVar var = name(a).stgVar;
613 asmAddPtr(con,(AsmObject)getObj(a));
616 #if !USE_ADDR_FOR_STRINGS
618 asmAddPtr(con,asmStringObj(textToStr(textOf(a))));
622 /* asmAddPtr(con,??); */
630 case LAMBDA: /* optimisation */
632 /* ToDo: merge this code with cgLambda */
633 AsmBCO bco = (AsmBCO)getObj(v);
634 AsmSp root = asmBeginArgCheck(bco);
635 map1Proc(cgBind,bco,reverse(stgLambdaArgs(rhs)));
636 asmEndArgCheck(bco,root);
638 cgExpr(bco,root,stgLambdaBody(rhs));
643 default: /* updateable caf */
645 AsmCAF caf = (AsmCAF)getObj(v);
646 asmEndCAF(caf,cgRhs(rhs));
652 static void zap( StgVar v )
655 // stgVarBody(v) = NIL;
658 /* external entry point */
659 Void cgBinds( List binds )
665 if (lastModule() != modulePrelude) {
666 printf("\n\ncgBinds: before ll\n\n" );
667 for (b=binds; nonNull(b); b=tl(b)) {
668 printStg ( stdout, hd(b) ); printf("\n\n");
673 binds = liftBinds(binds);
676 if (lastModule() != modulePrelude) {
677 printf("\n\ncgBinds: after ll\n\n" );
678 for (b=binds; nonNull(b); b=tl(b)) {
679 printStg ( stdout, hd(b) ); printf("\n\n");
684 for (b=binds,i=0; nonNull(b); b=tl(b),i++) {
688 for (b=binds,i=0; nonNull(b); b=tl(b),i++) {
689 //printf("endTop %s\n", maybeName(hd(b)));
693 //mapProc(zap,binds);
696 /* --------------------------------------------------------------------------
697 * Code Generator control:
698 * ------------------------------------------------------------------------*/
704 /* deliberate fall though */
713 /*-------------------------------------------------------------------------*/