2 /* --------------------------------------------------------------------------
5 * The Hugs 98 system is Copyright (c) Mark P Jones, Alastair Reid, the
6 * Yale Haskell Group, and the Oregon Graduate Institute of Science and
7 * Technology, 1994-1999, All rights reserved. It is distributed as
8 * free software under the license in the file "License", which is
9 * included in the distribution.
11 * $RCSfile: codegen.c,v $
13 * $Date: 2000/02/08 15:32:29 $
14 * ------------------------------------------------------------------------*/
21 #include "Assembler.h"
24 #include "Rts.h" /* IF_DEBUG */
27 /* --------------------------------------------------------------------------
28 * Local function prototypes:
29 * ------------------------------------------------------------------------*/
31 #define getPos(v) intOf(stgVarInfo(v))
32 #define setPos(v,sp) stgVarInfo(v) = mkInt(sp)
33 #define getObj(v) ptrOf(stgVarInfo(v))
34 #define setObj(v,obj) stgVarInfo(v) = mkPtr(obj)
36 #define repOf(x) charOf(stgVarRep(x))
38 static void cgBind ( AsmBCO bco, StgVar v );
39 static Void pushVar ( AsmBCO bco, StgVar v );
40 static Void pushAtom ( AsmBCO bco, StgAtom atom );
41 static Void alloc ( AsmBCO bco, StgRhs rhs );
42 static Void build ( AsmBCO bco, StgRhs rhs );
43 static Void cgExpr ( AsmBCO bco, AsmSp root, StgExpr e );
45 static AsmBCO cgAlts ( AsmSp root, AsmSp sp, List alts );
46 static void testPrimPats ( AsmBCO bco, AsmSp root, List pats, StgExpr e );
47 //static void cgPrimAlt ( AsmBCO bco, AsmSp root, List vs, StgExpr e );
48 static AsmBCO cgLambda ( StgExpr e );
49 static AsmBCO cgRhs ( StgRhs rhs );
50 static void beginTop ( StgVar v );
51 static void endTop ( StgVar v );
53 static StgVar currentTop;
55 /* --------------------------------------------------------------------------
57 * ------------------------------------------------------------------------*/
59 static Cell cptrFromName ( Name n )
63 Module m = name(n).mod;
64 Text mt = module(m).text;
65 sprintf(buf,"%s_%s_closure",
67 textToStr( enZcodeThenFindText ( textToStr (name(n).text) ) ) );
68 p = lookupOTabName ( m, buf );
70 ERRMSG(0) "Can't find object symbol %s", buf
76 static Bool varHasClosure( StgVar v )
78 return asmObjectHasClosure((AsmClosure*)ptrOf(stgVarInfo(v)));
81 /* should be AsmClosure* */
82 void* closureOfVar( StgVar v )
84 return asmClosureOfObject((AsmClosure*)ptrOf(stgVarInfo(v)));
87 char* lookupHugsName( void* closure )
91 for( nm=NAMEMIN; nm<nameHw; ++nm ) {
92 StgVar v = name(nm).stgVar;
94 && isPtr(stgVarInfo(v))
96 && closureOfVar(v) == closure) {
97 return textToStr(name(nm).text);
103 /* called at the start of GC */
104 void markHugsObjects( void )
108 for( nm=NAMEMIN; nm<nameHw; ++nm ) {
109 StgVar v = name(nm).stgVar;
110 if (isStgVar(v) && isPtr(stgVarInfo(v))) {
111 asmMarkObject((AsmClosure*)ptrOf(stgVarInfo(v)));
116 static void cgBindRep( AsmBCO bco, StgVar v, AsmRep rep )
118 setPos(v,asmBind(bco,rep));
121 static void cgBind( AsmBCO bco, StgVar v )
123 cgBindRep(bco,v,repOf(v));
126 static Void pushVar( AsmBCO bco, StgVar v )
130 printf ( "pushVar: %d ", v ); fflush(stdout);
131 print(v,10);printf("\n");
133 assert(isStgVar(v) || isCPtr(v));
136 asmGHCClosure(bco, cptrOf(v));
138 info = stgVarInfo(v);
140 asmClosure(bco,ptrOf(info));
141 } else if (isInt(info)) {
142 asmVar(bco,intOf(info),repOf(v));
149 static Void pushAtom( AsmBCO bco, StgAtom e )
152 printf ( "pushAtom: %d ", e ); fflush(stdout);
153 print(e,10);printf("\n");
160 if (nonNull(name(e).stgVar)) {
161 pushVar(bco,name(e).stgVar);
163 Cell /*CPtr*/ addr = cptrFromName(e);
164 fprintf ( stderr, "nativeAtom: name %s\n",
165 nameFromOPtr(cptrOf(addr)) );
170 asmConstChar(bco,charOf(e));
173 asmConstInt(bco,intOf(e));
176 asmConstInteger(bco,bignumToString(e));
179 asmConstDouble(bco,floatOf(e));
182 #if USE_ADDR_FOR_STRINGS
183 asmConstAddr(bco,textToStr(textOf(e)));
185 asmClosure(bco,asmStringObj(textToStr(textOf(e))));
189 asmGHCClosure(bco,cptrOf(e));
192 asmConstAddr(bco,ptrOf(e));
195 fprintf(stderr,"\nYoiks1: "); printExp(stderr,e);
196 internal("pushAtom");
200 static AsmBCO cgAlts( AsmSp root, AsmSp sp, List alts )
202 #ifdef CRUDE_PROFILING
203 AsmBCO bco = asmBeginContinuation(sp, currentTop + 1000000000);
205 AsmBCO bco = asmBeginContinuation(sp, alts);
208 = length(alts) == 2 &&
209 isDefaultAlt(hd(tl(alts))) &&
210 !isDefaultAlt(hd(alts));
212 /* refine the condition */
216 con = stgCaseAltCon(hd(alts));
218 /* special case: dictionary constructors */
219 if (strncmp(":D",textToStr(name(con).text),2)==0) {
223 /* special case: Tuples */
224 if (isTuple(con) || (isName(con) && con==nameUnit)) {
229 t = name(con).parent;
230 if (tycon(t).what == DATATYPE) {
231 if (length(tycon(t).defn) == 1) omit_test = TRUE;
237 for(; nonNull(alts); alts=tl(alts)) {
238 StgCaseAlt alt = hd(alts);
239 if (isDefaultAlt(alt)) {
240 cgBind(bco,stgDefaultVar(alt));
241 cgExpr(bco,root,stgDefaultBody(alt));
242 asmEndContinuation(bco);
243 return bco; /* ignore any further alternatives */
245 StgDiscr con = stgCaseAltCon(alt);
246 List vs = stgCaseAltVars(alt);
247 AsmSp begin = asmBeginAlt(bco);
249 if (omit_test) fix=-1; else fix = asmTest(bco,stgDiscrTag(con));
251 asmBind(bco,PTR_REP); /* Adjust simulated sp to acct for return value */
252 if (isBoxingCon(con)) {
253 setPos(hd(vs),asmUnbox(bco,boxingConRep(con)));
256 map1Proc(cgBind,bco,reverse(vs));
259 cgExpr(bco,root,stgCaseAltBody(alt));
260 asmEndAlt(bco,begin);
261 if (fix != -1) asmFixBranch(bco,fix);
264 /* if we got this far and didn't match, panic! */
266 asmEndContinuation(bco);
270 static void testPrimPats( AsmBCO bco, AsmSp root, List pats, StgExpr e )
275 StgVar pat = hd(pats);
276 if (isInt(stgVarBody(pat))) {
277 /* asmTestInt leaves stack unchanged - so no need to adjust it */
278 AsmPc tst = asmTestInt(bco,getPos(pat),intOf(stgVarBody(pat)));
279 assert(repOf(pat) == INT_REP);
280 testPrimPats(bco,root,tl(pats),e);
281 asmFixBranch(bco,tst);
283 testPrimPats(bco,root,tl(pats),e);
288 #if 0 /* appears to be unused */
289 static void cgPrimAlt( AsmBCO bco, AsmSp root, List vs, StgExpr e )
291 assert(0); /* ToDo: test for patterns */
292 map1Proc(cgBind,bco,vs); /* ToDo: are these in right order? */
298 static AsmBCO cgLambda( StgExpr e )
300 AsmBCO bco = asmBeginBCO(e);
302 AsmSp root = asmBeginArgCheck(bco);
303 map1Proc(cgBind,bco,reverse(stgLambdaArgs(e)));
304 asmEndArgCheck(bco,root);
307 cgExpr(bco,root,stgLambdaBody(e));
313 static AsmBCO cgRhs( StgRhs rhs )
315 AsmBCO bco = asmBeginBCO(rhs );
317 AsmSp root = asmBeginArgCheck(bco);
318 asmEndArgCheck(bco,root);
320 /* ppStgExpr(rhs); */
321 cgExpr(bco,root,rhs);
328 static Void cgExpr( AsmBCO bco, AsmSp root, StgExpr e )
331 printf("cgExpr:");ppStgExpr(e);printf("\n");
336 List binds = stgLetBinds(e);
337 map1Proc(alloc,bco,binds);
338 map1Proc(build,bco,binds);
339 cgExpr(bco,root,stgLetBody(e));
344 AsmSp begin = asmBeginEnter(bco);
345 asmClosure(bco,cgLambda(e));
346 asmEndEnter(bco,begin,root);
351 List alts = stgCaseAlts(e);
352 AsmSp sp = asmBeginCase(bco);
353 AsmSp caseroot = asmContinuation(bco,cgAlts(root,sp,alts));
354 cgExpr(bco,caseroot,stgCaseScrut(e));
360 StgExpr scrut = stgPrimCaseScrut(e);
361 List alts = stgPrimCaseAlts(e);
362 if (whatIs(scrut) == STGPRIM) { /* this is an optimisation */
364 /* No need to use return address or to Slide */
365 AsmSp beginPrim = asmBeginPrim(bco);
366 map1Proc(pushAtom,bco,reverse(stgPrimArgs(scrut)));
367 asmEndPrim(bco,(AsmPrim*)name(stgPrimOp(scrut)).primop,beginPrim);
369 for(; nonNull(alts); alts=tl(alts)) {
370 StgPrimAlt alt = hd(alts);
371 List pats = stgPrimAltVars(alt);
372 StgExpr body = stgPrimAltBody(alt);
373 AsmSp altBegin = asmBeginAlt(bco);
374 map1Proc(cgBind,bco,reverse(pats));
375 testPrimPats(bco,root,pats,body);
376 asmEndAlt(bco,altBegin);
378 /* if we got this far and didn't match, panic! */
381 } else if (whatIs(scrut) == STGVAR) { /* another optimisation */
383 /* No need to use return address or to Slide */
385 /* only part different from primop code... todo */
386 AsmSp beginCase = asmBeginCase(bco);
388 asmEndAlt(bco,beginCase); /* hack, hack - */
390 for(; nonNull(alts); alts=tl(alts)) {
391 StgPrimAlt alt = hd(alts);
392 List pats = stgPrimAltVars(alt);
393 StgExpr body = stgPrimAltBody(alt);
394 AsmSp altBegin = asmBeginAlt(bco);
395 map1Proc(cgBind,bco,pats);
396 testPrimPats(bco,root,pats,body);
397 asmEndAlt(bco,altBegin);
399 /* if we got this far and didn't match, panic! */
403 /* ToDo: implement this code... */
405 /* asmPushRet(bco,delayPrimAlt( stgPrimCaseVars(e),
406 stgPrimCaseBody(e))); */
407 /* cgExpr( bco,root,scrut ); */
411 case STGAPP: /* Tail call */
413 AsmSp env = asmBeginEnter(bco);
414 map1Proc(pushAtom,bco,reverse(stgAppArgs(e)));
415 pushAtom(bco,stgAppFun(e));
416 asmEndEnter(bco,env,root);
419 case NAME: /* Tail call (with no args) */
421 AsmSp env = asmBeginEnter(bco);
422 /* JRS 000112: next line used to be: pushVar(bco,name(e).stgVar); */
424 asmEndEnter(bco,env,root);
427 case STGVAR: /* Tail call (with no args), plus unboxed return */
433 AsmSp env = asmBeginEnter(bco);
435 asmEndEnter(bco,env,root);
440 /* cgTailCall(bco,singleton(e)); */
441 /* asmReturnInt(bco); */
444 internal("cgExpr StgVar");
447 case STGPRIM: /* Tail call again */
449 AsmSp beginPrim = asmBeginPrim(bco);
450 map1Proc(pushAtom,bco,reverse(stgPrimArgs(e)));
451 asmEndPrim(bco,(AsmPrim*)name(e).primop,beginPrim);
452 /* map1Proc(cgBind,bco,rs_vars); */
453 assert(0); /* asmReturn_retty(); */
457 fprintf(stderr,"\nYoiks2: "); printExp(stderr,e);
462 #define M_ITBLNAMES 35000
464 void* itblNames[M_ITBLNAMES];
467 /* allocate space for top level variable
468 * any change requires a corresponding change in 'build'.
470 static Void alloc( AsmBCO bco, StgVar v )
472 StgRhs rhs = stgVarBody(v);
475 printf("alloc: ");ppStgExpr(v);
477 switch (whatIs(rhs)) {
480 StgDiscr con = stgConCon(rhs);
481 List args = stgConArgs(rhs);
482 if (isBoxingCon(con)) {
483 pushAtom(bco,hd(args));
484 setPos(v,asmBox(bco,boxingConRep(con)));
487 void* vv = stgConInfo(con);
488 if (!(nItblNames < (M_ITBLNAMES-2)))
489 internal("alloc -- M_ITBLNAMES too small");
491 itblNames[nItblNames++] = vv;
492 itblNames[nItblNames++] = textToStr(name(con).text);
495 itblNames[nItblNames++] = vv;
496 itblNames[nItblNames++] = textToStr(ghcTupleText(con));
498 assert ( /* cant identify constructor name */ 0 );
499 setPos(v,asmAllocCONSTR(bco, vv));
505 List bs = stgAppArgs(rhs);
506 for (; nonNull(bs); bs=tl(bs)) {
507 if (isName(hd(bs))) {
510 ASSERT(whatIs(hd(bs))==STGVAR);
511 totSizeW += asmRepSizeW( charOf(stgVarRep(hd(bs))) );
514 setPos(v,asmAllocAP(bco,totSizeW));
515 //ORIGINALLY:setPos(v,asmAllocAP(bco,length(stgAppArgs(rhs))));
518 case LAMBDA: /* optimisation */
519 setObj(v,cgLambda(rhs));
522 setPos(v,asmAllocAP(bco,0));
527 static Void build( AsmBCO bco, StgVar v )
529 StgRhs rhs = stgVarBody(v);
532 switch (whatIs(rhs)) {
535 StgDiscr con = stgConCon(rhs);
536 List args = stgConArgs(rhs);
537 if (isBoxingCon(con)) {
538 doNothing(); /* already done in alloc */
540 AsmSp start = asmBeginPack(bco);
541 map1Proc(pushAtom,bco,reverse(args));
542 asmEndPack(bco,getPos(v),start,stgConInfo(con));
549 StgVar fun = stgAppFun(rhs);
551 List args = stgAppArgs(rhs);
553 if (nonNull(name(fun).stgVar))
554 fun = name(fun).stgVar; else
555 fun = cptrFromName(fun);
559 assert(isName(fun0));
560 itsaPAP = name(fun0).arity > length(args);
561 fprintf ( stderr, "nativeCall: name %s, arity %d, args %d\n",
562 nameFromOPtr(cptrOf(fun)), name(fun0).arity, length(args) );
565 if (nonNull(stgVarBody(fun))
566 && whatIs(stgVarBody(fun)) == LAMBDA
567 && length(stgLambdaArgs(stgVarBody(fun))) > length(args)
573 AsmSp start = asmBeginMkPAP(bco);
574 map1Proc(pushAtom,bco,reverse(args));
576 asmEndMkPAP(bco,getPos(v),start); /* optimisation */
578 AsmSp start = asmBeginMkAP(bco);
579 map1Proc(pushAtom,bco,reverse(args));
581 asmEndMkAP(bco,getPos(v),start);
585 case LAMBDA: /* optimisation */
586 doNothing(); /* already pushed in alloc */
589 /* These two cases look almost identical to the default but they're really
590 * special cases of STGAPP. The essential thing here is that we can't call
591 * cgRhs(rhs) because that expects the rhs to have no free variables when,
592 * in fact, the rhs is _always_ a free variable.
594 * ToDo: a simple optimiser would eliminate all examples
595 * of this except "let x = x in ..."
598 if (nonNull(name(rhs).stgVar))
599 rhs = name(rhs).stgVar; else
600 rhs = cptrFromName(rhs);
604 AsmSp start = asmBeginMkAP(bco);
606 asmEndMkAP(bco,getPos(v),start);
611 AsmSp start = asmBeginMkAP(bco); /* make it updateable! */
612 asmClosure(bco,cgRhs(rhs));
613 asmEndMkAP(bco,getPos(v),start);
619 /* --------------------------------------------------------------------------
620 * Top level variables
622 * ToDo: these should be handled by allocating a dynamic unentered CAF
623 * for each top level variable - this should be simpler!
624 * ------------------------------------------------------------------------*/
626 #if 0 /* appears to be unused */
627 static void cgAddVar( AsmObject obj, StgAtom v )
633 asmAddPtr(obj,getObj(v));
638 /* allocate AsmObject for top level variables
639 * any change requires a corresponding change in endTop
641 static void beginTop( StgVar v )
647 switch (whatIs(rhs)) {
650 //List as = stgConArgs(rhs);
651 setObj(v,asmBeginCon(stgConInfo(stgConCon(rhs))));
655 #ifdef CRUDE_PROFILING
656 setObj(v,asmBeginBCO(currentTop));
658 setObj(v,asmBeginBCO(rhs));
662 setObj(v,asmBeginCAF());
667 static void endTop( StgVar v )
669 StgRhs rhs = stgVarBody(v);
671 switch (whatIs(rhs)) {
674 List as = stgConArgs(rhs);
675 AsmCon con = (AsmCon)getObj(v);
676 for( ; nonNull(as); as=tl(as)) {
680 /* should be a delayed combinator! */
681 asmAddPtr(con,(AsmObject)getObj(a));
685 StgVar var = name(a).stgVar;
687 asmAddPtr(con,(AsmObject)getObj(a));
690 #if !USE_ADDR_FOR_STRINGS
692 asmAddPtr(con,asmStringObj(textToStr(textOf(a))));
696 /* asmAddPtr(con,??); */
704 case LAMBDA: /* optimisation */
706 /* ToDo: merge this code with cgLambda */
707 AsmBCO bco = (AsmBCO)getObj(v);
708 AsmSp root = asmBeginArgCheck(bco);
709 map1Proc(cgBind,bco,reverse(stgLambdaArgs(rhs)));
710 asmEndArgCheck(bco,root);
712 cgExpr(bco,root,stgLambdaBody(rhs));
717 default: /* updateable caf */
719 AsmCAF caf = (AsmCAF)getObj(v);
720 asmEndCAF(caf,cgRhs(rhs));
726 static void zap( StgVar v )
729 // stgVarBody(v) = NIL;
732 /* external entry point */
733 Void cgBinds( List binds )
739 if (lastModule() != modulePrelude) {
740 printf("\n\ncgBinds: before ll\n\n" );
741 for (b=binds; nonNull(b); b=tl(b)) {
742 printStg ( stdout, hd(b) ); printf("\n\n");
747 binds = liftBinds(binds);
750 if (lastModule() != modulePrelude) {
751 printf("\n\ncgBinds: after ll\n\n" );
752 for (b=binds; nonNull(b); b=tl(b)) {
753 printStg ( stdout, hd(b) ); printf("\n\n");
758 for (b=binds,i=0; nonNull(b); b=tl(b),i++) {
762 for (b=binds,i=0; nonNull(b); b=tl(b),i++) {
763 //printStg( stdout, hd(b) ); printf( "\n\n");
767 //mapProc(zap,binds);
770 /* --------------------------------------------------------------------------
771 * Code Generator control:
772 * ------------------------------------------------------------------------*/
786 /*-------------------------------------------------------------------------*/