[project @ 2000-04-12 09:37:19 by sewardj]
[ghc-hetmet.git] / ghc / interpreter / codegen.c
index 2b87d57..ef12398 100644 (file)
@@ -2,26 +2,28 @@
 /* --------------------------------------------------------------------------
  * Code generator
  *
- * Copyright (c) The University of Nottingham and Yale University, 1994-1997.
- * All rights reserved. See NOTICE for details and conditions of use etc...
- * Hugs version 1.4, December 1997
+ * The Hugs 98 system is Copyright (c) Mark P Jones, Alastair Reid, the
+ * Yale Haskell Group, and the Oregon Graduate Institute of Science and
+ * Technology, 1994-1999, All rights reserved.  It is distributed as
+ * free software under the license in the file "License", which is
+ * included in the distribution.
  *
  * $RCSfile: codegen.c,v $
- * $Revision: 1.8 $
- * $Date: 1999/07/06 15:24:36 $
+ * $Revision: 1.22 $
+ * $Date: 2000/04/12 09:37:19 $
  * ------------------------------------------------------------------------*/
 
-#include "prelude.h"
+#include "hugsbasictypes.h"
 #include "storage.h"
-#include "backend.h"
 #include "connect.h"
 #include "errors.h"
-#include "Assembler.h"
-#include "link.h"
 
+#include "Assembler.h"
 #include "Rts.h"    /* IF_DEBUG */
 #include "RtsFlags.h"
 
+/*#define DEBUG_CODEGEN*/
+
 /* --------------------------------------------------------------------------
  * Local function prototypes:
  * ------------------------------------------------------------------------*/
@@ -42,7 +44,6 @@ static Void  cgExpr        ( AsmBCO bco, AsmSp root, StgExpr e );
              
 static AsmBCO cgAlts       ( AsmSp root, AsmSp sp, List alts );
 static void   testPrimPats ( AsmBCO bco, AsmSp root, List pats, StgExpr e );
-//static void   cgPrimAlt    ( AsmBCO bco, AsmSp root, List vs, StgExpr e );
 static AsmBCO cgLambda     ( StgExpr e );
 static AsmBCO cgRhs        ( StgRhs rhs );
 static void   beginTop     ( StgVar v );
@@ -60,8 +61,10 @@ static Cell cptrFromName ( Name n )
    void* p;
    Module m = name(n).mod;
    Text  mt = module(m).text;
-   sprintf(buf,"%s_%s_closure", 
-               textToStr(mt), textToStr(name(n).text) );
+   sprintf(buf, MAYBE_LEADING_UNDERSCORE_STR("%s_%s_closure"), 
+                textToStr(mt), 
+                textToStr( enZcodeThenFindText ( 
+                   textToStr (name(n).text) ) ) );
    p = lookupOTabName ( m, buf );
    if (!p) {
       ERRMSG(0) "Can't find object symbol %s", buf
@@ -85,31 +88,20 @@ char* lookupHugsName( void* closure )
 {
     extern Name nameHw;
     Name nm;
-    for( nm=NAMEMIN; nm<nameHw; ++nm ) {
-        StgVar v  = name(nm).stgVar;
-        if (isStgVar(v) 
-            && isPtr(stgVarInfo(v)) 
-            && varHasClosure(v)
-            && closureOfVar(v) == closure) {
-            return textToStr(name(nm).text);
-        }
+    for( nm = NAME_BASE_ADDR; 
+         nm < NAME_BASE_ADDR+tabNameSz; ++nm ) 
+       if (tabName[nm-NAME_BASE_ADDR].inUse) {
+           StgVar v  = name(nm).stgVar;
+           if (isStgVar(v) 
+               && isPtr(stgVarInfo(v)) 
+               && varHasClosure(v)
+               && closureOfVar(v) == closure) {
+               return textToStr(name(nm).text);
+           }
     }
     return 0;
 }
 
-/* called at the start of GC */
-void markHugsObjects( void )
-{
-    extern Name nameHw;
-    Name nm;
-    for( nm=NAMEMIN; nm<nameHw; ++nm ) {
-        StgVar v  = name(nm).stgVar;
-        if (isStgVar(v) && isPtr(stgVarInfo(v))) {
-            asmMarkObject((AsmClosure*)ptrOf(stgVarInfo(v)));
-        }
-    }
-}
-
 static void cgBindRep( AsmBCO bco, StgVar v, AsmRep rep )
 {
     setPos(v,asmBind(bco,rep));
@@ -123,10 +115,11 @@ static void cgBind( AsmBCO bco, StgVar v )
 static Void pushVar( AsmBCO bco, StgVar v )
 {
     Cell info;
-
-    if (!(isStgVar(v) || isCPtr(v))) {
+#if 0
+printf ( "pushVar:  %d  ", v ); fflush(stdout);
+print(v,10);printf("\n");
+#endif
     assert(isStgVar(v) || isCPtr(v));
-    }
 
     if (isCPtr(v)) {
        asmGHCClosure(bco, cptrOf(v));
@@ -144,14 +137,25 @@ static Void pushVar( AsmBCO bco, StgVar v )
 
 static Void pushAtom( AsmBCO bco, StgAtom e )
 {
+#if 0
+printf ( "pushAtom: %d  ", e ); fflush(stdout);
+print(e,10);printf("\n");
+#endif
     switch (whatIs(e)) {
     case STGVAR: 
             pushVar(bco,e);
             break;
     case NAME: 
-            if (nonNull(name(e).stgVar))
-               pushVar(bco,name(e).stgVar); else
-               pushVar(bco,cptrFromName(e));
+            if (nonNull(name(e).stgVar)) {
+              pushVar(bco,name(e).stgVar);
+            } else {
+               Cell /*CPtr*/ addr = cptrFromName(e);
+#              if DEBUG_CODEGEN
+               fprintf ( stderr, "nativeAtom: name %s\n", 
+                                 nameFromOPtr(cptrOf(addr)) );
+#              endif
+              pushVar(bco,addr);
+            }
             break;
     case CHARCELL: 
             asmConstChar(bco,charOf(e));
@@ -163,17 +167,8 @@ static Void pushAtom( AsmBCO bco, StgAtom e )
             asmConstInteger(bco,bignumToString(e)); 
             break;
     case FLOATCELL: 
-#if 0
-            asmConstFloat(bco,e); /* ToDo: support both float and double! */
-#else
             asmConstDouble(bco,floatOf(e));
-#endif
-            break;
-#if DOUBLES
-    case DOUBLECELL: 
-            asmConstDouble(bco,doubleOf(e));
             break;
-#endif
     case STRCELL: 
 #if USE_ADDR_FOR_STRINGS
             asmConstAddr(bco,textToStr(textOf(e)));
@@ -188,7 +183,7 @@ static Void pushAtom( AsmBCO bco, StgAtom e )
             asmConstAddr(bco,ptrOf(e));
             break;
     default: 
-            fprintf(stderr,"\nYoiks: "); printExp(stderr,e);
+            fprintf(stderr,"\nYoiks1: "); printExp(stderr,e);
             internal("pushAtom");
     }
 }
@@ -200,7 +195,36 @@ static AsmBCO cgAlts( AsmSp root, AsmSp sp, List alts )
 #else
     AsmBCO bco = asmBeginContinuation(sp, alts);
 #endif
-    /* ppStgAlts(alts); */
+    Bool omit_test
+       = length(alts) == 2 &&
+         isDefaultAlt(hd(tl(alts))) &&
+         !isDefaultAlt(hd(alts));
+    if (omit_test) {
+       /* refine the condition */              
+       Name con;
+       Tycon t;
+       omit_test = FALSE;
+       con = stgCaseAltCon(hd(alts));
+
+       /* special case: dictionary constructors */
+       if (isName(con) && strncmp(":D",textToStr(name(con).text),2)==0) {
+          omit_test = TRUE;
+          goto xyzzy;
+       }
+       /* special case: Tuples */
+       if (isTuple(con) || (isName(con) && con==nameUnit)) {
+          omit_test = TRUE;
+          goto xyzzy;
+       }          
+
+       t = name(con).parent;
+       if (tycon(t).what == DATATYPE) {
+          if (length(tycon(t).defn) == 1) omit_test = TRUE;
+       }
+    }
+
+    xyzzy:
+
     for(; nonNull(alts); alts=tl(alts)) {
         StgCaseAlt alt  = hd(alts);
         if (isDefaultAlt(alt)) {
@@ -212,8 +236,9 @@ static AsmBCO cgAlts( AsmSp root, AsmSp sp, List alts )
             StgDiscr con   = stgCaseAltCon(alt);
             List     vs    = stgCaseAltVars(alt);
             AsmSp    begin = asmBeginAlt(bco);
-            AsmPc    fix   = asmTest(bco,stgDiscrTag(con)); 
-                     /* ToDo: omit in single constructor types! */
+            AsmPc    fix;
+            if (omit_test) fix=-1; else fix = asmTest(bco,stgDiscrTag(con)); 
+
            asmBind(bco,PTR_REP); /* Adjust simulated sp to acct for return value */
             if (isBoxingCon(con)) {
                 setPos(hd(vs),asmUnbox(bco,boxingConRep(con)));
@@ -224,7 +249,7 @@ static AsmBCO cgAlts( AsmSp root, AsmSp sp, List alts )
             }
             cgExpr(bco,root,stgCaseAltBody(alt));
             asmEndAlt(bco,begin);
-            asmFixBranch(bco,fix);
+            if (fix != -1) asmFixBranch(bco,fix);
         }
     }
     /* if we got this far and didn't match, panic! */
@@ -251,15 +276,6 @@ static void testPrimPats( AsmBCO bco, AsmSp root, List pats, StgExpr e )
     }
 }
 
-#if 0  /* appears to be unused */
-static void cgPrimAlt( AsmBCO bco, AsmSp root, List vs, StgExpr e )
-{
-    assert(0); /* ToDo: test for patterns */
-    map1Proc(cgBind,bco,vs); /* ToDo: are these in right order? */
-    cgExpr(bco,root,e);
-}
-#endif
-
 
 static AsmBCO cgLambda( StgExpr e )
 {
@@ -293,7 +309,9 @@ static AsmBCO cgRhs( StgRhs rhs )
 
 static Void cgExpr( AsmBCO bco, AsmSp root, StgExpr e )
 {
-  //printf("cgExpr:");ppStgExpr(e);printf("\n");
+#if 0
+    printf("cgExpr:");ppStgExpr(e);printf("\n");
+#endif
     switch (whatIs(e)) {
     case LETREC:
         {
@@ -366,7 +384,8 @@ static Void cgExpr( AsmBCO bco, AsmSp root, StgExpr e )
             } else {
                 /* ToDo: implement this code...  */
                 assert(0);
-                /* asmPushRet(bco,delayPrimAlt( stgPrimCaseVars(e), stgPrimCaseBody(e))); */
+                /* asmPushRet(bco,delayPrimAlt( stgPrimCaseVars(e), 
+                                                stgPrimCaseBody(e))); */
                 /* cgExpr( bco,root,scrut ); */
             }
             break;
@@ -382,7 +401,8 @@ static Void cgExpr( AsmBCO bco, AsmSp root, StgExpr e )
     case NAME: /* Tail call (with no args) */
         {
             AsmSp env = asmBeginEnter(bco);
-            pushVar(bco,name(e).stgVar);
+            /* JRS 000112: next line used to be: pushVar(bco,name(e).stgVar); */
+            pushAtom(bco,e);
             asmEndEnter(bco,env,root);
             break;
         }
@@ -416,16 +436,11 @@ static Void cgExpr( AsmBCO bco, AsmSp root, StgExpr e )
             break;
         }
     default:
-            fprintf(stderr,"\nYoiks: "); printExp(stderr,e);
+            fprintf(stderr,"\nYoiks2: "); printExp(stderr,e);
             internal("cgExpr");
     }
 }
 
-#define M_ITBLNAMES 35000
-
-void* itblNames[M_ITBLNAMES];
-int   nItblNames = 0;
-
 /* allocate space for top level variable
  * any change requires a corresponding change in 'build'.
  */
@@ -433,6 +448,9 @@ static Void alloc( AsmBCO bco, StgVar v )
 {
     StgRhs rhs = stgVarBody(v);
     assert(isStgVar(v));
+#if 0
+    printf("alloc: ");ppStgExpr(v);
+#endif
     switch (whatIs(rhs)) {
     case STGCON:
         {
@@ -442,24 +460,7 @@ static Void alloc( AsmBCO bco, StgVar v )
                 pushAtom(bco,hd(args));
                 setPos(v,asmBox(bco,boxingConRep(con)));
             } else {
-
-                void* vv = stgConInfo(con);
-                if (!(nItblNames < (M_ITBLNAMES-2))) 
-                   internal("alloc -- M_ITBLNAMES too small");
-                if (isName(con)) {
-                   itblNames[nItblNames++] = vv;
-                   itblNames[nItblNames++] = textToStr(name(con).text);
-                } else
-                if (isTuple(con)) {
-                   char* cc = malloc(10);
-                   assert(cc);
-                   sprintf(cc, "Tuple%d", tupleOf(con) );
-                   itblNames[nItblNames++] = vv;
-                   itblNames[nItblNames++] = cc;
-                } else
-                assert ( /* cant identify constructor name */ 0 );
-
-                setPos(v,asmAllocCONSTR(bco, vv));
+                setPos(v,asmAllocCONSTR(bco,stgConInfo(con)));
             }
             break;
         }
@@ -475,7 +476,6 @@ static Void alloc( AsmBCO bco, StgVar v )
                }
             }
             setPos(v,asmAllocAP(bco,totSizeW));
-            //ORIGINALLY:setPos(v,asmAllocAP(bco,length(stgAppArgs(rhs))));
             break;
          }
     case LAMBDA: /* optimisation */
@@ -491,7 +491,7 @@ static Void build( AsmBCO bco, StgVar v )
 {
     StgRhs rhs = stgVarBody(v);
     assert(isStgVar(v));
-
+    //ppStg(v);
     switch (whatIs(rhs)) {
     case STGCON:
         {
@@ -521,8 +521,11 @@ static Void build( AsmBCO bco, StgVar v )
             if (isCPtr(fun)) {
                assert(isName(fun0));
                itsaPAP = name(fun0).arity > length(args);
-fprintf ( stderr, "nativeCall: name %s, arity %d, args %d\n",
-               nameFromOPtr(cptrOf(fun)), name(fun0).arity, length(args) );
+#              if DEBUG_CODEGEN
+               fprintf ( stderr, "nativeCall: name %s, arity %d, args %d\n",
+                         nameFromOPtr(cptrOf(fun)), name(fun0).arity,
+                         length(args) );
+#              endif
             } else {
                itsaPAP = FALSE;
                if (nonNull(stgVarBody(fun))
@@ -558,7 +561,10 @@ fprintf ( stderr, "nativeCall: name %s, arity %d, args %d\n",
      * of this except "let x = x in ..."
      */
     case NAME:
-            rhs = name(rhs).stgVar;
+        if (nonNull(name(rhs).stgVar))
+           rhs = name(rhs).stgVar; else
+           rhs = cptrFromName(rhs);
+        /* fall thru */
     case STGVAR:
         {
             AsmSp  start = asmBeginMkAP(bco);
@@ -716,15 +722,33 @@ Void cgBinds( List binds )
 #endif
 
     for (b=binds,i=0; nonNull(b); b=tl(b),i++) {
+       /* printStg( stdout, hd(b) ); printf( "\n\n"); */
        beginTop(hd(b));
     }
 
     for (b=binds,i=0; nonNull(b); b=tl(b),i++) {
-      //printf("endTop %s\n", maybeName(hd(b)));
+       /* printStg( stdout, hd(b) ); printf( "\n\n"); */
        endTop(hd(b));
     }
 
-    //mapProc(zap,binds);
+    /* mapProc(zap,binds); */
+}
+
+/* Called by the evaluator's GC to tell Hugs to mark stuff in the
+   run-time heap.
+*/
+void markHugsObjects( void )
+{
+    extern Name nameHw;
+    Name nm;
+    for ( nm = NAME_BASE_ADDR; 
+          nm < NAME_BASE_ADDR+tabNameSz; ++nm )
+       if (tabName[nm-NAME_BASE_ADDR].inUse) {
+           StgVar v  = name(nm).stgVar;
+           if (isStgVar(v) && isPtr(stgVarInfo(v))) {
+               asmMarkObject(ptrOf(stgVarInfo(v)));
+           }
+       }
 }
 
 /* --------------------------------------------------------------------------
@@ -734,12 +758,11 @@ Void cgBinds( List binds )
 Void codegen(what)
 Int what; {
     switch (what) {
-    case INSTALL:
-            /* deliberate fall though */
-    case RESET: 
-            break;
-    case MARK: 
-            break;
+       case PREPREL:
+       case RESET: 
+       case MARK: 
+       case POSTPREL:
+          break;
     }
     liftControl(what);
 }