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/02/03 17:08:25 $
12 * ------------------------------------------------------------------------*/
19 #include "Assembler.h"
23 /* --------------------------------------------------------------------------
24 * Local function prototypes:
25 * ------------------------------------------------------------------------*/
27 #define getPos(v) intOf(stgVarInfo(v))
28 #define setPos(v,sp) stgVarInfo(v) = mkInt(sp)
29 #define getObj(v) ptrOf(stgVarInfo(v))
30 #define setObj(v,obj) stgVarInfo(v) = mkPtr(obj)
32 #define repOf(x) charOf(stgVarRep(x))
34 static void cgBind ( AsmBCO bco, StgVar v );
35 static Void pushVar ( AsmBCO bco, StgVar v );
36 static Void pushAtom ( AsmBCO bco, StgAtom atom );
37 static Void alloc ( AsmBCO bco, StgRhs rhs );
38 static Void build ( AsmBCO bco, StgRhs rhs );
39 static Void cgExpr ( AsmBCO bco, AsmSp root, StgExpr e );
41 static AsmBCO cgAlts ( AsmSp root, AsmSp sp, List alts );
42 static void testPrimPats ( AsmBCO bco, AsmSp root, List pats, StgExpr e );
43 static void cgPrimAlt ( AsmBCO bco, AsmSp root, List vs, StgExpr e );
44 static AsmBCO cgLambda ( StgExpr e );
45 static AsmBCO cgRhs ( StgRhs rhs );
46 static void beginTop ( StgVar v );
47 static void endTop ( StgVar v );
49 /* --------------------------------------------------------------------------
51 * ------------------------------------------------------------------------*/
53 static Bool varHasClosure( StgVar v )
55 return asmObjectHasClosure((AsmClosure*)ptrOf(stgVarInfo(v)));
58 /* should be AsmClosure* */
59 void* closureOfVar( StgVar v )
61 return asmClosureOfObject((AsmClosure*)ptrOf(stgVarInfo(v)));
64 char* lookupHugsName( void* closure )
68 for( nm=NAMEMIN; nm<nameHw; ++nm ) {
69 StgVar v = name(nm).stgVar;
71 && isPtr(stgVarInfo(v))
73 && closureOfVar(v) == closure) {
74 return textToStr(name(nm).text);
80 /* called at the start of GC */
81 void markHugsObjects( void )
85 for( nm=NAMEMIN; nm<nameHw; ++nm ) {
86 StgVar v = name(nm).stgVar;
87 if (isStgVar(v) && isPtr(stgVarInfo(v))) {
88 asmMarkObject((AsmClosure*)ptrOf(stgVarInfo(v)));
93 static void cgBindRep( AsmBCO bco, StgVar v, AsmRep rep )
95 setPos(v,asmBind(bco,rep));
98 static void cgBind( AsmBCO bco, StgVar v )
100 cgBindRep(bco,v,repOf(v));
103 static Void pushVar( AsmBCO bco, StgVar v )
105 Cell info = stgVarInfo(v);
108 asmClosure(bco,ptrOf(info));
109 } else if (isInt(info)) {
110 asmVar(bco,intOf(info),repOf(v));
116 static Void pushAtom( AsmBCO bco, StgAtom e )
123 pushVar(bco,name(e).stgVar);
126 asmConstChar(bco,charOf(e));
129 asmConstInt(bco,intOf(e));
131 #if BIGNUM_IS_INTEGER
133 asmConstInteger(bco,bignumToString(e));
135 #elif BIGNUM_IS_INT64
137 asmConstInt64(bco,bignumOf(e));
140 #warning What is BIGNUM?
144 asmConstFloat(bco,e); /* ToDo: support both float and double! */
146 asmConstDouble(bco,floatOf(e));
151 asmConstDouble(bco,doubleOf(e));
155 #if USE_ADDR_FOR_STRINGS
156 asmConstAddr(bco,textToStr(textOf(e)));
158 asmClosure(bco,asmStringObj(textToStr(textOf(e))));
162 asmConstAddr(bco,ptrOf(e));
165 fprintf(stderr,"\nYoiks: "); printExp(stderr,e);
166 internal("pushAtom");
170 static AsmBCO cgAlts( AsmSp root, AsmSp sp, List alts )
172 AsmBCO bco = asmBeginContinuation(sp);
173 /* ppStgAlts(alts); */
174 for(; nonNull(alts); alts=tl(alts)) {
175 StgCaseAlt alt = hd(alts);
176 StgPat pat = stgCaseAltPat(alt);
177 StgExpr body = stgCaseAltBody(alt);
178 if (isDefaultPat(pat)) {
179 AsmSp begin = asmBeginAlt(bco);
181 cgExpr(bco,root,body);
182 asmEndContinuation(bco);
183 return bco; /* ignore any further alternatives */
185 StgDiscr con = stgPatDiscr(pat);
186 List vs = stgPatVars(pat);
187 AsmSp begin = asmBeginAlt(bco);
188 AsmPc fix = asmTest(bco,stgDiscrTag(con)); /* ToDo: omit in single constructor types! */
190 if (isBoxingCon(con)) {
191 setPos(hd(vs),asmUnbox(bco,boxingConRep(con)));
194 map1Proc(cgBind,bco,rev(vs));
197 cgExpr(bco,root,body);
198 asmEndAlt(bco,begin);
199 asmFixBranch(bco,fix);
202 /* if we got this far and didn't match, panic! */
204 asmEndContinuation(bco);
208 static void testPrimPats( AsmBCO bco, AsmSp root, List pats, StgExpr e )
213 StgPrimPat pat = hd(pats);
214 if (isInt(stgVarBody(pat))) {
215 /* asmTestInt leaves stack unchanged - so no need to adjust it */
216 AsmPc tst = asmTestInt(bco,getPos(pat),intOf(stgVarBody(pat)));
217 assert(repOf(pat) == INT_REP);
218 testPrimPats(bco,root,tl(pats),e);
219 asmFixBranch(bco,tst);
221 testPrimPats(bco,root,tl(pats),e);
226 static void cgPrimAlt( AsmBCO bco, AsmSp root, List vs, StgExpr e )
228 assert(0); /* ToDo: test for patterns */
229 map1Proc(cgBind,bco,vs); /* ToDo: are these in right order? */
233 static AsmBCO cgLambda( StgExpr e )
235 AsmBCO bco = asmBeginBCO();
237 AsmSp root = asmBeginArgCheck(bco);
238 map1Proc(cgBind,bco,rev(stgLambdaArgs(e)));
239 asmEndArgCheck(bco,root);
242 cgExpr(bco,root,stgLambdaBody(e));
248 static AsmBCO cgRhs( StgRhs rhs )
250 AsmBCO bco = asmBeginBCO( );
252 AsmSp root = asmBeginArgCheck(bco);
253 asmEndArgCheck(bco,root);
255 /* ppStgExpr(rhs); */
256 cgExpr(bco,root,rhs);
262 static Void cgExpr( AsmBCO bco, AsmSp root, StgExpr e )
267 List binds = stgLetBinds(e);
268 map1Proc(alloc,bco,binds);
269 map1Proc(build,bco,binds);
270 cgExpr(bco,root,stgLetBody(e));
275 AsmSp begin = asmBeginEnter(bco);
276 asmClosure(bco,cgLambda(e));
277 asmEndEnter(bco,begin,root);
282 List alts = stgCaseAlts(e);
283 AsmSp sp = asmBeginCase(bco);
284 AsmSp caseroot = asmContinuation(bco,cgAlts(root,sp,alts));
285 cgExpr(bco,caseroot,stgCaseScrut(e));
291 StgExpr scrut = stgPrimCaseScrut(e);
292 List alts = stgPrimCaseAlts(e);
293 if (whatIs(scrut) == STGPRIM) { /* this is an optimisation */
295 /* No need to use return address or to Slide */
296 AsmSp beginPrim = asmBeginPrim(bco);
297 map1Proc(pushAtom,bco,rev(stgPrimArgs(scrut)));
298 asmEndPrim(bco,(AsmPrim*)name(stgPrimOp(scrut)).primop,beginPrim);
300 for(; nonNull(alts); alts=tl(alts)) {
301 StgPrimAlt alt = hd(alts);
302 List pats = stgPrimAltPats(alt);
303 StgExpr body = stgPrimAltBody(alt);
304 AsmSp altBegin = asmBeginAlt(bco);
305 map1Proc(cgBind,bco,rev(pats));
306 testPrimPats(bco,root,pats,body);
307 asmEndAlt(bco,altBegin);
309 /* if we got this far and didn't match, panic! */
312 } else if (whatIs(scrut) == STGVAR) { /* another optimisation */
314 /* No need to use return address or to Slide */
316 /* only part different from primop code... todo */
317 AsmSp beginCase = asmBeginCase(bco);
319 asmEndAlt(bco,beginCase); /* hack, hack - */
321 for(; nonNull(alts); alts=tl(alts)) {
322 StgPrimAlt alt = hd(alts);
323 List pats = stgPrimAltPats(alt);
324 StgExpr body = stgPrimAltBody(alt);
325 AsmSp altBegin = asmBeginAlt(bco);
326 map1Proc(cgBind,bco,pats);
327 testPrimPats(bco,root,pats,body);
328 asmEndAlt(bco,altBegin);
330 /* if we got this far and didn't match, panic! */
334 /* ToDo: implement this code... */
336 /* asmPushRet(bco,delayPrimAlt( stgPrimCaseVars(e), stgPrimCaseBody(e))); */
337 /* cgExpr( bco,root,scrut ); */
341 case STGAPP: /* Tail call */
343 AsmSp env = asmBeginEnter(bco);
344 map1Proc(pushAtom,bco,rev(stgAppArgs(e)));
345 pushAtom(bco,stgAppFun(e));
346 asmEndEnter(bco,env,root);
349 case NAME: /* Tail call (with no args) */
351 AsmSp env = asmBeginEnter(bco);
352 pushVar(bco,name(e).stgVar);
353 asmEndEnter(bco,env,root);
356 case STGVAR: /* Tail call (with no args), plus unboxed return */
362 AsmSp env = asmBeginEnter(bco);
364 asmEndEnter(bco,env,root);
369 /* cgTailCall(bco,singleton(e)); */
370 /* asmReturnInt(bco); */
373 internal("cgExpr StgVar");
376 case STGPRIM: /* Tail call again */
378 AsmSp beginPrim = asmBeginPrim(bco);
379 map1Proc(pushAtom,bco,rev(stgPrimArgs(e)));
380 asmEndPrim(bco,(AsmPrim*)name(e).primop,beginPrim);
381 /* map1Proc(cgBind,bco,rs_vars); */
382 assert(0); /* asmReturn_retty(); */
386 fprintf(stderr,"\nYoiks: "); printExp(stderr,e);
391 /* allocate space for top level variable
392 * any change requires a corresponding change in 'build'.
394 static Void alloc( AsmBCO bco, StgVar v )
396 StgRhs rhs = stgVarBody(v);
398 switch (whatIs(rhs)) {
401 StgDiscr con = stgConCon(rhs);
402 List args = stgConArgs(rhs);
403 if (isBoxingCon(con)) {
404 pushAtom(bco,hd(args));
405 setPos(v,asmBox(bco,boxingConRep(con)));
407 setPos(v,asmAllocCONSTR(bco,stgConInfo(con)));
412 setPos(v,asmAllocAP(bco,length(stgAppArgs(rhs))));
414 case LAMBDA: /* optimisation */
415 setObj(v,cgLambda(rhs));
418 setPos(v,asmAllocAP(bco,0));
423 static Void build( AsmBCO bco, StgVar v )
425 StgRhs rhs = stgVarBody(v);
427 switch (whatIs(rhs)) {
430 StgDiscr con = stgConCon(rhs);
431 List args = stgConArgs(rhs);
432 if (isBoxingCon(con)) {
433 doNothing(); /* already done in alloc */
435 AsmSp start = asmBeginPack(bco);
436 map1Proc(pushAtom,bco,rev(args));
437 asmEndPack(bco,getPos(v),start,stgConInfo(con));
443 StgVar fun = stgAppFun(rhs);
444 List args = stgAppArgs(rhs);
446 fun = name(fun).stgVar;
448 if (nonNull(stgVarBody(fun))
449 && whatIs(stgVarBody(fun)) == LAMBDA
450 && length(stgLambdaArgs(stgVarBody(fun))) > length(args)) {
451 AsmSp start = asmBeginMkPAP(bco);
452 map1Proc(pushAtom,bco,rev(args));
454 asmEndMkPAP(bco,getPos(v),start); /* optimisation */
456 AsmSp start = asmBeginMkAP(bco);
457 map1Proc(pushAtom,bco,rev(args));
459 asmEndMkAP(bco,getPos(v),start);
463 case LAMBDA: /* optimisation */
464 doNothing(); /* already pushed in alloc */
467 /* These two cases look almost identical to the default but they're really
468 * special cases of STGAPP. The essential thing here is that we can't call
469 * cgRhs(rhs) because that expects the rhs to have no free variables when,
470 * in fact, the rhs is _always_ a free variable.
472 * ToDo: a simple optimiser would eliminate all examples
473 * of this except "let x = x in ..."
476 rhs = name(rhs).stgVar;
479 AsmSp start = asmBeginMkAP(bco);
481 asmEndMkAP(bco,getPos(v),start);
486 AsmSp start = asmBeginMkAP(bco); /* make it updateable! */
487 asmClosure(bco,cgRhs(rhs));
488 asmEndMkAP(bco,getPos(v),start);
494 /* --------------------------------------------------------------------------
495 * Top level variables
497 * ToDo: these should be handled by allocating a dynamic unentered CAF
498 * for each top level variable - this should be simpler!
499 * ------------------------------------------------------------------------*/
501 static void cgAddVar( AsmObject obj, StgAtom v )
507 asmAddPtr(obj,getObj(v));
510 /* allocate AsmObject for top level variables
511 * any change requires a corresponding change in endTop
513 static void beginTop( StgVar v )
518 switch (whatIs(rhs)) {
521 List as = stgConArgs(rhs);
522 setObj(v,asmBeginCon(stgConInfo(stgConCon(rhs))));
526 setObj(v,asmBeginBCO());
529 setObj(v,asmBeginCAF());
534 static void endTop( StgVar v )
536 StgRhs rhs = stgVarBody(v);
538 switch (whatIs(rhs)) {
541 List as = stgConArgs(rhs);
542 AsmCon con = (AsmCon)getObj(v);
543 for( ; nonNull(as); as=tl(as)) {
547 /* should be a delayed combinator! */
548 asmAddPtr(con,(AsmObject)getObj(a));
552 StgVar var = name(a).stgVar;
554 asmAddPtr(con,(AsmObject)getObj(a));
557 #if !USE_ADDR_FOR_STRINGS
559 asmAddPtr(con,asmStringObj(textToStr(textOf(a))));
563 /* asmAddPtr(con,??); */
571 case LAMBDA: /* optimisation */
573 /* ToDo: merge this code with cgLambda */
574 AsmBCO bco = (AsmBCO)getObj(v);
575 AsmSp root = asmBeginArgCheck(bco);
576 map1Proc(cgBind,bco,rev(stgLambdaArgs(rhs)));
577 asmEndArgCheck(bco,root);
579 cgExpr(bco,root,stgLambdaBody(rhs));
584 default: /* updateable caf */
586 AsmCAF caf = (AsmCAF)getObj(v);
587 asmEndCAF(caf,cgRhs(rhs));
593 static void zap( StgVar v )
598 /* external entry point */
599 Void cgBinds( List binds )
601 binds = liftBinds(binds);
602 mapProc(beginTop,binds);
603 mapProc(endTop,binds);
607 /* --------------------------------------------------------------------------
608 * Code Generator control:
609 * ------------------------------------------------------------------------*/
615 /* deliberate fall though */
624 /*-------------------------------------------------------------------------*/