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/01/12 16:32:41 $
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", nameFromOPtr(cptrOf(addr)) );
169 asmConstChar(bco,charOf(e));
172 asmConstInt(bco,intOf(e));
175 asmConstInteger(bco,bignumToString(e));
178 asmConstDouble(bco,floatOf(e));
181 #if USE_ADDR_FOR_STRINGS
182 asmConstAddr(bco,textToStr(textOf(e)));
184 asmClosure(bco,asmStringObj(textToStr(textOf(e))));
188 asmGHCClosure(bco,cptrOf(e));
191 asmConstAddr(bco,ptrOf(e));
194 fprintf(stderr,"\nYoiks: "); printExp(stderr,e);
195 internal("pushAtom");
199 static AsmBCO cgAlts( AsmSp root, AsmSp sp, List alts )
201 #ifdef CRUDE_PROFILING
202 AsmBCO bco = asmBeginContinuation(sp, currentTop + 1000000000);
204 AsmBCO bco = asmBeginContinuation(sp, alts);
207 = length(alts) == 2 &&
208 isDefaultAlt(hd(tl(alts))) &&
209 !isDefaultAlt(hd(alts));
211 /* refine the condition */
215 con = stgCaseAltCon(hd(alts));
217 /* special case: dictionary constructors */
218 if (strncmp(":D",textToStr(name(con).text),2)==0) {
222 /* special case: Tuples */
223 if (isTuple(con) || (isName(con) && con==nameUnit)) {
228 t = name(con).parent;
229 if (tycon(t).what == DATATYPE) {
230 if (length(tycon(t).defn) == 1) omit_test = TRUE;
236 for(; nonNull(alts); alts=tl(alts)) {
237 StgCaseAlt alt = hd(alts);
238 if (isDefaultAlt(alt)) {
239 cgBind(bco,stgDefaultVar(alt));
240 cgExpr(bco,root,stgDefaultBody(alt));
241 asmEndContinuation(bco);
242 return bco; /* ignore any further alternatives */
244 StgDiscr con = stgCaseAltCon(alt);
245 List vs = stgCaseAltVars(alt);
246 AsmSp begin = asmBeginAlt(bco);
248 if (omit_test) fix=-1; else fix = asmTest(bco,stgDiscrTag(con));
250 asmBind(bco,PTR_REP); /* Adjust simulated sp to acct for return value */
251 if (isBoxingCon(con)) {
252 setPos(hd(vs),asmUnbox(bco,boxingConRep(con)));
255 map1Proc(cgBind,bco,reverse(vs));
258 cgExpr(bco,root,stgCaseAltBody(alt));
259 asmEndAlt(bco,begin);
260 if (fix != -1) asmFixBranch(bco,fix);
263 /* if we got this far and didn't match, panic! */
265 asmEndContinuation(bco);
269 static void testPrimPats( AsmBCO bco, AsmSp root, List pats, StgExpr e )
274 StgVar pat = hd(pats);
275 if (isInt(stgVarBody(pat))) {
276 /* asmTestInt leaves stack unchanged - so no need to adjust it */
277 AsmPc tst = asmTestInt(bco,getPos(pat),intOf(stgVarBody(pat)));
278 assert(repOf(pat) == INT_REP);
279 testPrimPats(bco,root,tl(pats),e);
280 asmFixBranch(bco,tst);
282 testPrimPats(bco,root,tl(pats),e);
287 #if 0 /* appears to be unused */
288 static void cgPrimAlt( AsmBCO bco, AsmSp root, List vs, StgExpr e )
290 assert(0); /* ToDo: test for patterns */
291 map1Proc(cgBind,bco,vs); /* ToDo: are these in right order? */
297 static AsmBCO cgLambda( StgExpr e )
299 AsmBCO bco = asmBeginBCO(e);
301 AsmSp root = asmBeginArgCheck(bco);
302 map1Proc(cgBind,bco,reverse(stgLambdaArgs(e)));
303 asmEndArgCheck(bco,root);
306 cgExpr(bco,root,stgLambdaBody(e));
312 static AsmBCO cgRhs( StgRhs rhs )
314 AsmBCO bco = asmBeginBCO(rhs );
316 AsmSp root = asmBeginArgCheck(bco);
317 asmEndArgCheck(bco,root);
319 /* ppStgExpr(rhs); */
320 cgExpr(bco,root,rhs);
327 static Void cgExpr( AsmBCO bco, AsmSp root, StgExpr e )
330 printf("cgExpr:");ppStgExpr(e);printf("\n");
335 List binds = stgLetBinds(e);
336 map1Proc(alloc,bco,binds);
337 map1Proc(build,bco,binds);
338 cgExpr(bco,root,stgLetBody(e));
343 AsmSp begin = asmBeginEnter(bco);
344 asmClosure(bco,cgLambda(e));
345 asmEndEnter(bco,begin,root);
350 List alts = stgCaseAlts(e);
351 AsmSp sp = asmBeginCase(bco);
352 AsmSp caseroot = asmContinuation(bco,cgAlts(root,sp,alts));
353 cgExpr(bco,caseroot,stgCaseScrut(e));
359 StgExpr scrut = stgPrimCaseScrut(e);
360 List alts = stgPrimCaseAlts(e);
361 if (whatIs(scrut) == STGPRIM) { /* this is an optimisation */
363 /* No need to use return address or to Slide */
364 AsmSp beginPrim = asmBeginPrim(bco);
365 map1Proc(pushAtom,bco,reverse(stgPrimArgs(scrut)));
366 asmEndPrim(bco,(AsmPrim*)name(stgPrimOp(scrut)).primop,beginPrim);
368 for(; nonNull(alts); alts=tl(alts)) {
369 StgPrimAlt alt = hd(alts);
370 List pats = stgPrimAltVars(alt);
371 StgExpr body = stgPrimAltBody(alt);
372 AsmSp altBegin = asmBeginAlt(bco);
373 map1Proc(cgBind,bco,reverse(pats));
374 testPrimPats(bco,root,pats,body);
375 asmEndAlt(bco,altBegin);
377 /* if we got this far and didn't match, panic! */
380 } else if (whatIs(scrut) == STGVAR) { /* another optimisation */
382 /* No need to use return address or to Slide */
384 /* only part different from primop code... todo */
385 AsmSp beginCase = asmBeginCase(bco);
387 asmEndAlt(bco,beginCase); /* hack, hack - */
389 for(; nonNull(alts); alts=tl(alts)) {
390 StgPrimAlt alt = hd(alts);
391 List pats = stgPrimAltVars(alt);
392 StgExpr body = stgPrimAltBody(alt);
393 AsmSp altBegin = asmBeginAlt(bco);
394 map1Proc(cgBind,bco,pats);
395 testPrimPats(bco,root,pats,body);
396 asmEndAlt(bco,altBegin);
398 /* if we got this far and didn't match, panic! */
402 /* ToDo: implement this code... */
404 /* asmPushRet(bco,delayPrimAlt( stgPrimCaseVars(e),
405 stgPrimCaseBody(e))); */
406 /* cgExpr( bco,root,scrut ); */
410 case STGAPP: /* Tail call */
412 AsmSp env = asmBeginEnter(bco);
413 map1Proc(pushAtom,bco,reverse(stgAppArgs(e)));
414 pushAtom(bco,stgAppFun(e));
415 asmEndEnter(bco,env,root);
418 case NAME: /* Tail call (with no args) */
420 AsmSp env = asmBeginEnter(bco);
421 /* JRS 000112: next line used to be: pushVar(bco,name(e).stgVar); */
423 asmEndEnter(bco,env,root);
426 case STGVAR: /* Tail call (with no args), plus unboxed return */
432 AsmSp env = asmBeginEnter(bco);
434 asmEndEnter(bco,env,root);
439 /* cgTailCall(bco,singleton(e)); */
440 /* asmReturnInt(bco); */
443 internal("cgExpr StgVar");
446 case STGPRIM: /* Tail call again */
448 AsmSp beginPrim = asmBeginPrim(bco);
449 map1Proc(pushAtom,bco,reverse(stgPrimArgs(e)));
450 asmEndPrim(bco,(AsmPrim*)name(e).primop,beginPrim);
451 /* map1Proc(cgBind,bco,rs_vars); */
452 assert(0); /* asmReturn_retty(); */
456 fprintf(stderr,"\nYoiks: "); printExp(stderr,e);
461 #define M_ITBLNAMES 35000
463 void* itblNames[M_ITBLNAMES];
466 /* allocate space for top level variable
467 * any change requires a corresponding change in 'build'.
469 static Void alloc( AsmBCO bco, StgVar v )
471 StgRhs rhs = stgVarBody(v);
473 switch (whatIs(rhs)) {
476 StgDiscr con = stgConCon(rhs);
477 List args = stgConArgs(rhs);
478 if (isBoxingCon(con)) {
479 pushAtom(bco,hd(args));
480 setPos(v,asmBox(bco,boxingConRep(con)));
483 void* vv = stgConInfo(con);
484 if (!(nItblNames < (M_ITBLNAMES-2)))
485 internal("alloc -- M_ITBLNAMES too small");
487 itblNames[nItblNames++] = vv;
488 itblNames[nItblNames++] = textToStr(name(con).text);
491 itblNames[nItblNames++] = vv;
492 itblNames[nItblNames++] = textToStr(ghcTupleText(con));
494 assert ( /* cant identify constructor name */ 0 );
495 setPos(v,asmAllocCONSTR(bco, vv));
501 List bs = stgAppArgs(rhs);
502 for (; nonNull(bs); bs=tl(bs)) {
503 if (isName(hd(bs))) {
506 ASSERT(whatIs(hd(bs))==STGVAR);
507 totSizeW += asmRepSizeW( charOf(stgVarRep(hd(bs))) );
510 setPos(v,asmAllocAP(bco,totSizeW));
511 //ORIGINALLY:setPos(v,asmAllocAP(bco,length(stgAppArgs(rhs))));
514 case LAMBDA: /* optimisation */
515 setObj(v,cgLambda(rhs));
518 setPos(v,asmAllocAP(bco,0));
523 static Void build( AsmBCO bco, StgVar v )
525 StgRhs rhs = stgVarBody(v);
528 switch (whatIs(rhs)) {
531 StgDiscr con = stgConCon(rhs);
532 List args = stgConArgs(rhs);
533 if (isBoxingCon(con)) {
534 doNothing(); /* already done in alloc */
536 AsmSp start = asmBeginPack(bco);
537 map1Proc(pushAtom,bco,reverse(args));
538 asmEndPack(bco,getPos(v),start,stgConInfo(con));
545 StgVar fun = stgAppFun(rhs);
547 List args = stgAppArgs(rhs);
549 if (nonNull(name(fun).stgVar))
550 fun = name(fun).stgVar; else
551 fun = cptrFromName(fun);
555 assert(isName(fun0));
556 itsaPAP = name(fun0).arity > length(args);
557 fprintf ( stderr, "nativeCall: name %s, arity %d, args %d\n",
558 nameFromOPtr(cptrOf(fun)), name(fun0).arity, length(args) );
561 if (nonNull(stgVarBody(fun))
562 && whatIs(stgVarBody(fun)) == LAMBDA
563 && length(stgLambdaArgs(stgVarBody(fun))) > length(args)
569 AsmSp start = asmBeginMkPAP(bco);
570 map1Proc(pushAtom,bco,reverse(args));
572 asmEndMkPAP(bco,getPos(v),start); /* optimisation */
574 AsmSp start = asmBeginMkAP(bco);
575 map1Proc(pushAtom,bco,reverse(args));
577 asmEndMkAP(bco,getPos(v),start);
581 case LAMBDA: /* optimisation */
582 doNothing(); /* already pushed in alloc */
585 /* These two cases look almost identical to the default but they're really
586 * special cases of STGAPP. The essential thing here is that we can't call
587 * cgRhs(rhs) because that expects the rhs to have no free variables when,
588 * in fact, the rhs is _always_ a free variable.
590 * ToDo: a simple optimiser would eliminate all examples
591 * of this except "let x = x in ..."
594 rhs = name(rhs).stgVar;
597 AsmSp start = asmBeginMkAP(bco);
599 asmEndMkAP(bco,getPos(v),start);
604 AsmSp start = asmBeginMkAP(bco); /* make it updateable! */
605 asmClosure(bco,cgRhs(rhs));
606 asmEndMkAP(bco,getPos(v),start);
612 /* --------------------------------------------------------------------------
613 * Top level variables
615 * ToDo: these should be handled by allocating a dynamic unentered CAF
616 * for each top level variable - this should be simpler!
617 * ------------------------------------------------------------------------*/
619 #if 0 /* appears to be unused */
620 static void cgAddVar( AsmObject obj, StgAtom v )
626 asmAddPtr(obj,getObj(v));
631 /* allocate AsmObject for top level variables
632 * any change requires a corresponding change in endTop
634 static void beginTop( StgVar v )
640 switch (whatIs(rhs)) {
643 //List as = stgConArgs(rhs);
644 setObj(v,asmBeginCon(stgConInfo(stgConCon(rhs))));
648 #ifdef CRUDE_PROFILING
649 setObj(v,asmBeginBCO(currentTop));
651 setObj(v,asmBeginBCO(rhs));
655 setObj(v,asmBeginCAF());
660 static void endTop( StgVar v )
662 StgRhs rhs = stgVarBody(v);
664 switch (whatIs(rhs)) {
667 List as = stgConArgs(rhs);
668 AsmCon con = (AsmCon)getObj(v);
669 for( ; nonNull(as); as=tl(as)) {
673 /* should be a delayed combinator! */
674 asmAddPtr(con,(AsmObject)getObj(a));
678 StgVar var = name(a).stgVar;
680 asmAddPtr(con,(AsmObject)getObj(a));
683 #if !USE_ADDR_FOR_STRINGS
685 asmAddPtr(con,asmStringObj(textToStr(textOf(a))));
689 /* asmAddPtr(con,??); */
697 case LAMBDA: /* optimisation */
699 /* ToDo: merge this code with cgLambda */
700 AsmBCO bco = (AsmBCO)getObj(v);
701 AsmSp root = asmBeginArgCheck(bco);
702 map1Proc(cgBind,bco,reverse(stgLambdaArgs(rhs)));
703 asmEndArgCheck(bco,root);
705 cgExpr(bco,root,stgLambdaBody(rhs));
710 default: /* updateable caf */
712 AsmCAF caf = (AsmCAF)getObj(v);
713 asmEndCAF(caf,cgRhs(rhs));
719 static void zap( StgVar v )
722 // stgVarBody(v) = NIL;
725 /* external entry point */
726 Void cgBinds( List binds )
732 if (lastModule() != modulePrelude) {
733 printf("\n\ncgBinds: before ll\n\n" );
734 for (b=binds; nonNull(b); b=tl(b)) {
735 printStg ( stdout, hd(b) ); printf("\n\n");
740 binds = liftBinds(binds);
743 if (lastModule() != modulePrelude) {
744 printf("\n\ncgBinds: after ll\n\n" );
745 for (b=binds; nonNull(b); b=tl(b)) {
746 printStg ( stdout, hd(b) ); printf("\n\n");
751 for (b=binds,i=0; nonNull(b); b=tl(b),i++) {
755 for (b=binds,i=0; nonNull(b); b=tl(b),i++) {
756 //printStg( stdout, hd(b) ); printf( "\n\n");
760 //mapProc(zap,binds);
763 /* --------------------------------------------------------------------------
764 * Code Generator control:
765 * ------------------------------------------------------------------------*/
779 /*-------------------------------------------------------------------------*/