tint: Allow ConstEval functions to fail
They now return a utils::Result so they can add an error to diagnostics
and return Failure. Returning nullptr still means cannot evaluate at
compile time, but not a failure.
Bug: tint:1581
Change-Id: Ic30d782fb9fa725ec2faf89a87f74de6282d0304
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/98107
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index ab25bfb..317a91a 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -1501,7 +1501,12 @@
}
auto stage = sem::EarliestStage(obj->Stage(), idx->Stage());
- auto val = const_eval_.Index(obj, idx);
+ const sem::Constant* val = nullptr;
+ if (auto r = const_eval_.Index(obj, idx)) {
+ val = r.Get();
+ } else {
+ return nullptr;
+ }
bool has_side_effects = idx->HasSideEffects() || obj->HasSideEffects();
auto* sem = builder_->create<sem::IndexAccessorExpression>(
expr, ty, stage, obj, idx, current_statement_, std::move(val), has_side_effects,
@@ -1520,7 +1525,12 @@
return nullptr;
}
- auto val = const_eval_.Bitcast(ty, inner);
+ const sem::Constant* val = nullptr;
+ if (auto r = const_eval_.Bitcast(ty, inner)) {
+ val = r.Get();
+ } else {
+ return nullptr;
+ }
auto stage = sem::EvaluationStage::kRuntime; // TODO(crbug.com/tint/1581)
auto* sem = builder_->create<sem::Expression>(expr, ty, stage, current_statement_,
std::move(val), inner->HasSideEffects());
@@ -1575,8 +1585,12 @@
const sem::Constant* value = nullptr;
auto stage = sem::EarliestStage(ctor_or_conv.target->Stage(), args_stage);
if (stage == sem::EvaluationStage::kConstant) {
- value =
- (const_eval_.*ctor_or_conv.const_eval_fn)(ctor_or_conv.target->ReturnType(), args);
+ if (auto r = (const_eval_.*ctor_or_conv.const_eval_fn)(
+ ctor_or_conv.target->ReturnType(), args)) {
+ value = r.Get();
+ } else {
+ return nullptr;
+ }
}
return builder_->create<sem::Call>(expr, ctor_or_conv.target, stage, std::move(args),
current_statement_, value, has_side_effects);
@@ -1593,7 +1607,11 @@
auto stage = args_stage; // The evaluation stage of the call
const sem::Constant* value = nullptr; // The constant value for the call
if (stage == sem::EvaluationStage::kConstant) {
- value = const_eval_.ArrayOrStructCtor(ty, args);
+ if (auto r = const_eval_.ArrayOrStructCtor(ty, args)) {
+ value = r.Get();
+ } else {
+ return nullptr;
+ }
if (!value) {
// Constant evaluation failed.
// Can happen for expressions that will fail validation (later).
@@ -1873,7 +1891,11 @@
// If the builtin is @const, and all arguments have constant values, evaluate the builtin now.
const sem::Constant* value = nullptr;
if (stage == sem::EvaluationStage::kConstant) {
- value = (const_eval_.*builtin.const_eval_fn)(builtin.sem->ReturnType(), args);
+ if (auto r = (const_eval_.*builtin.const_eval_fn)(builtin.sem->ReturnType(), args)) {
+ value = r.Get();
+ } else {
+ return nullptr;
+ }
}
bool has_side_effects =
@@ -2035,7 +2057,12 @@
return nullptr;
}
- auto val = const_eval_.Literal(ty, literal);
+ const sem::Constant* val = nullptr;
+ if (auto r = const_eval_.Literal(ty, literal)) {
+ val = r.Get();
+ } else {
+ return nullptr;
+ }
return builder_->create<sem::Expression>(literal, ty, sem::EvaluationStage::kConstant,
current_statement_, std::move(val),
/* has_side_effects */ false);
@@ -2156,7 +2183,12 @@
ret = builder_->create<sem::Reference>(ret, ref->StorageClass(), ref->Access());
}
- auto* val = const_eval_.MemberAccess(object, member);
+ const sem::Constant* val = nullptr;
+ if (auto r = const_eval_.MemberAccess(object, member)) {
+ val = r.Get();
+ } else {
+ return nullptr;
+ }
return builder_->create<sem::StructMemberAccess>(expr, ret, current_statement_, val, object,
member, has_side_effects, source_var);
}
@@ -2224,9 +2256,12 @@
// the swizzle.
ret = builder_->create<sem::Vector>(vec->type(), static_cast<uint32_t>(size));
}
- auto* val = const_eval_.Swizzle(ret, object, swizzle);
- return builder_->create<sem::Swizzle>(expr, ret, current_statement_, val, object,
- std::move(swizzle), has_side_effects, source_var);
+ if (auto r = const_eval_.Swizzle(ret, object, swizzle)) {
+ auto* val = r.Get();
+ return builder_->create<sem::Swizzle>(expr, ret, current_statement_, val, object,
+ std::move(swizzle), has_side_effects, source_var);
+ }
+ return nullptr;
}
AddError("invalid member accessor expression. Expected vector or struct, got '" +
@@ -2240,7 +2275,6 @@
const auto* rhs = sem_.Get(expr->rhs);
auto* lhs_ty = lhs->Type()->UnwrapRef();
auto* rhs_ty = rhs->Type()->UnwrapRef();
- auto stage = sem::EvaluationStage::kRuntime; // TODO(crbug.com/tint/1581)
auto op = intrinsic_table_->Lookup(expr->op, lhs_ty, rhs_ty, expr->source, false);
if (!op.result) {
@@ -2260,8 +2294,17 @@
}
const sem::Constant* value = nullptr;
- if (op.const_eval_fn) {
- value = (const_eval_.*op.const_eval_fn)(op.result, utils::Vector{lhs, rhs});
+ auto stage = sem::EarliestStage(lhs->Stage(), rhs->Stage());
+ if (stage == sem::EvaluationStage::kConstant) {
+ if (op.const_eval_fn) {
+ if (auto r = (const_eval_.*op.const_eval_fn)(op.result, utils::Vector{lhs, rhs})) {
+ value = r.Get();
+ } else {
+ return nullptr;
+ }
+ } else {
+ stage = sem::EvaluationStage::kRuntime;
+ }
}
bool has_side_effects = lhs->HasSideEffects() || rhs->HasSideEffects();
@@ -2337,7 +2380,11 @@
stage = expr->Stage();
if (stage == sem::EvaluationStage::kConstant) {
if (op.const_eval_fn) {
- value = (const_eval_.*op.const_eval_fn)(ty, utils::Vector{expr});
+ if (auto r = (const_eval_.*op.const_eval_fn)(ty, utils::Vector{expr})) {
+ value = r.Get();
+ } else {
+ return nullptr;
+ }
} else {
stage = sem::EvaluationStage::kRuntime;
}