]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
First part of IR sanity checking: def/use checks.
authorJulian Seward <jseward@acm.org>
Wed, 14 Jul 2004 22:36:10 +0000 (22:36 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 14 Jul 2004 22:36:10 +0000 (22:36 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@85

VEX/priv/ir/ir_defs.c
VEX/priv/main/vex_main.c
VEX/priv/main/vex_util.c
VEX/pub/libvex_ir.h

index c94450f2311951cf4502bab5d07d2d2067282e5e..33c9eafb55c52f0122d9bd97966029d8473619af 100644 (file)
@@ -235,7 +235,9 @@ void ppIRTypeEnv ( IRTypeEnv* env ) {
 void ppIRBB ( IRBB* bb )
 {
    IRStmt* s;
+   vex_printf("IRBB {\n");
    ppIRTypeEnv(bb->tyenv);
+   vex_printf("\n");
    for (s = bb->stmts; s; s = s->link) {
       vex_printf( "   ");
       ppIRStmt(s);
@@ -245,7 +247,7 @@ void ppIRBB ( IRBB* bb )
    ppIRJumpKind(bb->jumpkind);
    vex_printf( "} ");
    ppIRExpr( bb->next );
-   vex_printf( "\n");
+   vex_printf( "\n}\n");
 }
 
 
@@ -474,14 +476,118 @@ IRType typeOfIRExpr ( IRTypeEnv* tyenv, IRExpr* e )
 /* Checks:
 
    Everything is type-consistent.  No ill-typed anything.
+   The target address at the end of the BB is a 32- or 64-
+   bit expression, depending on the guest's word size.
 
    Each temp is assigned only once, before its uses.
+ */
 
+static
+__attribute((noreturn))
+void sanityCheckFail ( IRBB* bb, IRStmt* stmt, Char* what )
+{
+   vex_printf("\nIR SANITY CHECK FAILURE\n\n");
+   ppIRBB(bb);
+   if (stmt) {
+      vex_printf("\nIN STATEMENT:\n\n");
+      ppIRStmt(stmt);
+   }
+   vex_printf("\n\nERROR = %s\n\n", what );
+   vpanic("sanityCheckFail: exiting due to bad IR");
+}
 
- */
 
-void sanityCheckIRBB ( IRBB* bb )
+/* Traverse a Stmt/Expr, inspecting IRTemp uses.  Report any out of
+   range ones.  Report any which are read and for which the current
+   def_count is zero. */
+
+static
+void useBeforeDef_Expr ( IRBB* bb, IRStmt* stmt, IRExpr* expr, Int* def_counts )
 {
+   Int i;
+   switch (expr->tag) {
+      case Iex_Get: 
+         break;
+      case Iex_Tmp: 
+         if (expr->Iex.Tmp.tmp < 0 || expr->Iex.Tmp.tmp >= bb->tyenv->types_used)
+            sanityCheckFail(bb,stmt, "out of range Temp in IRExpr");
+         if (def_counts[expr->Iex.Tmp.tmp] < 1)
+            sanityCheckFail(bb,stmt, "IRTemp def before use in IRExpr");
+         break;
+      case Iex_Binop:
+         useBeforeDef_Expr(bb,stmt,expr->Iex.Binop.arg1,def_counts);
+         useBeforeDef_Expr(bb,stmt,expr->Iex.Binop.arg2,def_counts);
+         break;
+      case Iex_Unop:
+         useBeforeDef_Expr(bb,stmt,expr->Iex.Unop.arg,def_counts);
+         break;
+      case Iex_LDle:
+         useBeforeDef_Expr(bb,stmt,expr->Iex.LDle.addr,def_counts);
+         break;
+      case Iex_Const:
+         break;
+      case Iex_CCall:
+         for (i = 0; expr->Iex.CCall.args[i]; i++)
+            useBeforeDef_Expr(bb,stmt,expr->Iex.CCall.args[i],def_counts);
+         break;
+   }
+}
+
+static
+void useBeforeDef_Stmt ( IRBB* bb, IRStmt* stmt, Int* def_counts )
+{
+   switch (stmt->tag) {
+      case Ist_Put:
+         if (stmt->Ist.Put.guard)
+            useBeforeDef_Expr(bb,stmt,stmt->Ist.Put.guard,def_counts);
+         useBeforeDef_Expr(bb,stmt,stmt->Ist.Put.expr,def_counts);
+         break;
+      case Ist_Tmp:
+         useBeforeDef_Expr(bb,stmt,stmt->Ist.Tmp.expr,def_counts);
+         break;
+      case Ist_STle:
+         useBeforeDef_Expr(bb,stmt,stmt->Ist.STle.addr,def_counts);
+         useBeforeDef_Expr(bb,stmt,stmt->Ist.STle.data,def_counts);
+         break;
+      case Ist_Exit:
+         useBeforeDef_Expr(bb,stmt,stmt->Ist.Exit.cond,def_counts);
+         break;
+      default: 
+         vpanic("useBeforeDef_Stmt");
+   }
+}
+
+
+void sanityCheckIRBB ( IRBB* bb, IRType guest_word_size )
+{
+   Int     i;
+   IRStmt* stmt;
+   Int     n_temps    = bb->tyenv->types_used;
+   Int*    def_counts = LibVEX_Alloc(n_temps * sizeof(Int));
+
+   vassert(guest_word_size == Ity_I32
+          || guest_word_size == Ity_I64);
+
+   for (i = 0; i < n_temps; i++)
+      def_counts[i] = 0;
+
+   /* Count the defs of each temp.  Only one def is allowed.
+      Also, check that each used temp has already been defd. */
+   for (stmt = bb->stmts; stmt; stmt=stmt->link) {
+      useBeforeDef_Stmt(bb,stmt,def_counts);
+      if (stmt->tag == Ist_Tmp) {
+         if (stmt->Ist.Tmp.tmp < 0 || stmt->Ist.Tmp.tmp >= n_temps)
+            sanityCheckFail(bb, stmt, "Invalid temp in Tmp assignment");
+         def_counts[stmt->Ist.Tmp.tmp]++;
+         if (def_counts[stmt->Ist.Tmp.tmp] > 1)
+            sanityCheckFail(bb, stmt, "Tmp assigned more than once");
+      }
+   }
+
+   for (i = 0; i < n_temps; i++)
+     vex_printf("%d ", def_counts[i]);
+   vex_printf("\n");
+
 }
 
 /*---------------------------------------------------------------*/
index 33b68051a9de30538da901dd7c478f810e181221..fd8aec4ac300b0b022fefb11bd73b85ea6606289 100644 (file)
@@ -138,6 +138,7 @@ TranslateResult LibVEX_Translate (
       LibVEX_Clear(False);
       return TransAccessFail;
    }
+   sanityCheckIRBB(irbb, Ity_I32);
 return TransOK;
    /* Get the thing instrumented. */
    if (instrument)
index 73d70a65eb576bd0bc85bbbc1a72fb5ffd1a0849..cfb2c5ec624a5762caa1e5328988ff8e9edc1b6b 100644 (file)
@@ -43,12 +43,13 @@ static ULong storage_count_allocs_TOT = 0;
 void* LibVEX_Alloc ( Int nbytes ) 
 {
    vassert(vex_initdone);
-   vassert(nbytes > 0);
+   vassert(nbytes >= 0);
    if (vex_valgrind_support) {
       /* ugly hack */
       extern void* malloc ( int );
       return malloc(nbytes);
    } else {
+      if (nbytes == 0) nbytes = 8;
       nbytes = (nbytes + 7) & ~7;
       if (storage_used + nbytes > N_STORAGE_BYTES)
          vpanic("VEX storage exhausted.\n"
index 5c382ab3f4d65bb0bbcb9c23f18ece6f9b70de19..81a3d9806fd84d6409e318149b19c45bc4d962da 100644 (file)
@@ -310,6 +310,8 @@ extern IRType     lookupIRTypeEnv ( IRTypeEnv*, IRTemp );
 /* What is the type of this expression? */
 extern IRType typeOfIRExpr ( IRTypeEnv*, IRExpr* );
 
+/* Sanity check a BB of IR */
+extern void sanityCheckIRBB ( IRBB* bb, IRType guest_word_size );
 
 #endif /* ndef __LIBVEX_IR_H */