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>
This commit is contained in:
parent
6091d838a7
commit
c2a052eaa4
|
@ -479,8 +479,8 @@ const Constant* TransformElements(ProgramBuilder& builder, F&& f, CONSTANTS&&...
|
|||
|
||||
ConstEval::ConstEval(ProgramBuilder& b) : builder(b) {}
|
||||
|
||||
const sem::Constant* ConstEval::Literal(const sem::Type* ty,
|
||||
const ast::LiteralExpression* literal) {
|
||||
ConstEval::ConstantResult ConstEval::Literal(const sem::Type* ty,
|
||||
const ast::LiteralExpression* literal) {
|
||||
return Switch(
|
||||
literal,
|
||||
[&](const ast::BoolLiteralExpression* lit) {
|
||||
|
@ -510,8 +510,9 @@ const sem::Constant* ConstEval::Literal(const sem::Type* ty,
|
|||
});
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::ArrayOrStructCtor(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
ConstEval::ConstantResult ConstEval::ArrayOrStructCtor(
|
||||
const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
if (args.IsEmpty()) {
|
||||
return ZeroValue(builder, ty);
|
||||
}
|
||||
|
@ -530,8 +531,8 @@ const sem::Constant* ConstEval::ArrayOrStructCtor(const sem::Type* ty,
|
|||
return CreateComposite(builder, ty, std::move(els));
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::Conv(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
ConstEval::ConstantResult ConstEval::Conv(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
uint32_t el_count = 0;
|
||||
auto* el_ty = sem::Type::ElementOf(ty, &el_count);
|
||||
if (!el_ty) {
|
||||
|
@ -551,26 +552,26 @@ const sem::Constant* ConstEval::Conv(const sem::Type* ty,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::Zero(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*>) {
|
||||
ConstEval::ConstantResult ConstEval::Zero(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*>) {
|
||||
return ZeroValue(builder, ty);
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::Identity(const sem::Type*,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
ConstEval::ConstantResult ConstEval::Identity(const sem::Type*,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
return args[0]->ConstantValue();
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::VecSplat(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
ConstEval::ConstantResult ConstEval::VecSplat(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
if (auto* arg = args[0]->ConstantValue()) {
|
||||
return builder.create<Splat>(ty, arg, static_cast<const sem::Vector*>(ty)->Width());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::VecCtorS(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
ConstEval::ConstantResult ConstEval::VecCtorS(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
utils::Vector<const sem::Constant*, 4> els;
|
||||
for (auto* arg : args) {
|
||||
els.Push(arg->ConstantValue());
|
||||
|
@ -578,8 +579,8 @@ const sem::Constant* ConstEval::VecCtorS(const sem::Type* ty,
|
|||
return CreateComposite(builder, ty, std::move(els));
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::VecCtorM(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
ConstEval::ConstantResult ConstEval::VecCtorM(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
utils::Vector<const sem::Constant*, 4> els;
|
||||
for (auto* arg : args) {
|
||||
auto* val = arg->ConstantValue();
|
||||
|
@ -603,8 +604,8 @@ const sem::Constant* ConstEval::VecCtorM(const sem::Type* ty,
|
|||
return CreateComposite(builder, ty, std::move(els));
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::MatCtorS(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
ConstEval::ConstantResult ConstEval::MatCtorS(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
auto* m = static_cast<const sem::Matrix*>(ty);
|
||||
|
||||
utils::Vector<const sem::Constant*, 4> els;
|
||||
|
@ -619,8 +620,8 @@ const sem::Constant* ConstEval::MatCtorS(const sem::Type* ty,
|
|||
return CreateComposite(builder, ty, std::move(els));
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::MatCtorV(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
ConstEval::ConstantResult ConstEval::MatCtorV(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
utils::Vector<const sem::Constant*, 4> els;
|
||||
for (auto* arg : args) {
|
||||
els.Push(arg->ConstantValue());
|
||||
|
@ -628,16 +629,16 @@ const sem::Constant* ConstEval::MatCtorV(const sem::Type* ty,
|
|||
return CreateComposite(builder, ty, std::move(els));
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::Index(const sem::Expression* obj_expr,
|
||||
const sem::Expression* idx_expr) {
|
||||
ConstEval::ConstantResult ConstEval::Index(const sem::Expression* obj_expr,
|
||||
const sem::Expression* idx_expr) {
|
||||
auto obj_val = obj_expr->ConstantValue();
|
||||
if (!obj_val) {
|
||||
return {};
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto idx_val = idx_expr->ConstantValue();
|
||||
if (!idx_val) {
|
||||
return {};
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t el_count = 0;
|
||||
|
@ -656,18 +657,18 @@ const sem::Constant* ConstEval::Index(const sem::Expression* obj_expr,
|
|||
return obj_val->Index(static_cast<size_t>(idx));
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::MemberAccess(const sem::Expression* obj_expr,
|
||||
const sem::StructMember* member) {
|
||||
ConstEval::ConstantResult ConstEval::MemberAccess(const sem::Expression* obj_expr,
|
||||
const sem::StructMember* member) {
|
||||
auto obj_val = obj_expr->ConstantValue();
|
||||
if (!obj_val) {
|
||||
return {};
|
||||
return nullptr;
|
||||
}
|
||||
return obj_val->Index(static_cast<size_t>(member->Index()));
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::Swizzle(const sem::Type* ty,
|
||||
const sem::Expression* vec_expr,
|
||||
utils::VectorRef<uint32_t> indices) {
|
||||
ConstEval::ConstantResult ConstEval::Swizzle(const sem::Type* ty,
|
||||
const sem::Expression* vec_expr,
|
||||
utils::VectorRef<uint32_t> indices) {
|
||||
auto* vec_val = vec_expr->ConstantValue();
|
||||
if (!vec_val) {
|
||||
return nullptr;
|
||||
|
@ -681,13 +682,13 @@ const sem::Constant* ConstEval::Swizzle(const sem::Type* ty,
|
|||
}
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::Bitcast(const sem::Type*, const sem::Expression*) {
|
||||
ConstEval::ConstantResult ConstEval::Bitcast(const sem::Type*, const sem::Expression*) {
|
||||
// TODO(crbug.com/tint/1581): Implement @const intrinsics
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::OpComplement(const sem::Type*,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
ConstEval::ConstantResult ConstEval::OpComplement(const sem::Type*,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
auto transform = [&](const sem::Constant* c) {
|
||||
auto create = [&](auto i) {
|
||||
return CreateElement(builder, c->Type(), decltype(i)(~i.value));
|
||||
|
@ -697,14 +698,14 @@ const sem::Constant* ConstEval::OpComplement(const sem::Type*,
|
|||
return TransformElements(builder, transform, args[0]->ConstantValue());
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::OpMinus(const sem::Type*,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
ConstEval::ConstantResult ConstEval::OpMinus(const sem::Type*,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
auto transform = [&](const sem::Constant* c) {
|
||||
auto create = [&](auto i) { //
|
||||
// For signed integrals, avoid C++ UB by not negating the
|
||||
// smallest negative number. In WGSL, this operation is well
|
||||
// defined to return the same value, see:
|
||||
// https://gpuweb.github.io/gpuweb/wgsl/#arithmetic-expr.
|
||||
auto create = [&](auto i) {
|
||||
// For signed integrals, avoid C++ UB by not negating the
|
||||
// smallest negative number. In WGSL, this operation is well
|
||||
// defined to return the same value, see:
|
||||
// https://gpuweb.github.io/gpuweb/wgsl/#arithmetic-expr.
|
||||
using T = UnwrapNumber<decltype(i)>;
|
||||
if constexpr (std::is_integral_v<T>) {
|
||||
auto v = i.value;
|
||||
|
@ -721,8 +722,8 @@ const sem::Constant* ConstEval::OpMinus(const sem::Type*,
|
|||
return TransformElements(builder, transform, args[0]->ConstantValue());
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::atan2(const sem::Type*,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
ConstEval::ConstantResult ConstEval::atan2(const sem::Type*,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
auto transform = [&](const sem::Constant* c0, const sem::Constant* c1) {
|
||||
auto create = [&](auto i, auto j) {
|
||||
return CreateElement(builder, c0->Type(), decltype(i)(std::atan2(i.value, j.value)));
|
||||
|
@ -733,8 +734,8 @@ const sem::Constant* ConstEval::atan2(const sem::Type*,
|
|||
args[1]->ConstantValue());
|
||||
}
|
||||
|
||||
const sem::Constant* ConstEval::clamp(const sem::Type*,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
ConstEval::ConstantResult ConstEval::clamp(const sem::Type*,
|
||||
utils::VectorRef<const sem::Expression*> args) {
|
||||
auto transform = [&](const sem::Constant* c0, const sem::Constant* c1,
|
||||
const sem::Constant* c2) {
|
||||
auto create = [&](auto e, auto low, auto high) {
|
||||
|
|
|
@ -44,10 +44,6 @@ namespace tint::resolver {
|
|||
/// before calling a method to evaluate an expression's value.
|
||||
class ConstEval {
|
||||
public:
|
||||
/// Typedef for a constant evaluation function
|
||||
using Function = const sem::Constant* (ConstEval::*)(const sem::Type* result_ty,
|
||||
utils::VectorRef<const sem::Expression*>);
|
||||
|
||||
/// The result type of a method that may raise a diagnostic error and the caller should abort
|
||||
/// resolving. Can be one of three distinct values:
|
||||
/// * A non-null sem::Constant pointer. Returned when a expression resolves to a creation time
|
||||
|
@ -59,6 +55,10 @@ class ConstEval {
|
|||
/// resolving.
|
||||
using ConstantResult = utils::Result<const sem::Constant*>;
|
||||
|
||||
/// Typedef for a constant evaluation function
|
||||
using Function = ConstantResult (ConstEval::*)(const sem::Type* result_ty,
|
||||
utils::VectorRef<const sem::Expression*>);
|
||||
|
||||
/// Constructor
|
||||
/// @param b the program builder
|
||||
explicit ConstEval(ProgramBuilder& b);
|
||||
|
@ -70,37 +70,37 @@ class ConstEval {
|
|||
/// @param ty the target type - must be an array or constructor
|
||||
/// @param args the input arguments
|
||||
/// @return the constructed value, or null if the value cannot be calculated
|
||||
const sem::Constant* ArrayOrStructCtor(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args);
|
||||
ConstantResult ArrayOrStructCtor(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args);
|
||||
|
||||
/// @param ty the target type
|
||||
/// @param expr the input expression
|
||||
/// @return the bit-cast of the given expression to the given type, or null if the value cannot
|
||||
/// be calculated
|
||||
const sem::Constant* Bitcast(const sem::Type* ty, const sem::Expression* expr);
|
||||
ConstantResult Bitcast(const sem::Type* ty, const sem::Expression* expr);
|
||||
|
||||
/// @param obj the object being indexed
|
||||
/// @param idx the index expression
|
||||
/// @return the result of the index, or null if the value cannot be calculated
|
||||
const sem::Constant* Index(const sem::Expression* obj, const sem::Expression* idx);
|
||||
ConstantResult Index(const sem::Expression* obj, const sem::Expression* idx);
|
||||
|
||||
/// @param ty the result type
|
||||
/// @param lit the literal AST node
|
||||
/// @return the constant value of the literal
|
||||
const sem::Constant* Literal(const sem::Type* ty, const ast::LiteralExpression* lit);
|
||||
ConstantResult Literal(const sem::Type* ty, const ast::LiteralExpression* lit);
|
||||
|
||||
/// @param obj the object being accessed
|
||||
/// @param member the member
|
||||
/// @return the result of the member access, or null if the value cannot be calculated
|
||||
const sem::Constant* MemberAccess(const sem::Expression* obj, const sem::StructMember* member);
|
||||
ConstantResult MemberAccess(const sem::Expression* obj, const sem::StructMember* member);
|
||||
|
||||
/// @param ty the result type
|
||||
/// @param vector the vector being swizzled
|
||||
/// @param indices the swizzle indices
|
||||
/// @return the result of the swizzle, or null if the value cannot be calculated
|
||||
const sem::Constant* Swizzle(const sem::Type* ty,
|
||||
const sem::Expression* vector,
|
||||
utils::VectorRef<uint32_t> indices);
|
||||
ConstantResult Swizzle(const sem::Type* ty,
|
||||
const sem::Expression* vector,
|
||||
utils::VectorRef<uint32_t> indices);
|
||||
|
||||
/// Convert the `value` to `target_type`
|
||||
/// @param ty the result type
|
||||
|
@ -117,73 +117,65 @@ class ConstEval {
|
|||
/// @param ty the result type
|
||||
/// @param args the input arguments
|
||||
/// @return the converted value, or null if the value cannot be calculated
|
||||
const sem::Constant* Conv(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||
ConstantResult Conv(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||
|
||||
/// Zero value type constructor
|
||||
/// @param ty the result type
|
||||
/// @param args the input arguments (no arguments provided)
|
||||
/// @return the constructed value, or null if the value cannot be calculated
|
||||
const sem::Constant* Zero(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||
ConstantResult Zero(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||
|
||||
/// Identity value type constructor
|
||||
/// @param ty the result type
|
||||
/// @param args the input arguments
|
||||
/// @return the constructed value, or null if the value cannot be calculated
|
||||
const sem::Constant* Identity(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args);
|
||||
ConstantResult Identity(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||
|
||||
/// Vector splat constructor
|
||||
/// @param ty the vector type
|
||||
/// @param args the input arguments
|
||||
/// @return the constructed value, or null if the value cannot be calculated
|
||||
const sem::Constant* VecSplat(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args);
|
||||
ConstantResult VecSplat(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||
|
||||
/// Vector constructor using scalars
|
||||
/// @param ty the vector type
|
||||
/// @param args the input arguments
|
||||
/// @return the constructed value, or null if the value cannot be calculated
|
||||
const sem::Constant* VecCtorS(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args);
|
||||
ConstantResult VecCtorS(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||
|
||||
/// Vector constructor using a mix of scalars and smaller vectors
|
||||
/// @param ty the vector type
|
||||
/// @param args the input arguments
|
||||
/// @return the constructed value, or null if the value cannot be calculated
|
||||
const sem::Constant* VecCtorM(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args);
|
||||
ConstantResult VecCtorM(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||
|
||||
/// Matrix constructor using scalar values
|
||||
/// @param ty the matrix type
|
||||
/// @param args the input arguments
|
||||
/// @return the constructed value, or null if the value cannot be calculated
|
||||
const sem::Constant* MatCtorS(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args);
|
||||
ConstantResult MatCtorS(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||
|
||||
/// Matrix constructor using column vectors
|
||||
/// @param ty the matrix type
|
||||
/// @param args the input arguments
|
||||
/// @return the constructed value, or null if the value cannot be calculated
|
||||
const sem::Constant* MatCtorV(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args);
|
||||
ConstantResult MatCtorV(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Operators
|
||||
// Unary Operators
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Complement operator '~'
|
||||
/// @param ty the integer type
|
||||
/// @param args the input arguments
|
||||
/// @return the result value, or null if the value cannot be calculated
|
||||
const sem::Constant* OpComplement(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args);
|
||||
ConstantResult OpComplement(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||
|
||||
/// Minus operator '-'
|
||||
/// @param ty the expression type
|
||||
/// @param args the input arguments
|
||||
/// @return the result value, or null if the value cannot be calculated
|
||||
const sem::Constant* OpMinus(const sem::Type* ty,
|
||||
utils::VectorRef<const sem::Expression*> args);
|
||||
ConstantResult OpMinus(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Builtins
|
||||
|
@ -193,13 +185,13 @@ class ConstEval {
|
|||
/// @param ty the expression type
|
||||
/// @param args the input arguments
|
||||
/// @return the result value, or null if the value cannot be calculated
|
||||
const sem::Constant* atan2(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||
ConstantResult atan2(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||
|
||||
/// clamp builtin
|
||||
/// @param ty the expression type
|
||||
/// @param args the input arguments
|
||||
/// @return the result value, or null if the value cannot be calculated
|
||||
const sem::Constant* clamp(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||
ConstantResult clamp(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||
|
||||
private:
|
||||
/// Adds the given error message to the diagnostics
|
||||
|
|
|
@ -1501,7 +1501,12 @@ sem::Expression* Resolver::IndexAccessor(const ast::IndexAccessorExpression* exp
|
|||
}
|
||||
|
||||
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 @@ sem::Expression* Resolver::Bitcast(const ast::BitcastExpression* expr) {
|
|||
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 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
|
|||
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 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
|
|||
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 @@ sem::Call* Resolver::BuiltinCall(const ast::CallExpression* expr,
|
|||
// 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 @@ sem::Expression* Resolver::Literal(const ast::LiteralExpression* literal) {
|
|||
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 @@ sem::Expression* Resolver::MemberAccessor(const ast::MemberAccessorExpression* e
|
|||
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 @@ sem::Expression* Resolver::MemberAccessor(const ast::MemberAccessorExpression* e
|
|||
// 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 @@ sem::Expression* Resolver::Binary(const ast::BinaryExpression* expr) {
|
|||
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 @@ sem::Expression* Resolver::Binary(const ast::BinaryExpression* expr) {
|
|||
}
|
||||
|
||||
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 @@ sem::Expression* Resolver::UnaryOp(const ast::UnaryOpExpression* unary) {
|
|||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue