From 292bd1b6716e4d6321cbee8bf73d9d88c928f6a9 Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Sun, 30 May 2021 18:02:30 -0700 Subject: [PATCH] more robust treatment of arithmetic coercions --- src/Expr.cc | 33 ++++++++++----------------------- src/Expr.h | 2 +- src/script_opt/Expr.cc | 16 +++++++++++----- 3 files changed, 22 insertions(+), 29 deletions(-) diff --git a/src/Expr.cc b/src/Expr.cc index 4c7bf81540..514622ce52 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -3844,49 +3844,36 @@ ArithCoerceExpr::ArithCoerceExpr(ExprPtr arg_op, TypeTag t) ExprError("bad coercion value"); } -ValPtr ArithCoerceExpr::FoldSingleVal(Val* v, InternalTypeTag t) const +ValPtr ArithCoerceExpr::FoldSingleVal(ValPtr v, const TypePtr& t) const { - switch ( t ) { - case TYPE_INTERNAL_DOUBLE: - return make_intrusive(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; - } + return check_and_promote(v, t.get(), false, location); } ValPtr ArithCoerceExpr::Fold(Val* v) const { - InternalTypeTag t = type->InternalType(); + auto t = GetType(); if ( ! is_vector(v) ) { // Our result type might be vector, in which case this // 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 ) - 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(); - auto result = make_intrusive(GetType()); + auto result = make_intrusive(cast_intrusive(t)); + + auto yt = t->AsVectorType()->Yield(); for ( unsigned int i = 0; i < vv->Size(); ++i ) { auto elt = vv->ValAt(i); if ( elt ) - result->Assign(i, FoldSingleVal(elt.get(), t)); + result->Assign(i, FoldSingleVal(elt, yt)); else result->Assign(i, nullptr); } diff --git a/src/Expr.h b/src/Expr.h index 4809048513..a91c9d4335 100644 --- a/src/Expr.h +++ b/src/Expr.h @@ -1213,7 +1213,7 @@ public: ExprPtr Reduce(Reducer* c, StmtPtr& red_stmt) override; protected: - ValPtr FoldSingleVal(Val* v, InternalTypeTag t) const; + ValPtr FoldSingleVal(ValPtr v, const TypePtr& t) const; ValPtr Fold(Val* v) const override; }; diff --git a/src/script_opt/Expr.cc b/src/script_opt/Expr.cc index 8a30d4478e..4279a781f5 100644 --- a/src/script_opt/Expr.cc +++ b/src/script_opt/Expr.cc @@ -2075,8 +2075,13 @@ ExprPtr ArithCoerceExpr::Duplicate() bool ArithCoerceExpr::WillTransform(Reducer* c) const { - return op->Tag() == EXPR_CONST && - IsArithmetic(op->AsConstExpr()->Value()->GetType()->Tag()); + if ( op->Tag() != EXPR_CONST ) + return false; + + if ( IsArithmetic(GetType()->Tag()) ) + return true; + + return IsArithmetic(op->AsConstExpr()->Value()->GetType()->Tag()); } 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 ) { - auto cv = op->AsConstExpr()->Value(); - auto tag = cv->GetType()->Tag(); + const auto& t = GetType(); + auto cv = op->AsConstExpr()->ValuePtr(); + const auto& ct = cv->GetType(); - if ( IsArithmetic(tag) ) + if ( IsArithmetic(t->Tag()) || IsArithmetic(ct->Tag()) ) return make_intrusive(FoldSingleVal(cv, t)); }