[project @ 2000-01-13 14:33:57 by hwloidl]
[ghc-hetmet.git] / ghc / interpreter / translate.c
index 72dd432..ead65fc 100644 (file)
@@ -10,8 +10,8 @@
  * included in the distribution.
  *
  * $RCSfile: translate.c,v $
- * $Revision: 1.10 $
- * $Date: 1999/10/19 11:01:24 $
+ * $Revision: 1.24 $
+ * $Date: 1999/12/10 15:59:56 $
  * ------------------------------------------------------------------------*/
 
 #include "prelude.h"
@@ -203,7 +203,6 @@ StgExpr failExpr;
             }
         }
     case NUMCASE:
-#if OVERLOADED_CONSTANTS                
         {
             Triple nc    = snd(e);
             Offset o     = fst3(nc);
@@ -212,6 +211,7 @@ StgExpr failExpr;
             Cell   scrut = stgOffset(o,sc);
             Cell   h     = getHead(discr);
             Int    da    = discrArity(discr);
+            char   str[30];
 
 #if NPLUSK
             if (whatIs(h) == ADDPAT && argCount == 1) {
@@ -234,8 +234,10 @@ StgExpr failExpr;
                     dIntegral = mkStgVar(dIntegral,NIL);
                     binds = cons(dIntegral,binds);
                 }
+
                 /* box number */
-                n = mkStgVar(mkStgCon(nameMkInteger,singleton(n)),NIL);
+                sprintf(str, "%d", n);
+                n = mkStgVar(mkStgCon(nameMkInteger,singleton(stringToBignum(str))),NIL);
                 binds = cons(n,binds);
 
                 /* coerce number to right type (using Integral dict) */
@@ -316,46 +318,7 @@ StgExpr failExpr;
                    );
             }
         }
-#else /* ! OVERLOADED_CONSTANTS */
-        {
-            Triple nc    = snd(e);
-            Offset o     = fst3(nc);
-            Cell   discr = snd3(nc);
-            Cell   r     = thd3(nc);
-            Cell   scrut = stgOffset(o,sc);
-            Cell   h     = getHead(discr);
-            Int    da    = discrArity(discr);
-            Cell   n     = discr;
-            List   binds = NIL;
-            Name   eq
-                = isInt(discr)    ? nameEqInt
-                : isBignum(discr) ? nameEqInteger
-                :                   nameEqDouble;
-            Name   box
-                = isInt(discr)    ? nameMkI
-                : isBignum(discr) ? nameMkBignum
-                :                   nameMkD;
-            StgExpr test = NIL;
-            Cell   altsc = sc;
-            Cell   vs    = NIL;
-            Int    i;
-
-            for(i=1; i<=da; ++i) {
-                Cell nv = mkStgVar(NIL,NIL);
-                vs    = cons(nv,vs);
-                altsc = cons(pair(mkOffset(co+i),nv),altsc);
-            }
 
-            /* bind number */
-            n = mkStgVar(mkStgCon(box,singleton(n)),NIL);
-            binds = cons(n,binds);
-            
-            test = mkStgLet(binds, mkStgApp(eq, doubleton(n,scrut)));
-            return makeStgIf(test,
-                             stgExpr(r,co+da,altsc,failExpr),
-                             failExpr);
-        }
-#endif /* ! OVERLOADED_CONSTANTS */
     case LETREC:
         {
             List binds = NIL;
@@ -401,11 +364,13 @@ StgExpr failExpr;
             }
             return mkStgLet(binds,stgRhs(snd(snd(e)),co,sc,failExpr/*namePMFail*/));
         }
+
     default: /* convert to an StgApp or StgVar plus some bindings */
         {   
             List args  = NIL;
             List binds = NIL;
             List as    = NIL;
+            Int  length_args;
 
             /* Unwind args */
             while (isAp(e)) {
@@ -417,11 +382,7 @@ StgExpr failExpr;
             /* Special cases */
             if (e == nameSel && length(args) == 3) {
                 Cell   con   = hd(args);
-#if 0
-                StgVar v     = stgOffset(hd(tl(args)),sc);
-#else
                 StgExpr v    = stgExpr(hd(tl(args)),co,sc,namePMFail);
-#endif
                 Int    ix    = intOf(hd(tl(tl(args))));
                 Int    da    = discrArity(con);
                 List   vs    = NIL;
@@ -439,13 +400,10 @@ StgExpr failExpr;
             /* Arguments must be StgAtoms */
             for(as=args; nonNull(as); as=tl(as)) {
                 StgRhs a = stgRhs(hd(as),co,sc,namePMFail);
-#if 1 /* optional flattening of let bindings */
                 if (whatIs(a) == LETREC) {
                     binds = appendOnto(stgLetBinds(a),binds);
                     a = stgLetBody(a);
                 }
-#endif
-                    
                 if (!isAtomic(a)) {
                     a     = mkStgVar(a,NIL);
                     binds = cons(a,binds);
@@ -453,6 +411,24 @@ StgExpr failExpr;
                 hd(as) = a;
             }
 
+            /* Special case: saturated constructor application */
+            length_args = length(args);
+            if ( (isName(e) && isCfun(e)
+                  && name(e).arity > 0 
+                  && name(e).arity == length_args)
+                 ||
+                 (isTuple(e) && tycon(e).tuple == length_args)
+               ) {
+               StgVar v; 
+               /* fprintf ( stderr, "saturated application of %s\n",
+                           textToStr(isTuple(e) ? tycon(e).text : name(e).text)); */
+               v = mkStgVar(mkStgCon(e,args),NIL);
+               binds = cons(v,binds);
+               return mkStgLet(binds,v);
+
+               
+            }
+
             /* Function must be StgVar or Name */
             e = stgRhs(e,co,sc,namePMFail);
             if (!isStgVar(e) && !isName(e)) {
@@ -494,16 +470,11 @@ Void stgDefn( Name n, Int arity, Cell e )
     }
     stgVarBody(name(n).stgVar) 
        = makeStgLambda(vs,stgExpr(e,arity,sc,namePMFail));
-    s = stgSize(stgVarBody(name(n).stgVar));
-    name(n).stgSize = s;
-    if (s <= SMALL_INLINE_SIZE && !name(n).inlineMe) {
-       name(n).inlineMe = TRUE;
-    }
 }
 
 Void implementCfun(c,scs)               /* Build implementation for constr */
 Name c;                                 /* fun c.  scs lists integers (1..)*/
-List scs; {                             /* in incr order of strict comps.  */
+List scs; {                             /* in incr order of strict fields. */
     Int a = name(c).arity;
 
     if (a > 0) {
@@ -526,10 +497,8 @@ List scs; {                             /* in incr order of strict comps.  */
         StgVar v = mkStgVar(mkStgCon(c,NIL),NIL);
         name(c).stgVar = v;
     }
-    name(c).inlineMe = TRUE;
-    name(c).stgSize = stgSize(stgVarBody(name(c).stgVar));
     stgGlobals = cons(pair(c,name(c).stgVar),stgGlobals); 
-    //printStg(stderr, name(c).stgVar); fprintf(stderr,"\n\n");
+    /* printStg(stderr, name(c).stgVar); fprintf(stderr,"\n\n"); */
 }
 
 /* --------------------------------------------------------------------------
@@ -570,6 +539,7 @@ static Cell foreignTy ( Bool outBound, Type t )
     else if (t == typeAddr)   return mkChar(ADDR_REP);
     else if (t == typeFloat)  return mkChar(FLOAT_REP);
     else if (t == typeDouble) return mkChar(DOUBLE_REP);
+    else if (t == typeStable) return mkChar(STABLE_REP);
 #ifdef PROVIDE_FOREIGN
     else if (t == typeForeign)return mkChar(FOREIGN_REP); 
          /* ToDo: argty only! */
@@ -610,29 +580,27 @@ static Cell foreignInboundTy ( Type t )
 static Name repToBox( char c )
 {
     switch (c) {
-    case CHAR_REP:    return nameMkC;
-    case INT_REP:     return nameMkI;
-    case INTEGER_REP: return nameMkInteger;
-    case WORD_REP:    return nameMkW;
-    case ADDR_REP:    return nameMkA;
-    case FLOAT_REP:   return nameMkF;
-    case DOUBLE_REP:  return nameMkD;
-    case ARR_REP:     return nameMkPrimArray;            
-    case BARR_REP:    return nameMkPrimByteArray;
-    case REF_REP:     return nameMkRef;                  
-    case MUTARR_REP:  return nameMkPrimMutableArray;     
-    case MUTBARR_REP: return nameMkPrimMutableByteArray; 
-    case STABLE_REP:  return nameMkStable;
+    case CHAR_REP:     return nameMkC;
+    case INT_REP:      return nameMkI;
+    case INTEGER_REP:  return nameMkInteger;
+    case WORD_REP:     return nameMkW;
+    case ADDR_REP:     return nameMkA;
+    case FLOAT_REP:    return nameMkF;
+    case DOUBLE_REP:   return nameMkD;
+    case ARR_REP:      return nameMkPrimArray;            
+    case BARR_REP:     return nameMkPrimByteArray;
+    case REF_REP:      return nameMkRef;                  
+    case MUTARR_REP:   return nameMkPrimMutableArray;     
+    case MUTBARR_REP:  return nameMkPrimMutableByteArray; 
+    case STABLE_REP:   return nameMkStable;
+    case THREADID_REP: return nameMkThreadId;
+    case MVAR_REP:     return nameMkPrimMVar;
 #ifdef PROVIDE_WEAK
     case WEAK_REP:  return nameMkWeak;
 #endif
 #ifdef PROVIDE_FOREIGN
     case FOREIGN_REP: return nameMkForeign;
 #endif
-#ifdef PROVIDE_CONCURRENT
-    case THREADID_REP: return nameMkThreadId;
-    case MVAR_REP:     return nameMkMVar;
-#endif
     default: return NIL;
     }
 }
@@ -658,10 +626,14 @@ static StgPrimAlt boxResults( String reps, StgVar state )
         }
         rs = cons(v,rs);
     }
+
     /* Construct tuple of results */
+    if (i == 0) {
+        e = nameUnit;
+    } else
     if (i == 1) {
         e = hd(bs);
-    } else { /* includes i==0 case */
+    } else {
         StgVar r = mkStgVar(mkStgCon(mkTuple(i),rev(bs)),NIL);
         rbinds = cons(r,rbinds);
         e = r;
@@ -705,7 +677,6 @@ static StgRhs unboxVars( String reps, List b_args, List u_args, StgExpr e )
     if (nonNull(b_args)) {
         StgVar b_arg = hd(b_args); /* boxed arg   */
         StgVar u_arg = hd(u_args); /* unboxed arg */
-        //StgRep k     = mkStgRep(*reps);
         Name   box   = repToBox(*reps);
         e = unboxVars(reps+1,tl(b_args),tl(u_args),e);
         if (isNull(box)) {
@@ -791,8 +762,6 @@ Name n; {
     StgRhs   rhs = makeStgPrim(n,p->monad!=MONAD_Id,NIL,p->args,p->results);
     StgVar   v   = mkStgVar(rhs,NIL);
     name(n).stgVar   = v;
-    name(n).stgSize  = stgSize(stgVarBody(v));
-    name(n).inlineMe = TRUE;
     stgGlobals=cons(pair(n,v),stgGlobals);  /* so it will get codegened */
 }
 
@@ -823,7 +792,8 @@ Void implementForeignImport ( Name n )
     List argTys    = NIL;
     List resultTys = NIL;
     CFunDescriptor* descriptor = 0;
-    Bool addState = TRUE;
+    Bool addState  = TRUE;
+    Bool dynamic   = isNull(name(n).defn);
     while (getHead(t)==typeArrow && argCount==2) {
         Type ta = fullExpand(arg(fun(t)));
         Type tr = arg(t);
@@ -831,6 +801,17 @@ Void implementForeignImport ( Name n )
         t = tr;
     }
     argTys = rev(argTys);
+
+    /* argTys now holds the argument tys.  If this is a dynamic call,
+       the first one had better be an Addr.
+    */
+    if (dynamic) {
+       if (isNull(argTys) || hd(argTys) != typeAddr) {
+          ERRMSG(name(n).line) "First argument in f-i-dynamic must be an Addr"
+          EEND;
+       }
+    }
+
     if (getHead(t) == typeIO) {
         resultTys = getArgs(t);
         assert(length(resultTys) == 1);
@@ -850,35 +831,76 @@ Void implementForeignImport ( Name n )
     }
     mapOver(foreignOutboundTy,argTys);  /* allows foreignObj, byteArrays, etc */
     mapOver(foreignInboundTy,resultTys); /* doesn't */
-    descriptor = mkDescriptor(charListToString(argTys),
-                              charListToString(resultTys));
+    descriptor 
+       = mkDescriptor(charListToString(argTys),
+                      charListToString(resultTys));
     if (!descriptor) {
-       ERRMSG(0) "Can't allocate memory for call descriptor"
+       ERRMSG(name(n).line) "Can't allocate memory for call descriptor"
        EEND;
     }
 
-    name(n).primop = addState ? &ccall_IO : &ccall_Id;
+    /* ccall is the default convention, if it wasn't specified */
+    if (isNull(name(n).callconv)
+        || name(n).callconv == textCcall) {
+       name(n).primop = addState ? &ccall_ccall_IO : &ccall_ccall_Id;
+    } 
+    else if (name(n).callconv == textStdcall) {
+       if (!stdcallAllowed()) {
+          ERRMSG(name(n).line) "stdcall is not supported on this platform"
+          EEND;
+       }
+       name(n).primop = addState ? &ccall_stdcall_IO : &ccall_stdcall_Id;
+    }
+    else
+       internal ( "implementForeignImport: unknown calling convention");
+
     {
-        Pair    extName = name(n).defn;
-        void*   funPtr  = getDLLSymbol(textToStr(textOf(fst(extName))),
-                                       textToStr(textOf(snd(extName))));
-        List extra_args = doubleton(mkPtr(descriptor),mkPtr(funPtr));
-        StgRhs rhs = makeStgPrim(n,addState,extra_args,descriptor->arg_tys,
-                                 descriptor->result_tys);
-        StgVar v   = mkStgVar(rhs,NIL);
-        if (funPtr == 0) {
-            ERRMSG(0) "Could not find foreign function \"%s\" in \"%s\"", 
-                textToStr(textOf(snd(extName))),
-                textToStr(textOf(fst(extName)))
-            EEND;
+        Pair   extName;
+        void*  funPtr;
+        List   extra_args;
+        StgRhs rhs;
+        StgVar v;
+
+        if (dynamic) {
+           funPtr     = NULL;
+           extra_args = singleton(mkPtr(descriptor));
+           /* and we know that the first arg will be the function pointer */
+        } else {
+           extName = name(n).defn;
+           funPtr  = getDLLSymbol(name(n).line,
+                                  textToStr(textOf(fst(extName))),
+                                  textToStr(textOf(snd(extName))));
+           if (funPtr == 0) {
+               ERRMSG(name(n).line) 
+                   "Could not find foreign function \"%s\" in \"%s\"", 
+                   textToStr(textOf(snd(extName))),
+                   textToStr(textOf(fst(extName)))
+               EEND;
+           }
+           extra_args = doubleton(mkPtr(descriptor),mkPtr(funPtr));
         }
-        /* ppStg(v); */
+
+        rhs              = makeStgPrim(n,addState,extra_args,
+                                       descriptor->arg_tys,
+                                       descriptor->result_tys);
+        v                = mkStgVar(rhs,NIL);
         name(n).defn     = NIL;
         name(n).stgVar   = v;
-        name(n).stgSize  = stgSize(stgVarBody(v));
-        name(n).inlineMe = TRUE; 
-        stgGlobals=cons(pair(n,v),stgGlobals);/*so it will get codegen'd */
+        stgGlobals       = cons(pair(n,v),stgGlobals);
     }
+
+    /* At this point the descriptor contains a tags for all args,
+       because that makes makeStgPrim generate the correct unwrap
+       code.  From now on, the descriptor is only used at the time
+       the actual ccall is made.  So we need to zap the leading
+       addr arg IF this is a f-i-dynamic call.
+    */
+    if (dynamic) {
+       descriptor->arg_tys++;
+       descriptor->num_args--;
+    }
+
+    
 }
 
 
@@ -886,7 +908,8 @@ Void implementForeignImport ( Name n )
  *
  * \ fun s0 ->
      let e1 = A# "...."
-     in  primMkAdjThunk fun s0 e1
+         e3 = C# 'c' -- (ccall), or 's' (stdcall)
+     in  primMkAdjThunk fun e1 e3 s0
 
    we require, and check that,
      fun :: prim_arg* -> IO prim_result
@@ -896,11 +919,12 @@ Void implementForeignExport ( Name n )
     Type t         = name(n).type;
     List argTys    = NIL;
     List resultTys = NIL;
+    Char cc_char;
 
     if (getHead(t)==typeArrow && argCount==2) {
        t = arg(fun(t));
     } else {
-        ERRMSG(0) "foreign export has illegal type" ETHEN
+        ERRMSG(name(n).line) "foreign export has illegal type" ETHEN
         ERRTEXT " \"" ETHEN ERRTYPE(t);
         ERRTEXT "\""
         EEND;        
@@ -918,7 +942,7 @@ Void implementForeignExport ( Name n )
         assert(length(resultTys) == 1);
         resultTys = hd(resultTys);
     } else {
-        ERRMSG(0) "foreign export doesn't return an IO type" ETHEN
+        ERRMSG(name(n).line) "foreign export doesn't return an IO type" ETHEN
         ERRTEXT " \"" ETHEN ERRTYPE(t);
         ERRTEXT "\""
         EEND;        
@@ -927,11 +951,27 @@ Void implementForeignExport ( Name n )
 
     mapOver(foreignInboundTy,argTys);
 
+    /* ccall is the default convention, if it wasn't specified */
+    if (isNull(name(n).callconv)
+        || name(n).callconv == textCcall) {
+        cc_char = 'c';
+    } 
+    else if (name(n).callconv == textStdcall) {
+       if (!stdcallAllowed()) {
+          ERRMSG(name(n).line) "stdcall is not supported on this platform"
+          EEND;
+       }
+       cc_char = 's';
+    }
+    else
+       internal ( "implementForeignExport: unknown calling convention");
+
+
     {
     List     tdList;
     Text     tdText;
     List     args;
-    StgVar   e1, e2, v;
+    StgVar   e1, e2, e3, v;
     StgExpr  fun;
 
     tdList = cons(mkChar(':'),argTys);
@@ -944,34 +984,33 @@ Void implementForeignExport ( Name n )
                 mkStgCon(nameMkA,singleton(ap(STRCELL,tdText))),
                 NIL
              );
-     e2    = mkStgVar(
+    e2     = mkStgVar(
                 mkStgApp(nameUnpackString,singleton(e1)),
                 NIL
              );
-
+    e3     = mkStgVar(
+                mkStgCon(nameMkC,singleton(mkChar(cc_char))),
+                NIL
+             );
     fun    = mkStgLambda(
                 args,
                 mkStgLet(
-                   doubleton(e1,e2),
+                   tripleton(e1,e2,e3),
                    mkStgApp(
                       nameCreateAdjThunk,
-                      tripleton(hd(args),e2,hd(tl(args)))
+                      cons(hd(args),cons(e2,cons(e3,cons(hd(tl(args)),NIL))))
                    )
                 )
              );
 
     v = mkStgVar(fun,NIL);
-    /* ppStg(v); */
 
     name(n).defn     = NIL;    
     name(n).stgVar   = v;
-    name(n).stgSize  = stgSize(stgVarBody(v));
-    name(n).inlineMe = FALSE;
     stgGlobals       = cons(pair(n,v),stgGlobals);
     }
 }
 
-// ToDo: figure out how to set inlineMe for these (non-Name) things
 Void implementTuple(size)
 Int size; {
     if (size > 0) {
@@ -994,16 +1033,14 @@ Int size; {
 Void translateControl(what)
 Int what; {
     switch (what) {
-    case INSTALL:
-        {
-            /* deliberate fall through */
-        }
-    case RESET: 
-            stgGlobals=NIL;
-            break;
-    case MARK: 
-            mark(stgGlobals);
-            break;
+       case POSTPREL: break;
+       case PREPREL:
+       case RESET: 
+          stgGlobals=NIL;
+          break;
+       case MARK: 
+          mark(stgGlobals);
+          break;
     }
 }