[project @ 2000-07-31 10:12:19 by simonmar]
[ghc-hetmet.git] / ghc / rts / Assembler.c
index fa0984a..6746185 100644 (file)
@@ -5,8 +5,8 @@
  * Copyright (c) 1994-1998.
  *
  * $RCSfile: Assembler.c,v $
- * $Revision: 1.29 $
- * $Date: 2000/05/10 09:00:20 $
+ * $Revision: 1.32 $
+ * $Date: 2000/06/15 13:23:51 $
  *
  * This module provides functions to construct BCOs and other closures
  * required by the bytecode compiler.
@@ -106,6 +106,7 @@ AsmObject asmNewObject ( void )
    objects      = obj;
    obj->n_refs  = obj->n_words = obj->n_insns = 0;
    obj->closure = NULL;
+   obj->stgexpr = 0; /*NIL*/
    obj->magic   = 0x31415927;
    INITIALISE_TABLE(AsmEntity,obj->entities,
                               obj->sizeEntities,
@@ -136,6 +137,52 @@ void asmAddEntity ( AsmObject   obj,
    }
 }
 
+/* Support for the peephole optimiser.  Find the instruction
+   byte n back, carefully stepping over any non Asm_Insn8 entities
+   on the way.
+*/
+static Instr asmInstrBack ( AsmBCO bco, StgInt n )
+{
+   StgInt ue = bco->usedEntities;
+   while (1) {
+      if (ue < 0 || n <= 0) barf("asmInstrBack");
+      ue--;
+      if (bco->entities[ue].kind != Asm_Insn8) continue;
+      n--;
+      if (n == 0) return bco->entities[ue].val;
+   }
+}
+
+
+/* Throw away n Asm_Insn8 bytes, and slide backwards any Asm_Insn8 entities
+   as necessary.
+*/
+static void asmInstrRecede ( AsmBCO bco, StgInt n )
+{
+   StgInt ue = bco->usedEntities;
+   StgInt wr;
+   while (1) {
+      if (ue < 0 || n <= 0) barf("asmInstrRecede");
+      ue--;
+      if (bco->entities[ue].kind != Asm_Insn8) continue;
+      n--;
+      bco->n_insns--;
+      if (n == 0) break;
+   }
+   /* Now ue is the place where we would recede usedEntities to,
+      except that there may be stuff to slide downwards.
+   */
+   wr = ue;
+   for (; ue < bco->usedEntities; ue++) {
+      if (bco->entities[ue].kind != Asm_Insn8) {
+         bco->entities[wr] = bco->entities[ue];
+         wr++;
+      }
+   }
+   bco->usedEntities = wr;
+}
+
+
 static int asmFindInNonPtrs ( AsmBCO bco, StgWord w )
 {
    int i, j = 0;
@@ -240,6 +287,7 @@ StgClosure* asmDerefEntity ( Asm_Entity entity )
    return NULL; /*notreached*/
 }
 
+
 void asmCopyAndLink ( void )
 {
    int       j, k;
@@ -259,7 +307,7 @@ void asmCopyAndLink ( void )
             bco->n_words  = abco->n_words;
             bco->n_instrs = abco->n_insns + (obj->max_sp <= 255 ? 2 : 3);
             bco->stgexpr  = abco->stgexpr;
-
+           //ppStgExpr(bco->stgexpr);
             /* First copy in the ptrs. */
             k = 0;
             for (j = 0; j < obj->usedEntities; j++) {
@@ -430,9 +478,10 @@ void asmEndCAF( AsmCAF caf __attribute__ ((unused)) )
 
 AsmBCO asmBeginBCO( int /*StgExpr*/ e )
 {
-   AsmBCO bco = asmNewObject();
+   AsmBCO bco   = asmNewObject();
    bco->kind    = Asm_BCO;
    bco->stgexpr = e;
+   //ppStgExpr(bco->stgexpr);
    bco->sp      = 0;
    bco->max_sp  = 0;
    bco->lastOpc = i_INTERNAL_ERROR;
@@ -497,18 +546,6 @@ static void asmInstr16 ( AsmBCO bco, StgWord i )
     asmAddInstr(bco,i % 256);
 }
 
-#if 0
-static Instr asmInstrBack ( AsmBCO bco, StgWord n )
-{
-   return bco->is.elems[bco->is.len - n];
-}
-
-static void asmInstrRecede ( AsmBCO bco, StgWord n )
-{
-   if (bco->is.len < n) barf("asmInstrRecede");
-   bco->is.len -= n;
-}
-#endif
 
 #define asmAddNonPtrWords(bco,ty,x)                      \
     {                                                    \
@@ -575,7 +612,7 @@ int asmRepSizeW ( AsmRep rep )
 
 static void emiti_ ( AsmBCO bco, Instr opcode )
 {
-#if 0
+#if 1
    StgInt x, y;
    if (bco->lastOpc == i_SLIDE && opcode == i_ENTER) {
       /* SLIDE x y ; ENTER   ===>  SE x y */
@@ -604,7 +641,7 @@ static void emiti_ ( AsmBCO bco, Instr opcode )
 
 static void emiti_8 ( AsmBCO bco, Instr opcode, int arg1 )
 {
-#if 0
+#if 1
    StgInt x;
    if (bco->lastOpc == i_VAR && opcode == i_VAR) {
       /* VAR x ; VAR y ===>  VV x y */
@@ -824,6 +861,40 @@ static void emit_i_ALLOC_CONSTR ( AsmBCO bco, int arg1 )
       emiti_16(bco,i_ALLOC_CONSTR_big,arg1);
 }
 
+#ifdef XMLAMBDA
+static void emit_i_ALLOC_ROW( AsmBCO bco, int n )
+{
+  ASSERT(n >= 0);
+  if (n < 256)
+      emiti_8 ( bco, i_ALLOC_ROW, n ); else
+      emiti_16( bco, i_ALLOC_ROW_big, n );
+}
+
+static void emit_i_PACK_ROW (AsmBCO bco, int var )
+{
+   ASSERT(var >= 0);
+   if (var < 256)
+      emiti_8 ( bco, i_PACK_ROW, var ); else
+      emiti_16( bco, i_PACK_ROW_big, var );
+}
+
+static void emit_i_PACK_INJ (AsmBCO bco, int var )
+{
+   ASSERT(var >= 0);
+   if (var < 256)
+      emiti_8 ( bco, i_PACK_INJ, var ); else
+      emiti_16( bco, i_PACK_INJ_big, var );
+}
+
+static void emit_i_TEST_INJ (AsmBCO bco, int var )
+{
+   ASSERT(var >= 0);
+   if (var < 256)
+      emiti_8_16 ( bco, i_TEST_INJ, var, 0 ); else
+      emiti_16_16( bco, i_TEST_INJ_big, var, 0 );
+}
+#endif
+
 /* --------------------------------------------------------------------------
  * Arg checks.
  * ------------------------------------------------------------------------*/
@@ -1377,6 +1448,12 @@ AsmPrim asmPrimOps[] = {
     , { "primIsNegativeZeroDouble",  "D",  "B",  MONAD_Id, i_PRIMOP1, i_isNegativeZeroDouble }
     , { "primIsIEEEDouble",          "",   "B",  MONAD_Id, i_PRIMOP1, i_isIEEEDouble }
 
+#ifdef XMLAMBDA
+    /* primitive row operations. */
+    , { "primRowInsertAt",           "XIa","X",  MONAD_Id, i_PRIMOP2, i_rowInsertAt }
+    , { "primRowRemoveAt",           "XI", "aX", MONAD_Id, i_PRIMOP2, i_rowRemoveAt }
+#endif
+
     /* Ref operations */
     , { "primNewRef",                "a",  "R",  MONAD_ST, i_PRIMOP2, i_newRef }
     , { "primWriteRef",              "Ra", "",   MONAD_ST, i_PRIMOP2, i_writeRef }
@@ -1680,10 +1757,10 @@ AsmSp asmBeginPack( AsmBCO bco )
 void asmEndPack( AsmBCO bco, AsmVar v, AsmSp start, AsmInfo info )
 {
     nat size = bco->sp - start;
-    assert(bco->sp >= start);
-    assert(start >= v);
+    ASSERT(bco->sp >= start);
+    ASSERT(start >= v);
     /* only reason to include info is for this assertion */
-    assert(info->layout.payload.ptrs == size);
+    ASSERT(info->layout.payload.ptrs == size);
     emit_i_PACK(bco, bco->sp - v);
     setSp(bco, start);
 }
@@ -1787,6 +1864,104 @@ AsmInfo asmMkInfo( AsmNat tag, AsmNat ptrs )
     return info;
 }
 
+#ifdef XMLAMBDA
+/* -----------------------------------------------------------------------
+ All the XMLambda primitives.
+------------------------------------------------------------------------*/
+
+/* -----------------------------------------------------------------------
+ allocation & unpacking of rows  
+------------------------------------------------------------------------*/
+AsmVar asmAllocRow   ( AsmBCO bco, AsmNat n /*number of fields*/ )
+{
+    emit_i_ALLOC_ROW(bco,n);             
+
+    incSp(bco, sizeofW(StgClosurePtr));
+    return bco->sp;
+}
+
+AsmSp asmBeginPackRow( AsmBCO bco )
+{
+    return bco->sp;
+}
+
+void asmEndPackRow( AsmBCO bco, AsmVar v, AsmSp start, AsmNat n /*#fields*/ )
+{
+    nat size = bco->sp - start;
+    ASSERT(bco->sp >= start);
+    ASSERT(start >= v);
+    /* only reason to include n is for this assertion */
+    ASSERT(n == size);
+    emit_i_PACK_ROW(bco,bco->sp - v);  
+    setSp(bco, start);
+}
+
+void asmBeginUnpackRow( AsmBCO bco )
+{
+    /* dummy to make it look prettier */
+}
+
+void asmEndUnpackRow( AsmBCO bco )
+{
+    emiti_(bco,i_UNPACK_ROW);
+}
+
+/*------------------------------------------------------------------------
+ Inj primitives.
+ The Inj constructor contains the value and its index: an unboxed int 
+ data Inj = forall a. Inj a Int# 
+ There is no "big" form for the INJ_CONST instructions. The index
+ is therefore still limited to 256 values.
+------------------------------------------------------------------------*/
+AsmVar asmInj( AsmBCO bco, AsmVar index )
+{    
+    emit_i_PACK_INJ( bco, bco->sp - index );
+
+    decSp(bco, sizeofW(StgPtr));    /* pop argument value */
+    incSp(bco, sizeofW(StgPtr));    /* push Inj result    */
+    return bco->sp;
+}
+
+AsmVar asmInjConst( AsmBCO bco, AsmIndex x )
+{
+    ASSERT( x >= 0 && x <= 255 );
+    emiti_8 (bco, i_PACK_INJ_CONST, x );
+
+    decSp(bco, sizeofW(StgPtr));   /* pop argument value */
+    incSp(bco, sizeofW(StgPtr));   /* push Inj result */
+    return bco->sp;
+}
+
+/* UNPACK_INJ only returns the value; the index should be
+   tested using the TEST_INJ instructions. */
+AsmVar asmUnInj( AsmBCO bco )
+{
+    emiti_(bco,i_UNPACK_INJ);
+    incSp(bco, sizeofW(StgPtr));  /* push the value */
+    return bco->sp;
+}
+
+AsmPc asmTestInj( AsmBCO bco, AsmVar index )
+{
+    emit_i_TEST_INJ(bco,bco->sp - index);
+    return bco->n_insns;
+}
+
+AsmPc asmTestInjConst( AsmBCO bco, AsmIndex x )
+{
+    ASSERT( x >= 0 && x <= 255 );
+    emiti_8_16 (bco, i_TEST_INJ_CONST, x, 0 );
+    return bco->n_insns;
+}
+
+AsmVar asmConstIndex( AsmBCO bco, AsmIndex x )
+{
+    ASSERT( x >= 0 && x <= 65535 );
+    asmConstInt(bco,x);
+    return bco->sp;
+}
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 #endif /* INTERPRETER */