⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iropt.c

📁 unix下调试内存泄露的工具源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*---------------------------------------------------------------*//*---                                                         ---*//*--- This file (ir/iropt.c) is                               ---*//*--- Copyright (C) OpenWorks LLP.  All rights reserved.      ---*//*---                                                         ---*//*---------------------------------------------------------------*//*   This file is part of LibVEX, a library for dynamic binary   instrumentation and translation.   Copyright (C) 2004-2005 OpenWorks LLP.  All rights reserved.   This library is made available under a dual licensing scheme.   If you link LibVEX against other code all of which is itself   licensed under the GNU General Public License, version 2 dated June   1991 ("GPL v2"), then you may use LibVEX under the terms of the GPL   v2, as appearing in the file LICENSE.GPL.  If the file LICENSE.GPL   is missing, you can obtain a copy of the GPL v2 from the Free   Software Foundation Inc., 51 Franklin St, Fifth Floor, Boston, MA   02110-1301, USA.   For any other uses of LibVEX, you must first obtain a commercial   license from OpenWorks LLP.  Please contact info@open-works.co.uk   for information about commercial licensing.   This software is provided by OpenWorks LLP "as is" and any express   or implied warranties, including, but not limited to, the implied   warranties of merchantability and fitness for a particular purpose   are disclaimed.  In no event shall OpenWorks LLP be liable for any   direct, indirect, incidental, special, exemplary, or consequential   damages (including, but not limited to, procurement of substitute   goods or services; loss of use, data, or profits; or business   interruption) however caused and on any theory of liability,   whether in contract, strict liability, or tort (including   negligence or otherwise) arising in any way out of the use of this   software, even if advised of the possibility of such damage.   Neither the names of the U.S. Department of Energy nor the   University of California nor the names of its contributors may be   used to endorse or promote products derived from this software   without prior written permission.*/#include "libvex_basictypes.h"#include "libvex_ir.h"#include "libvex.h"#include "main/vex_util.h"#include "main/vex_globals.h"#include "ir/iropt.h"/* Set to 1 for lots of debugging output. */#define DEBUG_IROPT 0/* What iropt does, 29 Dec 04.   It takes an IRBB and produces a new one with the same meaning,   defined thus:   After execution of the new BB, all guest state and guest memory is   the same as after execution of the original.  This is true   regardless of how the block was exited (at the end vs side exit).   In addition, parts of the guest state will be identical to that   created by execution of the original at the following observation   points:   * In a dirty helper call, any parts of the guest state that the     helper states that it reads or modifies will be up to date.     Also, guest memory will be up to date.  Parts of the guest state     not marked as being read or modified by the helper cannot be     assumed to be up-to-date at the point where the helper is called.   * Immediately prior to any load or store, those parts of the guest     state marked as requiring precise exceptions will be up to date.     Also, guest memory will be up to date.  Parts of the guest state     not marked as requiring precise exceptions cannot be assumed to     be up-to-date at the point of the load/store.   The relative order of loads and stores (including loads/stores of   guest memory done by dirty helpers annotated as such) is not   changed.  However, the relative order of loads with no intervening   stores/modifies may be changed.     Transformation order   ~~~~~~~~~~~~~~~~~~~~   There are three levels of optimisation, controlled by   vex_control.iropt_level.  Define first:   "Cheap transformations" are the following sequence:      * Redundant-Get removal      * Redundant-Put removal      * Constant propagation/folding      * Dead code removal      * Specialisation of clean helper functions      * Dead code removal   "Expensive transformations" are the following sequence:      * CSE      * Folding of add/sub chains      * Redundant-GetI removal      * Redundant-PutI removal      * Dead code removal   Then the transformations are as follows, as defined by   vex_control.iropt_level:   Level 0:       * Flatten into atomic form.   Level 1: the following sequence:      * Flatten into atomic form.      * Cheap transformations.   Level 2: the following sequence      * Flatten into atomic form.      * Cheap transformations.      * If block contains GetI or PutI, Expensive transformations.      * Try unrolling loops.  Three possible outcomes:        - No effect: do nothing more.        - Unrolled a loop, and block does not contain GetI or PutI:          Do: * CSE              * Dead code removal        - Unrolled a loop, and block contains GetI or PutI:          Do: * Expensive transformations              * Cheap transformations*//* Implementation notes, 29 Dec 04.   TODO (important): I think rPutI removal ignores precise exceptions   and is therefore in a sense, wrong.  In the sense that PutIs are   assumed not to write parts of the guest state that we need to have   up-to-date at loads/stores.  So far on x86 guest that has not   mattered since indeed only the x87 FP registers and tags are   accessed using GetI/PutI, and there is no need so far for them to   be up to date at mem exception points.  The rPutI pass should be   fixed.   TODO: improve pessimistic handling of precise exceptions     in the tree builder.   TODO: check interaction of rGetI and dirty helpers.       F64i constants are treated differently from other constants.   They are not regarded as atoms, and instead lifted off and   bound to temps.  This allows them to participate in CSE, which   is important for getting good performance for x86 guest code.   CSE up F64 literals (already doing F64is)   CSE: consider carefully the requirement for precise exns        prior to making CSE any more aggressive.  *//*---------------------------------------------------------------*//*--- Finite mappery, of a sort                               ---*//*---------------------------------------------------------------*//* General map from HWord-sized thing HWord-sized thing.  Could be by   hashing, but it's not clear whether or not this would really be any   faster. */typedef   struct {      Bool*  inuse;      HWord* key;      HWord* val;      Int    size;      Int    used;   }   HashHW;static HashHW* newHHW ( void ){   HashHW* h = LibVEX_Alloc(sizeof(HashHW));   h->size   = 8;   h->used   = 0;   h->inuse  = LibVEX_Alloc(h->size * sizeof(Bool));   h->key    = LibVEX_Alloc(h->size * sizeof(HWord));   h->val    = LibVEX_Alloc(h->size * sizeof(HWord));   return h;}/* Look up key in the map. */static Bool lookupHHW ( HashHW* h, /*OUT*/HWord* val, HWord key ){   Int i;   /* vex_printf("lookupHHW(%llx)\n", key ); */   for (i = 0; i < h->used; i++) {      if (h->inuse[i] && h->key[i] == key) {         if (val)            *val = h->val[i];         return True;      }   }   return False;}/* Add key->val to the map.  Replaces any existing binding for key. */static void addToHHW ( HashHW* h, HWord key, HWord val ){   Int i, j;   /* vex_printf("addToHHW(%llx, %llx)\n", key, val); */   /* Find and replace existing binding, if any. */   for (i = 0; i < h->used; i++) {      if (h->inuse[i] && h->key[i] == key) {         h->val[i] = val;         return;      }   }   /* Ensure a space is available. */   if (h->used == h->size) {      /* Copy into arrays twice the size. */      Bool*  inuse2 = LibVEX_Alloc(2 * h->size * sizeof(Bool));      HWord* key2   = LibVEX_Alloc(2 * h->size * sizeof(HWord));      HWord* val2   = LibVEX_Alloc(2 * h->size * sizeof(HWord));      for (i = j = 0; i < h->size; i++) {         if (!h->inuse[i]) continue;         inuse2[j] = True;         key2[j] = h->key[i];         val2[j] = h->val[i];         j++;      }      h->used = j;      h->size *= 2;      h->inuse = inuse2;      h->key = key2;      h->val = val2;   }   /* Finally, add it. */   vassert(h->used < h->size);   h->inuse[h->used] = True;   h->key[h->used] = key;   h->val[h->used] = val;   h->used++;}/*---------------------------------------------------------------*//*--- Flattening out a BB into atomic SSA form                ---*//*---------------------------------------------------------------*//* Non-critical helper, heuristic for reducing the number of tmp-tmp   copies made by flattening.  If in doubt return False. */static Bool isFlat ( IRExpr* e ){   if (e->tag == Iex_Get)       return True;   if (e->tag == Iex_Binop)      return toBool( isIRAtom(e->Iex.Binop.arg1)                      && isIRAtom(e->Iex.Binop.arg2) );   if (e->tag == Iex_Load)      return isIRAtom(e->Iex.Load.addr);   return False;}/* 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_GetI:         t1 = newIRTemp(bb->tyenv, ty);         addStmtToIRBB(bb, IRStmt_Tmp(t1,            IRExpr_GetI(ex->Iex.GetI.descr,                        flatten_Expr(bb, ex->Iex.GetI.ix),                        ex->Iex.GetI.bias)));         return IRExpr_Tmp(t1);      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_Load:         t1 = newIRTemp(bb->tyenv, ty);         addStmtToIRBB(bb, IRStmt_Tmp(t1,            IRExpr_Load(ex->Iex.Load.end,                        ex->Iex.Load.ty,                         flatten_Expr(bb, ex->Iex.Load.addr))));         return IRExpr_Tmp(t1);      case Iex_CCall:         newargs = sopyIRExprVec(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.cee,                         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:         /* Lift F64i constants out onto temps so they can be CSEd            later. */         if (ex->Iex.Const.con->tag == Ico_F64i) {            t1 = newIRTemp(bb->tyenv, ty);            addStmtToIRBB(bb, IRStmt_Tmp(t1,               IRExpr_Const(ex->Iex.Const.con)));            return IRExpr_Tmp(t1);         } else {            /* Leave all other constants alone. */            return ex;         }      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 ){   Int i;   IRExpr  *e1, *e2;   IRDirty *d,  *d2;   switch (st->tag) {      case Ist_Put:         if (isIRAtom(st->Ist.Put.data)) {            /* optimisation to reduce the amount of heap wasted               by the flattener */            addStmtToIRBB(bb, st);         } else {            /* general case, always correct */            e1 = flatten_Expr(bb, st->Ist.Put.data);            addStmtToIRBB(bb, IRStmt_Put(st->Ist.Put.offset, e1));         }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -