📄 irdefs.c
字号:
/*---------------------------------------------------------------*/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++;}/*---------------------------------------------------------------*//*--- Helper functions for the IR -- IR Type Environments ---*//*---------------------------------------------------------------*//* Allocate a new IRTemp, given its type. */IRTemp newIRTemp ( IRTypeEnv* env, IRType ty ){ vassert(env); vassert(env->types_used >= 0); vassert(env->types_size >= 0); vassert(env->types_used <= env->types_size); if (env->types_used < env->types_size) { env->types[env->types_used] = ty; return env->types_used++; } else { Int i; Int new_size = env->types_size==0 ? 8 : 2*env->types_size; IRType* new_types = LibVEX_Alloc(new_size * sizeof(IRType)); for (i = 0; i < env->types_used; i++) new_types[i] = env->types[i]; env->types = new_types; env->types_size = new_size; return newIRTemp(env, ty); }}/*---------------------------------------------------------------*//*--- Helper functions for the IR -- finding types of exprs ---*//*---------------------------------------------------------------*/inline IRType typeOfIRTemp ( IRTypeEnv* env, IRTemp tmp ){ vassert(tmp >= 0); vassert(tmp < env->types_used); return env->types[tmp];}IRType typeOfIRConst ( IRConst* con ){ switch (con->tag) { case Ico_U1: return Ity_I1; case Ico_U8: return Ity_I8; case Ico_U16: return Ity_I16; case Ico_U32: return Ity_I32; case Ico_U64: return Ity_I64; case Ico_F64: return Ity_F64; case Ico_F64i: return Ity_F64; case Ico_V128: return Ity_V128; default: vpanic("typeOfIRConst"); }}IRType typeOfIRExpr ( IRTypeEnv* tyenv, IRExpr* e ){ IRType t_dst, t_arg1, t_arg2; start: switch (e->tag) { case Iex_Load: return e->Iex.Load.ty; case Iex_Get: return e->Iex.Get.ty; case Iex_GetI: return e->Iex.GetI.descr->elemTy; case Iex_Tmp: return typeOfIRTemp(tyenv, e->Iex.Tmp.tmp); case Iex_Const: return typeOfIRConst(e->Iex.Const.con); case Iex_Binop: typeOfPrimop(e->Iex.Binop.op, &t_dst, &t_arg1, &t_arg2); return t_dst; case Iex_Unop: typeOfPrimop(e->Iex.Unop.op, &t_dst, &t_arg1, &t_arg2); return t_dst; case Iex_CCall: return e->Iex.CCall.retty; case Iex_Mux0X: e = e->Iex.Mux0X.expr0; goto start; /* return typeOfIRExpr(tyenv, e->Iex.Mux0X.expr0); */ case Iex_Binder: vpanic("typeOfIRExpr: Binder is not a valid expression"); default: ppIRExpr(e); vpanic("typeOfIRExpr"); }}/* Is this any value actually in the enumeration 'IRType' ? */Bool isPlausibleIRType ( IRType ty ){ switch (ty) { case Ity_INVALID: case Ity_I1: case Ity_I8: case Ity_I16: case Ity_I32: case Ity_I64: case Ity_I128: case Ity_F32: case Ity_F64: case Ity_V128: return True; default: return False; }}/*---------------------------------------------------------------*//*--- Sanity checking -- FLATNESS ---*//*---------------------------------------------------------------*//* Check that the canonical flatness constraints hold on an IRStmt. The only place where any expression is allowed to be non-atomic is the RHS of IRStmt_Tmp. *//* Relies on: inline static Bool isAtom ( IRExpr* e ) { return e->tag == Iex_Tmp || e->tag == Iex_Const; }*/Bool isFlatIRStmt ( IRStmt* st ){ Int i; IRExpr* e; IRDirty* di; switch (st->tag) { case Ist_AbiHint: return isIRAtom(st->Ist.AbiHint.base); case Ist_Put: return isIRAtom(st->Ist.Put.data); case Ist_PutI: return toBool( isIRAtom(st->Ist.PutI.ix) && isIRAtom(st->Ist.PutI.data) ); case Ist_Tmp: /* This is the only interesting case. The RHS can be any expression, *but* all its subexpressions *must* be atoms. */ e = st->Ist.Tmp.data; switch (e->tag) { case Iex_Binder: return True; case Iex_Get: return True; case Iex_GetI: return isIRAtom(e->Iex.GetI.ix); case Iex_Tmp: return True; case Iex_Binop: return toBool( isIRAtom(e->Iex.Binop.arg1) && isIRAtom(e->Iex.Binop.arg2)); case Iex_Unop: return isIRAtom(e->Iex.Unop.arg); case Iex_Load: return isIRAtom(e->Iex.Load.addr); case Iex_Const: return True; case Iex_CCall: for (i = 0; e->Iex.CCall.args[i]; i++) if (!isIRAtom(e->Iex.CCall.args[i])) return False; return True; case Iex_Mux0X: return toBool ( isIRAtom(e->Iex.Mux0X.cond) && isIRAtom(e->Iex.Mux0X.expr0) && isIRAtom(e->Iex.Mux0X.exprX)); default: vpanic("isFlatIRStmt(e)"); } /*notreached*/ vassert(0); case Ist_Store: return toBool( isIRAtom(st->Ist.Store.addr) && isIRAtom(st->Ist.Store.data) ); case Ist_Dirty: di = st->Ist.Dirty.details; if (!isIRAtom(di->guard)) return False; for (i = 0; di->args[i]; i++) if (!isIRAtom(di->args[i])) return False; if (di->mAddr && !isIRAtom(di->mAddr)) return False; return True; case Ist_NoOp: case Ist_IMark: case Ist_MFence: return True; case Ist_Exit: return isIRAtom(st->Ist.Exit.guard); default: vpanic("isFlatIRStmt(st)"); }}/*---------------------------------------------------------------*//*--- Sanity checking ---*//*---------------------------------------------------------------*//* 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 inline Int countArgs ( IRExpr** args ){ Int i; for (i = 0; args[i]; i++) ; return i;}static__attribute((noreturn))void sanityCheckFail ( IRBB* bb, IRStmt* stmt, HChar* 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");}static Bool saneIRArray ( IRArray* arr ){ if (arr->base < 0 || arr->base > 10000 /* somewhat arbitrary */) return False; if (arr->elemTy == Ity_I1) return False; if (arr->nElems <= 0 || arr->nElems > 500 /* somewhat arbitrary */) return False; return True;}static Bool saneIRCallee ( IRCallee* cee ){ if (cee->name == NULL) return False; if (cee->addr == 0) return False; if (cee->regparms < 0 || cee->regparms > 3) return False; return True;}static Bool saneIRConst ( IRConst* con ){ switch (con->tag) { case Ico_U1: return toBool( con->Ico.U1 == True || con->Ico.U1 == False ); default: /* Is there anything we can meaningfully check? I don't think so. */ return True; }}/* 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. */staticvoid useBeforeDef_Temp ( IRBB* bb, IRStmt* stmt, IRTemp tmp, Int* def_counts ){ if (tmp < 0 || tmp >= bb->tyenv->types_used) sanityCheckFail(bb,stmt, "out of range Temp in IRExpr"); if (def_counts[tmp] < 1) sanityCheckFail(bb,stmt, "IRTemp use before def in IRExpr");}staticvoid useBeforeDef_Expr ( IRBB* bb, IRStmt* stmt, IRExpr* expr, Int* def_counts ){ Int i; switch (expr->tag) { case Iex_Get: break; case Iex_GetI: useBeforeDef_Expr(bb,stmt,expr->Iex.GetI.ix,def_counts); break; case Iex_Tmp: useBeforeDef_Temp(bb,stmt,expr->Iex.Tmp.tmp,def_counts); 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_Load: useBeforeDef_Expr(bb,stmt,expr->Iex.Load.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; case Iex_Mux0X: useBeforeDef_Expr(bb,stmt,expr->Iex.Mux0X.cond,def_counts); useBeforeDef_Expr(bb,stmt,expr->Iex.Mux0X.expr0,def_counts); useBeforeDef_Expr(bb,stmt,expr->Iex.Mux0X.exprX,def_counts); break; default: vpanic("useBeforeDef_Expr"); }}staticvoid useBeforeDef_Stmt ( IRBB* bb, IRStmt* stmt, Int* def_counts ){ Int i; IRDirty* d; switch (stmt->tag) { case Ist_IMark: break; case Ist_AbiHint: useBeforeDef_Expr(bb,stmt,stmt->Ist.AbiHint.base,def_counts); break; case Ist_Put: useBeforeDef_Expr(bb,stmt,stmt->Ist.Put.data,def_counts); break; case Ist_PutI: useBeforeDef_Expr(bb,stmt,stmt->Ist.PutI.ix,def_counts); useBeforeDef_Expr(bb,stmt,stmt->Ist.PutI.data,def_counts); break; case Ist_Tmp: useBeforeDef_Expr(bb,stmt,stmt->Ist.Tmp.data,def_counts); break; case Ist_Store: useBeforeDef_Expr(bb,stmt,stmt->Ist.Store.addr,def_counts); useBeforeDef_Expr(bb,stmt,stmt->Ist.Store.data,def_counts); break; case Ist_Dirty: d = stmt->Ist.Dirty.details; for (i = 0; d->args[i] != NULL; i++) useBeforeDef_Expr(bb,stmt,d->args[i],def_counts); if (d->mFx != Ifx_None) useBeforeDef_Expr(bb,stmt,d->mAddr,def_counts); break; case Ist_NoOp: case Ist_MFence: break; case Ist_Exit: useBeforeDef_Expr(bb,stmt,stmt->Ist.Exit.guard,def_counts); break; default: vpanic("useBeforeDef_Stmt"); }}staticvoid tcExpr ( IRBB* bb, IRStmt* stmt, IRExpr* expr, IRType gWordTy ){ Int i; IRType t_dst, t_arg1, t_arg2; IRTypeEnv* tyenv = bb->tyenv; switch (expr->tag) { case Iex_Get: case Iex_Tmp: break; case Iex_GetI: tcExpr(bb,stmt, expr->Iex.GetI
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -