= mkIRExprVec_3( IRExpr_Get(OFFB_CC_OP, Ity_I32),
IRExpr_Get(OFFB_CC_RES, Ity_I32),
IRExpr_Get(OFFB_CC_AUX, Ity_I32) );
- return mkIRExprCCall(
- Ity_I32,
- 0/*regparm*/,
- "calculate_eflags_all", &calculate_eflags_all,
- args
- );
+ IRExpr* call
+ = mkIRExprCCall(
+ Ity_I32,
+ 0/*regparm*/,
+ "calculate_eflags_all", &calculate_eflags_all,
+ args
+ );
+ /* Exclude OP and AUX from definedness checking. We're only
+ interested in RES. */
+ call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<2);
+ return call;
}
-/* Build IR to calculate just the carry flag from stored
- CC_OP/CC_RES/CC_AUX. Returns an expression :: Ity_I32. */
-static IRExpr* mk_calculate_eflags_c ( void )
+/* Build IR to calculate some particular condition from stored
+ CC_OP/CC_RES/CC_AUX. Returns an expression :: Ity_Bit. */
+static IRExpr* mk_calculate_condition ( Condcode cond )
{
IRExpr** args
- = mkIRExprVec_3( IRExpr_Get(OFFB_CC_OP, Ity_I32),
+ = mkIRExprVec_4( mkU32(cond),
+ IRExpr_Get(OFFB_CC_OP, Ity_I32),
IRExpr_Get(OFFB_CC_RES, Ity_I32),
IRExpr_Get(OFFB_CC_AUX, Ity_I32) );
- return mkIRExprCCall(
- Ity_I32,
- 0/*regparm*/,
- "calculate_eflags_c", &calculate_eflags_c,
- args
- );
+ IRExpr* call
+ = mkIRExprCCall(
+ Ity_I32,
+ 0/*regparm*/,
+ "calculate_condition", &calculate_condition,
+ args
+ );
+ /* Exclude the requested condition, OP and AUX from definedness
+ checking. We're only interested in RES. */
+ call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<1) | (1 << 3);
+ return unop(Iop_32to1, call);
}
-/* Build IR to calculate some particular condition from stored
- CC_OP/CC_RES/CC_AUX. Returns an expression :: Ity_Bit. */
-static IRExpr* mk_calculate_condition ( Condcode cond )
+/* Build IR to calculate just the carry flag from stored
+ CC_OP/CC_RES/CC_AUX. Returns an expression :: Ity_I32. */
+static IRExpr* mk_calculate_eflags_c ( void )
{
IRExpr** args
- = mkIRExprVec_4( mkU32(cond),
- IRExpr_Get(OFFB_CC_OP, Ity_I32),
+ = mkIRExprVec_3( IRExpr_Get(OFFB_CC_OP, Ity_I32),
IRExpr_Get(OFFB_CC_RES, Ity_I32),
IRExpr_Get(OFFB_CC_AUX, Ity_I32) );
- return unop(Iop_32to1,
- mkIRExprCCall(
- Ity_I32,
- 0/*regparm*/,
- "calculate_condition", &calculate_condition,
- args
- )
- );
+ IRExpr* call
+ = mkIRExprCCall(
+ Ity_I32,
+ 0/*regparm*/,
+ "calculate_eflags_c", &calculate_eflags_c,
+ args
+ );
+ /* Exclude OP and AUX from definedness checking. We're only
+ interested in RES. */
+ call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<2);
+ return call;
}
{
vex_printf("%s", ce->name);
if (ce->regparms > 0)
- vex_printf("[%d]", ce->regparms);
+ vex_printf("[rp=%d]", ce->regparms);
+ if (ce->mcx_mask > 0)
+ vex_printf("[mcx=0x%x]", ce->mcx_mask);
vex_printf("{%p}", (void*)ce->addr);
}
ce->regparms = regparms;
ce->name = name;
ce->addr = addr;
+ ce->mcx_mask = 0;
vassert(regparms >= 0 && regparms <= 3);
vassert(name != NULL);
vassert(addr != 0);
IRCallee* dopyIRCallee ( IRCallee* ce )
{
- return mkIRCallee(ce->regparms, ce->name, ce->addr);
+ IRCallee* ce2 = mkIRCallee(ce->regparms, ce->name, ce->addr);
+ ce2->mcx_mask = ce->mcx_mask;
+ return ce2;
}
IRArray* dopyIRArray ( IRArray* d )
sanityCheckFail(bb,stmt,"Iex.CCall.cee: bad IRCallee");
if (expr->Iex.CCall.cee->regparms > countArgs(expr->Iex.CCall.args))
sanityCheckFail(bb,stmt,"Iex.CCall.cee: #regparms > #args");
- for (i = 0; expr->Iex.CCall.args[i]; i++)
+ for (i = 0; expr->Iex.CCall.args[i]; i++) {
+ if (i >= 32)
+ sanityCheckFail(bb,stmt,"Iex.CCall: > 32 args");
tcExpr(bb,stmt, expr->Iex.CCall.args[i], gWordTy);
+ }
if (expr->Iex.CCall.retty == Ity_Bit)
sanityCheckFail(bb,stmt,"Iex.CCall.retty: cannot return :: Ity_Bit");
for (i = 0; expr->Iex.CCall.args[i]; i++)
&& typeOfIRTemp(tyenv, d->tmp) == Ity_Bit)
sanityCheckFail(bb,stmt,"IRStmt.Dirty.dst :: Ity_Bit");
for (i = 0; d->args[i] != NULL; i++) {
+ if (i >= 32)
+ sanityCheckFail(bb,stmt,"IRStmt.Dirty: > 32 args");
if (typeOfIRExpr(tyenv, d->args[i]) == Ity_Bit)
sanityCheckFail(bb,stmt,"IRStmt.Dirty.arg[i] :: Ity_Bit");
}
end that the callee has been declared
"__attribute__((regparm(n)))". On some targets (x86) the back end
will need to construct a non-standard sequence to call a function
- declared like this. */
+ declared like this.
+
+ mcx_mask is a sop to Memcheck. It indicates which args should be
+ considered 'always defined' when lazily computing definedness of
+ the result. Bit 0 of mcx_mask corresponds to args[0], bit 1 to
+ args[1], etc. If a bit is set, the corresponding arg is excluded
+ (hence "x" in "mcx") from definedness checking.
+*/
typedef
struct {
Int regparms;
Char* name;
void* addr;
+ UInt mcx_mask;
}
IRCallee;