]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
iropt: implement flattening (into SSA form). This caused various
authorJulian Seward <jseward@acm.org>
Tue, 17 Aug 2004 23:59:23 +0000 (23:59 +0000)
committerJulian Seward <jseward@acm.org>
Tue, 17 Aug 2004 23:59:23 +0000 (23:59 +0000)
primops to become exposed when previously they were treated as part
of a pattern, hence the changes to host-x86/*.c to handle them.

git-svn-id: svn://svn.valgrind.org/vex/trunk@173

VEX/priv/guest-x86/toIR.c
VEX/priv/host-x86/hdefs.c
VEX/priv/host-x86/hdefs.h
VEX/priv/host-x86/isel.c
VEX/priv/ir/irdefs.c
VEX/priv/ir/iropt.c
VEX/priv/main/vex_main.c
VEX/pub/libvex_ir.h

index 6848a29b004588d4bcb612181839611e63a58a8e..2e4a6543d3f590821269107cef469e9dd886ec48 100644 (file)
@@ -47,26 +47,14 @@ static UChar* guest_code;
 /* CONST */
 static Addr32 guest_eip;
 
-/* The BBIR* into which we're generating code. */
-/* What it points to changes as we work through the bb. */
+/* The IRBB* into which we're generating code. */
 static IRBB* irbb;
 
-/* Points to the last stmt added to the statement list of irbb, so
-   that when a new stmt is added, the .link field can be correctly
-   updated. */
-static IRStmt* last_stmt;
-
 
 /* Add a statement to the list held by "irbb". */
-static void stmt ( IRStmt* stmt )
+static void stmt ( IRStmt* st )
 {
-   stmt->link = NULL;
-   if (irbb->stmts == NULL) {
-      irbb->stmts = stmt;
-   } else {
-      last_stmt->link = stmt;
-   }
-   last_stmt = stmt;
+   addStmtToIRBB( irbb, st );
 }
 
 /* Generate a new temporary of the given type. */
@@ -4970,7 +4958,7 @@ static UInt disInstr ( UInt delta, Bool* isEnd )
    UChar sorb = 0;
 
    /* For printing the stmts after each insn. */
-   IRStmt* first_stmt = last_stmt;
+   Int first_stmt_idx = irbb->stmts_used;
 
    *isEnd = False;
    addr = t1 = t2 = INVALID_IRTEMP; 
@@ -8437,21 +8425,14 @@ static UInt disInstr ( UInt delta, Bool* isEnd )
   decode_success:
    /* All decode successes end up here. */
    DIP("\n");
-   if (first_stmt == NULL)
-      first_stmt = irbb->stmts;
-   else
-      first_stmt = first_stmt->link;
-   while (True) {
-      if (!first_stmt) 
-         break;
-      if (print_codegen) {
-         vex_printf("              ");
-         ppIRStmt(first_stmt);
-         vex_printf("\n");
-      }
-      if (first_stmt == last_stmt)
-        break;
-      first_stmt = first_stmt->link;
+   { Int i;
+     for (i = first_stmt_idx; i < irbb->stmts_used; i++) {
+        if (print_codegen) {
+           vex_printf("              ");
+           ppIRStmt(irbb->stmts[i]);
+           vex_printf("\n");
+        }
+     }
    }
    if (*isEnd) {
       vassert(irbb->next != NULL);
@@ -8494,8 +8475,7 @@ IRBB* bbToIR_X86Instr ( UChar* x86code,
    print_codegen     = (vex_verbosity >= 1);
    guest_code        = x86code;
    guest_eip         = (Addr32)eip;
-   irbb              = mkIRBB( newIRTypeEnv(), NULL, NULL, Ijk_Boring );
-   last_stmt         = NULL;
+   irbb              = emptyIRBB();
 
    vassert((eip >> 32) == 0);
    vassert(vex_guest_insns_per_bb >= 1);
index 451bf9bff69504da907c266c5a81919ac76d670d..ccc6b5f32f6a716b54b031737d6a7270fb7010d4 100644 (file)
@@ -537,6 +537,13 @@ X86Instr* X86Instr_Store ( UChar sz, HReg src, X86AMode* dst ) {
    vassert(sz == 1 || sz == 2);
    return i;
 }
+X86Instr* X86Instr_Set32 ( X86CondCode cond, HReg dst ) {
+   X86Instr* i       = LibVEX_Alloc(sizeof(X86Instr));
+   i->tag            = Xin_Set32;
+   i->Xin.Set32.cond = cond;
+   i->Xin.Set32.dst  = dst;
+   return i;
+}
 X86Instr* X86Instr_FpUnary ( X86FpOp op, HReg src, HReg dst ) {
    X86Instr* i        = LibVEX_Alloc(sizeof(X86Instr));
    i->tag             = Xin_FpUnary;
@@ -675,6 +682,10 @@ void ppX86Instr ( X86Instr* i ) {
          vex_printf(",");
          ppX86AMode(i->Xin.Store.dst);
          return;
+      case Xin_Set32:
+         vex_printf("setl%s ", showX86CondCode(i->Xin.Set32.cond));
+         ppHRegX86(i->Xin.Set32.dst);
+         return;
       case Xin_FpUnary:
          vex_printf("g%sD ", showX86FpOp(i->Xin.FpUnary.op));
          ppHRegX86(i->Xin.FpUnary.src);
@@ -800,6 +811,9 @@ void getRegUsage_X86Instr (HRegUsage* u, X86Instr* i)
          addHRegUse(u, HRmRead, i->Xin.Store.src);
          addRegUsage_X86AMode(u, i->Xin.Store.dst);
          return;
+      case Xin_Set32:
+         addHRegUse(u, HRmWrite, i->Xin.Set32.dst);
+         return;
       case Xin_FpUnary:
          addHRegUse(u, HRmRead, i->Xin.FpUnary.src);
          addHRegUse(u, HRmWrite, i->Xin.FpUnary.dst);
@@ -887,6 +901,9 @@ void mapRegs_X86Instr (HRegRemap* m, X86Instr* i)
          mapReg(m, &i->Xin.Store.src);
          mapRegs_X86AMode(m, i->Xin.Store.dst);
          return;
+      case Xin_Set32:
+         mapReg(m, &i->Xin.Set32.dst);
+         return;
       case Xin_FpBinary:
          mapReg(m, &i->Xin.FpBinary.srcL);
          mapReg(m, &i->Xin.FpBinary.srcR);
@@ -1425,6 +1442,9 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i )
             *p++ = 0x68;
             p = emit32(p, i->Xin.Push.src->Xrmi.Imm.imm32);
             goto done;
+         case Xrmi_Reg:
+            *p++ = 0x50 + iregNo(i->Xin.Push.src->Xrmi.Reg.reg);
+            goto done;
         default: 
             goto bad;
       }
@@ -1550,6 +1570,36 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i )
       }
       break;
 
+   case Xin_Set32:
+      /* Make the destination register be 1 or 0, depending on whether
+         the relevant condition holds.  We have to dodge and weave
+         when the destination is %esi or %edi as we cannot directly
+         emit the native 'setb %reg' for those.  Further complication:
+         the top 24 bits of the destination should be forced to zero,
+         but doing 'xor %r,%r' kills the flag(s) we are about to read.
+         Sigh. */
+      /* First: movl $0, %dst */
+      *p++ = 0xB8 + iregNo(i->Xin.Set32.dst);
+      p = emit32(p, 0);
+      /* Do we need to swap in %eax? */
+
+      if (iregNo(i->Xin.Set32.dst) >= 4) {
+         /* xchg %eax, %dst */
+         *p++ = 0x90 + iregNo(i->Xin.Set32.dst);
+         /* setb lo8(%reg) */
+         *p++ = 0x0F; 
+         *p++ = 0x90 + (UChar)(i->Xin.Set32.cond);
+         p = doAMode_R(p, fake(0), hregX86_EAX());
+         /* xchg %eax, %dst */
+         *p++ = 0x90 + iregNo(i->Xin.Set32.dst);
+      } else {
+         /* setb lo8(%reg) */
+         *p++ = 0x0F; 
+         *p++ = 0x90 + (UChar)(i->Xin.Set32.cond);
+         p = doAMode_R(p, fake(0), i->Xin.Set32.dst);
+      }
+      goto done;
+
    case Xin_Store:
       if (i->Xin.Store.sz == 2) {
          /* This case, at least, is simple, given that we can
@@ -1652,13 +1702,13 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i )
         /* ffree %st(7) */
         p = do_ffree_st7(p);
         /* pushl %hi ; pushl %lo */
-        *p++ = 0x50 + hregNumber(i->Xin.FpI64.iregHi);
-        *p++ = 0x50 + hregNumber(i->Xin.FpI64.iregLo);
+        *p++ = 0x50 + iregNo(i->Xin.FpI64.iregHi);
+        *p++ = 0x50 + iregNo(i->Xin.FpI64.iregLo);
         /* fildll 0(%esp) */
         *p++ = 0xDF; *p++ = 0x6C; *p++ = 0x24; *p++ = 0x00; 
         /* addl $8, %esp */
         *p++ = 0x83; *p++ = 0xC4; *p++ = 0x08; 
-        p = do_fstp_st(p, 1+hregNumber(i->Xin.FpI64.freg));
+        p = do_fstp_st(p, 1+iregNo(i->Xin.FpI64.freg));
         goto done;
      }
 
index 5e698f703fa66a0da02b93400d2eb9599c3138fd..b77e30d9c9b97e922c22e3b23fbc3d4e250b8997 100644 (file)
@@ -273,6 +273,7 @@ typedef
       Xin_CMov32,    /* conditional move */
       Xin_LoadEX,    /* mov{s,z}{b,w}l from mem to reg */
       Xin_Store,     /* store 16/8 bit value in memory */
+      Xin_Set32,     /* convert condition code to 32-bit value */
       Xin_FpUnary,   /* FP fake unary op */
       Xin_FpBinary,  /* FP fake binary op */
       Xin_FpLdSt,    /* FP fake load/store */
@@ -366,6 +367,11 @@ typedef
             HReg      src;
             X86AMode* dst;
          } Store;
+         /* Convert a x86 condition code to a 32-bit value (0 or 1). */
+         struct {
+            X86CondCode cond;
+            HReg        dst;
+         } Set32;
          /* X86 Floating point (fake 3-operand, "flat reg file" insns) */
          struct {
             X86FpOp op;
@@ -409,6 +415,7 @@ extern X86Instr* X86Instr_CMov32   ( X86CondCode, X86RM* src, HReg dst );
 extern X86Instr* X86Instr_LoadEX   ( UChar szSmall, Bool syned,
                                      X86AMode* src, HReg dst );
 extern X86Instr* X86Instr_Store    ( UChar sz, HReg src, X86AMode* dst );
+extern X86Instr* X86Instr_Set32    ( X86CondCode cond, HReg dst );
 extern X86Instr* X86Instr_FpUnary  ( X86FpOp op, HReg src, HReg dst );
 extern X86Instr* X86Instr_FpBinary ( X86FpOp op, HReg srcL, HReg srcR, HReg dst );
 extern X86Instr* X86Instr_FpLdSt   ( Bool isLoad, UChar sz, HReg reg, X86AMode* );
index a653da2071f6f81e848dc0595f54358816aaa94f..1dca90d49942404351101c42308dfe813ec0b071 100644 (file)
@@ -230,6 +230,7 @@ static X86RM*    iselIntExpr_RM    ( ISelEnv* env, IRExpr* e );
 static X86AMode* iselIntExpr_AMode ( ISelEnv* env, IRExpr* e );
 static void      iselIntExpr64     ( HReg* rHi, HReg* rLo, 
                                      ISelEnv* env, IRExpr* e );
+static X86CondCode iselCondCode ( ISelEnv* env, IRExpr* e );
 
 
 static X86Instr* mk_MOVsd_RR ( HReg src, HReg dst )
@@ -487,6 +488,12 @@ static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e )
             addInstr(env, X86Instr_Sh32(Xsh_SHR, shift, X86RM_Reg(dst)));
             return dst;
          }
+         case Iop_1Uto8: {
+            HReg dst         = newVRegI(env);
+            X86CondCode cond = iselCondCode(env, e->Iex.Unop.arg);
+            addInstr(env, X86Instr_Set32(cond,dst));
+            return dst;
+         }
          case Iop_16to8:
          case Iop_32to8:
          case Iop_32to16:
@@ -776,6 +783,15 @@ static X86CondCode iselCondCode ( ISelEnv* env, IRExpr* e )
       return Xcc_Z;
    }
 
+   /* var */
+   if (e->tag == Iex_Tmp) {
+      HReg r32 = lookupIRTemp(env, e->Iex.Tmp.tmp);
+      HReg dst = newVRegI(env);
+      addInstr(env, mk_MOVsd_RR(r32,dst));
+      addInstr(env, X86Instr_Alu32R(Xalu_AND,X86RMI_Imm(1),dst));
+      return Xcc_NZ;
+   }
+
    ppIRExpr(e);
    vpanic("iselCondCode");
 }
@@ -1145,6 +1161,12 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
          addInstr(env, mk_MOVsd_RR(rLo,dstLo) );
          return;
       }
+      if (ty == Ity_Bit) {
+         X86CondCode cond = iselCondCode(env, stmt->Ist.Tmp.expr);
+         HReg dst = lookupIRTemp(env, tmp);
+         addInstr(env, X86Instr_Set32(cond, dst));
+         return;
+      }
       if (ty == Ity_F64) {
          HReg dst = lookupIRTemp(env, tmp);
          HReg src = iselDblExpr(env, stmt->Ist.Tmp.expr);
@@ -1202,7 +1224,6 @@ HInstrArray* iselBB_X86 ( IRBB* bb, Addr64(*find_helper)(Char*) )
 {
    Int     i, j;
    HReg    hreg, hregHI;
-   IRStmt* stmt;
 
    /* Make up an initial environment to use. */
    ISelEnv* env = LibVEX_Alloc(sizeof(ISelEnv));
@@ -1245,8 +1266,8 @@ HInstrArray* iselBB_X86 ( IRBB* bb, Addr64(*find_helper)(Char*) )
    env->vreg_ctr = j;
 
    /* Ok, finally we can iterate over the statements. */
-   for (stmt = bb->stmts; stmt; stmt=stmt->link)
-      iselStmt(env,stmt);
+   for (i = 0; i < bb->stmts_used; i++)
+      iselStmt(env,bb->stmts[i]);
 
    iselNext(env,bb->next,bb->jumpkind);
 
index f6862ff040a142fa0e7853d790285b2fa38bf785..7415517d22c7713da1920140b27616db31a6d3b8 100644 (file)
@@ -269,15 +269,17 @@ void ppIRTypeEnv ( IRTypeEnv* env ) {
 }
 
 
+
+
 void ppIRBB ( IRBB* bb )
 {
-   IRStmt* s;
+   Int i;
    vex_printf("IRBB {\n");
    ppIRTypeEnv(bb->tyenv);
    vex_printf("\n");
-   for (s = bb->stmts; s; s = s->link) {
+   for (i = 0; i < bb->stmts_used; i++) {
       vex_printf( "   ");
-      ppIRStmt(s);
+      ppIRStmt(bb->stmts[i]);
       vex_printf( "\n");
    }
    vex_printf( "   goto {");
@@ -413,7 +415,6 @@ IRExpr* IRExpr_Mux0X ( IRExpr* cond, IRExpr* expr0, IRExpr* exprX ) {
 IRStmt* IRStmt_Put ( Int off, IRExpr* value ) {
    IRStmt* s         = LibVEX_Alloc(sizeof(IRStmt));
    s->tag            = Ist_Put;
-   s->link           = NULL;
    s->Ist.Put.offset = off;
    s->Ist.Put.expr   = value;
    return s;
@@ -422,7 +423,6 @@ IRStmt* IRStmt_PutI ( IRExpr* off, IRExpr* value,
                       UShort minoff, UShort maxoff ) {
    IRStmt* s          = LibVEX_Alloc(sizeof(IRStmt));
    s->tag             = Ist_PutI;
-   s->link            = NULL;
    s->Ist.PutI.offset = off;
    s->Ist.PutI.expr   = value;
    s->Ist.PutI.minoff = minoff;
@@ -432,7 +432,6 @@ IRStmt* IRStmt_PutI ( IRExpr* off, IRExpr* value,
 IRStmt* IRStmt_Tmp ( IRTemp tmp, IRExpr* expr ) {
    IRStmt* s       = LibVEX_Alloc(sizeof(IRStmt));
    s->tag          = Ist_Tmp;
-   s->link         = NULL;
    s->Ist.Tmp.tmp  = tmp;
    s->Ist.Tmp.expr = expr;
    return s;
@@ -440,7 +439,6 @@ IRStmt* IRStmt_Tmp ( IRTemp tmp, IRExpr* expr ) {
 IRStmt* IRStmt_STle ( IRExpr* addr, IRExpr* value ) {
    IRStmt* s        = LibVEX_Alloc(sizeof(IRStmt));
    s->tag           = Ist_STle;
-   s->link          = NULL;
    s->Ist.STle.addr = addr;
    s->Ist.STle.data = value;
    return s;
@@ -448,24 +446,40 @@ IRStmt* IRStmt_STle ( IRExpr* addr, IRExpr* value ) {
 IRStmt* IRStmt_Exit ( IRExpr* cond, IRConst* dst ) {
    IRStmt* s        = LibVEX_Alloc(sizeof(IRStmt));
    s->tag           = Ist_Exit;
-   s->link          = NULL;
    s->Ist.Exit.cond = cond;
    s->Ist.Exit.dst  = dst;
    return s;
 }
 
-/* Constructors -- IRBB */
+/* Constructors -- IRBB (sort of) */
 
-IRBB* mkIRBB ( IRTypeEnv* env, IRStmt* stmts, 
-               IRExpr* next, IRJumpKind jumpkind ) {
-   IRBB* bb     = LibVEX_Alloc(sizeof(IRBB));
-   bb->tyenv    = env;
-   bb->stmts    = stmts;
-   bb->next     = next;
-   bb->jumpkind = jumpkind;
+IRBB* emptyIRBB ( void )
+{
+   IRBB* bb       = LibVEX_Alloc(sizeof(IRBB));
+   bb->tyenv      = emptyIRTypeEnv();
+   bb->stmts_used = 0;
+   bb->stmts_size = 8;
+   bb->stmts      = LibVEX_Alloc(bb->stmts_size * sizeof(IRStmt*));
+   bb->next       = NULL;
+   bb->jumpkind   = Ijk_Boring;
    return bb;
 }
 
+void addStmtToIRBB ( IRBB* bb, IRStmt* st )
+{
+   Int i;
+   if (bb->stmts_used == bb->stmts_size) {
+      IRStmt** stmts2 = LibVEX_Alloc(2 * bb->stmts_size * sizeof(IRStmt*));
+      for (i = 0; i < bb->stmts_size; i++)
+         stmts2[i] = bb->stmts[i];
+      bb->stmts = stmts2;
+      bb->stmts_size *= 2;
+   }
+   vassert(bb->stmts_used < bb->stmts_size);
+   bb->stmts[bb->stmts_used] = st;
+   bb->stmts_used++;
+}
+
 
 /*---------------------------------------------------------------*/
 /*--- Primop types                                            ---*/
@@ -578,10 +592,12 @@ void typeOfPrimop ( IROp op, IRType* t_dst, IRType* t_arg1, IRType* t_arg2 )
 
 
 /*---------------------------------------------------------------*/
-/*--- Helper functions for the IR                             ---*/
+/*--- Helper functions for the IR -- IR Type Environments     ---*/
 /*---------------------------------------------------------------*/
 
-IRTypeEnv* newIRTypeEnv ( void )
+/* Make a new, empty IRTypeEnv. */
+
+IRTypeEnv* emptyIRTypeEnv ( void )
 {
    IRTypeEnv* env   = LibVEX_Alloc(sizeof(IRTypeEnv));
    env->types       = LibVEX_Alloc(8 * sizeof(IRType));
@@ -590,6 +606,22 @@ IRTypeEnv* newIRTypeEnv ( void )
    return env;
 }
 
+/* Make an exact copy of the given IRTypeEnv, usually so we can
+   add new stuff to the copy without messing up the original. */
+
+IRTypeEnv* copyIRTypeEnv ( IRTypeEnv* src )
+{
+   Int i;
+   IRTypeEnv* dst = LibVEX_Alloc(sizeof(IRTypeEnv));
+   dst->types_size = src->types_size;
+   dst->types_used = src->types_used;
+   dst->types = LibVEX_Alloc(dst->types_size * sizeof(IRType));
+   for (i = 0; i < src->types_used; i++)
+      dst->types[i] = src->types[i];
+   return dst;
+}
+
+/* Allocate a new IRTemp, given its type. */
 
 IRTemp newIRTemp ( IRTypeEnv* env, IRType ty )
 {
@@ -613,6 +645,8 @@ IRTemp newIRTemp ( IRTypeEnv* env, IRType ty )
    }
 }
 
+/* Find the type of a temporary previously allocated in an
+   environment. */
 
 IRType lookupIRTypeEnv ( IRTypeEnv* env, IRTemp tmp )
 {
@@ -622,6 +656,10 @@ IRType lookupIRTypeEnv ( IRTypeEnv* env, IRTemp tmp )
 }
 
 
+/*---------------------------------------------------------------*/
+/*--- Helper functions for the IR -- finding types of exprs   ---*/
+/*---------------------------------------------------------------*/
+
 IRType typeOfIRConst ( IRConst* con )
 {
    switch (con->tag) {
@@ -919,6 +957,11 @@ void sanityCheckIRBB ( IRBB* bb, IRType guest_word_size )
    vassert(guest_word_size == Ity_I32
           || guest_word_size == Ity_I64);
 
+   if (bb->stmts_used < 0 || bb->stmts_size < 8
+       || bb->stmts_used > bb->stmts_size)
+      /* this BB is so strange we can't even print it */
+      vpanic("sanityCheckIRBB: stmts array limits wierd");
+
    /* Ensure each temp has a plausible type. */
    for (i = 0; i < n_temps; i++) {
       IRType ty = lookupIRTypeEnv(bb->tyenv,(IRTemp)i);
@@ -935,7 +978,8 @@ void sanityCheckIRBB ( IRBB* bb, IRType guest_word_size )
    for (i = 0; i < n_temps; i++)
       def_counts[i] = 0;
 
-   for (stmt = bb->stmts; stmt; stmt=stmt->link) {
+   for (i = 0; i < bb->stmts_used; i++) {
+      stmt = bb->stmts[i];
       useBeforeDef_Stmt(bb,stmt,def_counts);
       if (stmt->tag == Ist_Tmp) {
          if (stmt->Ist.Tmp.tmp < 0 || stmt->Ist.Tmp.tmp >= n_temps)
@@ -947,8 +991,8 @@ void sanityCheckIRBB ( IRBB* bb, IRType guest_word_size )
    }
 
    /* Typecheck everything. */
-   for (stmt = bb->stmts; stmt; stmt=stmt->link)
-      tcStmt( bb, stmt, guest_word_size );
+   for (i = 0; i < bb->stmts_used; i++)
+      tcStmt( bb, bb->stmts[i], guest_word_size );
    if (typeOfIRExpr(bb->tyenv,bb->next) != guest_word_size)
       sanityCheckFail(bb, NULL, "bb->next field has wrong type");
 }
index 9cfcf1e7323ede597cd22fdb7920ab424594b77c..240f25bad3da22d114df742369f9bccff43b4582 100644 (file)
@@ -115,6 +115,152 @@ static void addToH64 ( Hash64* h, ULong key, ULong val )
    h->used++;
 }
 
+/*---------------------------------------------------------------*/
+/*--- Flattening out a BB into pure SSA form                  ---*/
+/*---------------------------------------------------------------*/
+
+/* Clone the NULL-terminated vector of IRExpr*s attached to a
+   CCall. */
+
+static IRExpr** copyIexCCallArgs ( IRExpr** vec )
+{
+   Int      i;
+   IRExpr** newvec;
+   for (i = 0; vec[i]; i++)
+      ;
+   newvec = LibVEX_Alloc((i+1)*sizeof(IRExpr*));
+   for (i = 0; vec[i]; i++)
+      newvec[i] = vec[i];
+   newvec[i] = NULL;
+   return newvec;
+}
+
+
+/* Flatten out 'ex' so it is atomic, returning a new expression with
+   the same value, after having appended extra IRTemp assignments to
+   the end of 'bb'. */
+
+static IRExpr* flatten_Expr ( IRBB* bb, IRExpr* ex )
+{
+   Int i;
+   IRExpr** newargs;
+   IRType ty = typeOfIRExpr(bb->tyenv, ex);
+   IRTemp t1;
+
+   switch (ex->tag) {
+
+      case Iex_Get:
+         t1 = newIRTemp(bb->tyenv, ty);
+         addStmtToIRBB(bb, 
+            IRStmt_Tmp(t1, ex));
+         return IRExpr_Tmp(t1);
+
+      case Iex_Binop:
+         t1 = newIRTemp(bb->tyenv, ty);
+         addStmtToIRBB(bb, IRStmt_Tmp(t1, 
+            IRExpr_Binop(ex->Iex.Binop.op,
+                         flatten_Expr(bb, ex->Iex.Binop.arg1),
+                         flatten_Expr(bb, ex->Iex.Binop.arg2))));
+         return IRExpr_Tmp(t1);
+
+      case Iex_Unop:
+         t1 = newIRTemp(bb->tyenv, ty);
+         addStmtToIRBB(bb, IRStmt_Tmp(t1, 
+            IRExpr_Unop(ex->Iex.Unop.op,
+                        flatten_Expr(bb, ex->Iex.Unop.arg))));
+         return IRExpr_Tmp(t1);
+
+      case Iex_LDle:
+         t1 = newIRTemp(bb->tyenv, ty);
+         addStmtToIRBB(bb, IRStmt_Tmp(t1,
+            IRExpr_LDle(ex->Iex.LDle.ty, 
+                        flatten_Expr(bb, ex->Iex.LDle.addr))));
+         return IRExpr_Tmp(t1);
+
+      case Iex_CCall:
+         newargs = copyIexCCallArgs(ex->Iex.CCall.args);
+         for (i = 0; newargs[i]; i++)
+            newargs[i] = flatten_Expr(bb, newargs[i]);
+         t1 = newIRTemp(bb->tyenv, ty);
+         addStmtToIRBB(bb, IRStmt_Tmp(t1,
+            IRExpr_CCall(ex->Iex.CCall.name,
+                         ex->Iex.CCall.retty,
+                         newargs)));
+         return IRExpr_Tmp(t1);
+
+      case Iex_Mux0X:
+         t1 = newIRTemp(bb->tyenv, ty);
+         addStmtToIRBB(bb, IRStmt_Tmp(t1,
+            IRExpr_Mux0X(flatten_Expr(bb, ex->Iex.Mux0X.cond),
+                         flatten_Expr(bb, ex->Iex.Mux0X.expr0),
+                         flatten_Expr(bb, ex->Iex.Mux0X.exprX))));
+         return IRExpr_Tmp(t1);
+
+      case Iex_Const:
+      case Iex_Tmp:
+         return ex;
+
+      default:
+         vex_printf("\n");
+         ppIRExpr(ex); 
+         vex_printf("\n");
+         vpanic("flatten_Expr");
+   }
+}
+
+
+/* Append a completely flattened form of 'st' to the end of 'bb'. */
+
+static void flatten_Stmt ( IRBB* bb, IRStmt* st )
+{
+   IRExpr *e1, *e2;
+   switch (st->tag) {
+      case Ist_Put:
+         e1 = flatten_Expr(bb, st->Ist.Put.expr);
+         addStmtToIRBB(bb, IRStmt_Put(st->Ist.Put.offset, e1));
+         break;
+#if 0
+      case Ist_PutI:
+        e1 = flatten_Expr(bb, st->Ist.PutI.offset);
+        e2 = flatten_Expr(bb, st->Ist.PutI.expr);
+        addStmtToIRBB(bb, IRStmt_PutI(e1, e2, st->Ist.PutI.minoff,
+                          st->Ist.PutI.maxoff));
+        break;
+#endif
+      case Ist_Tmp:
+         e1 = flatten_Expr(bb, st->Ist.Tmp.expr);
+         addStmtToIRBB(bb, IRStmt_Tmp(st->Ist.Tmp.tmp, e1));
+         break;
+      case Ist_STle:
+         e1 = flatten_Expr(bb, st->Ist.STle.addr);
+         e2 = flatten_Expr(bb, st->Ist.STle.data);
+         addStmtToIRBB(bb, IRStmt_STle(e1,e2));
+         break;
+      case Ist_Exit:
+         e1 = flatten_Expr(bb, st->Ist.Exit.cond);
+         addStmtToIRBB(bb, IRStmt_Exit(e1, st->Ist.Exit.dst));
+         break;
+      default:
+         vex_printf("\n");
+         ppIRStmt(st); 
+         vex_printf("\n");
+         vpanic("flatten_Stmt");
+   }
+}
+
+static IRBB* flatten_BB ( IRBB* in )
+{
+   Int   i;
+   IRBB* out;
+   out = emptyIRBB();
+   out->tyenv = copyIRTypeEnv( in->tyenv );
+   for (i = 0; i < in->stmts_used; i++)
+      flatten_Stmt( out, in->stmts[i] );
+   out->next     = flatten_Expr( out, in->next );
+   out->jumpkind = in->jumpkind;
+   return out;
+}
+
 
 /*---------------------------------------------------------------*/
 /*--- iropt main                                              ---*/
@@ -130,7 +276,8 @@ static void addToH64 ( Hash64* h, ULong key, ULong val )
 /* exported from this file */
 IRBB* do_iropt_BB ( IRBB* bb0 )
 {
-   return bb0;
+   IRBB* flat = flatten_BB ( bb0 );
+   return flat;
 }
 
 
index 096d2e8ad0c4aa9b7de931b4d9242a1e87fc8bdd..fb88ae4cc09480ef4402b038b5e368ad1592714f 100644 (file)
@@ -174,6 +174,7 @@ TranslateResult LibVEX_Translate (
 
    /* Clean it up, hopefully a lot. */
    irbb = do_iropt_BB ( irbb );
+   sanityCheckIRBB(irbb, Ity_I32);
 
    if (vex_verbosity > 0) {
       vex_printf("\n-------- After IR optimisation --------\n");
index cdcb9fc01d4c468c8ba44ff13ab38f8ccf7b78e8..b97e10ec293d5bd7176a73e60e145cb595eab2c6 100644 (file)
@@ -285,7 +285,6 @@ typedef
             IRConst* dst;
          } Exit;
       } Ist;
-      struct _IRStmt* link;
    }
    IRStmt;
 
@@ -342,22 +341,27 @@ typedef
 extern void ppIRTypeEnv ( IRTypeEnv* );
 
 
-/* Basic blocks contain 4 fields:
+/* Basic blocks contain:
    - A table giving a type for each temp
-   - A list of statements
+   - An expandable array of statements
    - An expression of type 32 or 64 bits, depending on the
      guest's word size, indicating the next destination.
+   - An indication of any special actions (JumpKind) needed
+     for this final jump.
 */
 typedef
    struct _IRBB {
       IRTypeEnv* tyenv;
-      IRStmt*    stmts;
+      IRStmt**   stmts;
+      Int        stmts_size;
+      Int        stmts_used;
       IRExpr*    next;
       IRJumpKind jumpkind;
    }
    IRBB;
 
-extern IRBB* mkIRBB ( IRTypeEnv*, IRStmt*, IRExpr*, IRJumpKind );
+extern IRBB* emptyIRBB ( void );
+extern void  addStmtToIRBB ( IRBB*, IRStmt* );
 
 extern void ppIRBB ( IRBB* );
 
@@ -367,9 +371,10 @@ extern void ppIRBB ( IRBB* );
 /*---------------------------------------------------------------*/
 
 /* For messing with IR type environments */
-extern IRTypeEnv* newIRTypeEnv    ( void );
+extern IRTypeEnv* emptyIRTypeEnv  ( void );
 extern IRTemp     newIRTemp       ( IRTypeEnv*, IRType );
 extern IRType     lookupIRTypeEnv ( IRTypeEnv*, IRTemp );
+extern IRTypeEnv* copyIRTypeEnv   ( IRTypeEnv* );
 
 /* What is the type of this expression? */
 extern IRType typeOfIRConst ( IRConst* );