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: 1999/10/15 21:41:02 $
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",
66 textToStr(mt), textToStr(name(n).text) );
67 p = lookupOTabName ( m, buf );
69 ERRMSG(0) "Can't find object symbol %s", buf
75 static Bool varHasClosure( StgVar v )
77 return asmObjectHasClosure((AsmClosure*)ptrOf(stgVarInfo(v)));
80 /* should be AsmClosure* */
81 void* closureOfVar( StgVar v )
83 return asmClosureOfObject((AsmClosure*)ptrOf(stgVarInfo(v)));
86 char* lookupHugsName( void* closure )
90 for( nm=NAMEMIN; nm<nameHw; ++nm ) {
91 StgVar v = name(nm).stgVar;
93 && isPtr(stgVarInfo(v))
95 && closureOfVar(v) == closure) {
96 return textToStr(name(nm).text);
102 /* called at the start of GC */
103 void markHugsObjects( void )
107 for( nm=NAMEMIN; nm<nameHw; ++nm ) {
108 StgVar v = name(nm).stgVar;
109 if (isStgVar(v) && isPtr(stgVarInfo(v))) {
110 asmMarkObject((AsmClosure*)ptrOf(stgVarInfo(v)));
115 static void cgBindRep( AsmBCO bco, StgVar v, AsmRep rep )
117 setPos(v,asmBind(bco,rep));
120 static void cgBind( AsmBCO bco, StgVar v )
122 cgBindRep(bco,v,repOf(v));
125 static Void pushVar( AsmBCO bco, StgVar v )
129 if (!(isStgVar(v) || isCPtr(v))) {
130 assert(isStgVar(v) || isCPtr(v));
134 asmGHCClosure(bco, cptrOf(v));
136 info = stgVarInfo(v);
138 asmClosure(bco,ptrOf(info));
139 } else if (isInt(info)) {
140 asmVar(bco,intOf(info),repOf(v));
147 static Void pushAtom( AsmBCO bco, StgAtom e )
154 if (nonNull(name(e).stgVar))
155 pushVar(bco,name(e).stgVar); else
156 pushVar(bco,cptrFromName(e));
159 asmConstChar(bco,charOf(e));
162 asmConstInt(bco,intOf(e));
165 asmConstInteger(bco,bignumToString(e));
169 asmConstFloat(bco,e); /* ToDo: support both float and double! */
171 asmConstDouble(bco,floatOf(e));
176 asmConstDouble(bco,doubleOf(e));
180 #if USE_ADDR_FOR_STRINGS
181 asmConstAddr(bco,textToStr(textOf(e)));
183 asmClosure(bco,asmStringObj(textToStr(textOf(e))));
187 asmGHCClosure(bco,cptrOf(e));
190 asmConstAddr(bco,ptrOf(e));
193 fprintf(stderr,"\nYoiks: "); printExp(stderr,e);
194 internal("pushAtom");
198 static AsmBCO cgAlts( AsmSp root, AsmSp sp, List alts )
200 #ifdef CRUDE_PROFILING
201 AsmBCO bco = asmBeginContinuation(sp, currentTop + 1000000000);
203 AsmBCO bco = asmBeginContinuation(sp, alts);
205 /* ppStgAlts(alts); */
206 for(; nonNull(alts); alts=tl(alts)) {
207 StgCaseAlt alt = hd(alts);
208 if (isDefaultAlt(alt)) {
209 cgBind(bco,stgDefaultVar(alt));
210 cgExpr(bco,root,stgDefaultBody(alt));
211 asmEndContinuation(bco);
212 return bco; /* ignore any further alternatives */
214 StgDiscr con = stgCaseAltCon(alt);
215 List vs = stgCaseAltVars(alt);
216 AsmSp begin = asmBeginAlt(bco);
217 AsmPc fix = asmTest(bco,stgDiscrTag(con));
218 /* ToDo: omit in single constructor types! */
219 asmBind(bco,PTR_REP); /* Adjust simulated sp to acct for return value */
220 if (isBoxingCon(con)) {
221 setPos(hd(vs),asmUnbox(bco,boxingConRep(con)));
224 map1Proc(cgBind,bco,reverse(vs));
227 cgExpr(bco,root,stgCaseAltBody(alt));
228 asmEndAlt(bco,begin);
229 asmFixBranch(bco,fix);
232 /* if we got this far and didn't match, panic! */
234 asmEndContinuation(bco);
238 static void testPrimPats( AsmBCO bco, AsmSp root, List pats, StgExpr e )
243 StgVar pat = hd(pats);
244 if (isInt(stgVarBody(pat))) {
245 /* asmTestInt leaves stack unchanged - so no need to adjust it */
246 AsmPc tst = asmTestInt(bco,getPos(pat),intOf(stgVarBody(pat)));
247 assert(repOf(pat) == INT_REP);
248 testPrimPats(bco,root,tl(pats),e);
249 asmFixBranch(bco,tst);
251 testPrimPats(bco,root,tl(pats),e);
256 #if 0 /* appears to be unused */
257 static void cgPrimAlt( AsmBCO bco, AsmSp root, List vs, StgExpr e )
259 assert(0); /* ToDo: test for patterns */
260 map1Proc(cgBind,bco,vs); /* ToDo: are these in right order? */
266 static AsmBCO cgLambda( StgExpr e )
268 AsmBCO bco = asmBeginBCO(e);
270 AsmSp root = asmBeginArgCheck(bco);
271 map1Proc(cgBind,bco,reverse(stgLambdaArgs(e)));
272 asmEndArgCheck(bco,root);
275 cgExpr(bco,root,stgLambdaBody(e));
281 static AsmBCO cgRhs( StgRhs rhs )
283 AsmBCO bco = asmBeginBCO(rhs );
285 AsmSp root = asmBeginArgCheck(bco);
286 asmEndArgCheck(bco,root);
288 /* ppStgExpr(rhs); */
289 cgExpr(bco,root,rhs);
296 static Void cgExpr( AsmBCO bco, AsmSp root, StgExpr e )
298 //printf("cgExpr:");ppStgExpr(e);printf("\n");
302 List binds = stgLetBinds(e);
303 map1Proc(alloc,bco,binds);
304 map1Proc(build,bco,binds);
305 cgExpr(bco,root,stgLetBody(e));
310 AsmSp begin = asmBeginEnter(bco);
311 asmClosure(bco,cgLambda(e));
312 asmEndEnter(bco,begin,root);
317 List alts = stgCaseAlts(e);
318 AsmSp sp = asmBeginCase(bco);
319 AsmSp caseroot = asmContinuation(bco,cgAlts(root,sp,alts));
320 cgExpr(bco,caseroot,stgCaseScrut(e));
326 StgExpr scrut = stgPrimCaseScrut(e);
327 List alts = stgPrimCaseAlts(e);
328 if (whatIs(scrut) == STGPRIM) { /* this is an optimisation */
330 /* No need to use return address or to Slide */
331 AsmSp beginPrim = asmBeginPrim(bco);
332 map1Proc(pushAtom,bco,reverse(stgPrimArgs(scrut)));
333 asmEndPrim(bco,(AsmPrim*)name(stgPrimOp(scrut)).primop,beginPrim);
335 for(; nonNull(alts); alts=tl(alts)) {
336 StgPrimAlt alt = hd(alts);
337 List pats = stgPrimAltVars(alt);
338 StgExpr body = stgPrimAltBody(alt);
339 AsmSp altBegin = asmBeginAlt(bco);
340 map1Proc(cgBind,bco,reverse(pats));
341 testPrimPats(bco,root,pats,body);
342 asmEndAlt(bco,altBegin);
344 /* if we got this far and didn't match, panic! */
347 } else if (whatIs(scrut) == STGVAR) { /* another optimisation */
349 /* No need to use return address or to Slide */
351 /* only part different from primop code... todo */
352 AsmSp beginCase = asmBeginCase(bco);
354 asmEndAlt(bco,beginCase); /* hack, hack - */
356 for(; nonNull(alts); alts=tl(alts)) {
357 StgPrimAlt alt = hd(alts);
358 List pats = stgPrimAltVars(alt);
359 StgExpr body = stgPrimAltBody(alt);
360 AsmSp altBegin = asmBeginAlt(bco);
361 map1Proc(cgBind,bco,pats);
362 testPrimPats(bco,root,pats,body);
363 asmEndAlt(bco,altBegin);
365 /* if we got this far and didn't match, panic! */
369 /* ToDo: implement this code... */
371 /* asmPushRet(bco,delayPrimAlt( stgPrimCaseVars(e), stgPrimCaseBody(e))); */
372 /* cgExpr( bco,root,scrut ); */
376 case STGAPP: /* Tail call */
378 AsmSp env = asmBeginEnter(bco);
379 map1Proc(pushAtom,bco,reverse(stgAppArgs(e)));
380 pushAtom(bco,stgAppFun(e));
381 asmEndEnter(bco,env,root);
384 case NAME: /* Tail call (with no args) */
386 AsmSp env = asmBeginEnter(bco);
387 pushVar(bco,name(e).stgVar);
388 asmEndEnter(bco,env,root);
391 case STGVAR: /* Tail call (with no args), plus unboxed return */
397 AsmSp env = asmBeginEnter(bco);
399 asmEndEnter(bco,env,root);
404 /* cgTailCall(bco,singleton(e)); */
405 /* asmReturnInt(bco); */
408 internal("cgExpr StgVar");
411 case STGPRIM: /* Tail call again */
413 AsmSp beginPrim = asmBeginPrim(bco);
414 map1Proc(pushAtom,bco,reverse(stgPrimArgs(e)));
415 asmEndPrim(bco,(AsmPrim*)name(e).primop,beginPrim);
416 /* map1Proc(cgBind,bco,rs_vars); */
417 assert(0); /* asmReturn_retty(); */
421 fprintf(stderr,"\nYoiks: "); printExp(stderr,e);
426 #define M_ITBLNAMES 35000
428 void* itblNames[M_ITBLNAMES];
431 /* allocate space for top level variable
432 * any change requires a corresponding change in 'build'.
434 static Void alloc( AsmBCO bco, StgVar v )
436 StgRhs rhs = stgVarBody(v);
438 switch (whatIs(rhs)) {
441 StgDiscr con = stgConCon(rhs);
442 List args = stgConArgs(rhs);
443 if (isBoxingCon(con)) {
444 pushAtom(bco,hd(args));
445 setPos(v,asmBox(bco,boxingConRep(con)));
448 void* vv = stgConInfo(con);
449 if (!(nItblNames < (M_ITBLNAMES-2)))
450 internal("alloc -- M_ITBLNAMES too small");
452 itblNames[nItblNames++] = vv;
453 itblNames[nItblNames++] = textToStr(name(con).text);
456 char* cc = malloc(10);
458 sprintf(cc, "Tuple%d", tupleOf(con) );
459 itblNames[nItblNames++] = vv;
460 itblNames[nItblNames++] = cc;
462 assert ( /* cant identify constructor name */ 0 );
464 setPos(v,asmAllocCONSTR(bco, vv));
470 List bs = stgAppArgs(rhs);
471 for (; nonNull(bs); bs=tl(bs)) {
472 if (isName(hd(bs))) {
475 ASSERT(whatIs(hd(bs))==STGVAR);
476 totSizeW += asmRepSizeW( charOf(stgVarRep(hd(bs))) );
479 setPos(v,asmAllocAP(bco,totSizeW));
480 //ORIGINALLY:setPos(v,asmAllocAP(bco,length(stgAppArgs(rhs))));
483 case LAMBDA: /* optimisation */
484 setObj(v,cgLambda(rhs));
487 setPos(v,asmAllocAP(bco,0));
492 static Void build( AsmBCO bco, StgVar v )
494 StgRhs rhs = stgVarBody(v);
497 switch (whatIs(rhs)) {
500 StgDiscr con = stgConCon(rhs);
501 List args = stgConArgs(rhs);
502 if (isBoxingCon(con)) {
503 doNothing(); /* already done in alloc */
505 AsmSp start = asmBeginPack(bco);
506 map1Proc(pushAtom,bco,reverse(args));
507 asmEndPack(bco,getPos(v),start,stgConInfo(con));
514 StgVar fun = stgAppFun(rhs);
516 List args = stgAppArgs(rhs);
518 if (nonNull(name(fun).stgVar))
519 fun = name(fun).stgVar; else
520 fun = cptrFromName(fun);
524 assert(isName(fun0));
525 itsaPAP = name(fun0).arity > length(args);
526 fprintf ( stderr, "nativeCall: name %s, arity %d, args %d\n",
527 nameFromOPtr(cptrOf(fun)), name(fun0).arity, length(args) );
530 if (nonNull(stgVarBody(fun))
531 && whatIs(stgVarBody(fun)) == LAMBDA
532 && length(stgLambdaArgs(stgVarBody(fun))) > length(args)
538 AsmSp start = asmBeginMkPAP(bco);
539 map1Proc(pushAtom,bco,reverse(args));
541 asmEndMkPAP(bco,getPos(v),start); /* optimisation */
543 AsmSp start = asmBeginMkAP(bco);
544 map1Proc(pushAtom,bco,reverse(args));
546 asmEndMkAP(bco,getPos(v),start);
550 case LAMBDA: /* optimisation */
551 doNothing(); /* already pushed in alloc */
554 /* These two cases look almost identical to the default but they're really
555 * special cases of STGAPP. The essential thing here is that we can't call
556 * cgRhs(rhs) because that expects the rhs to have no free variables when,
557 * in fact, the rhs is _always_ a free variable.
559 * ToDo: a simple optimiser would eliminate all examples
560 * of this except "let x = x in ..."
563 rhs = name(rhs).stgVar;
566 AsmSp start = asmBeginMkAP(bco);
568 asmEndMkAP(bco,getPos(v),start);
573 AsmSp start = asmBeginMkAP(bco); /* make it updateable! */
574 asmClosure(bco,cgRhs(rhs));
575 asmEndMkAP(bco,getPos(v),start);
581 /* --------------------------------------------------------------------------
582 * Top level variables
584 * ToDo: these should be handled by allocating a dynamic unentered CAF
585 * for each top level variable - this should be simpler!
586 * ------------------------------------------------------------------------*/
588 #if 0 /* appears to be unused */
589 static void cgAddVar( AsmObject obj, StgAtom v )
595 asmAddPtr(obj,getObj(v));
600 /* allocate AsmObject for top level variables
601 * any change requires a corresponding change in endTop
603 static void beginTop( StgVar v )
609 switch (whatIs(rhs)) {
612 //List as = stgConArgs(rhs);
613 setObj(v,asmBeginCon(stgConInfo(stgConCon(rhs))));
617 #ifdef CRUDE_PROFILING
618 setObj(v,asmBeginBCO(currentTop));
620 setObj(v,asmBeginBCO(rhs));
624 setObj(v,asmBeginCAF());
629 static void endTop( StgVar v )
631 StgRhs rhs = stgVarBody(v);
633 switch (whatIs(rhs)) {
636 List as = stgConArgs(rhs);
637 AsmCon con = (AsmCon)getObj(v);
638 for( ; nonNull(as); as=tl(as)) {
642 /* should be a delayed combinator! */
643 asmAddPtr(con,(AsmObject)getObj(a));
647 StgVar var = name(a).stgVar;
649 asmAddPtr(con,(AsmObject)getObj(a));
652 #if !USE_ADDR_FOR_STRINGS
654 asmAddPtr(con,asmStringObj(textToStr(textOf(a))));
658 /* asmAddPtr(con,??); */
666 case LAMBDA: /* optimisation */
668 /* ToDo: merge this code with cgLambda */
669 AsmBCO bco = (AsmBCO)getObj(v);
670 AsmSp root = asmBeginArgCheck(bco);
671 map1Proc(cgBind,bco,reverse(stgLambdaArgs(rhs)));
672 asmEndArgCheck(bco,root);
674 cgExpr(bco,root,stgLambdaBody(rhs));
679 default: /* updateable caf */
681 AsmCAF caf = (AsmCAF)getObj(v);
682 asmEndCAF(caf,cgRhs(rhs));
688 static void zap( StgVar v )
691 // stgVarBody(v) = NIL;
694 /* external entry point */
695 Void cgBinds( List binds )
701 if (lastModule() != modulePrelude) {
702 printf("\n\ncgBinds: before ll\n\n" );
703 for (b=binds; nonNull(b); b=tl(b)) {
704 printStg ( stdout, hd(b) ); printf("\n\n");
709 binds = liftBinds(binds);
712 if (lastModule() != modulePrelude) {
713 printf("\n\ncgBinds: after ll\n\n" );
714 for (b=binds; nonNull(b); b=tl(b)) {
715 printStg ( stdout, hd(b) ); printf("\n\n");
720 for (b=binds,i=0; nonNull(b); b=tl(b),i++) {
724 for (b=binds,i=0; nonNull(b); b=tl(b),i++) {
725 //printf("endTop %s\n", maybeName(hd(b)));
729 //mapProc(zap,binds);
732 /* --------------------------------------------------------------------------
733 * Code Generator control:
734 * ------------------------------------------------------------------------*/
740 /* deliberate fall though */
749 /*-------------------------------------------------------------------------*/