more robust treatment of arithmetic coercions

This commit is contained in:
Vern Paxson 2021-05-30 18:02:30 -07:00
parent e06d988bfd
commit 292bd1b671
3 changed files with 22 additions and 29 deletions

View file

@ -3844,49 +3844,36 @@ ArithCoerceExpr::ArithCoerceExpr(ExprPtr arg_op, TypeTag t)
ExprError("bad coercion value"); ExprError("bad coercion value");
} }
ValPtr ArithCoerceExpr::FoldSingleVal(Val* v, InternalTypeTag t) const ValPtr ArithCoerceExpr::FoldSingleVal(ValPtr v, const TypePtr& t) const
{ {
switch ( t ) { return check_and_promote(v, t.get(), false, location);
case TYPE_INTERNAL_DOUBLE:
return make_intrusive<DoubleVal>(v->CoerceToDouble());
case TYPE_INTERNAL_INT:
return val_mgr->Int(v->CoerceToInt());
case TYPE_INTERNAL_UNSIGNED:
return val_mgr->Count(v->CoerceToUnsigned());
default:
RuntimeErrorWithCallStack("bad type in CoerceExpr::Fold");
return nullptr;
}
} }
ValPtr ArithCoerceExpr::Fold(Val* v) const ValPtr ArithCoerceExpr::Fold(Val* v) const
{ {
InternalTypeTag t = type->InternalType(); auto t = GetType();
if ( ! is_vector(v) ) if ( ! is_vector(v) )
{ {
// Our result type might be vector, in which case this // Our result type might be vector, in which case this
// invocation is being done per-element rather than on // invocation is being done per-element rather than on
// the whole vector. Correct the type tag if necessary. // the whole vector. Correct the type if so.
if ( type->Tag() == TYPE_VECTOR ) if ( type->Tag() == TYPE_VECTOR )
t = GetType()->AsVectorType()->Yield()->InternalType(); t = t->AsVectorType()->Yield();
return FoldSingleVal(v, t); return FoldSingleVal({NewRef{}, v}, t);
} }
t = GetType()->AsVectorType()->Yield()->InternalType();
VectorVal* vv = v->AsVectorVal(); VectorVal* vv = v->AsVectorVal();
auto result = make_intrusive<VectorVal>(GetType<VectorType>()); auto result = make_intrusive<VectorVal>(cast_intrusive<VectorType>(t));
auto yt = t->AsVectorType()->Yield();
for ( unsigned int i = 0; i < vv->Size(); ++i ) for ( unsigned int i = 0; i < vv->Size(); ++i )
{ {
auto elt = vv->ValAt(i); auto elt = vv->ValAt(i);
if ( elt ) if ( elt )
result->Assign(i, FoldSingleVal(elt.get(), t)); result->Assign(i, FoldSingleVal(elt, yt));
else else
result->Assign(i, nullptr); result->Assign(i, nullptr);
} }

View file

@ -1213,7 +1213,7 @@ public:
ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override; ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override;
protected: protected:
ValPtr FoldSingleVal(Val* v, InternalTypeTag t) const; ValPtr FoldSingleVal(ValPtr v, const TypePtr& t) const;
ValPtr Fold(Val* v) const override; ValPtr Fold(Val* v) const override;
}; };

View file

@ -2075,8 +2075,13 @@ ExprPtr ArithCoerceExpr::Duplicate()
bool ArithCoerceExpr::WillTransform(Reducer* c) const bool ArithCoerceExpr::WillTransform(Reducer* c) const
{ {
return op->Tag() == EXPR_CONST && if ( op->Tag() != EXPR_CONST )
IsArithmetic(op->AsConstExpr()->Value()->GetType()->Tag()); return false;
if ( IsArithmetic(GetType()->Tag()) )
return true;
return IsArithmetic(op->AsConstExpr()->Value()->GetType()->Tag());
} }
ExprPtr ArithCoerceExpr::Reduce(Reducer* c, StmtPtr& red_stmt) ExprPtr ArithCoerceExpr::Reduce(Reducer* c, StmtPtr& red_stmt)
@ -2093,10 +2098,11 @@ ExprPtr ArithCoerceExpr::Reduce(Reducer* c, StmtPtr& red_stmt)
if ( op->Tag() == EXPR_CONST ) if ( op->Tag() == EXPR_CONST )
{ {
auto cv = op->AsConstExpr()->Value(); const auto& t = GetType();
auto tag = cv->GetType()->Tag(); auto cv = op->AsConstExpr()->ValuePtr();
const auto& ct = cv->GetType();
if ( IsArithmetic(tag) ) if ( IsArithmetic(t->Tag()) || IsArithmetic(ct->Tag()) )
return make_intrusive<ConstExpr>(FoldSingleVal(cv, t)); return make_intrusive<ConstExpr>(FoldSingleVal(cv, t));
} }