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) {}
|
ConstEval::ConstEval(ProgramBuilder& b) : builder(b) {}
|
||||||
|
|
||||||
const sem::Constant* ConstEval::Literal(const sem::Type* ty,
|
ConstEval::ConstantResult ConstEval::Literal(const sem::Type* ty,
|
||||||
const ast::LiteralExpression* literal) {
|
const ast::LiteralExpression* literal) {
|
||||||
return Switch(
|
return Switch(
|
||||||
literal,
|
literal,
|
||||||
[&](const ast::BoolLiteralExpression* lit) {
|
[&](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,
|
ConstEval::ConstantResult ConstEval::ArrayOrStructCtor(
|
||||||
utils::VectorRef<const sem::Expression*> args) {
|
const sem::Type* ty,
|
||||||
|
utils::VectorRef<const sem::Expression*> args) {
|
||||||
if (args.IsEmpty()) {
|
if (args.IsEmpty()) {
|
||||||
return ZeroValue(builder, ty);
|
return ZeroValue(builder, ty);
|
||||||
}
|
}
|
||||||
|
@ -530,8 +531,8 @@ const sem::Constant* ConstEval::ArrayOrStructCtor(const sem::Type* ty,
|
||||||
return CreateComposite(builder, ty, std::move(els));
|
return CreateComposite(builder, ty, std::move(els));
|
||||||
}
|
}
|
||||||
|
|
||||||
const sem::Constant* ConstEval::Conv(const sem::Type* ty,
|
ConstEval::ConstantResult ConstEval::Conv(const sem::Type* ty,
|
||||||
utils::VectorRef<const sem::Expression*> args) {
|
utils::VectorRef<const sem::Expression*> args) {
|
||||||
uint32_t el_count = 0;
|
uint32_t el_count = 0;
|
||||||
auto* el_ty = sem::Type::ElementOf(ty, &el_count);
|
auto* el_ty = sem::Type::ElementOf(ty, &el_count);
|
||||||
if (!el_ty) {
|
if (!el_ty) {
|
||||||
|
@ -551,26 +552,26 @@ const sem::Constant* ConstEval::Conv(const sem::Type* ty,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sem::Constant* ConstEval::Zero(const sem::Type* ty,
|
ConstEval::ConstantResult ConstEval::Zero(const sem::Type* ty,
|
||||||
utils::VectorRef<const sem::Expression*>) {
|
utils::VectorRef<const sem::Expression*>) {
|
||||||
return ZeroValue(builder, ty);
|
return ZeroValue(builder, ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
const sem::Constant* ConstEval::Identity(const sem::Type*,
|
ConstEval::ConstantResult ConstEval::Identity(const sem::Type*,
|
||||||
utils::VectorRef<const sem::Expression*> args) {
|
utils::VectorRef<const sem::Expression*> args) {
|
||||||
return args[0]->ConstantValue();
|
return args[0]->ConstantValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
const sem::Constant* ConstEval::VecSplat(const sem::Type* ty,
|
ConstEval::ConstantResult ConstEval::VecSplat(const sem::Type* ty,
|
||||||
utils::VectorRef<const sem::Expression*> args) {
|
utils::VectorRef<const sem::Expression*> args) {
|
||||||
if (auto* arg = args[0]->ConstantValue()) {
|
if (auto* arg = args[0]->ConstantValue()) {
|
||||||
return builder.create<Splat>(ty, arg, static_cast<const sem::Vector*>(ty)->Width());
|
return builder.create<Splat>(ty, arg, static_cast<const sem::Vector*>(ty)->Width());
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sem::Constant* ConstEval::VecCtorS(const sem::Type* ty,
|
ConstEval::ConstantResult ConstEval::VecCtorS(const sem::Type* ty,
|
||||||
utils::VectorRef<const sem::Expression*> args) {
|
utils::VectorRef<const sem::Expression*> args) {
|
||||||
utils::Vector<const sem::Constant*, 4> els;
|
utils::Vector<const sem::Constant*, 4> els;
|
||||||
for (auto* arg : args) {
|
for (auto* arg : args) {
|
||||||
els.Push(arg->ConstantValue());
|
els.Push(arg->ConstantValue());
|
||||||
|
@ -578,8 +579,8 @@ const sem::Constant* ConstEval::VecCtorS(const sem::Type* ty,
|
||||||
return CreateComposite(builder, ty, std::move(els));
|
return CreateComposite(builder, ty, std::move(els));
|
||||||
}
|
}
|
||||||
|
|
||||||
const sem::Constant* ConstEval::VecCtorM(const sem::Type* ty,
|
ConstEval::ConstantResult ConstEval::VecCtorM(const sem::Type* ty,
|
||||||
utils::VectorRef<const sem::Expression*> args) {
|
utils::VectorRef<const sem::Expression*> args) {
|
||||||
utils::Vector<const sem::Constant*, 4> els;
|
utils::Vector<const sem::Constant*, 4> els;
|
||||||
for (auto* arg : args) {
|
for (auto* arg : args) {
|
||||||
auto* val = arg->ConstantValue();
|
auto* val = arg->ConstantValue();
|
||||||
|
@ -603,8 +604,8 @@ const sem::Constant* ConstEval::VecCtorM(const sem::Type* ty,
|
||||||
return CreateComposite(builder, ty, std::move(els));
|
return CreateComposite(builder, ty, std::move(els));
|
||||||
}
|
}
|
||||||
|
|
||||||
const sem::Constant* ConstEval::MatCtorS(const sem::Type* ty,
|
ConstEval::ConstantResult ConstEval::MatCtorS(const sem::Type* ty,
|
||||||
utils::VectorRef<const sem::Expression*> args) {
|
utils::VectorRef<const sem::Expression*> args) {
|
||||||
auto* m = static_cast<const sem::Matrix*>(ty);
|
auto* m = static_cast<const sem::Matrix*>(ty);
|
||||||
|
|
||||||
utils::Vector<const sem::Constant*, 4> els;
|
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));
|
return CreateComposite(builder, ty, std::move(els));
|
||||||
}
|
}
|
||||||
|
|
||||||
const sem::Constant* ConstEval::MatCtorV(const sem::Type* ty,
|
ConstEval::ConstantResult ConstEval::MatCtorV(const sem::Type* ty,
|
||||||
utils::VectorRef<const sem::Expression*> args) {
|
utils::VectorRef<const sem::Expression*> args) {
|
||||||
utils::Vector<const sem::Constant*, 4> els;
|
utils::Vector<const sem::Constant*, 4> els;
|
||||||
for (auto* arg : args) {
|
for (auto* arg : args) {
|
||||||
els.Push(arg->ConstantValue());
|
els.Push(arg->ConstantValue());
|
||||||
|
@ -628,16 +629,16 @@ const sem::Constant* ConstEval::MatCtorV(const sem::Type* ty,
|
||||||
return CreateComposite(builder, ty, std::move(els));
|
return CreateComposite(builder, ty, std::move(els));
|
||||||
}
|
}
|
||||||
|
|
||||||
const sem::Constant* ConstEval::Index(const sem::Expression* obj_expr,
|
ConstEval::ConstantResult ConstEval::Index(const sem::Expression* obj_expr,
|
||||||
const sem::Expression* idx_expr) {
|
const sem::Expression* idx_expr) {
|
||||||
auto obj_val = obj_expr->ConstantValue();
|
auto obj_val = obj_expr->ConstantValue();
|
||||||
if (!obj_val) {
|
if (!obj_val) {
|
||||||
return {};
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto idx_val = idx_expr->ConstantValue();
|
auto idx_val = idx_expr->ConstantValue();
|
||||||
if (!idx_val) {
|
if (!idx_val) {
|
||||||
return {};
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t el_count = 0;
|
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));
|
return obj_val->Index(static_cast<size_t>(idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
const sem::Constant* ConstEval::MemberAccess(const sem::Expression* obj_expr,
|
ConstEval::ConstantResult ConstEval::MemberAccess(const sem::Expression* obj_expr,
|
||||||
const sem::StructMember* member) {
|
const sem::StructMember* member) {
|
||||||
auto obj_val = obj_expr->ConstantValue();
|
auto obj_val = obj_expr->ConstantValue();
|
||||||
if (!obj_val) {
|
if (!obj_val) {
|
||||||
return {};
|
return nullptr;
|
||||||
}
|
}
|
||||||
return obj_val->Index(static_cast<size_t>(member->Index()));
|
return obj_val->Index(static_cast<size_t>(member->Index()));
|
||||||
}
|
}
|
||||||
|
|
||||||
const sem::Constant* ConstEval::Swizzle(const sem::Type* ty,
|
ConstEval::ConstantResult ConstEval::Swizzle(const sem::Type* ty,
|
||||||
const sem::Expression* vec_expr,
|
const sem::Expression* vec_expr,
|
||||||
utils::VectorRef<uint32_t> indices) {
|
utils::VectorRef<uint32_t> indices) {
|
||||||
auto* vec_val = vec_expr->ConstantValue();
|
auto* vec_val = vec_expr->ConstantValue();
|
||||||
if (!vec_val) {
|
if (!vec_val) {
|
||||||
return nullptr;
|
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
|
// TODO(crbug.com/tint/1581): Implement @const intrinsics
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sem::Constant* ConstEval::OpComplement(const sem::Type*,
|
ConstEval::ConstantResult ConstEval::OpComplement(const sem::Type*,
|
||||||
utils::VectorRef<const sem::Expression*> args) {
|
utils::VectorRef<const sem::Expression*> args) {
|
||||||
auto transform = [&](const sem::Constant* c) {
|
auto transform = [&](const sem::Constant* c) {
|
||||||
auto create = [&](auto i) {
|
auto create = [&](auto i) {
|
||||||
return CreateElement(builder, c->Type(), decltype(i)(~i.value));
|
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());
|
return TransformElements(builder, transform, args[0]->ConstantValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
const sem::Constant* ConstEval::OpMinus(const sem::Type*,
|
ConstEval::ConstantResult ConstEval::OpMinus(const sem::Type*,
|
||||||
utils::VectorRef<const sem::Expression*> args) {
|
utils::VectorRef<const sem::Expression*> args) {
|
||||||
auto transform = [&](const sem::Constant* c) {
|
auto transform = [&](const sem::Constant* c) {
|
||||||
auto create = [&](auto i) { //
|
auto create = [&](auto i) {
|
||||||
// For signed integrals, avoid C++ UB by not negating the
|
// For signed integrals, avoid C++ UB by not negating the
|
||||||
// smallest negative number. In WGSL, this operation is well
|
// smallest negative number. In WGSL, this operation is well
|
||||||
// defined to return the same value, see:
|
// defined to return the same value, see:
|
||||||
// https://gpuweb.github.io/gpuweb/wgsl/#arithmetic-expr.
|
// https://gpuweb.github.io/gpuweb/wgsl/#arithmetic-expr.
|
||||||
using T = UnwrapNumber<decltype(i)>;
|
using T = UnwrapNumber<decltype(i)>;
|
||||||
if constexpr (std::is_integral_v<T>) {
|
if constexpr (std::is_integral_v<T>) {
|
||||||
auto v = i.value;
|
auto v = i.value;
|
||||||
|
@ -721,8 +722,8 @@ const sem::Constant* ConstEval::OpMinus(const sem::Type*,
|
||||||
return TransformElements(builder, transform, args[0]->ConstantValue());
|
return TransformElements(builder, transform, args[0]->ConstantValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
const sem::Constant* ConstEval::atan2(const sem::Type*,
|
ConstEval::ConstantResult ConstEval::atan2(const sem::Type*,
|
||||||
utils::VectorRef<const sem::Expression*> args) {
|
utils::VectorRef<const sem::Expression*> args) {
|
||||||
auto transform = [&](const sem::Constant* c0, const sem::Constant* c1) {
|
auto transform = [&](const sem::Constant* c0, const sem::Constant* c1) {
|
||||||
auto create = [&](auto i, auto j) {
|
auto create = [&](auto i, auto j) {
|
||||||
return CreateElement(builder, c0->Type(), decltype(i)(std::atan2(i.value, j.value)));
|
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());
|
args[1]->ConstantValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
const sem::Constant* ConstEval::clamp(const sem::Type*,
|
ConstEval::ConstantResult ConstEval::clamp(const sem::Type*,
|
||||||
utils::VectorRef<const sem::Expression*> args) {
|
utils::VectorRef<const sem::Expression*> args) {
|
||||||
auto transform = [&](const sem::Constant* c0, const sem::Constant* c1,
|
auto transform = [&](const sem::Constant* c0, const sem::Constant* c1,
|
||||||
const sem::Constant* c2) {
|
const sem::Constant* c2) {
|
||||||
auto create = [&](auto e, auto low, auto high) {
|
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.
|
/// before calling a method to evaluate an expression's value.
|
||||||
class ConstEval {
|
class ConstEval {
|
||||||
public:
|
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
|
/// 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:
|
/// resolving. Can be one of three distinct values:
|
||||||
/// * A non-null sem::Constant pointer. Returned when a expression resolves to a creation time
|
/// * A non-null sem::Constant pointer. Returned when a expression resolves to a creation time
|
||||||
|
@ -59,6 +55,10 @@ class ConstEval {
|
||||||
/// resolving.
|
/// resolving.
|
||||||
using ConstantResult = utils::Result<const sem::Constant*>;
|
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
|
/// Constructor
|
||||||
/// @param b the program builder
|
/// @param b the program builder
|
||||||
explicit ConstEval(ProgramBuilder& b);
|
explicit ConstEval(ProgramBuilder& b);
|
||||||
|
@ -70,37 +70,37 @@ class ConstEval {
|
||||||
/// @param ty the target type - must be an array or constructor
|
/// @param ty the target type - must be an array or constructor
|
||||||
/// @param args the input arguments
|
/// @param args the input arguments
|
||||||
/// @return the constructed value, or null if the value cannot be calculated
|
/// @return the constructed value, or null if the value cannot be calculated
|
||||||
const sem::Constant* ArrayOrStructCtor(const sem::Type* ty,
|
ConstantResult ArrayOrStructCtor(const sem::Type* ty,
|
||||||
utils::VectorRef<const sem::Expression*> args);
|
utils::VectorRef<const sem::Expression*> args);
|
||||||
|
|
||||||
/// @param ty the target type
|
/// @param ty the target type
|
||||||
/// @param expr the input expression
|
/// @param expr the input expression
|
||||||
/// @return the bit-cast of the given expression to the given type, or null if the value cannot
|
/// @return the bit-cast of the given expression to the given type, or null if the value cannot
|
||||||
/// be calculated
|
/// 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 obj the object being indexed
|
||||||
/// @param idx the index expression
|
/// @param idx the index expression
|
||||||
/// @return the result of the index, or null if the value cannot be calculated
|
/// @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 ty the result type
|
||||||
/// @param lit the literal AST node
|
/// @param lit the literal AST node
|
||||||
/// @return the constant value of the literal
|
/// @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 obj the object being accessed
|
||||||
/// @param member the member
|
/// @param member the member
|
||||||
/// @return the result of the member access, or null if the value cannot be calculated
|
/// @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 ty the result type
|
||||||
/// @param vector the vector being swizzled
|
/// @param vector the vector being swizzled
|
||||||
/// @param indices the swizzle indices
|
/// @param indices the swizzle indices
|
||||||
/// @return the result of the swizzle, or null if the value cannot be calculated
|
/// @return the result of the swizzle, or null if the value cannot be calculated
|
||||||
const sem::Constant* Swizzle(const sem::Type* ty,
|
ConstantResult Swizzle(const sem::Type* ty,
|
||||||
const sem::Expression* vector,
|
const sem::Expression* vector,
|
||||||
utils::VectorRef<uint32_t> indices);
|
utils::VectorRef<uint32_t> indices);
|
||||||
|
|
||||||
/// Convert the `value` to `target_type`
|
/// Convert the `value` to `target_type`
|
||||||
/// @param ty the result type
|
/// @param ty the result type
|
||||||
|
@ -117,73 +117,65 @@ class ConstEval {
|
||||||
/// @param ty the result type
|
/// @param ty the result type
|
||||||
/// @param args the input arguments
|
/// @param args the input arguments
|
||||||
/// @return the converted value, or null if the value cannot be calculated
|
/// @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
|
/// Zero value type constructor
|
||||||
/// @param ty the result type
|
/// @param ty the result type
|
||||||
/// @param args the input arguments (no arguments provided)
|
/// @param args the input arguments (no arguments provided)
|
||||||
/// @return the constructed value, or null if the value cannot be calculated
|
/// @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
|
/// Identity value type constructor
|
||||||
/// @param ty the result type
|
/// @param ty the result type
|
||||||
/// @param args the input arguments
|
/// @param args the input arguments
|
||||||
/// @return the constructed value, or null if the value cannot be calculated
|
/// @return the constructed value, or null if the value cannot be calculated
|
||||||
const sem::Constant* Identity(const sem::Type* ty,
|
ConstantResult Identity(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||||
utils::VectorRef<const sem::Expression*> args);
|
|
||||||
|
|
||||||
/// Vector splat constructor
|
/// Vector splat constructor
|
||||||
/// @param ty the vector type
|
/// @param ty the vector type
|
||||||
/// @param args the input arguments
|
/// @param args the input arguments
|
||||||
/// @return the constructed value, or null if the value cannot be calculated
|
/// @return the constructed value, or null if the value cannot be calculated
|
||||||
const sem::Constant* VecSplat(const sem::Type* ty,
|
ConstantResult VecSplat(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||||
utils::VectorRef<const sem::Expression*> args);
|
|
||||||
|
|
||||||
/// Vector constructor using scalars
|
/// Vector constructor using scalars
|
||||||
/// @param ty the vector type
|
/// @param ty the vector type
|
||||||
/// @param args the input arguments
|
/// @param args the input arguments
|
||||||
/// @return the constructed value, or null if the value cannot be calculated
|
/// @return the constructed value, or null if the value cannot be calculated
|
||||||
const sem::Constant* VecCtorS(const sem::Type* ty,
|
ConstantResult VecCtorS(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||||
utils::VectorRef<const sem::Expression*> args);
|
|
||||||
|
|
||||||
/// Vector constructor using a mix of scalars and smaller vectors
|
/// Vector constructor using a mix of scalars and smaller vectors
|
||||||
/// @param ty the vector type
|
/// @param ty the vector type
|
||||||
/// @param args the input arguments
|
/// @param args the input arguments
|
||||||
/// @return the constructed value, or null if the value cannot be calculated
|
/// @return the constructed value, or null if the value cannot be calculated
|
||||||
const sem::Constant* VecCtorM(const sem::Type* ty,
|
ConstantResult VecCtorM(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||||
utils::VectorRef<const sem::Expression*> args);
|
|
||||||
|
|
||||||
/// Matrix constructor using scalar values
|
/// Matrix constructor using scalar values
|
||||||
/// @param ty the matrix type
|
/// @param ty the matrix type
|
||||||
/// @param args the input arguments
|
/// @param args the input arguments
|
||||||
/// @return the constructed value, or null if the value cannot be calculated
|
/// @return the constructed value, or null if the value cannot be calculated
|
||||||
const sem::Constant* MatCtorS(const sem::Type* ty,
|
ConstantResult MatCtorS(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||||
utils::VectorRef<const sem::Expression*> args);
|
|
||||||
|
|
||||||
/// Matrix constructor using column vectors
|
/// Matrix constructor using column vectors
|
||||||
/// @param ty the matrix type
|
/// @param ty the matrix type
|
||||||
/// @param args the input arguments
|
/// @param args the input arguments
|
||||||
/// @return the constructed value, or null if the value cannot be calculated
|
/// @return the constructed value, or null if the value cannot be calculated
|
||||||
const sem::Constant* MatCtorV(const sem::Type* ty,
|
ConstantResult MatCtorV(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||||
utils::VectorRef<const sem::Expression*> args);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Operators
|
// Unary Operators
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/// Complement operator '~'
|
/// Complement operator '~'
|
||||||
/// @param ty the integer type
|
/// @param ty the integer type
|
||||||
/// @param args the input arguments
|
/// @param args the input arguments
|
||||||
/// @return the result value, or null if the value cannot be calculated
|
/// @return the result value, or null if the value cannot be calculated
|
||||||
const sem::Constant* OpComplement(const sem::Type* ty,
|
ConstantResult OpComplement(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||||
utils::VectorRef<const sem::Expression*> args);
|
|
||||||
|
|
||||||
/// Minus operator '-'
|
/// Minus operator '-'
|
||||||
/// @param ty the expression type
|
/// @param ty the expression type
|
||||||
/// @param args the input arguments
|
/// @param args the input arguments
|
||||||
/// @return the result value, or null if the value cannot be calculated
|
/// @return the result value, or null if the value cannot be calculated
|
||||||
const sem::Constant* OpMinus(const sem::Type* ty,
|
ConstantResult OpMinus(const sem::Type* ty, utils::VectorRef<const sem::Expression*> args);
|
||||||
utils::VectorRef<const sem::Expression*> args);
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Builtins
|
// Builtins
|
||||||
|
@ -193,13 +185,13 @@ class ConstEval {
|
||||||
/// @param ty the expression type
|
/// @param ty the expression type
|
||||||
/// @param args the input arguments
|
/// @param args the input arguments
|
||||||
/// @return the result value, or null if the value cannot be calculated
|
/// @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
|
/// clamp builtin
|
||||||
/// @param ty the expression type
|
/// @param ty the expression type
|
||||||
/// @param args the input arguments
|
/// @param args the input arguments
|
||||||
/// @return the result value, or null if the value cannot be calculated
|
/// @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:
|
private:
|
||||||
/// Adds the given error message to the diagnostics
|
/// 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 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();
|
bool has_side_effects = idx->HasSideEffects() || obj->HasSideEffects();
|
||||||
auto* sem = builder_->create<sem::IndexAccessorExpression>(
|
auto* sem = builder_->create<sem::IndexAccessorExpression>(
|
||||||
expr, ty, stage, obj, idx, current_statement_, std::move(val), has_side_effects,
|
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;
|
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 stage = sem::EvaluationStage::kRuntime; // TODO(crbug.com/tint/1581)
|
||||||
auto* sem = builder_->create<sem::Expression>(expr, ty, stage, current_statement_,
|
auto* sem = builder_->create<sem::Expression>(expr, ty, stage, current_statement_,
|
||||||
std::move(val), inner->HasSideEffects());
|
std::move(val), inner->HasSideEffects());
|
||||||
|
@ -1575,8 +1585,12 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
|
||||||
const sem::Constant* value = nullptr;
|
const sem::Constant* value = nullptr;
|
||||||
auto stage = sem::EarliestStage(ctor_or_conv.target->Stage(), args_stage);
|
auto stage = sem::EarliestStage(ctor_or_conv.target->Stage(), args_stage);
|
||||||
if (stage == sem::EvaluationStage::kConstant) {
|
if (stage == sem::EvaluationStage::kConstant) {
|
||||||
value =
|
if (auto r = (const_eval_.*ctor_or_conv.const_eval_fn)(
|
||||||
(const_eval_.*ctor_or_conv.const_eval_fn)(ctor_or_conv.target->ReturnType(), args);
|
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),
|
return builder_->create<sem::Call>(expr, ctor_or_conv.target, stage, std::move(args),
|
||||||
current_statement_, value, has_side_effects);
|
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
|
auto stage = args_stage; // The evaluation stage of the call
|
||||||
const sem::Constant* value = nullptr; // The constant value for the call
|
const sem::Constant* value = nullptr; // The constant value for the call
|
||||||
if (stage == sem::EvaluationStage::kConstant) {
|
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) {
|
if (!value) {
|
||||||
// Constant evaluation failed.
|
// Constant evaluation failed.
|
||||||
// Can happen for expressions that will fail validation (later).
|
// 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.
|
// If the builtin is @const, and all arguments have constant values, evaluate the builtin now.
|
||||||
const sem::Constant* value = nullptr;
|
const sem::Constant* value = nullptr;
|
||||||
if (stage == sem::EvaluationStage::kConstant) {
|
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 =
|
bool has_side_effects =
|
||||||
|
@ -2035,7 +2057,12 @@ sem::Expression* Resolver::Literal(const ast::LiteralExpression* literal) {
|
||||||
return nullptr;
|
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,
|
return builder_->create<sem::Expression>(literal, ty, sem::EvaluationStage::kConstant,
|
||||||
current_statement_, std::move(val),
|
current_statement_, std::move(val),
|
||||||
/* has_side_effects */ false);
|
/* 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());
|
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,
|
return builder_->create<sem::StructMemberAccess>(expr, ret, current_statement_, val, object,
|
||||||
member, has_side_effects, source_var);
|
member, has_side_effects, source_var);
|
||||||
}
|
}
|
||||||
|
@ -2224,9 +2256,12 @@ sem::Expression* Resolver::MemberAccessor(const ast::MemberAccessorExpression* e
|
||||||
// the swizzle.
|
// the swizzle.
|
||||||
ret = builder_->create<sem::Vector>(vec->type(), static_cast<uint32_t>(size));
|
ret = builder_->create<sem::Vector>(vec->type(), static_cast<uint32_t>(size));
|
||||||
}
|
}
|
||||||
auto* val = const_eval_.Swizzle(ret, object, swizzle);
|
if (auto r = const_eval_.Swizzle(ret, object, swizzle)) {
|
||||||
return builder_->create<sem::Swizzle>(expr, ret, current_statement_, val, object,
|
auto* val = r.Get();
|
||||||
std::move(swizzle), has_side_effects, source_var);
|
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 '" +
|
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);
|
const auto* rhs = sem_.Get(expr->rhs);
|
||||||
auto* lhs_ty = lhs->Type()->UnwrapRef();
|
auto* lhs_ty = lhs->Type()->UnwrapRef();
|
||||||
auto* rhs_ty = rhs->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);
|
auto op = intrinsic_table_->Lookup(expr->op, lhs_ty, rhs_ty, expr->source, false);
|
||||||
if (!op.result) {
|
if (!op.result) {
|
||||||
|
@ -2260,8 +2294,17 @@ sem::Expression* Resolver::Binary(const ast::BinaryExpression* expr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const sem::Constant* value = nullptr;
|
const sem::Constant* value = nullptr;
|
||||||
if (op.const_eval_fn) {
|
auto stage = sem::EarliestStage(lhs->Stage(), rhs->Stage());
|
||||||
value = (const_eval_.*op.const_eval_fn)(op.result, utils::Vector{lhs, rhs});
|
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();
|
bool has_side_effects = lhs->HasSideEffects() || rhs->HasSideEffects();
|
||||||
|
@ -2337,7 +2380,11 @@ sem::Expression* Resolver::UnaryOp(const ast::UnaryOpExpression* unary) {
|
||||||
stage = expr->Stage();
|
stage = expr->Stage();
|
||||||
if (stage == sem::EvaluationStage::kConstant) {
|
if (stage == sem::EvaluationStage::kConstant) {
|
||||||
if (op.const_eval_fn) {
|
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 {
|
} else {
|
||||||
stage = sem::EvaluationStage::kRuntime;
|
stage = sem::EvaluationStage::kRuntime;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue