[project @ 2000-04-14 15:18:05 by sewardj]
[ghc-hetmet.git] / ghc / rts / Assembler.c
index b5bec41..a382920 100644 (file)
@@ -5,8 +5,8 @@
  * Copyright (c) 1994-1998.
  *
  * $RCSfile: Assembler.c,v $
- * $Revision: 1.16 $
- * $Date: 1999/11/18 12:10:24 $
+ * $Revision: 1.26 $
+ * $Date: 2000/04/14 15:18:06 $
  *
  * This module provides functions to construct BCOs and other closures
  * required by the bytecode compiler.
@@ -79,25 +79,33 @@ typedef struct {
 
 #define Queue Instrs
 #define Type  StgWord8
+#define MAKE_findIn 0
 #include "QueueTemplate.h"
+#undef MAKE_findIn
 #undef Type
 #undef Queue
 
 #define Queue Ptrs
 #define Type  AsmObject
+#define MAKE_findIn 0
 #include "QueueTemplate.h"
+#undef MAKE_findIn
 #undef Type
 #undef Queue
 
 #define Queue Refs
 #define Type  AsmRef
+#define MAKE_findIn 0
 #include "QueueTemplate.h"
+#undef MAKE_findIn
 #undef Type
 #undef Queue
 
 #define Queue NonPtrs
 #define Type  StgWord
+#define MAKE_findIn 1
 #include "QueueTemplate.h"
+#undef MAKE_findIn
 #undef Type
 #undef Queue
 
@@ -146,8 +154,6 @@ struct AsmBCO_ {
     /* abstract machine ("executed" during compilation) */
     AsmSp    sp;          /* stack ptr */
     AsmSp    max_sp;
-    StgWord  hp;          /* heap ptr  */
-    StgWord  max_hp;
     Instr    lastOpc;
 };
 
@@ -172,8 +178,8 @@ static void asmResolveRef( AsmObject obj, AsmNat i, AsmClosure reference )
     case CONSTR:
         {
             StgClosure* con = stgCast(StgClosure*,obj->closure);
-            ASSERT(i < get_itbl(con)->layout.payload.nptrs && payloadCPtr(con,i) == NULL);
-            payloadCPtr(con,i) = reference;
+            ASSERT(i < get_itbl(con)->layout.payload.nptrs && con->payload[i] == NULL);
+            con->payload[i] = reference;
             break;
         }
     case AP_UPD:
@@ -184,8 +190,8 @@ static void asmResolveRef( AsmObject obj, AsmNat i, AsmClosure reference )
                 ASSERT(ap->fun == NULL);
                 ap->fun = reference;
             } else {
-                ASSERT(payloadCPtr(ap,i-1) == NULL);
-                payloadCPtr(ap,i-1) = reference;
+                ASSERT(ap->payload[i-1] == NULL);
+                ap->payload[i-1] = (StgPtr)reference;
             }
             break;
         }
@@ -262,26 +268,6 @@ static StgClosure* asmAlloc( nat size )
     return o;
 }
 
-static void grabHpUpd( AsmBCO bco, nat size )
-{
-    /* ToDo: sometimes we should test for MIN_UPD_SIZE instead */
-    ASSERT( size >= MIN_UPD_SIZE + sizeofW(StgHeader) );
-    bco->hp += size;
-}
-
-static void grabHpNonUpd( AsmBCO bco, nat size )
-{
-    /* ToDo: sometimes we should test for MIN_UPD_SIZE instead */
-    ASSERT( size >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
-    bco->hp += size;
-}
-
-static void resetHp( AsmBCO bco, nat hp )
-{
-    bco->max_hp = stg_max(bco->hp,bco->max_hp);
-    bco->hp     = hp;
-}
-
 static void setSp( AsmBCO bco, AsmSp sp )
 {
     bco->max_sp = stg_max(bco->sp,bco->max_sp);
@@ -337,8 +323,8 @@ void asmEndCon( AsmCon con )
     StgClosure* c = asmAlloc(CONSTR_sizeW(p,np));
     StgClosure* o = stgCast(StgClosure*,c);
     SET_HDR(o,con->info,??);
-    mapQueue(Ptrs,    AsmObject, con->object.ptrs, payloadCPtr(o,i) = NULL);
-    { nat i; for( i=0; i<np; ++i ) { payloadWord(o,p+i) = 0xdeadbeef; } }
+    mapQueue(Ptrs,    AsmObject, con->object.ptrs, o->payload[i] = NULL);
+    { nat i; for( i=0; i<np; ++i ) { o->payload[p+i] = (StgClosure *)0xdeadbeef; }}
     asmEndObject(&con->object,c);
 }
 
@@ -377,7 +363,6 @@ AsmBCO asmBeginBCO( int /*StgExpr*/ e )
 
     bco->stgexpr = e;
     bco->max_sp = bco->sp = 0;
-    bco->max_hp = bco->hp = 0;
     bco->lastOpc = i_INTERNAL_ERROR;
     return bco;
 }
@@ -400,7 +385,6 @@ void asmEndBCO( AsmBCO bco )
     {
         nat j = 0;
         bco->max_sp = stg_max(bco->sp,bco->max_sp);
-        bco->max_hp = stg_max(bco->hp,bco->max_hp);
 
         ASSERT(bco->max_sp <= 65535);
         if (bco->max_sp <= 255) {
@@ -467,6 +451,11 @@ static void asmWord( AsmBCO bco, StgWord i )
     insertNonPtrs( &bco->nps, i );
 }
 
+static int asmFindInNonPtrs ( AsmBCO bco, StgWord i )
+{
+   return findInNonPtrs ( &bco->nps, i );
+}
+
 #define asmWords(bco,ty,x)                               \
     {                                                    \
         union { ty a; AsmWord b[sizeofW(ty)]; } p;       \
@@ -764,6 +753,14 @@ static void emit_i_RETADDR ( AsmBCO bco, int arg1 )
       emiti_16(bco,i_RETADDR_big,arg1);
 }
 
+static void emit_i_ALLOC_CONSTR ( AsmBCO bco, int arg1 )
+{
+   ASSERT(arg1 >= 0);
+   if (arg1 < 256)
+      emiti_8 (bco,i_ALLOC_CONSTR,    arg1); else
+      emiti_16(bco,i_ALLOC_CONSTR_big,arg1);
+}
+
 
 /* --------------------------------------------------------------------------
  * Arg checks.
@@ -780,8 +777,6 @@ void   asmEndArgCheck   ( AsmBCO bco, AsmSp last_arg )
     nat args = bco->sp - last_arg;
     if (args != 0) { /* optimisation */
         emiti_8(bco,i_ARG_CHECK,args);
-        grabHpNonUpd(bco,PAP_sizeW(args-1));
-        resetHp(bco,0);
     }
 }
 
@@ -890,32 +885,25 @@ AsmVar asmBox( AsmBCO bco, AsmRep rep )
     switch (rep) {
     case CHAR_REP:
             emiti_(bco,i_PACK_CHAR);
-            grabHpNonUpd(bco,Czh_sizeW);
             break;
     case INT_REP:
             emiti_(bco,i_PACK_INT);
-            grabHpNonUpd(bco,Izh_sizeW);
             break;
     case THREADID_REP:
     case WORD_REP:
             emiti_(bco,i_PACK_WORD);
-            grabHpNonUpd(bco,Wzh_sizeW);
             break;
     case ADDR_REP:
             emiti_(bco,i_PACK_ADDR);
-            grabHpNonUpd(bco,Azh_sizeW);
             break;
     case FLOAT_REP:
             emiti_(bco,i_PACK_FLOAT);
-            grabHpNonUpd(bco,Fzh_sizeW);
             break;
     case DOUBLE_REP:
             emiti_(bco,i_PACK_DOUBLE);
-            grabHpNonUpd(bco,Dzh_sizeW);
             break;
     case STABLE_REP:
             emiti_(bco,i_PACK_STABLE);
-            grabHpNonUpd(bco,Stablezh_sizeW);
             break;
 
     default:
@@ -1105,18 +1093,23 @@ AsmSp asmBeginPrim( AsmBCO bco )
     return bco->sp;
 }
 
-void   asmEndPrim( AsmBCO bco, const AsmPrim* prim, AsmSp base )
+void asmEndPrim( AsmBCO bco, const AsmPrim* prim, AsmSp base )
 {
     emiti_8(bco,prim->prefix,prim->opcode);
     setSp(bco, base);
 }
 
+char* asmGetPrimopName ( AsmPrim* p )
+{
+   return p->name;
+}
+
 /* Hugs used to let you add arbitrary primops with arbitrary types
  * just by editing Prelude.hs or any other file you wanted.
  * We deliberately avoided that approach because we wanted more
  * control over which primops are provided.
  */
-const AsmPrim asmPrimOps[] = {
+AsmPrim asmPrimOps[] = {
 
     /* Char# operations */
       { "primGtChar",                "CC", "B",  MONAD_Id, i_PRIMOP1, i_gtChar }
@@ -1379,7 +1372,7 @@ const AsmPrim asmPrimOps[] = {
 
 #ifdef PROVIDE_FOREIGN
     /* ForeignObj# operations */
-    , { "primMakeForeignObj",        "A",  "f",  MONAD_IO, i_PRIMOP2, i_makeForeignObj }
+    , { "primMkForeignObj",          "A",  "f",  MONAD_IO, i_PRIMOP2, i_mkForeignObj }
 #endif
 #ifdef PROVIDE_WEAK
     /* WeakPair# operations */
@@ -1406,36 +1399,50 @@ const AsmPrim asmPrimOps[] = {
 #endif
 #ifdef PROVIDE_CONCURRENT
     /* Concurrency operations */
-    , { "primFork",                  "a", "T",   MONAD_IO, i_PRIMOP2, i_fork }
+    , { "primForkIO",                "a", "T",   MONAD_IO, i_PRIMOP2, i_forkIO }
     , { "primKillThread",            "T", "",    MONAD_IO, i_PRIMOP2, i_killThread }
-    , { "primDelay",                 "I", "",    MONAD_IO, i_PRIMOP2, i_delay }
+    , { "primRaiseInThread",         "TE", "",   MONAD_IO, i_PRIMOP2, i_raiseInThread }
+
     , { "primWaitRead",              "I", "",    MONAD_IO, i_PRIMOP2, i_waitRead }
     , { "primWaitWrite",             "I", "",    MONAD_IO, i_PRIMOP2, i_waitWrite }
+    , { "primYield",                 "", "",     MONAD_IO, i_PRIMOP2, i_yield }    , { "primDelay",                 "I", "",    MONAD_IO, i_PRIMOP2, i_delay }
+    , { "primGetThreadId",           "",   "T",  MONAD_IO, i_PRIMOP2, i_getThreadId }
+    , { "primCmpThreadIds",          "TT", "I",  MONAD_Id, i_PRIMOP2, i_cmpThreadIds }
 #endif
-    , { "primNewEmptyMVar",         "",  "r",   MONAD_IO, i_PRIMOP2, i_newMVar }
+    , { "primNewEmptyMVar",          "",  "r",   MONAD_IO, i_PRIMOP2, i_newMVar }
       /* primTakeMVar is handwritten bytecode */
     , { "primPutMVar",               "ra", "",   MONAD_IO, i_PRIMOP2, i_putMVar } 
     , { "primSameMVar",              "rr", "B",  MONAD_Id, i_PRIMOP2, i_sameMVar }
-    , { "primGetThreadId",           "",   "T",  MONAD_IO, i_PRIMOP2, i_getThreadId }
-    , { "primCmpThreadIds",          "TT", "I",  MONAD_Id, i_PRIMOP2, i_cmpThreadIds }
-    , { "primForkIO",                 "a", "T",  MONAD_IO, i_PRIMOP2, i_forkIO }
+
   
     /* Ccall is polyadic - so it's excluded from this table */
 
     , { 0,0,0,0,0,0 }
 };
 
-const AsmPrim ccall_ccall_Id
+AsmPrim ccall_ccall_Id
    = { "ccall", 0, 0, MONAD_IO, i_PRIMOP2, i_ccall_ccall_Id };
-const AsmPrim ccall_ccall_IO
+AsmPrim ccall_ccall_IO
    = { "ccall", 0, 0, MONAD_IO, i_PRIMOP2, i_ccall_ccall_IO };
-const AsmPrim ccall_stdcall_Id 
+AsmPrim ccall_stdcall_Id 
    = { "ccall", 0, 0, MONAD_IO, i_PRIMOP2, i_ccall_stdcall_Id };
-const AsmPrim ccall_stdcall_IO 
+AsmPrim ccall_stdcall_IO 
    = { "ccall", 0, 0, MONAD_IO, i_PRIMOP2, i_ccall_stdcall_IO };
 
+#ifdef DEBUG
+void checkBytecodeCount( void );
+void checkBytecodeCount( void ) 
+{
+  if (MAX_Primop1 >= 255) {
+    printf("Too many Primop1 bytecodes (%d)\n",MAX_Primop1);
+  }
+  if (MAX_Primop2 >= 255) {
+    printf("Too many Primop2 bytecodes (%d)\n",MAX_Primop2);
+  }
+}
+#endif
 
-const AsmPrim* asmFindPrim( char* s )
+AsmPrim* asmFindPrim( char* s )
 {
     int i;
     for (i=0; asmPrimOps[i].name; ++i) {
@@ -1446,7 +1453,7 @@ const AsmPrim* asmFindPrim( char* s )
     return 0;
 }
 
-const AsmPrim* asmFindPrimop( AsmInstr prefix, AsmInstr op )
+AsmPrim* asmFindPrimop( AsmInstr prefix, AsmInstr op )
 {
     nat i;
     for (i=0; asmPrimOps[i].name; ++i) {
@@ -1555,11 +1562,21 @@ AsmBCO asm_BCO_takeMVar ( void )
 
 AsmVar asmAllocCONSTR   ( AsmBCO bco, AsmInfo info )
 {
+    int i;
     ASSERT( sizeW_fromITBL(info) >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
-    emiti_8(bco,i_ALLOC_CONSTR,bco->nps.len);
-    asmWords(bco,AsmInfo,info);
+
+    /* Look in this bco's collection of nonpointers (literals)
+       to see if the itbl pointer is already there.  If so, re-use it. */
+    i = asmFindInNonPtrs ( bco, (StgWord)info );
+
+    if (i == -1) {
+       emit_i_ALLOC_CONSTR(bco,bco->nps.len);
+       asmWords(bco,AsmInfo,info);
+    } else {
+       emit_i_ALLOC_CONSTR(bco,i);
+    }
+
     incSp(bco, sizeofW(StgClosurePtr));
-    grabHpNonUpd(bco,sizeW_fromITBL(info));
     return bco->sp;
 }
 
@@ -1593,7 +1610,6 @@ AsmVar asmAllocAP( AsmBCO bco, AsmNat words )
 {
     emiti_8(bco,i_ALLOC_AP,words);
     incSp(bco, sizeofW(StgPtr));
-    grabHpUpd(bco,AP_sizeW(words));
     return bco->sp;
 }