Convert the resolver over to utils::StringStream.
This CL updates the resolver to use utils::StringStream instead of std::stringstream. Bug: tint:1686 Change-Id: Ib15a9ae3228757bbddcf787fa9130ca19bc9eab7 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/121980 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
e143338f65
commit
b23cda4bc2
|
@ -44,6 +44,7 @@
|
||||||
#include "src/tint/type/texture_dimension.h"
|
#include "src/tint/type/texture_dimension.h"
|
||||||
#include "src/tint/utils/reverse.h"
|
#include "src/tint/utils/reverse.h"
|
||||||
#include "src/tint/utils/string.h"
|
#include "src/tint/utils/string.h"
|
||||||
|
#include "src/tint/utils/string_stream.h"
|
||||||
|
|
||||||
namespace tint::reader::wgsl {
|
namespace tint::reader::wgsl {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -911,7 +912,7 @@ Expect<ENUM> ParserImpl::expect_enum(std::string_view name,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a sensible error message
|
/// Create a sensible error message
|
||||||
std::ostringstream err;
|
utils::StringStream err;
|
||||||
err << "expected " << name;
|
err << "expected " << name;
|
||||||
|
|
||||||
if (!use.empty()) {
|
if (!use.empty()) {
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include "src/tint/resolver/resolver.h"
|
#include "src/tint/resolver/resolver.h"
|
||||||
#include "src/tint/resolver/resolver_test_helper.h"
|
#include "src/tint/resolver/resolver_test_helper.h"
|
||||||
|
#include "src/tint/utils/string_stream.h"
|
||||||
|
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
@ -196,7 +197,7 @@ INSTANTIATE_TEST_SUITE_P(ResolverAliasAnalysisTest,
|
||||||
TwoPointerConfig{builtin::AddressSpace::kPrivate, false},
|
TwoPointerConfig{builtin::AddressSpace::kPrivate, false},
|
||||||
TwoPointerConfig{builtin::AddressSpace::kPrivate, true}),
|
TwoPointerConfig{builtin::AddressSpace::kPrivate, true}),
|
||||||
[](const ::testing::TestParamInfo<TwoPointers::ParamType>& p) {
|
[](const ::testing::TestParamInfo<TwoPointers::ParamType>& p) {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << (p.param.aliased ? "Aliased" : "Unaliased") << "_"
|
ss << (p.param.aliased ? "Aliased" : "Unaliased") << "_"
|
||||||
<< p.param.address_space;
|
<< p.param.address_space;
|
||||||
return ss.str();
|
return ss.str();
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "src/tint/resolver/resolver_test_helper.h"
|
#include "src/tint/resolver/resolver_test_helper.h"
|
||||||
#include "src/tint/transform/add_block_attribute.h"
|
#include "src/tint/transform/add_block_attribute.h"
|
||||||
#include "src/tint/type/texture_dimension.h"
|
#include "src/tint/type/texture_dimension.h"
|
||||||
|
#include "src/tint/utils/string_stream.h"
|
||||||
|
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
@ -1164,7 +1165,7 @@ TEST_P(ArrayStrideTest, All) {
|
||||||
auto& params = GetParam();
|
auto& params = GetParam();
|
||||||
ast::Type el_ty = params.create_el_type(*this);
|
ast::Type el_ty = params.create_el_type(*this);
|
||||||
|
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "el_ty: " << FriendlyName(el_ty) << ", stride: " << params.stride
|
ss << "el_ty: " << FriendlyName(el_ty) << ", stride: " << params.stride
|
||||||
<< ", should_pass: " << params.should_pass;
|
<< ", should_pass: " << params.should_pass;
|
||||||
SCOPED_TRACE(ss.str());
|
SCOPED_TRACE(ss.str());
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "src/tint/type/test_helper.h"
|
#include "src/tint/type/test_helper.h"
|
||||||
#include "src/tint/type/texture_dimension.h"
|
#include "src/tint/type/texture_dimension.h"
|
||||||
#include "src/tint/utils/string.h"
|
#include "src/tint/utils/string.h"
|
||||||
|
#include "src/tint/utils/string_stream.h"
|
||||||
|
|
||||||
using ::testing::ElementsAre;
|
using ::testing::ElementsAre;
|
||||||
using ::testing::HasSubstr;
|
using ::testing::HasSubstr;
|
||||||
|
@ -2185,7 +2186,7 @@ INSTANTIATE_TEST_SUITE_P(ResolverTest,
|
||||||
|
|
||||||
static std::string to_str(const std::string& function,
|
static std::string to_str(const std::string& function,
|
||||||
utils::VectorRef<const sem::Parameter*> params) {
|
utils::VectorRef<const sem::Parameter*> params) {
|
||||||
std::stringstream out;
|
utils::StringStream out;
|
||||||
out << function << "(";
|
out << function << "(";
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (auto* param : params) {
|
for (auto* param : params) {
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "src/tint/ast/builtin_texture_helper_test.h"
|
#include "src/tint/ast/builtin_texture_helper_test.h"
|
||||||
#include "src/tint/resolver/resolver_test_helper.h"
|
#include "src/tint/resolver/resolver_test_helper.h"
|
||||||
#include "src/tint/sem/value_constructor.h"
|
#include "src/tint/sem/value_constructor.h"
|
||||||
|
#include "src/tint/utils/string_stream.h"
|
||||||
|
|
||||||
using namespace tint::number_suffixes; // NOLINT
|
using namespace tint::number_suffixes; // NOLINT
|
||||||
|
|
||||||
|
@ -335,7 +336,7 @@ TEST_P(BuiltinTextureConstExprArgValidationTest, Immediate) {
|
||||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
} else {
|
} else {
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
if (is_vector) {
|
if (is_vector) {
|
||||||
err << "12:34 error: each component of the " << param.name
|
err << "12:34 error: each component of the " << param.name
|
||||||
<< " argument must be at least " << param.min << " and at most " << param.max
|
<< " argument must be at least " << param.min << " and at most " << param.max
|
||||||
|
@ -392,7 +393,7 @@ TEST_P(BuiltinTextureConstExprArgValidationTest, GlobalConst) {
|
||||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
} else {
|
} else {
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
if (is_vector) {
|
if (is_vector) {
|
||||||
err << "12:34 error: each component of the " << param.name
|
err << "12:34 error: each component of the " << param.name
|
||||||
<< " argument must be at least " << param.min << " and at most " << param.max
|
<< " argument must be at least " << param.min << " and at most " << param.max
|
||||||
|
@ -442,7 +443,7 @@ TEST_P(BuiltinTextureConstExprArgValidationTest, GlobalVar) {
|
||||||
});
|
});
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
err << "12:34 error: the " << param.name << " argument must be a const-expression";
|
err << "12:34 error: the " << param.name << " argument must be a const-expression";
|
||||||
EXPECT_EQ(r()->error(), err.str());
|
EXPECT_EQ(r()->error(), err.str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "src/tint/ast/call_statement.h"
|
#include "src/tint/ast/call_statement.h"
|
||||||
#include "src/tint/builtin/builtin_value.h"
|
#include "src/tint/builtin/builtin_value.h"
|
||||||
#include "src/tint/resolver/resolver_test_helper.h"
|
#include "src/tint/resolver/resolver_test_helper.h"
|
||||||
|
#include "src/tint/utils/string_stream.h"
|
||||||
|
|
||||||
using namespace tint::number_suffixes; // NOLINT
|
using namespace tint::number_suffixes; // NOLINT
|
||||||
|
|
||||||
|
@ -145,7 +146,7 @@ TEST_P(ResolverBuiltinsStageTest, All_input) {
|
||||||
if (params.is_valid) {
|
if (params.is_valid) {
|
||||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
} else {
|
} else {
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
err << "12:34 error: @builtin(" << params.builtin << ")";
|
err << "12:34 error: @builtin(" << params.builtin << ")";
|
||||||
err << " cannot be used in input of " << params.stage << " pipeline stage";
|
err << " cannot be used in input of " << params.stage << " pipeline stage";
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
#include "src/tint/utils/bitcast.h"
|
#include "src/tint/utils/bitcast.h"
|
||||||
#include "src/tint/utils/compiler_macros.h"
|
#include "src/tint/utils/compiler_macros.h"
|
||||||
#include "src/tint/utils/map.h"
|
#include "src/tint/utils/map.h"
|
||||||
|
#include "src/tint/utils/string_stream.h"
|
||||||
#include "src/tint/utils/transform.h"
|
#include "src/tint/utils/transform.h"
|
||||||
|
|
||||||
using namespace tint::number_suffixes; // NOLINT
|
using namespace tint::number_suffixes; // NOLINT
|
||||||
|
@ -184,8 +185,7 @@ auto ZeroTypeDispatch(const type::Type* type, F&& f) {
|
||||||
|
|
||||||
template <typename NumberT>
|
template <typename NumberT>
|
||||||
std::string OverflowErrorMessage(NumberT lhs, const char* op, NumberT rhs) {
|
std::string OverflowErrorMessage(NumberT lhs, const char* op, NumberT rhs) {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << std::setprecision(20);
|
|
||||||
ss << "'" << lhs.value << " " << op << " " << rhs.value << "' cannot be represented as '"
|
ss << "'" << lhs.value << " " << op << " " << rhs.value << "' cannot be represented as '"
|
||||||
<< FriendlyName<NumberT>() << "'";
|
<< FriendlyName<NumberT>() << "'";
|
||||||
return ss.str();
|
return ss.str();
|
||||||
|
@ -193,8 +193,7 @@ std::string OverflowErrorMessage(NumberT lhs, const char* op, NumberT rhs) {
|
||||||
|
|
||||||
template <typename VALUE_TY>
|
template <typename VALUE_TY>
|
||||||
std::string OverflowErrorMessage(VALUE_TY value, std::string_view target_ty) {
|
std::string OverflowErrorMessage(VALUE_TY value, std::string_view target_ty) {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << std::setprecision(20);
|
|
||||||
ss << "value " << value << " cannot be represented as "
|
ss << "value " << value << " cannot be represented as "
|
||||||
<< "'" << target_ty << "'";
|
<< "'" << target_ty << "'";
|
||||||
return ss.str();
|
return ss.str();
|
||||||
|
@ -202,8 +201,7 @@ std::string OverflowErrorMessage(VALUE_TY value, std::string_view target_ty) {
|
||||||
|
|
||||||
template <typename NumberT>
|
template <typename NumberT>
|
||||||
std::string OverflowExpErrorMessage(std::string_view base, NumberT exp) {
|
std::string OverflowExpErrorMessage(std::string_view base, NumberT exp) {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << std::setprecision(20);
|
|
||||||
ss << base << "^" << exp << " cannot be represented as "
|
ss << base << "^" << exp << " cannot be represented as "
|
||||||
<< "'" << FriendlyName<NumberT>() << "'";
|
<< "'" << FriendlyName<NumberT>() << "'";
|
||||||
return ss.str();
|
return ss.str();
|
||||||
|
|
|
@ -1077,7 +1077,15 @@ TEST_F(ResolverConstEvalTest, BinaryAbstractAddOverflow_AFloat) {
|
||||||
GlobalConst("c", Add(Source{{1, 1}}, Expr(AFloat::Highest()), AFloat::Highest()));
|
GlobalConst("c", Add(Source{{1, 1}}, Expr(AFloat::Highest()), AFloat::Highest()));
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
EXPECT_EQ(r()->error(),
|
EXPECT_EQ(r()->error(),
|
||||||
"1:1 error: '1.7976931348623157081e+308 + 1.7976931348623157081e+308' cannot be "
|
"1:1 error: "
|
||||||
|
"'17976931348623157081452742373170435679807056752584499659891747680315726078002853876"
|
||||||
|
"058955863276687817154045895351438246423432132688946418276846754670353751698604991057"
|
||||||
|
"655128207624549009038932894407586850845513394230458323690322294816580855933212334827"
|
||||||
|
"4797826204144723168738177180919299881250404026184124858368.0 + "
|
||||||
|
"179769313486231570814527423731704356798070567525844996598917476803157260780028538760"
|
||||||
|
"589558632766878171540458953514382464234321326889464182768467546703537516986049910576"
|
||||||
|
"551282076245490090389328944075868508455133942304583236903222948165808559332123348274"
|
||||||
|
"797826204144723168738177180919299881250404026184124858368.0' cannot be "
|
||||||
"represented as 'abstract-float'");
|
"represented as 'abstract-float'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1085,7 +1093,16 @@ TEST_F(ResolverConstEvalTest, BinaryAbstractAddUnderflow_AFloat) {
|
||||||
GlobalConst("c", Add(Source{{1, 1}}, Expr(AFloat::Lowest()), AFloat::Lowest()));
|
GlobalConst("c", Add(Source{{1, 1}}, Expr(AFloat::Lowest()), AFloat::Lowest()));
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
EXPECT_EQ(r()->error(),
|
EXPECT_EQ(r()->error(),
|
||||||
"1:1 error: '-1.7976931348623157081e+308 + -1.7976931348623157081e+308' cannot be "
|
"1:1 error: "
|
||||||
|
"'-"
|
||||||
|
"179769313486231570814527423731704356798070567525844996598917476803157260780028538760"
|
||||||
|
"589558632766878171540458953514382464234321326889464182768467546703537516986049910576"
|
||||||
|
"551282076245490090389328944075868508455133942304583236903222948165808559332123348274"
|
||||||
|
"797826204144723168738177180919299881250404026184124858368.0 + "
|
||||||
|
"-17976931348623157081452742373170435679807056752584499659891747680315726078002853876"
|
||||||
|
"058955863276687817154045895351438246423432132688946418276846754670353751698604991057"
|
||||||
|
"655128207624549009038932894407586850845513394230458323690322294816580855933212334827"
|
||||||
|
"4797826204144723168738177180919299881250404026184124858368.0' cannot be "
|
||||||
"represented as 'abstract-float'");
|
"represented as 'abstract-float'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1584,8 +1601,13 @@ TEST_F(ResolverConstEvalTest, NonShortCircuit_And_Invalid_Materialize) {
|
||||||
GlobalConst("result", binary);
|
GlobalConst("result", binary);
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
EXPECT_EQ(r()->error(),
|
EXPECT_EQ(
|
||||||
"12:34 error: value 1.7976931348623157081e+308 cannot be represented as 'f32'");
|
r()->error(),
|
||||||
|
"12:34 error: value "
|
||||||
|
"179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558"
|
||||||
|
"632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245"
|
||||||
|
"490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168"
|
||||||
|
"738177180919299881250404026184124858368.000000000 cannot be represented as 'f32'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalTest, ShortCircuit_And_Error_Materialize) {
|
TEST_F(ResolverConstEvalTest, ShortCircuit_And_Error_Materialize) {
|
||||||
|
@ -1630,8 +1652,13 @@ TEST_F(ResolverConstEvalTest, NonShortCircuit_Or_Invalid_Materialize) {
|
||||||
GlobalConst("result", binary);
|
GlobalConst("result", binary);
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
EXPECT_EQ(r()->error(),
|
EXPECT_EQ(
|
||||||
"12:34 error: value 1.7976931348623157081e+308 cannot be represented as 'f32'");
|
r()->error(),
|
||||||
|
"12:34 error: value "
|
||||||
|
"179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558"
|
||||||
|
"632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245"
|
||||||
|
"490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168"
|
||||||
|
"738177180919299881250404026184124858368.000000000 cannot be represented as 'f32'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalTest, ShortCircuit_Or_Error_Materialize) {
|
TEST_F(ResolverConstEvalTest, ShortCircuit_Or_Error_Materialize) {
|
||||||
|
|
|
@ -2025,9 +2025,11 @@ std::vector<Case> Pack2x16floatCases() {
|
||||||
C({Vec(f32(10), f32(-10.5))}, Val(u32(0xc940'4900))),
|
C({Vec(f32(10), f32(-10.5))}, Val(u32(0xc940'4900))),
|
||||||
|
|
||||||
E({Vec(f32(0), f32::Highest())},
|
E({Vec(f32(0), f32::Highest())},
|
||||||
"12:34 error: value 3.4028234663852885981e+38 cannot be represented as 'f16'"),
|
"12:34 error: value 340282346638528859811704183484516925440.000000000 cannot be "
|
||||||
|
"represented as 'f16'"),
|
||||||
E({Vec(f32::Lowest(), f32(0))},
|
E({Vec(f32::Lowest(), f32(0))},
|
||||||
"12:34 error: value -3.4028234663852885981e+38 cannot be represented as 'f16'"),
|
"12:34 error: value -340282346638528859811704183484516925440.000000000 cannot be "
|
||||||
|
"represented as 'f16'"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
INSTANTIATE_TEST_SUITE_P( //
|
INSTANTIATE_TEST_SUITE_P( //
|
||||||
|
@ -2848,15 +2850,16 @@ std::vector<Case> QuantizeToF16Cases() {
|
||||||
Vec(0x0.034p-14_f, -0x0.034p-14_f, 0x0.068p-14_f, -0x0.068p-14_f)),
|
Vec(0x0.034p-14_f, -0x0.034p-14_f, 0x0.068p-14_f, -0x0.068p-14_f)),
|
||||||
|
|
||||||
// Value out of f16 range
|
// Value out of f16 range
|
||||||
E({65504.003_f}, "12:34 error: value 65504.00390625 cannot be represented as 'f16'"),
|
E({65504.003_f}, "12:34 error: value 65504.003906250 cannot be represented as 'f16'"),
|
||||||
E({-65504.003_f}, "12:34 error: value -65504.00390625 cannot be represented as 'f16'"),
|
E({-65504.003_f}, "12:34 error: value -65504.003906250 cannot be represented as 'f16'"),
|
||||||
E({0x1.234p56_f}, "12:34 error: value 81979586966978560 cannot be represented as 'f16'"),
|
E({0x1.234p56_f},
|
||||||
|
"12:34 error: value 81979586966978560.000000000 cannot be represented as 'f16'"),
|
||||||
E({0x4.321p65_f},
|
E({0x4.321p65_f},
|
||||||
"12:34 error: value 1.5478871919272394752e+20 cannot be represented as 'f16'"),
|
"12:34 error: value 154788719192723947520.000000000 cannot be represented as 'f16'"),
|
||||||
E({Vec(65504.003_f, 0_f)},
|
E({Vec(65504.003_f, 0_f)},
|
||||||
"12:34 error: value 65504.00390625 cannot be represented as 'f16'"),
|
"12:34 error: value 65504.003906250 cannot be represented as 'f16'"),
|
||||||
E({Vec(0_f, -0x4.321p65_f)},
|
E({Vec(0_f, -0x4.321p65_f)},
|
||||||
"12:34 error: value -1.5478871919272394752e+20 cannot be represented as 'f16'"),
|
"12:34 error: value -154788719192723947520.000000000 cannot be represented as 'f16'"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
INSTANTIATE_TEST_SUITE_P( //
|
INSTANTIATE_TEST_SUITE_P( //
|
||||||
|
|
|
@ -431,7 +431,8 @@ TEST_F(ResolverConstEvalTest, Vec3_Convert_Large_f32_to_f16) {
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
EXPECT_EQ(r()->error(), "12:34 error: value 10000000000 cannot be represented as 'f16'");
|
EXPECT_EQ(r()->error(),
|
||||||
|
"12:34 error: value 10000000000.000000000 cannot be represented as 'f16'");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalTest, Vec3_Convert_Small_f32_to_f16) {
|
TEST_F(ResolverConstEvalTest, Vec3_Convert_Small_f32_to_f16) {
|
||||||
|
|
|
@ -75,7 +75,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Add_AFloat_Overflow) {
|
||||||
EXPECT_EQ(result.Get()->ValueAs<AFloat>(), 0.f);
|
EXPECT_EQ(result.Get()->ValueAs<AFloat>(), 0.f);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
error(),
|
error(),
|
||||||
R"(warning: '1.7976931348623157081e+308 + 1.7976931348623157081e+308' cannot be represented as 'abstract-float')");
|
R"(warning: '179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0 + 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0' cannot be represented as 'abstract-float')");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Add_F32_Overflow) {
|
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Add_F32_Overflow) {
|
||||||
|
@ -86,7 +86,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Add_F32_Overflow) {
|
||||||
EXPECT_EQ(result.Get()->ValueAs<f32>(), 0.f);
|
EXPECT_EQ(result.Get()->ValueAs<f32>(), 0.f);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
error(),
|
error(),
|
||||||
R"(warning: '3.4028234663852885981e+38 + 3.4028234663852885981e+38' cannot be represented as 'f32')");
|
R"(warning: '340282346638528859811704183484516925440.0 + 340282346638528859811704183484516925440.0' cannot be represented as 'f32')");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Sub_AInt_Overflow) {
|
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Sub_AInt_Overflow) {
|
||||||
|
@ -107,7 +107,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Sub_AFloat_Overflow) {
|
||||||
EXPECT_EQ(result.Get()->ValueAs<AFloat>(), 0.f);
|
EXPECT_EQ(result.Get()->ValueAs<AFloat>(), 0.f);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
error(),
|
error(),
|
||||||
R"(warning: '-1.7976931348623157081e+308 - 1.7976931348623157081e+308' cannot be represented as 'abstract-float')");
|
R"(warning: '-179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0 - 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0' cannot be represented as 'abstract-float')");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Sub_F32_Overflow) {
|
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Sub_F32_Overflow) {
|
||||||
|
@ -118,7 +118,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Sub_F32_Overflow) {
|
||||||
EXPECT_EQ(result.Get()->ValueAs<f32>(), 0.f);
|
EXPECT_EQ(result.Get()->ValueAs<f32>(), 0.f);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
error(),
|
error(),
|
||||||
R"(warning: '-3.4028234663852885981e+38 - 3.4028234663852885981e+38' cannot be represented as 'f32')");
|
R"(warning: '-340282346638528859811704183484516925440.0 - 340282346638528859811704183484516925440.0' cannot be represented as 'f32')");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Mul_AInt_Overflow) {
|
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Mul_AInt_Overflow) {
|
||||||
|
@ -139,7 +139,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Mul_AFloat_Overflow) {
|
||||||
EXPECT_EQ(result.Get()->ValueAs<AFloat>(), 0.f);
|
EXPECT_EQ(result.Get()->ValueAs<AFloat>(), 0.f);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
error(),
|
error(),
|
||||||
R"(warning: '1.7976931348623157081e+308 * 1.7976931348623157081e+308' cannot be represented as 'abstract-float')");
|
R"(warning: '179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0 * 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0' cannot be represented as 'abstract-float')");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Mul_F32_Overflow) {
|
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Mul_F32_Overflow) {
|
||||||
|
@ -150,7 +150,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Mul_F32_Overflow) {
|
||||||
EXPECT_EQ(result.Get()->ValueAs<f32>(), 0.f);
|
EXPECT_EQ(result.Get()->ValueAs<f32>(), 0.f);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
error(),
|
error(),
|
||||||
R"(warning: '3.4028234663852885981e+38 * 3.4028234663852885981e+38' cannot be represented as 'f32')");
|
R"(warning: '340282346638528859811704183484516925440.0 * 340282346638528859811704183484516925440.0' cannot be represented as 'f32')");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Div_AInt_ZeroDenominator) {
|
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Div_AInt_ZeroDenominator) {
|
||||||
|
@ -186,7 +186,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Div_AFloat_ZeroDenominator) {
|
||||||
auto result = const_eval.OpDivide(a->Type(), utils::Vector{a, b}, {});
|
auto result = const_eval.OpDivide(a->Type(), utils::Vector{a, b}, {});
|
||||||
ASSERT_TRUE(result);
|
ASSERT_TRUE(result);
|
||||||
EXPECT_EQ(result.Get()->ValueAs<AFloat>(), 42.f);
|
EXPECT_EQ(result.Get()->ValueAs<AFloat>(), 42.f);
|
||||||
EXPECT_EQ(error(), R"(warning: '42 / 0' cannot be represented as 'abstract-float')");
|
EXPECT_EQ(error(), R"(warning: '42.0 / 0.0' cannot be represented as 'abstract-float')");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Div_F32_ZeroDenominator) {
|
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Div_F32_ZeroDenominator) {
|
||||||
|
@ -195,7 +195,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Div_F32_ZeroDenominator) {
|
||||||
auto result = const_eval.OpDivide(a->Type(), utils::Vector{a, b}, {});
|
auto result = const_eval.OpDivide(a->Type(), utils::Vector{a, b}, {});
|
||||||
ASSERT_TRUE(result);
|
ASSERT_TRUE(result);
|
||||||
EXPECT_EQ(result.Get()->ValueAs<f32>(), 42.f);
|
EXPECT_EQ(result.Get()->ValueAs<f32>(), 42.f);
|
||||||
EXPECT_EQ(error(), R"(warning: '42 / 0' cannot be represented as 'f32')");
|
EXPECT_EQ(error(), R"(warning: '42.0 / 0.0' cannot be represented as 'f32')");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Div_I32_MostNegativeByMinInt) {
|
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Div_I32_MostNegativeByMinInt) {
|
||||||
|
@ -240,7 +240,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Mod_AFloat_ZeroDenominator) {
|
||||||
auto result = const_eval.OpModulo(a->Type(), utils::Vector{a, b}, {});
|
auto result = const_eval.OpModulo(a->Type(), utils::Vector{a, b}, {});
|
||||||
ASSERT_TRUE(result);
|
ASSERT_TRUE(result);
|
||||||
EXPECT_EQ(result.Get()->ValueAs<AFloat>(), 0.f);
|
EXPECT_EQ(result.Get()->ValueAs<AFloat>(), 0.f);
|
||||||
EXPECT_EQ(error(), R"(warning: '42 % 0' cannot be represented as 'abstract-float')");
|
EXPECT_EQ(error(), R"(warning: '42.0 % 0.0' cannot be represented as 'abstract-float')");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Mod_F32_ZeroDenominator) {
|
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Mod_F32_ZeroDenominator) {
|
||||||
|
@ -249,7 +249,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Mod_F32_ZeroDenominator) {
|
||||||
auto result = const_eval.OpModulo(a->Type(), utils::Vector{a, b}, {});
|
auto result = const_eval.OpModulo(a->Type(), utils::Vector{a, b}, {});
|
||||||
ASSERT_TRUE(result);
|
ASSERT_TRUE(result);
|
||||||
EXPECT_EQ(result.Get()->ValueAs<f32>(), 0.f);
|
EXPECT_EQ(result.Get()->ValueAs<f32>(), 0.f);
|
||||||
EXPECT_EQ(error(), R"(warning: '42 % 0' cannot be represented as 'f32')");
|
EXPECT_EQ(error(), R"(warning: '42.0 % 0.0' cannot be represented as 'f32')");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Mod_I32_MostNegativeByMinInt) {
|
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Mod_I32_MostNegativeByMinInt) {
|
||||||
|
@ -363,7 +363,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Exp_F32_Overflow) {
|
||||||
auto result = const_eval.exp(a->Type(), utils::Vector{a}, {});
|
auto result = const_eval.exp(a->Type(), utils::Vector{a}, {});
|
||||||
ASSERT_TRUE(result);
|
ASSERT_TRUE(result);
|
||||||
EXPECT_EQ(result.Get()->ValueAs<f32>(), 0.f);
|
EXPECT_EQ(result.Get()->ValueAs<f32>(), 0.f);
|
||||||
EXPECT_EQ(error(), R"(warning: e^1000 cannot be represented as 'f32')");
|
EXPECT_EQ(error(), R"(warning: e^1000.000000000 cannot be represented as 'f32')");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Exp2_F32_Overflow) {
|
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Exp2_F32_Overflow) {
|
||||||
|
@ -371,7 +371,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Exp2_F32_Overflow) {
|
||||||
auto result = const_eval.exp2(a->Type(), utils::Vector{a}, {});
|
auto result = const_eval.exp2(a->Type(), utils::Vector{a}, {});
|
||||||
ASSERT_TRUE(result);
|
ASSERT_TRUE(result);
|
||||||
EXPECT_EQ(result.Get()->ValueAs<f32>(), 0.f);
|
EXPECT_EQ(result.Get()->ValueAs<f32>(), 0.f);
|
||||||
EXPECT_EQ(error(), R"(warning: 2^1000 cannot be represented as 'f32')");
|
EXPECT_EQ(error(), R"(warning: 2^1000.000000000 cannot be represented as 'f32')");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalRuntimeSemanticsTest, ExtractBits_I32_TooManyBits) {
|
TEST_F(ResolverConstEvalRuntimeSemanticsTest, ExtractBits_I32_TooManyBits) {
|
||||||
|
@ -476,7 +476,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Pack2x16Float_OutOfRange) {
|
||||||
auto result = const_eval.pack2x16float(create<type::U32>(), utils::Vector{vec}, {});
|
auto result = const_eval.pack2x16float(create<type::U32>(), utils::Vector{vec}, {});
|
||||||
ASSERT_TRUE(result);
|
ASSERT_TRUE(result);
|
||||||
EXPECT_EQ(result.Get()->ValueAs<u32>(), 0x51430000);
|
EXPECT_EQ(result.Get()->ValueAs<u32>(), 0x51430000);
|
||||||
EXPECT_EQ(error(), R"(warning: value 75250 cannot be represented as 'f16')");
|
EXPECT_EQ(error(), R"(warning: value 75250.000000000 cannot be represented as 'f16')");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Pow_F32_Overflow) {
|
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Pow_F32_Overflow) {
|
||||||
|
@ -485,7 +485,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Pow_F32_Overflow) {
|
||||||
auto result = const_eval.pow(a->Type(), utils::Vector{a, b}, {});
|
auto result = const_eval.pow(a->Type(), utils::Vector{a, b}, {});
|
||||||
ASSERT_TRUE(result);
|
ASSERT_TRUE(result);
|
||||||
EXPECT_EQ(result.Get()->ValueAs<f32>(), 0.f);
|
EXPECT_EQ(result.Get()->ValueAs<f32>(), 0.f);
|
||||||
EXPECT_EQ(error(), R"(warning: '2 ^ 1000' cannot be represented as 'f32')");
|
EXPECT_EQ(error(), R"(warning: '2.0 ^ 1000.0' cannot be represented as 'f32')");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Unpack2x16Float_OutOfRange) {
|
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Unpack2x16Float_OutOfRange) {
|
||||||
|
@ -502,7 +502,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, QuantizeToF16_OutOfRange) {
|
||||||
auto result = const_eval.quantizeToF16(create<type::U32>(), utils::Vector{a}, {});
|
auto result = const_eval.quantizeToF16(create<type::U32>(), utils::Vector{a}, {});
|
||||||
ASSERT_TRUE(result);
|
ASSERT_TRUE(result);
|
||||||
EXPECT_EQ(result.Get()->ValueAs<u32>(), 0);
|
EXPECT_EQ(result.Get()->ValueAs<u32>(), 0);
|
||||||
EXPECT_EQ(error(), R"(warning: value 75250 cannot be represented as 'f16')");
|
EXPECT_EQ(error(), R"(warning: value 75250.000000000 cannot be represented as 'f16')");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Sqrt_F32_OutOfRange) {
|
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Sqrt_F32_OutOfRange) {
|
||||||
|
@ -534,8 +534,9 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Convert_F32_TooHigh) {
|
||||||
auto result = const_eval.Convert(create<type::F32>(), a, {});
|
auto result = const_eval.Convert(create<type::F32>(), a, {});
|
||||||
ASSERT_TRUE(result);
|
ASSERT_TRUE(result);
|
||||||
EXPECT_EQ(result.Get()->ValueAs<f32>(), f32::kHighestValue);
|
EXPECT_EQ(result.Get()->ValueAs<f32>(), f32::kHighestValue);
|
||||||
EXPECT_EQ(error(),
|
EXPECT_EQ(
|
||||||
R"(warning: value 1.7976931348623157081e+308 cannot be represented as 'f32')");
|
error(),
|
||||||
|
R"(warning: value 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000000 cannot be represented as 'f32')");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Convert_F32_TooLow) {
|
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Convert_F32_TooLow) {
|
||||||
|
@ -543,8 +544,9 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Convert_F32_TooLow) {
|
||||||
auto result = const_eval.Convert(create<type::F32>(), a, {});
|
auto result = const_eval.Convert(create<type::F32>(), a, {});
|
||||||
ASSERT_TRUE(result);
|
ASSERT_TRUE(result);
|
||||||
EXPECT_EQ(result.Get()->ValueAs<f32>(), f32::kLowestValue);
|
EXPECT_EQ(result.Get()->ValueAs<f32>(), f32::kLowestValue);
|
||||||
EXPECT_EQ(error(),
|
EXPECT_EQ(
|
||||||
R"(warning: value -1.7976931348623157081e+308 cannot be represented as 'f32')");
|
error(),
|
||||||
|
R"(warning: value -179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000000 cannot be represented as 'f32')");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Convert_F16_TooHigh) {
|
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Convert_F16_TooHigh) {
|
||||||
|
@ -552,7 +554,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Convert_F16_TooHigh) {
|
||||||
auto result = const_eval.Convert(create<type::F16>(), a, {});
|
auto result = const_eval.Convert(create<type::F16>(), a, {});
|
||||||
ASSERT_TRUE(result);
|
ASSERT_TRUE(result);
|
||||||
EXPECT_EQ(result.Get()->ValueAs<f32>(), f16::kHighestValue);
|
EXPECT_EQ(result.Get()->ValueAs<f32>(), f16::kHighestValue);
|
||||||
EXPECT_EQ(error(), R"(warning: value 1000000 cannot be represented as 'f16')");
|
EXPECT_EQ(error(), R"(warning: value 1000000.000000000 cannot be represented as 'f16')");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Convert_F16_TooLow) {
|
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Convert_F16_TooLow) {
|
||||||
|
@ -560,7 +562,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Convert_F16_TooLow) {
|
||||||
auto result = const_eval.Convert(create<type::F16>(), a, {});
|
auto result = const_eval.Convert(create<type::F16>(), a, {});
|
||||||
ASSERT_TRUE(result);
|
ASSERT_TRUE(result);
|
||||||
EXPECT_EQ(result.Get()->ValueAs<f32>(), f16::kLowestValue);
|
EXPECT_EQ(result.Get()->ValueAs<f32>(), f16::kLowestValue);
|
||||||
EXPECT_EQ(error(), R"(warning: value -1000000 cannot be represented as 'f16')");
|
EXPECT_EQ(error(), R"(warning: value -1000000.000000000 cannot be represented as 'f16')");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Vec_Overflow_SingleComponent) {
|
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Vec_Overflow_SingleComponent) {
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "src/tint/resolver/resolver_test_helper.h"
|
#include "src/tint/resolver/resolver_test_helper.h"
|
||||||
#include "src/tint/type/test_helper.h"
|
#include "src/tint/type/test_helper.h"
|
||||||
|
#include "src/tint/utils/string_stream.h"
|
||||||
|
|
||||||
namespace tint::resolver {
|
namespace tint::resolver {
|
||||||
|
|
||||||
|
@ -218,8 +219,7 @@ inline void ConcatIntoIf([[maybe_unused]] Vec& v1, [[maybe_unused]] Vecs&&... vs
|
||||||
/// Returns the overflow error message for binary ops
|
/// Returns the overflow error message for binary ops
|
||||||
template <typename NumberT>
|
template <typename NumberT>
|
||||||
inline std::string OverflowErrorMessage(NumberT lhs, const char* op, NumberT rhs) {
|
inline std::string OverflowErrorMessage(NumberT lhs, const char* op, NumberT rhs) {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << std::setprecision(20);
|
|
||||||
ss << "'" << lhs.value << " " << op << " " << rhs.value << "' cannot be represented as '"
|
ss << "'" << lhs.value << " " << op << " " << rhs.value << "' cannot be represented as '"
|
||||||
<< FriendlyName<NumberT>() << "'";
|
<< FriendlyName<NumberT>() << "'";
|
||||||
return ss.str();
|
return ss.str();
|
||||||
|
@ -228,8 +228,7 @@ inline std::string OverflowErrorMessage(NumberT lhs, const char* op, NumberT rhs
|
||||||
/// Returns the overflow error message for conversions
|
/// Returns the overflow error message for conversions
|
||||||
template <typename VALUE_TY>
|
template <typename VALUE_TY>
|
||||||
std::string OverflowErrorMessage(VALUE_TY value, std::string_view target_ty) {
|
std::string OverflowErrorMessage(VALUE_TY value, std::string_view target_ty) {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << std::setprecision(20);
|
|
||||||
ss << "value " << value << " cannot be represented as "
|
ss << "value " << value << " cannot be represented as "
|
||||||
<< "'" << target_ty << "'";
|
<< "'" << target_ty << "'";
|
||||||
return ss.str();
|
return ss.str();
|
||||||
|
@ -238,8 +237,7 @@ std::string OverflowErrorMessage(VALUE_TY value, std::string_view target_ty) {
|
||||||
/// Returns the overflow error message for exponentiation
|
/// Returns the overflow error message for exponentiation
|
||||||
template <typename NumberT>
|
template <typename NumberT>
|
||||||
std::string OverflowExpErrorMessage(std::string_view base, NumberT exp) {
|
std::string OverflowExpErrorMessage(std::string_view base, NumberT exp) {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << std::setprecision(20);
|
|
||||||
ss << base << "^" << exp << " cannot be represented as "
|
ss << base << "^" << exp << " cannot be represented as "
|
||||||
<< "'" << FriendlyName<NumberT>() << "'";
|
<< "'" << FriendlyName<NumberT>() << "'";
|
||||||
return ss.str();
|
return ss.str();
|
||||||
|
|
|
@ -65,6 +65,7 @@
|
||||||
#include "src/tint/utils/defer.h"
|
#include "src/tint/utils/defer.h"
|
||||||
#include "src/tint/utils/map.h"
|
#include "src/tint/utils/map.h"
|
||||||
#include "src/tint/utils/scoped_assignment.h"
|
#include "src/tint/utils/scoped_assignment.h"
|
||||||
|
#include "src/tint/utils/string_stream.h"
|
||||||
#include "src/tint/utils/unique_vector.h"
|
#include "src/tint/utils/unique_vector.h"
|
||||||
|
|
||||||
#define TINT_DUMP_DEPENDENCY_GRAPH 0
|
#define TINT_DUMP_DEPENDENCY_GRAPH 0
|
||||||
|
@ -711,7 +712,7 @@ struct DependencyAnalysis {
|
||||||
/// found in `stack`.
|
/// found in `stack`.
|
||||||
/// @param stack is the global dependency stack that contains a loop.
|
/// @param stack is the global dependency stack that contains a loop.
|
||||||
void CyclicDependencyFound(const Global* root, utils::VectorRef<const Global*> stack) {
|
void CyclicDependencyFound(const Global* root, utils::VectorRef<const Global*> stack) {
|
||||||
std::stringstream msg;
|
utils::StringStream msg;
|
||||||
msg << "cyclic dependency found: ";
|
msg << "cyclic dependency found: ";
|
||||||
constexpr size_t kLoopNotStarted = ~0u;
|
constexpr size_t kLoopNotStarted = ~0u;
|
||||||
size_t loop_start = kLoopNotStarted;
|
size_t loop_start = kLoopNotStarted;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "src/tint/builtin/builtin_value.h"
|
#include "src/tint/builtin/builtin_value.h"
|
||||||
#include "src/tint/resolver/resolver.h"
|
#include "src/tint/resolver/resolver.h"
|
||||||
#include "src/tint/resolver/resolver_test_helper.h"
|
#include "src/tint/resolver/resolver_test_helper.h"
|
||||||
|
#include "src/tint/utils/string_stream.h"
|
||||||
|
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
|
|
||||||
|
@ -1054,7 +1055,7 @@ TEST_P(ResolverFunctionParameterValidationTest, AddressSpaceNoExtension) {
|
||||||
if (param.expectation == Expectation::kAlwaysPass) {
|
if (param.expectation == Expectation::kAlwaysPass) {
|
||||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||||
} else {
|
} else {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << param.address_space;
|
ss << param.address_space;
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
if (param.expectation == Expectation::kInvalid) {
|
if (param.expectation == Expectation::kInvalid) {
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "src/tint/utils/hashmap.h"
|
#include "src/tint/utils/hashmap.h"
|
||||||
#include "src/tint/utils/math.h"
|
#include "src/tint/utils/math.h"
|
||||||
#include "src/tint/utils/scoped_assignment.h"
|
#include "src/tint/utils/scoped_assignment.h"
|
||||||
|
#include "src/tint/utils/string_stream.h"
|
||||||
|
|
||||||
namespace tint::resolver {
|
namespace tint::resolver {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -1202,12 +1203,12 @@ class Impl : public IntrinsicTable {
|
||||||
sem::EvaluationStage earliest_eval_stage) const;
|
sem::EvaluationStage earliest_eval_stage) const;
|
||||||
|
|
||||||
// Prints the overload for emitting diagnostics
|
// Prints the overload for emitting diagnostics
|
||||||
void PrintOverload(std::ostream& ss,
|
void PrintOverload(utils::StringStream& ss,
|
||||||
const OverloadInfo* overload,
|
const OverloadInfo* overload,
|
||||||
const char* intrinsic_name) const;
|
const char* intrinsic_name) const;
|
||||||
|
|
||||||
// Prints the list of candidates for emitting diagnostics
|
// Prints the list of candidates for emitting diagnostics
|
||||||
void PrintCandidates(std::ostream& ss,
|
void PrintCandidates(utils::StringStream& ss,
|
||||||
utils::VectorRef<Candidate> candidates,
|
utils::VectorRef<Candidate> candidates,
|
||||||
const char* intrinsic_name) const;
|
const char* intrinsic_name) const;
|
||||||
|
|
||||||
|
@ -1232,7 +1233,7 @@ std::string CallSignature(ProgramBuilder& builder,
|
||||||
const char* intrinsic_name,
|
const char* intrinsic_name,
|
||||||
utils::VectorRef<const type::Type*> args,
|
utils::VectorRef<const type::Type*> args,
|
||||||
const type::Type* template_arg = nullptr) {
|
const type::Type* template_arg = nullptr) {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << intrinsic_name;
|
ss << intrinsic_name;
|
||||||
if (template_arg) {
|
if (template_arg) {
|
||||||
ss << "<" << template_arg->FriendlyName(builder.Symbols()) << ">";
|
ss << "<" << template_arg->FriendlyName(builder.Symbols()) << ">";
|
||||||
|
@ -1271,7 +1272,7 @@ Impl::Builtin Impl::Lookup(sem::BuiltinType builtin_type,
|
||||||
|
|
||||||
// Generates an error when no overloads match the provided arguments
|
// Generates an error when no overloads match the provided arguments
|
||||||
auto on_no_match = [&](utils::VectorRef<Candidate> candidates) {
|
auto on_no_match = [&](utils::VectorRef<Candidate> candidates) {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "no matching call to " << CallSignature(builder, intrinsic_name, args) << std::endl;
|
ss << "no matching call to " << CallSignature(builder, intrinsic_name, args) << std::endl;
|
||||||
if (!candidates.IsEmpty()) {
|
if (!candidates.IsEmpty()) {
|
||||||
ss << std::endl
|
ss << std::endl
|
||||||
|
@ -1340,7 +1341,7 @@ IntrinsicTable::UnaryOperator Impl::Lookup(ast::UnaryOp op,
|
||||||
|
|
||||||
// Generates an error when no overloads match the provided arguments
|
// Generates an error when no overloads match the provided arguments
|
||||||
auto on_no_match = [&, name = intrinsic_name](utils::VectorRef<Candidate> candidates) {
|
auto on_no_match = [&, name = intrinsic_name](utils::VectorRef<Candidate> candidates) {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "no matching overload for " << CallSignature(builder, name, args) << std::endl;
|
ss << "no matching overload for " << CallSignature(builder, name, args) << std::endl;
|
||||||
if (!candidates.IsEmpty()) {
|
if (!candidates.IsEmpty()) {
|
||||||
ss << std::endl
|
ss << std::endl
|
||||||
|
@ -1418,7 +1419,7 @@ IntrinsicTable::BinaryOperator Impl::Lookup(ast::BinaryOp op,
|
||||||
|
|
||||||
// Generates an error when no overloads match the provided arguments
|
// Generates an error when no overloads match the provided arguments
|
||||||
auto on_no_match = [&, name = intrinsic_name](utils::VectorRef<Candidate> candidates) {
|
auto on_no_match = [&, name = intrinsic_name](utils::VectorRef<Candidate> candidates) {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "no matching overload for " << CallSignature(builder, name, args) << std::endl;
|
ss << "no matching overload for " << CallSignature(builder, name, args) << std::endl;
|
||||||
if (!candidates.IsEmpty()) {
|
if (!candidates.IsEmpty()) {
|
||||||
ss << std::endl
|
ss << std::endl
|
||||||
|
@ -1453,7 +1454,7 @@ IntrinsicTable::CtorOrConv Impl::Lookup(CtorConvIntrinsic type,
|
||||||
|
|
||||||
// Generates an error when no overloads match the provided arguments
|
// Generates an error when no overloads match the provided arguments
|
||||||
auto on_no_match = [&](utils::VectorRef<Candidate> candidates) {
|
auto on_no_match = [&](utils::VectorRef<Candidate> candidates) {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "no matching constructor for " << CallSignature(builder, name, args, template_arg)
|
ss << "no matching constructor for " << CallSignature(builder, name, args, template_arg)
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
Candidates ctor, conv;
|
Candidates ctor, conv;
|
||||||
|
@ -1755,7 +1756,7 @@ MatchState Impl::Match(TemplateState& templates,
|
||||||
return MatchState(builder, templates, matchers, overload, matcher_indices, earliest_eval_stage);
|
return MatchState(builder, templates, matchers, overload, matcher_indices, earliest_eval_stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Impl::PrintOverload(std::ostream& ss,
|
void Impl::PrintOverload(utils::StringStream& ss,
|
||||||
const OverloadInfo* overload,
|
const OverloadInfo* overload,
|
||||||
const char* intrinsic_name) const {
|
const char* intrinsic_name) const {
|
||||||
TemplateState templates;
|
TemplateState templates;
|
||||||
|
@ -1827,7 +1828,7 @@ void Impl::PrintOverload(std::ostream& ss,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Impl::PrintCandidates(std::ostream& ss,
|
void Impl::PrintCandidates(utils::StringStream& ss,
|
||||||
utils::VectorRef<Candidate> candidates,
|
utils::VectorRef<Candidate> candidates,
|
||||||
const char* intrinsic_name) const {
|
const char* intrinsic_name) const {
|
||||||
for (auto& candidate : candidates) {
|
for (auto& candidate : candidates) {
|
||||||
|
@ -1865,7 +1866,7 @@ void Impl::ErrAmbiguousOverload(const char* intrinsic_name,
|
||||||
utils::VectorRef<const type::Type*> args,
|
utils::VectorRef<const type::Type*> args,
|
||||||
TemplateState templates,
|
TemplateState templates,
|
||||||
utils::VectorRef<Candidate> candidates) const {
|
utils::VectorRef<Candidate> candidates) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "ambiguous overload while attempting to match " << intrinsic_name;
|
ss << "ambiguous overload while attempting to match " << intrinsic_name;
|
||||||
for (size_t i = 0; i < std::numeric_limits<size_t>::max(); i++) {
|
for (size_t i = 0; i < std::numeric_limits<size_t>::max(); i++) {
|
||||||
if (auto* ty = templates.Type(i)) {
|
if (auto* ty = templates.Type(i)) {
|
||||||
|
|
|
@ -71,7 +71,7 @@ const type::Type* Ia::Match(MatchState& state, const type::Type* ty) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Ia::String(MatchState*) const {
|
std::string Ia::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "abstract-int";
|
ss << "abstract-int";
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ const type::Type* Fa::Match(MatchState& state, const type::Type* ty) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Fa::String(MatchState*) const {
|
std::string Fa::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "abstract-float";
|
ss << "abstract-float";
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
@ -627,7 +627,7 @@ const type::Type* Vec::Match(MatchState& state, const type::Type* ty) const {
|
||||||
std::string Vec::String(MatchState* state) const {
|
std::string Vec::String(MatchState* state) const {
|
||||||
const std::string N = state->NumName();
|
const std::string N = state->NumName();
|
||||||
const std::string T = state->TypeName();
|
const std::string T = state->TypeName();
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "vec" << N << "<" << T << ">";
|
ss << "vec" << N << "<" << T << ">";
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
@ -673,7 +673,7 @@ std::string Mat::String(MatchState* state) const {
|
||||||
const std::string N = state->NumName();
|
const std::string N = state->NumName();
|
||||||
const std::string M = state->NumName();
|
const std::string M = state->NumName();
|
||||||
const std::string T = state->TypeName();
|
const std::string T = state->TypeName();
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "mat" << N << "x" << M << "<" << T << ">";
|
ss << "mat" << N << "x" << M << "<" << T << ">";
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
@ -1431,7 +1431,7 @@ const type::Type* ModfResult::Match(MatchState& state, const type::Type* ty) con
|
||||||
|
|
||||||
std::string ModfResult::String(MatchState* state) const {
|
std::string ModfResult::String(MatchState* state) const {
|
||||||
const std::string T = state->TypeName();
|
const std::string T = state->TypeName();
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "__modf_result_" << T;
|
ss << "__modf_result_" << T;
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
@ -1471,7 +1471,7 @@ const type::Type* ModfResultVec::Match(MatchState& state, const type::Type* ty)
|
||||||
std::string ModfResultVec::String(MatchState* state) const {
|
std::string ModfResultVec::String(MatchState* state) const {
|
||||||
const std::string N = state->NumName();
|
const std::string N = state->NumName();
|
||||||
const std::string T = state->TypeName();
|
const std::string T = state->TypeName();
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "__modf_result_vec" << N << "_" << T;
|
ss << "__modf_result_vec" << N << "_" << T;
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
@ -1505,7 +1505,7 @@ const type::Type* FrexpResult::Match(MatchState& state, const type::Type* ty) co
|
||||||
|
|
||||||
std::string FrexpResult::String(MatchState* state) const {
|
std::string FrexpResult::String(MatchState* state) const {
|
||||||
const std::string T = state->TypeName();
|
const std::string T = state->TypeName();
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "__frexp_result_" << T;
|
ss << "__frexp_result_" << T;
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
@ -1545,7 +1545,7 @@ const type::Type* FrexpResultVec::Match(MatchState& state, const type::Type* ty)
|
||||||
std::string FrexpResultVec::String(MatchState* state) const {
|
std::string FrexpResultVec::String(MatchState* state) const {
|
||||||
const std::string N = state->NumName();
|
const std::string N = state->NumName();
|
||||||
const std::string T = state->TypeName();
|
const std::string T = state->TypeName();
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "__frexp_result_vec" << N << "_" << T;
|
ss << "__frexp_result_vec" << N << "_" << T;
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
@ -1624,7 +1624,7 @@ const type::Type* Scalar::Match(MatchState& state, const type::Type* ty) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Scalar::String(MatchState*) const {
|
std::string Scalar::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
||||||
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
||||||
ss << Ia().String(nullptr) << ", " << Fa().String(nullptr) << ", " << F32().String(nullptr) << ", " << F16().String(nullptr) << ", " << I32().String(nullptr) << ", " << U32().String(nullptr) << " or " << Bool().String(nullptr);
|
ss << Ia().String(nullptr) << ", " << Fa().String(nullptr) << ", " << F32().String(nullptr) << ", " << F16().String(nullptr) << ", " << I32().String(nullptr) << ", " << U32().String(nullptr) << " or " << Bool().String(nullptr);
|
||||||
|
@ -1667,7 +1667,7 @@ const type::Type* ConcreteScalar::Match(MatchState& state, const type::Type* ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ConcreteScalar::String(MatchState*) const {
|
std::string ConcreteScalar::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
||||||
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
||||||
ss << F32().String(nullptr) << ", " << F16().String(nullptr) << ", " << I32().String(nullptr) << ", " << U32().String(nullptr) << " or " << Bool().String(nullptr);
|
ss << F32().String(nullptr) << ", " << F16().String(nullptr) << ", " << I32().String(nullptr) << ", " << U32().String(nullptr) << " or " << Bool().String(nullptr);
|
||||||
|
@ -1713,7 +1713,7 @@ const type::Type* ScalarNoF32::Match(MatchState& state, const type::Type* ty) co
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ScalarNoF32::String(MatchState*) const {
|
std::string ScalarNoF32::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
||||||
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
||||||
ss << Ia().String(nullptr) << ", " << Fa().String(nullptr) << ", " << I32().String(nullptr) << ", " << F16().String(nullptr) << ", " << U32().String(nullptr) << " or " << Bool().String(nullptr);
|
ss << Ia().String(nullptr) << ", " << Fa().String(nullptr) << ", " << I32().String(nullptr) << ", " << F16().String(nullptr) << ", " << U32().String(nullptr) << " or " << Bool().String(nullptr);
|
||||||
|
@ -1759,7 +1759,7 @@ const type::Type* ScalarNoF16::Match(MatchState& state, const type::Type* ty) co
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ScalarNoF16::String(MatchState*) const {
|
std::string ScalarNoF16::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
||||||
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
||||||
ss << Ia().String(nullptr) << ", " << Fa().String(nullptr) << ", " << F32().String(nullptr) << ", " << I32().String(nullptr) << ", " << U32().String(nullptr) << " or " << Bool().String(nullptr);
|
ss << Ia().String(nullptr) << ", " << Fa().String(nullptr) << ", " << F32().String(nullptr) << ", " << I32().String(nullptr) << ", " << U32().String(nullptr) << " or " << Bool().String(nullptr);
|
||||||
|
@ -1805,7 +1805,7 @@ const type::Type* ScalarNoI32::Match(MatchState& state, const type::Type* ty) co
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ScalarNoI32::String(MatchState*) const {
|
std::string ScalarNoI32::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
||||||
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
||||||
ss << Ia().String(nullptr) << ", " << Fa().String(nullptr) << ", " << F32().String(nullptr) << ", " << F16().String(nullptr) << ", " << U32().String(nullptr) << " or " << Bool().String(nullptr);
|
ss << Ia().String(nullptr) << ", " << Fa().String(nullptr) << ", " << F32().String(nullptr) << ", " << F16().String(nullptr) << ", " << U32().String(nullptr) << " or " << Bool().String(nullptr);
|
||||||
|
@ -1851,7 +1851,7 @@ const type::Type* ScalarNoU32::Match(MatchState& state, const type::Type* ty) co
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ScalarNoU32::String(MatchState*) const {
|
std::string ScalarNoU32::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
||||||
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
||||||
ss << Ia().String(nullptr) << ", " << Fa().String(nullptr) << ", " << F32().String(nullptr) << ", " << F16().String(nullptr) << ", " << I32().String(nullptr) << " or " << Bool().String(nullptr);
|
ss << Ia().String(nullptr) << ", " << Fa().String(nullptr) << ", " << F32().String(nullptr) << ", " << F16().String(nullptr) << ", " << I32().String(nullptr) << " or " << Bool().String(nullptr);
|
||||||
|
@ -1897,7 +1897,7 @@ const type::Type* ScalarNoBool::Match(MatchState& state, const type::Type* ty) c
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ScalarNoBool::String(MatchState*) const {
|
std::string ScalarNoBool::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
||||||
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
||||||
ss << Ia().String(nullptr) << ", " << Fa().String(nullptr) << ", " << F32().String(nullptr) << ", " << F16().String(nullptr) << ", " << I32().String(nullptr) << " or " << U32().String(nullptr);
|
ss << Ia().String(nullptr) << ", " << Fa().String(nullptr) << ", " << F32().String(nullptr) << ", " << F16().String(nullptr) << ", " << I32().String(nullptr) << " or " << U32().String(nullptr);
|
||||||
|
@ -1943,7 +1943,7 @@ const type::Type* FiaFiu32F16::Match(MatchState& state, const type::Type* ty) co
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FiaFiu32F16::String(MatchState*) const {
|
std::string FiaFiu32F16::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
||||||
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
||||||
ss << Fa().String(nullptr) << ", " << Ia().String(nullptr) << ", " << F32().String(nullptr) << ", " << I32().String(nullptr) << ", " << U32().String(nullptr) << " or " << F16().String(nullptr);
|
ss << Fa().String(nullptr) << ", " << Ia().String(nullptr) << ", " << F32().String(nullptr) << ", " << I32().String(nullptr) << ", " << U32().String(nullptr) << " or " << F16().String(nullptr);
|
||||||
|
@ -1986,7 +1986,7 @@ const type::Type* FiaFi32F16::Match(MatchState& state, const type::Type* ty) con
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FiaFi32F16::String(MatchState*) const {
|
std::string FiaFi32F16::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
||||||
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
||||||
ss << Fa().String(nullptr) << ", " << Ia().String(nullptr) << ", " << F32().String(nullptr) << ", " << I32().String(nullptr) << " or " << F16().String(nullptr);
|
ss << Fa().String(nullptr) << ", " << Ia().String(nullptr) << ", " << F32().String(nullptr) << ", " << I32().String(nullptr) << " or " << F16().String(nullptr);
|
||||||
|
@ -2029,7 +2029,7 @@ const type::Type* FiaFiu32::Match(MatchState& state, const type::Type* ty) const
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FiaFiu32::String(MatchState*) const {
|
std::string FiaFiu32::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
||||||
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
||||||
ss << Fa().String(nullptr) << ", " << Ia().String(nullptr) << ", " << F32().String(nullptr) << ", " << I32().String(nullptr) << " or " << U32().String(nullptr);
|
ss << Fa().String(nullptr) << ", " << Ia().String(nullptr) << ", " << F32().String(nullptr) << ", " << I32().String(nullptr) << " or " << U32().String(nullptr);
|
||||||
|
@ -2063,7 +2063,7 @@ const type::Type* FaF32::Match(MatchState& state, const type::Type* ty) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FaF32::String(MatchState*) const {
|
std::string FaF32::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
||||||
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
||||||
ss << Fa().String(nullptr) << " or " << F32().String(nullptr);
|
ss << Fa().String(nullptr) << " or " << F32().String(nullptr);
|
||||||
|
@ -2100,7 +2100,7 @@ const type::Type* FaF32F16::Match(MatchState& state, const type::Type* ty) const
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string FaF32F16::String(MatchState*) const {
|
std::string FaF32F16::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
||||||
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
||||||
ss << Fa().String(nullptr) << ", " << F32().String(nullptr) << " or " << F16().String(nullptr);
|
ss << Fa().String(nullptr) << ", " << F32().String(nullptr) << " or " << F16().String(nullptr);
|
||||||
|
@ -2137,7 +2137,7 @@ const type::Type* IaIu32::Match(MatchState& state, const type::Type* ty) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string IaIu32::String(MatchState*) const {
|
std::string IaIu32::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
||||||
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
||||||
ss << Ia().String(nullptr) << ", " << I32().String(nullptr) << " or " << U32().String(nullptr);
|
ss << Ia().String(nullptr) << ", " << I32().String(nullptr) << " or " << U32().String(nullptr);
|
||||||
|
@ -2171,7 +2171,7 @@ const type::Type* IaI32::Match(MatchState& state, const type::Type* ty) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string IaI32::String(MatchState*) const {
|
std::string IaI32::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
||||||
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
||||||
ss << Ia().String(nullptr) << " or " << I32().String(nullptr);
|
ss << Ia().String(nullptr) << " or " << I32().String(nullptr);
|
||||||
|
@ -2211,7 +2211,7 @@ const type::Type* Fiu32F16::Match(MatchState& state, const type::Type* ty) const
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Fiu32F16::String(MatchState*) const {
|
std::string Fiu32F16::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
||||||
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
||||||
ss << F32().String(nullptr) << ", " << I32().String(nullptr) << ", " << U32().String(nullptr) << " or " << F16().String(nullptr);
|
ss << F32().String(nullptr) << ", " << I32().String(nullptr) << ", " << U32().String(nullptr) << " or " << F16().String(nullptr);
|
||||||
|
@ -2248,7 +2248,7 @@ const type::Type* Fiu32::Match(MatchState& state, const type::Type* ty) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Fiu32::String(MatchState*) const {
|
std::string Fiu32::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
||||||
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
||||||
ss << F32().String(nullptr) << ", " << I32().String(nullptr) << " or " << U32().String(nullptr);
|
ss << F32().String(nullptr) << ", " << I32().String(nullptr) << " or " << U32().String(nullptr);
|
||||||
|
@ -2285,7 +2285,7 @@ const type::Type* Fi32F16::Match(MatchState& state, const type::Type* ty) const
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Fi32F16::String(MatchState*) const {
|
std::string Fi32F16::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
||||||
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
||||||
ss << F32().String(nullptr) << ", " << I32().String(nullptr) << " or " << F16().String(nullptr);
|
ss << F32().String(nullptr) << ", " << I32().String(nullptr) << " or " << F16().String(nullptr);
|
||||||
|
@ -2319,7 +2319,7 @@ const type::Type* Fi32::Match(MatchState& state, const type::Type* ty) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Fi32::String(MatchState*) const {
|
std::string Fi32::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
||||||
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
||||||
ss << F32().String(nullptr) << " or " << I32().String(nullptr);
|
ss << F32().String(nullptr) << " or " << I32().String(nullptr);
|
||||||
|
@ -2353,7 +2353,7 @@ const type::Type* F32F16::Match(MatchState& state, const type::Type* ty) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string F32F16::String(MatchState*) const {
|
std::string F32F16::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
||||||
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
||||||
ss << F32().String(nullptr) << " or " << F16().String(nullptr);
|
ss << F32().String(nullptr) << " or " << F16().String(nullptr);
|
||||||
|
@ -2387,7 +2387,7 @@ const type::Type* Iu32::Match(MatchState& state, const type::Type* ty) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Iu32::String(MatchState*) const {
|
std::string Iu32::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
||||||
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
||||||
ss << I32().String(nullptr) << " or " << U32().String(nullptr);
|
ss << I32().String(nullptr) << " or " << U32().String(nullptr);
|
||||||
|
|
|
@ -221,7 +221,7 @@ std::string {{$class}}::String(MatchState*{{if .TemplateParams}} state{{end}}) c
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- if .DisplayName }}
|
{{- if .DisplayName }}
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss{{range SplitDisplayName .DisplayName}} << {{.}}{{end}};
|
ss{{range SplitDisplayName .DisplayName}} << {{.}}{{end}};
|
||||||
return ss.str();
|
return ss.str();
|
||||||
{{- else if .TemplateParams }}
|
{{- else if .TemplateParams }}
|
||||||
|
@ -264,7 +264,7 @@ const type::Type* {{$class}}::Match(MatchState& state, const type::Type* ty) con
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string {{$class}}::String(MatchState*) const {
|
std::string {{$class}}::String(MatchState*) const {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
// Note: We pass nullptr to the TypeMatcher::String() functions, as 'matcher's do not support
|
||||||
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
// template arguments, nor can they match sub-types. As such, they have no use for the MatchState.
|
||||||
ss
|
ss
|
||||||
|
|
|
@ -84,6 +84,7 @@
|
||||||
#include "src/tint/utils/reverse.h"
|
#include "src/tint/utils/reverse.h"
|
||||||
#include "src/tint/utils/scoped_assignment.h"
|
#include "src/tint/utils/scoped_assignment.h"
|
||||||
#include "src/tint/utils/string.h"
|
#include "src/tint/utils/string.h"
|
||||||
|
#include "src/tint/utils/string_stream.h"
|
||||||
#include "src/tint/utils/transform.h"
|
#include "src/tint/utils/transform.h"
|
||||||
#include "src/tint/utils/vector.h"
|
#include "src/tint/utils/vector.h"
|
||||||
|
|
||||||
|
@ -3099,7 +3100,7 @@ sem::Expression* Resolver::Identifier(const ast::IdentifierExpression* expr) {
|
||||||
filtered.Push(str);
|
filtered.Push(str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::ostringstream msg;
|
utils::StringStream msg;
|
||||||
utils::SuggestAlternatives(unresolved->name,
|
utils::SuggestAlternatives(unresolved->name,
|
||||||
filtered.Slice().Reinterpret<char const* const>(), msg);
|
filtered.Slice().Reinterpret<char const* const>(), msg);
|
||||||
AddNote(msg.str(), expr->source);
|
AddNote(msg.str(), expr->source);
|
||||||
|
@ -3464,7 +3465,7 @@ bool Resolver::DiagnosticControl(const ast::DiagnosticControl& control) {
|
||||||
if (rule != builtin::DiagnosticRule::kUndefined) {
|
if (rule != builtin::DiagnosticRule::kUndefined) {
|
||||||
validator_.DiagnosticFilters().Set(rule, control.severity);
|
validator_.DiagnosticFilters().Set(rule, control.severity);
|
||||||
} else {
|
} else {
|
||||||
std::ostringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "unrecognized diagnostic rule '" << rule_name << "'\n";
|
ss << "unrecognized diagnostic rule '" << rule_name << "'\n";
|
||||||
utils::SuggestAlternatives(rule_name, builtin::kDiagnosticRuleStrings, ss);
|
utils::SuggestAlternatives(rule_name, builtin::kDiagnosticRuleStrings, ss);
|
||||||
AddWarning(ss.str(), control.rule_name->source);
|
AddWarning(ss.str(), control.rule_name->source);
|
||||||
|
@ -3584,7 +3585,7 @@ type::Array* Resolver::Array(const Source& array_source,
|
||||||
if (auto const_count = el_count->As<type::ConstantArrayCount>()) {
|
if (auto const_count = el_count->As<type::ConstantArrayCount>()) {
|
||||||
size = const_count->value * stride;
|
size = const_count->value * stride;
|
||||||
if (size > std::numeric_limits<uint32_t>::max()) {
|
if (size > std::numeric_limits<uint32_t>::max()) {
|
||||||
std::stringstream msg;
|
utils::StringStream msg;
|
||||||
msg << "array byte size (0x" << std::hex << size
|
msg << "array byte size (0x" << std::hex << size
|
||||||
<< ") must not exceed 0xffffffff bytes";
|
<< ") must not exceed 0xffffffff bytes";
|
||||||
AddError(msg.str(), count_source);
|
AddError(msg.str(), count_source);
|
||||||
|
@ -3822,7 +3823,7 @@ sem::Struct* Resolver::Structure(const ast::Struct* str) {
|
||||||
|
|
||||||
offset = utils::RoundUp(align, offset);
|
offset = utils::RoundUp(align, offset);
|
||||||
if (offset > std::numeric_limits<uint32_t>::max()) {
|
if (offset > std::numeric_limits<uint32_t>::max()) {
|
||||||
std::stringstream msg;
|
utils::StringStream msg;
|
||||||
msg << "struct member offset (0x" << std::hex << offset << ") must not exceed 0x"
|
msg << "struct member offset (0x" << std::hex << offset << ") must not exceed 0x"
|
||||||
<< std::hex << std::numeric_limits<uint32_t>::max() << " bytes";
|
<< std::hex << std::numeric_limits<uint32_t>::max() << " bytes";
|
||||||
AddError(msg.str(), member->source);
|
AddError(msg.str(), member->source);
|
||||||
|
@ -3844,7 +3845,7 @@ sem::Struct* Resolver::Structure(const ast::Struct* str) {
|
||||||
struct_size = utils::RoundUp(struct_align, struct_size);
|
struct_size = utils::RoundUp(struct_align, struct_size);
|
||||||
|
|
||||||
if (struct_size > std::numeric_limits<uint32_t>::max()) {
|
if (struct_size > std::numeric_limits<uint32_t>::max()) {
|
||||||
std::stringstream msg;
|
utils::StringStream msg;
|
||||||
msg << "struct size (0x" << std::hex << struct_size << ") must not exceed 0xffffffff bytes";
|
msg << "struct size (0x" << std::hex << struct_size << ") must not exceed 0xffffffff bytes";
|
||||||
AddError(msg.str(), str->source);
|
AddError(msg.str(), str->source);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -4192,7 +4193,7 @@ bool Resolver::ApplyAddressSpaceUsageToType(builtin::AddressSpace address_space,
|
||||||
if (decl &&
|
if (decl &&
|
||||||
!ApplyAddressSpaceUsageToType(
|
!ApplyAddressSpaceUsageToType(
|
||||||
address_space, const_cast<type::Type*>(member->Type()), decl->type->source)) {
|
address_space, const_cast<type::Type*>(member->Type()), decl->type->source)) {
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
err << "while analyzing structure member " << sem_.TypeNameOf(str) << "."
|
err << "while analyzing structure member " << sem_.TypeNameOf(str) << "."
|
||||||
<< builder_->Symbols().NameFor(member->Name());
|
<< builder_->Symbols().NameFor(member->Name());
|
||||||
AddNote(err.str(), member->Source());
|
AddNote(err.str(), member->Source());
|
||||||
|
@ -4223,7 +4224,7 @@ bool Resolver::ApplyAddressSpaceUsageToType(builtin::AddressSpace address_space,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (builtin::IsHostShareable(address_space) && !validator_.IsHostShareable(ty)) {
|
if (builtin::IsHostShareable(address_space) && !validator_.IsHostShareable(ty)) {
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
err << "Type '" << sem_.TypeNameOf(ty) << "' cannot be used in address space '"
|
err << "Type '" << sem_.TypeNameOf(ty) << "' cannot be used in address space '"
|
||||||
<< address_space << "' as it is non-host-shareable";
|
<< address_space << "' as it is non-host-shareable";
|
||||||
AddError(err.str(), usage);
|
AddError(err.str(), usage);
|
||||||
|
@ -4248,7 +4249,7 @@ SEM* Resolver::StatementScope(const ast::Statement* ast, SEM* sem, F&& callback)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std::ostringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "attribute is not valid for " << use;
|
ss << "attribute is not valid for " << use;
|
||||||
AddError(ss.str(), attr->source);
|
AddError(ss.str(), attr->source);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include "src/tint/type/reference.h"
|
#include "src/tint/type/reference.h"
|
||||||
#include "src/tint/type/sampled_texture.h"
|
#include "src/tint/type/sampled_texture.h"
|
||||||
#include "src/tint/type/texture_dimension.h"
|
#include "src/tint/type/texture_dimension.h"
|
||||||
|
#include "src/tint/utils/string_stream.h"
|
||||||
|
|
||||||
using ::testing::ElementsAre;
|
using ::testing::ElementsAre;
|
||||||
using ::testing::HasSubstr;
|
using ::testing::HasSubstr;
|
||||||
|
@ -1647,7 +1648,7 @@ TEST_P(Expr_Binary_Test_Valid, All) {
|
||||||
ast::Type rhs_type = params.create_rhs_type(*this);
|
ast::Type rhs_type = params.create_rhs_type(*this);
|
||||||
auto* result_type = params.create_result_type(*this);
|
auto* result_type = params.create_result_type(*this);
|
||||||
|
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << FriendlyName(lhs_type) << " " << params.op << " " << FriendlyName(rhs_type);
|
ss << FriendlyName(lhs_type) << " " << params.op << " " << FriendlyName(rhs_type);
|
||||||
SCOPED_TRACE(ss.str());
|
SCOPED_TRACE(ss.str());
|
||||||
|
|
||||||
|
@ -1679,7 +1680,7 @@ TEST_P(Expr_Binary_Test_WithAlias_Valid, All) {
|
||||||
ast::Type lhs_type = create_lhs_type(*this);
|
ast::Type lhs_type = create_lhs_type(*this);
|
||||||
ast::Type rhs_type = create_rhs_type(*this);
|
ast::Type rhs_type = create_rhs_type(*this);
|
||||||
|
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << FriendlyName(lhs_type) << " " << params.op << " " << FriendlyName(rhs_type);
|
ss << FriendlyName(lhs_type) << " " << params.op << " " << FriendlyName(rhs_type);
|
||||||
|
|
||||||
ss << ", After aliasing: " << FriendlyName(lhs_type) << " " << params.op << " "
|
ss << ", After aliasing: " << FriendlyName(lhs_type) << " " << params.op << " "
|
||||||
|
@ -1728,7 +1729,7 @@ TEST_P(Expr_Binary_Test_Invalid, All) {
|
||||||
ast::Type lhs_type = lhs_create_type_func(*this);
|
ast::Type lhs_type = lhs_create_type_func(*this);
|
||||||
ast::Type rhs_type = rhs_create_type_func(*this);
|
ast::Type rhs_type = rhs_create_type_func(*this);
|
||||||
|
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << FriendlyName(lhs_type) << " " << op << " " << FriendlyName(rhs_type);
|
ss << FriendlyName(lhs_type) << " " << op << " " << FriendlyName(rhs_type);
|
||||||
SCOPED_TRACE(ss.str());
|
SCOPED_TRACE(ss.str());
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include "src/tint/sem/while_statement.h"
|
#include "src/tint/sem/while_statement.h"
|
||||||
#include "src/tint/utils/block_allocator.h"
|
#include "src/tint/utils/block_allocator.h"
|
||||||
#include "src/tint/utils/map.h"
|
#include "src/tint/utils/map.h"
|
||||||
|
#include "src/tint/utils/string_stream.h"
|
||||||
#include "src/tint/utils/unique_vector.h"
|
#include "src/tint/utils/unique_vector.h"
|
||||||
|
|
||||||
// Set to `1` to dump the uniformity graph for each function in graphviz format.
|
// Set to `1` to dump the uniformity graph for each function in graphviz format.
|
||||||
|
@ -1778,7 +1779,7 @@ class UniformityGraph {
|
||||||
non_uniform_source->ast,
|
non_uniform_source->ast,
|
||||||
[&](const ast::IdentifierExpression* ident) {
|
[&](const ast::IdentifierExpression* ident) {
|
||||||
auto* var = sem_.GetVal(ident)->UnwrapLoad()->As<sem::VariableUser>()->Variable();
|
auto* var = sem_.GetVal(ident)->UnwrapLoad()->As<sem::VariableUser>()->Variable();
|
||||||
std::ostringstream ss;
|
utils::StringStream ss;
|
||||||
if (auto* param = var->As<sem::Parameter>()) {
|
if (auto* param = var->As<sem::Parameter>()) {
|
||||||
auto* func = param->Owner()->As<sem::Function>();
|
auto* func = param->Owner()->As<sem::Function>();
|
||||||
ss << param_type(param) << "'" << NameFor(ident) << "' of '" << NameFor(func)
|
ss << param_type(param) << "'" << NameFor(ident) << "' of '" << NameFor(func)
|
||||||
|
@ -1791,7 +1792,7 @@ class UniformityGraph {
|
||||||
},
|
},
|
||||||
[&](const ast::Variable* v) {
|
[&](const ast::Variable* v) {
|
||||||
auto* var = sem_.Get(v);
|
auto* var = sem_.Get(v);
|
||||||
std::ostringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "reading from " << var_type(var) << "'" << NameFor(v)
|
ss << "reading from " << var_type(var) << "'" << NameFor(v)
|
||||||
<< "' may result in a non-uniform value";
|
<< "' may result in a non-uniform value";
|
||||||
diagnostics_.add_note(diag::System::Resolver, ss.str(), v->source);
|
diagnostics_.add_note(diag::System::Resolver, ss.str(), v->source);
|
||||||
|
@ -1808,7 +1809,7 @@ class UniformityGraph {
|
||||||
case Node::kFunctionCallArgumentContents: {
|
case Node::kFunctionCallArgumentContents: {
|
||||||
auto* arg = c->args[non_uniform_source->arg_index];
|
auto* arg = c->args[non_uniform_source->arg_index];
|
||||||
auto* var = sem_.GetVal(arg)->RootIdentifier();
|
auto* var = sem_.GetVal(arg)->RootIdentifier();
|
||||||
std::ostringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "reading from " << var_type(var) << "'" << NameFor(var)
|
ss << "reading from " << var_type(var) << "'" << NameFor(var)
|
||||||
<< "' may result in a non-uniform value";
|
<< "' may result in a non-uniform value";
|
||||||
diagnostics_.add_note(diag::System::Resolver, ss.str(),
|
diagnostics_.add_note(diag::System::Resolver, ss.str(),
|
||||||
|
@ -1895,7 +1896,7 @@ class UniformityGraph {
|
||||||
|
|
||||||
// Show the place where the non-uniform argument was passed.
|
// Show the place where the non-uniform argument was passed.
|
||||||
// If this is a builtin, this will be the trigger location for the failure.
|
// If this is a builtin, this will be the trigger location for the failure.
|
||||||
std::ostringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "possibly non-uniform value passed" << (is_value ? "" : " via pointer")
|
ss << "possibly non-uniform value passed" << (is_value ? "" : " via pointer")
|
||||||
<< " here";
|
<< " here";
|
||||||
report(call->args[cause->arg_index]->source, ss.str(), /* note */ user_func != nullptr);
|
report(call->args[cause->arg_index]->source, ss.str(), /* note */ user_func != nullptr);
|
||||||
|
@ -1907,7 +1908,7 @@ class UniformityGraph {
|
||||||
{
|
{
|
||||||
// Show a builtin was reachable from this call (which may be the call itself).
|
// Show a builtin was reachable from this call (which may be the call itself).
|
||||||
// This will be the trigger location for the failure.
|
// This will be the trigger location for the failure.
|
||||||
std::ostringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "'" << NameFor(builtin_call->target)
|
ss << "'" << NameFor(builtin_call->target)
|
||||||
<< "' must only be called from uniform control flow";
|
<< "' must only be called from uniform control flow";
|
||||||
report(builtin_call->source, ss.str(), /* note */ false);
|
report(builtin_call->source, ss.str(), /* note */ false);
|
||||||
|
@ -1915,7 +1916,7 @@ class UniformityGraph {
|
||||||
|
|
||||||
if (builtin_call != call) {
|
if (builtin_call != call) {
|
||||||
// The call was to a user function, so show that call too.
|
// The call was to a user function, so show that call too.
|
||||||
std::ostringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "called ";
|
ss << "called ";
|
||||||
if (target->As<sem::Function>() != SemCall(builtin_call)->Stmt()->Function()) {
|
if (target->As<sem::Function>() != SemCall(builtin_call)->Stmt()->Function()) {
|
||||||
ss << "indirectly ";
|
ss << "indirectly ";
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "src/tint/program_builder.h"
|
#include "src/tint/program_builder.h"
|
||||||
#include "src/tint/reader/wgsl/parser.h"
|
#include "src/tint/reader/wgsl/parser.h"
|
||||||
#include "src/tint/resolver/uniformity.h"
|
#include "src/tint/resolver/uniformity.h"
|
||||||
|
#include "src/tint/utils/string_stream.h"
|
||||||
|
|
||||||
#include "gmock/gmock.h"
|
#include "gmock/gmock.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
@ -7890,7 +7891,7 @@ class UniformityAnalysisDiagnosticFilterTest
|
||||||
|
|
||||||
TEST_P(UniformityAnalysisDiagnosticFilterTest, Directive) {
|
TEST_P(UniformityAnalysisDiagnosticFilterTest, Directive) {
|
||||||
auto& param = GetParam();
|
auto& param = GetParam();
|
||||||
std::ostringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "diagnostic(" << param << ", derivative_uniformity);"
|
ss << "diagnostic(" << param << ", derivative_uniformity);"
|
||||||
<< R"(
|
<< R"(
|
||||||
@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
|
@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
|
||||||
|
@ -7909,7 +7910,7 @@ fn foo() {
|
||||||
if (param == builtin::DiagnosticSeverity::kOff) {
|
if (param == builtin::DiagnosticSeverity::kOff) {
|
||||||
EXPECT_TRUE(error_.empty());
|
EXPECT_TRUE(error_.empty());
|
||||||
} else {
|
} else {
|
||||||
std::ostringstream err;
|
utils::StringStream err;
|
||||||
err << ToStr(param) << ": 'textureSample' must only be called";
|
err << ToStr(param) << ": 'textureSample' must only be called";
|
||||||
EXPECT_THAT(error_, ::testing::HasSubstr(err.str()));
|
EXPECT_THAT(error_, ::testing::HasSubstr(err.str()));
|
||||||
}
|
}
|
||||||
|
@ -7917,7 +7918,7 @@ fn foo() {
|
||||||
|
|
||||||
TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnFunction) {
|
TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnFunction) {
|
||||||
auto& param = GetParam();
|
auto& param = GetParam();
|
||||||
std::ostringstream ss;
|
utils::StringStream ss;
|
||||||
ss << R"(
|
ss << R"(
|
||||||
@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
|
@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
|
||||||
@group(0) @binding(1) var t : texture_2d<f32>;
|
@group(0) @binding(1) var t : texture_2d<f32>;
|
||||||
|
@ -7936,7 +7937,7 @@ TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnFunction) {
|
||||||
if (param == builtin::DiagnosticSeverity::kOff) {
|
if (param == builtin::DiagnosticSeverity::kOff) {
|
||||||
EXPECT_TRUE(error_.empty());
|
EXPECT_TRUE(error_.empty());
|
||||||
} else {
|
} else {
|
||||||
std::ostringstream err;
|
utils::StringStream err;
|
||||||
err << ToStr(param) << ": 'textureSample' must only be called";
|
err << ToStr(param) << ": 'textureSample' must only be called";
|
||||||
EXPECT_THAT(error_, ::testing::HasSubstr(err.str()));
|
EXPECT_THAT(error_, ::testing::HasSubstr(err.str()));
|
||||||
}
|
}
|
||||||
|
@ -7944,7 +7945,7 @@ TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnFunction) {
|
||||||
|
|
||||||
TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnBlock) {
|
TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnBlock) {
|
||||||
auto& param = GetParam();
|
auto& param = GetParam();
|
||||||
std::ostringstream ss;
|
utils::StringStream ss;
|
||||||
ss << R"(
|
ss << R"(
|
||||||
@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
|
@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
|
||||||
@group(0) @binding(1) var t : texture_2d<f32>;
|
@group(0) @binding(1) var t : texture_2d<f32>;
|
||||||
|
@ -7962,7 +7963,7 @@ fn foo() {
|
||||||
if (param == builtin::DiagnosticSeverity::kOff) {
|
if (param == builtin::DiagnosticSeverity::kOff) {
|
||||||
EXPECT_TRUE(error_.empty());
|
EXPECT_TRUE(error_.empty());
|
||||||
} else {
|
} else {
|
||||||
std::ostringstream err;
|
utils::StringStream err;
|
||||||
err << ToStr(param) << ": 'textureSample' must only be called";
|
err << ToStr(param) << ": 'textureSample' must only be called";
|
||||||
EXPECT_THAT(error_, ::testing::HasSubstr(err.str()));
|
EXPECT_THAT(error_, ::testing::HasSubstr(err.str()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,6 +71,7 @@
|
||||||
#include "src/tint/utils/reverse.h"
|
#include "src/tint/utils/reverse.h"
|
||||||
#include "src/tint/utils/scoped_assignment.h"
|
#include "src/tint/utils/scoped_assignment.h"
|
||||||
#include "src/tint/utils/string.h"
|
#include "src/tint/utils/string.h"
|
||||||
|
#include "src/tint/utils/string_stream.h"
|
||||||
#include "src/tint/utils/transform.h"
|
#include "src/tint/utils/transform.h"
|
||||||
|
|
||||||
namespace tint::resolver {
|
namespace tint::resolver {
|
||||||
|
@ -380,7 +381,7 @@ bool Validator::VariableInitializer(const ast::Variable* v,
|
||||||
|
|
||||||
// Value type has to match storage type
|
// Value type has to match storage type
|
||||||
if (storage_ty != value_type) {
|
if (storage_ty != value_type) {
|
||||||
std::stringstream s;
|
utils::StringStream s;
|
||||||
s << "cannot initialize " << v->Kind() << " of type '" << sem_.TypeNameOf(storage_ty)
|
s << "cannot initialize " << v->Kind() << " of type '" << sem_.TypeNameOf(storage_ty)
|
||||||
<< "' with value of type '" << sem_.TypeNameOf(initializer_ty) << "'";
|
<< "' with value of type '" << sem_.TypeNameOf(initializer_ty) << "'";
|
||||||
AddError(s.str(), v->source);
|
AddError(s.str(), v->source);
|
||||||
|
@ -842,7 +843,7 @@ bool Validator::Parameter(const ast::Function* func, const sem::Variable* var) c
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "function parameter of pointer type cannot be in '" << sc
|
ss << "function parameter of pointer type cannot be in '" << sc
|
||||||
<< "' address space";
|
<< "' address space";
|
||||||
AddError(ss.str(), decl->source);
|
AddError(ss.str(), decl->source);
|
||||||
|
@ -870,7 +871,7 @@ bool Validator::BuiltinAttribute(const ast::BuiltinAttribute* attr,
|
||||||
ast::PipelineStage stage,
|
ast::PipelineStage stage,
|
||||||
const bool is_input) const {
|
const bool is_input) const {
|
||||||
auto* type = storage_ty->UnwrapRef();
|
auto* type = storage_ty->UnwrapRef();
|
||||||
std::stringstream stage_name;
|
utils::StringStream stage_name;
|
||||||
stage_name << stage;
|
stage_name << stage;
|
||||||
bool is_stage_mismatch = false;
|
bool is_stage_mismatch = false;
|
||||||
bool is_output = !is_input;
|
bool is_output = !is_input;
|
||||||
|
@ -883,7 +884,7 @@ bool Validator::BuiltinAttribute(const ast::BuiltinAttribute* attr,
|
||||||
is_stage_mismatch = true;
|
is_stage_mismatch = true;
|
||||||
}
|
}
|
||||||
if (!(type->is_float_vector() && type->As<type::Vector>()->Width() == 4)) {
|
if (!(type->is_float_vector() && type->As<type::Vector>()->Width() == 4)) {
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
err << "store type of @builtin(" << builtin << ") must be 'vec4<f32>'";
|
err << "store type of @builtin(" << builtin << ") must be 'vec4<f32>'";
|
||||||
AddError(err.str(), attr->source);
|
AddError(err.str(), attr->source);
|
||||||
return false;
|
return false;
|
||||||
|
@ -898,7 +899,7 @@ bool Validator::BuiltinAttribute(const ast::BuiltinAttribute* attr,
|
||||||
is_stage_mismatch = true;
|
is_stage_mismatch = true;
|
||||||
}
|
}
|
||||||
if (!(type->is_unsigned_integer_vector() && type->As<type::Vector>()->Width() == 3)) {
|
if (!(type->is_unsigned_integer_vector() && type->As<type::Vector>()->Width() == 3)) {
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
err << "store type of @builtin(" << builtin << ") must be 'vec3<u32>'";
|
err << "store type of @builtin(" << builtin << ") must be 'vec3<u32>'";
|
||||||
AddError(err.str(), attr->source);
|
AddError(err.str(), attr->source);
|
||||||
return false;
|
return false;
|
||||||
|
@ -910,7 +911,7 @@ bool Validator::BuiltinAttribute(const ast::BuiltinAttribute* attr,
|
||||||
is_stage_mismatch = true;
|
is_stage_mismatch = true;
|
||||||
}
|
}
|
||||||
if (!type->Is<type::F32>()) {
|
if (!type->Is<type::F32>()) {
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
err << "store type of @builtin(" << builtin << ") must be 'f32'";
|
err << "store type of @builtin(" << builtin << ") must be 'f32'";
|
||||||
AddError(err.str(), attr->source);
|
AddError(err.str(), attr->source);
|
||||||
return false;
|
return false;
|
||||||
|
@ -922,7 +923,7 @@ bool Validator::BuiltinAttribute(const ast::BuiltinAttribute* attr,
|
||||||
is_stage_mismatch = true;
|
is_stage_mismatch = true;
|
||||||
}
|
}
|
||||||
if (!type->Is<type::Bool>()) {
|
if (!type->Is<type::Bool>()) {
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
err << "store type of @builtin(" << builtin << ") must be 'bool'";
|
err << "store type of @builtin(" << builtin << ") must be 'bool'";
|
||||||
AddError(err.str(), attr->source);
|
AddError(err.str(), attr->source);
|
||||||
return false;
|
return false;
|
||||||
|
@ -934,7 +935,7 @@ bool Validator::BuiltinAttribute(const ast::BuiltinAttribute* attr,
|
||||||
is_stage_mismatch = true;
|
is_stage_mismatch = true;
|
||||||
}
|
}
|
||||||
if (!type->Is<type::U32>()) {
|
if (!type->Is<type::U32>()) {
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
err << "store type of @builtin(" << builtin << ") must be 'u32'";
|
err << "store type of @builtin(" << builtin << ") must be 'u32'";
|
||||||
AddError(err.str(), attr->source);
|
AddError(err.str(), attr->source);
|
||||||
return false;
|
return false;
|
||||||
|
@ -947,7 +948,7 @@ bool Validator::BuiltinAttribute(const ast::BuiltinAttribute* attr,
|
||||||
is_stage_mismatch = true;
|
is_stage_mismatch = true;
|
||||||
}
|
}
|
||||||
if (!type->Is<type::U32>()) {
|
if (!type->Is<type::U32>()) {
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
err << "store type of @builtin(" << builtin << ") must be 'u32'";
|
err << "store type of @builtin(" << builtin << ") must be 'u32'";
|
||||||
AddError(err.str(), attr->source);
|
AddError(err.str(), attr->source);
|
||||||
return false;
|
return false;
|
||||||
|
@ -958,7 +959,7 @@ bool Validator::BuiltinAttribute(const ast::BuiltinAttribute* attr,
|
||||||
is_stage_mismatch = true;
|
is_stage_mismatch = true;
|
||||||
}
|
}
|
||||||
if (!type->Is<type::U32>()) {
|
if (!type->Is<type::U32>()) {
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
err << "store type of @builtin(" << builtin << ") must be 'u32'";
|
err << "store type of @builtin(" << builtin << ") must be 'u32'";
|
||||||
AddError(err.str(), attr->source);
|
AddError(err.str(), attr->source);
|
||||||
return false;
|
return false;
|
||||||
|
@ -970,7 +971,7 @@ bool Validator::BuiltinAttribute(const ast::BuiltinAttribute* attr,
|
||||||
is_stage_mismatch = true;
|
is_stage_mismatch = true;
|
||||||
}
|
}
|
||||||
if (!type->Is<type::U32>()) {
|
if (!type->Is<type::U32>()) {
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
err << "store type of @builtin(" << builtin << ") must be 'u32'";
|
err << "store type of @builtin(" << builtin << ") must be 'u32'";
|
||||||
AddError(err.str(), attr->source);
|
AddError(err.str(), attr->source);
|
||||||
return false;
|
return false;
|
||||||
|
@ -981,7 +982,7 @@ bool Validator::BuiltinAttribute(const ast::BuiltinAttribute* attr,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_stage_mismatch) {
|
if (is_stage_mismatch) {
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
err << "@builtin(" << builtin << ") cannot be used in "
|
err << "@builtin(" << builtin << ") cannot be used in "
|
||||||
<< (is_input ? "input of " : "output of ") << stage_name.str() << " pipeline stage";
|
<< (is_input ? "input of " : "output of ") << stage_name.str() << " pipeline stage";
|
||||||
AddError(err.str(), attr->source);
|
AddError(err.str(), attr->source);
|
||||||
|
@ -1156,7 +1157,7 @@ bool Validator::EntryPoint(const sem::Function* func, ast::PipelineStage stage)
|
||||||
pipeline_io_attribute = attr;
|
pipeline_io_attribute = attr;
|
||||||
|
|
||||||
if (builtins.Contains(builtin)) {
|
if (builtins.Contains(builtin)) {
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
err << "@builtin(" << builtin << ") appears multiple times as pipeline "
|
err << "@builtin(" << builtin << ") appears multiple times as pipeline "
|
||||||
<< (param_or_ret == ParamOrRetType::kParameter ? "input" : "output");
|
<< (param_or_ret == ParamOrRetType::kParameter ? "input" : "output");
|
||||||
AddError(err.str(), decl->source);
|
AddError(err.str(), decl->source);
|
||||||
|
@ -1949,7 +1950,7 @@ bool Validator::PipelineStages(utils::VectorRef<sem::Function*> entry_points) co
|
||||||
if (stage != ast::PipelineStage::kCompute) {
|
if (stage != ast::PipelineStage::kCompute) {
|
||||||
for (auto* var : func->DirectlyReferencedGlobals()) {
|
for (auto* var : func->DirectlyReferencedGlobals()) {
|
||||||
if (var->AddressSpace() == builtin::AddressSpace::kWorkgroup) {
|
if (var->AddressSpace() == builtin::AddressSpace::kWorkgroup) {
|
||||||
std::stringstream stage_name;
|
utils::StringStream stage_name;
|
||||||
stage_name << stage;
|
stage_name << stage;
|
||||||
for (auto* user : var->Users()) {
|
for (auto* user : var->Users()) {
|
||||||
if (func == user->Stmt()->Function()) {
|
if (func == user->Stmt()->Function()) {
|
||||||
|
@ -1973,7 +1974,7 @@ bool Validator::PipelineStages(utils::VectorRef<sem::Function*> entry_points) co
|
||||||
for (auto* builtin : func->DirectlyCalledBuiltins()) {
|
for (auto* builtin : func->DirectlyCalledBuiltins()) {
|
||||||
if (!builtin->SupportedStages().Contains(stage)) {
|
if (!builtin->SupportedStages().Contains(stage)) {
|
||||||
auto* call = func->FindDirectCallTo(builtin);
|
auto* call = func->FindDirectCallTo(builtin);
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
err << "built-in cannot be used by " << stage << " pipeline stage";
|
err << "built-in cannot be used by " << stage << " pipeline stage";
|
||||||
AddError(err.str(),
|
AddError(err.str(),
|
||||||
call ? call->Declaration()->source : func->Declaration()->source);
|
call ? call->Declaration()->source : func->Declaration()->source);
|
||||||
|
@ -1987,7 +1988,7 @@ bool Validator::PipelineStages(utils::VectorRef<sem::Function*> entry_points) co
|
||||||
auto check_no_discards = [&](const sem::Function* func, const sem::Function* entry_point) {
|
auto check_no_discards = [&](const sem::Function* func, const sem::Function* entry_point) {
|
||||||
if (auto* discard = func->DiscardStatement()) {
|
if (auto* discard = func->DiscardStatement()) {
|
||||||
auto stage = entry_point->Declaration()->PipelineStage();
|
auto stage = entry_point->Declaration()->PipelineStage();
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
err << "discard statement cannot be used in " << stage << " pipeline stage";
|
err << "discard statement cannot be used in " << stage << " pipeline stage";
|
||||||
AddError(err.str(), discard->Declaration()->source);
|
AddError(err.str(), discard->Declaration()->source);
|
||||||
backtrace(func, entry_point);
|
backtrace(func, entry_point);
|
||||||
|
@ -2283,7 +2284,7 @@ bool Validator::LocationAttribute(const ast::LocationAttribute* loc_attr,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!locations.Add(location)) {
|
if (!locations.Add(location)) {
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
err << "@location(" << location << ") appears multiple times";
|
err << "@location(" << location << ") appears multiple times";
|
||||||
AddError(err.str(), loc_attr->source);
|
AddError(err.str(), loc_attr->source);
|
||||||
return false;
|
return false;
|
||||||
|
@ -2543,12 +2544,12 @@ bool Validator::DiagnosticControls(utils::VectorRef<const ast::DiagnosticControl
|
||||||
auto diag_added = diagnostics.Add(dc->rule_name->symbol, dc);
|
auto diag_added = diagnostics.Add(dc->rule_name->symbol, dc);
|
||||||
if (!diag_added && (*diag_added.value)->severity != dc->severity) {
|
if (!diag_added && (*diag_added.value)->severity != dc->severity) {
|
||||||
{
|
{
|
||||||
std::ostringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "conflicting diagnostic " << use;
|
ss << "conflicting diagnostic " << use;
|
||||||
AddError(ss.str(), dc->rule_name->source);
|
AddError(ss.str(), dc->rule_name->source);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::ostringstream ss;
|
utils::StringStream ss;
|
||||||
ss << "severity of '" << symbols_.NameFor(dc->rule_name->symbol) << "' set to '"
|
ss << "severity of '" << symbols_.NameFor(dc->rule_name->symbol) << "' set to '"
|
||||||
<< dc->severity << "' here";
|
<< dc->severity << "' here";
|
||||||
AddNote(ss.str(), (*diag_added.value)->rule_name->source);
|
AddNote(ss.str(), (*diag_added.value)->rule_name->source);
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "src/tint/sem/value_constructor.h"
|
#include "src/tint/sem/value_constructor.h"
|
||||||
#include "src/tint/sem/value_conversion.h"
|
#include "src/tint/sem/value_conversion.h"
|
||||||
#include "src/tint/type/reference.h"
|
#include "src/tint/type/reference.h"
|
||||||
|
#include "src/tint/utils/string_stream.h"
|
||||||
|
|
||||||
using namespace tint::number_suffixes; // NOLINT
|
using namespace tint::number_suffixes; // NOLINT
|
||||||
|
|
||||||
|
@ -354,7 +355,7 @@ TEST_P(ConversionConstructorValidTest, All) {
|
||||||
auto rhs_type = params.rhs_type(*this);
|
auto rhs_type = params.rhs_type(*this);
|
||||||
auto* rhs_value_expr = params.rhs_value_expr(*this, 0);
|
auto* rhs_value_expr = params.rhs_value_expr(*this, 0);
|
||||||
|
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << FriendlyName(lhs_type1) << " = " << FriendlyName(lhs_type2) << "("
|
ss << FriendlyName(lhs_type1) << " = " << FriendlyName(lhs_type2) << "("
|
||||||
<< FriendlyName(rhs_type) << "(<rhs value expr>))";
|
<< FriendlyName(rhs_type) << "(<rhs value expr>))";
|
||||||
SCOPED_TRACE(ss.str());
|
SCOPED_TRACE(ss.str());
|
||||||
|
@ -447,7 +448,7 @@ TEST_P(ConversionConstructorInvalidTest, All) {
|
||||||
auto rhs_type = rhs_params.ast(*this);
|
auto rhs_type = rhs_params.ast(*this);
|
||||||
auto* rhs_value_expr = rhs_params.expr_from_double(*this, 0);
|
auto* rhs_value_expr = rhs_params.expr_from_double(*this, 0);
|
||||||
|
|
||||||
std::stringstream ss;
|
utils::StringStream ss;
|
||||||
ss << FriendlyName(lhs_type1) << " = " << FriendlyName(lhs_type2) << "("
|
ss << FriendlyName(lhs_type1) << " = " << FriendlyName(lhs_type2) << "("
|
||||||
<< FriendlyName(rhs_type) << "(<rhs value expr>))";
|
<< FriendlyName(rhs_type) << "(<rhs value expr>))";
|
||||||
SCOPED_TRACE(ss.str());
|
SCOPED_TRACE(ss.str());
|
||||||
|
@ -2414,7 +2415,7 @@ TEST_P(MatrixConstructorTest, ColumnConstructor_Error_TooFewArguments) {
|
||||||
Enable(builtin::Extension::kF16);
|
Enable(builtin::Extension::kF16);
|
||||||
|
|
||||||
const std::string element_type_name = param.get_element_type_name();
|
const std::string element_type_name = param.get_element_type_name();
|
||||||
std::stringstream args_tys;
|
utils::StringStream args_tys;
|
||||||
utils::Vector<const ast::Expression*, 8> args;
|
utils::Vector<const ast::Expression*, 8> args;
|
||||||
for (uint32_t i = 0; i < param.columns - 1; i++) {
|
for (uint32_t i = 0; i < param.columns - 1; i++) {
|
||||||
ast::Type vec_type = param.create_column_ast_type(*this);
|
ast::Type vec_type = param.create_column_ast_type(*this);
|
||||||
|
@ -2443,7 +2444,7 @@ TEST_P(MatrixConstructorTest, ElementConstructor_Error_TooFewArguments) {
|
||||||
Enable(builtin::Extension::kF16);
|
Enable(builtin::Extension::kF16);
|
||||||
|
|
||||||
const std::string element_type_name = param.get_element_type_name();
|
const std::string element_type_name = param.get_element_type_name();
|
||||||
std::stringstream args_tys;
|
utils::StringStream args_tys;
|
||||||
utils::Vector<const ast::Expression*, 8> args;
|
utils::Vector<const ast::Expression*, 8> args;
|
||||||
for (uint32_t i = 0; i < param.columns * param.rows - 1; i++) {
|
for (uint32_t i = 0; i < param.columns * param.rows - 1; i++) {
|
||||||
args.Push(Call(param.create_element_ast_type(*this)));
|
args.Push(Call(param.create_element_ast_type(*this)));
|
||||||
|
@ -2471,7 +2472,7 @@ TEST_P(MatrixConstructorTest, ColumnConstructor_Error_TooManyArguments) {
|
||||||
Enable(builtin::Extension::kF16);
|
Enable(builtin::Extension::kF16);
|
||||||
|
|
||||||
const std::string element_type_name = param.get_element_type_name();
|
const std::string element_type_name = param.get_element_type_name();
|
||||||
std::stringstream args_tys;
|
utils::StringStream args_tys;
|
||||||
utils::Vector<const ast::Expression*, 8> args;
|
utils::Vector<const ast::Expression*, 8> args;
|
||||||
for (uint32_t i = 0; i < param.columns + 1; i++) {
|
for (uint32_t i = 0; i < param.columns + 1; i++) {
|
||||||
ast::Type vec_type = param.create_column_ast_type(*this);
|
ast::Type vec_type = param.create_column_ast_type(*this);
|
||||||
|
@ -2500,7 +2501,7 @@ TEST_P(MatrixConstructorTest, ElementConstructor_Error_TooManyArguments) {
|
||||||
Enable(builtin::Extension::kF16);
|
Enable(builtin::Extension::kF16);
|
||||||
|
|
||||||
const std::string element_type_name = param.get_element_type_name();
|
const std::string element_type_name = param.get_element_type_name();
|
||||||
std::stringstream args_tys;
|
utils::StringStream args_tys;
|
||||||
utils::Vector<const ast::Expression*, 8> args;
|
utils::Vector<const ast::Expression*, 8> args;
|
||||||
for (uint32_t i = 0; i < param.columns * param.rows + 1; i++) {
|
for (uint32_t i = 0; i < param.columns * param.rows + 1; i++) {
|
||||||
args.Push(Call(param.create_element_ast_type(*this)));
|
args.Push(Call(param.create_element_ast_type(*this)));
|
||||||
|
@ -2527,7 +2528,7 @@ TEST_P(MatrixConstructorTest, ColumnConstructor_Error_InvalidArgumentType) {
|
||||||
|
|
||||||
Enable(builtin::Extension::kF16);
|
Enable(builtin::Extension::kF16);
|
||||||
|
|
||||||
std::stringstream args_tys;
|
utils::StringStream args_tys;
|
||||||
utils::Vector<const ast::Expression*, 8> args;
|
utils::Vector<const ast::Expression*, 8> args;
|
||||||
for (uint32_t i = 0; i < param.columns; i++) {
|
for (uint32_t i = 0; i < param.columns; i++) {
|
||||||
auto vec_type = ty.vec<u32>(param.rows);
|
auto vec_type = ty.vec<u32>(param.rows);
|
||||||
|
@ -2555,7 +2556,7 @@ TEST_P(MatrixConstructorTest, ElementConstructor_Error_InvalidArgumentType) {
|
||||||
|
|
||||||
Enable(builtin::Extension::kF16);
|
Enable(builtin::Extension::kF16);
|
||||||
|
|
||||||
std::stringstream args_tys;
|
utils::StringStream args_tys;
|
||||||
utils::Vector<const ast::Expression*, 8> args;
|
utils::Vector<const ast::Expression*, 8> args;
|
||||||
for (uint32_t i = 0; i < param.columns; i++) {
|
for (uint32_t i = 0; i < param.columns; i++) {
|
||||||
args.Push(Expr(1_u));
|
args.Push(Expr(1_u));
|
||||||
|
@ -2588,7 +2589,7 @@ TEST_P(MatrixConstructorTest, ColumnConstructor_Error_TooFewRowsInVectorArgument
|
||||||
Enable(builtin::Extension::kF16);
|
Enable(builtin::Extension::kF16);
|
||||||
|
|
||||||
const std::string element_type_name = param.get_element_type_name();
|
const std::string element_type_name = param.get_element_type_name();
|
||||||
std::stringstream args_tys;
|
utils::StringStream args_tys;
|
||||||
utils::Vector<const ast::Expression*, 8> args;
|
utils::Vector<const ast::Expression*, 8> args;
|
||||||
for (uint32_t i = 0; i < param.columns; i++) {
|
for (uint32_t i = 0; i < param.columns; i++) {
|
||||||
ast::Type valid_vec_type = param.create_column_ast_type(*this);
|
ast::Type valid_vec_type = param.create_column_ast_type(*this);
|
||||||
|
@ -2626,7 +2627,7 @@ TEST_P(MatrixConstructorTest, ColumnConstructor_Error_TooManyRowsInVectorArgumen
|
||||||
Enable(builtin::Extension::kF16);
|
Enable(builtin::Extension::kF16);
|
||||||
|
|
||||||
const std::string element_type_name = param.get_element_type_name();
|
const std::string element_type_name = param.get_element_type_name();
|
||||||
std::stringstream args_tys;
|
utils::StringStream args_tys;
|
||||||
utils::Vector<const ast::Expression*, 8> args;
|
utils::Vector<const ast::Expression*, 8> args;
|
||||||
for (uint32_t i = 0; i < param.columns; i++) {
|
for (uint32_t i = 0; i < param.columns; i++) {
|
||||||
ast::Type valid_vec_type = param.create_column_ast_type(*this);
|
ast::Type valid_vec_type = param.create_column_ast_type(*this);
|
||||||
|
@ -2715,7 +2716,7 @@ TEST_P(MatrixConstructorTest, ElementTypeAlias_Error) {
|
||||||
|
|
||||||
auto* elem_type_alias = Alias("ElemType", param.create_element_ast_type(*this));
|
auto* elem_type_alias = Alias("ElemType", param.create_element_ast_type(*this));
|
||||||
|
|
||||||
std::stringstream args_tys;
|
utils::StringStream args_tys;
|
||||||
utils::Vector<const ast::Expression*, 4> args;
|
utils::Vector<const ast::Expression*, 4> args;
|
||||||
for (uint32_t i = 0; i < param.columns; i++) {
|
for (uint32_t i = 0; i < param.columns; i++) {
|
||||||
auto vec_type = ty.vec(ty.u32(), param.rows);
|
auto vec_type = ty.vec(ty.u32(), param.rows);
|
||||||
|
@ -2797,7 +2798,7 @@ TEST_P(MatrixConstructorTest, ArgumentElementTypeAlias_Error) {
|
||||||
ast::Type matrix_type = param.create_mat_ast_type(*this);
|
ast::Type matrix_type = param.create_mat_ast_type(*this);
|
||||||
auto* u32_type_alias = Alias("UnsignedInt", ty.u32());
|
auto* u32_type_alias = Alias("UnsignedInt", ty.u32());
|
||||||
|
|
||||||
std::stringstream args_tys;
|
utils::StringStream args_tys;
|
||||||
utils::Vector<const ast::Expression*, 4> args;
|
utils::Vector<const ast::Expression*, 4> args;
|
||||||
for (uint32_t i = 0; i < param.columns; i++) {
|
for (uint32_t i = 0; i < param.columns; i++) {
|
||||||
auto vec_type = ty.vec(ty.Of(u32_type_alias), param.rows);
|
auto vec_type = ty.vec(ty.Of(u32_type_alias), param.rows);
|
||||||
|
@ -2874,7 +2875,7 @@ TEST_P(MatrixConstructorTest, CannotInferElementTypeFromVectors_Mismatch) {
|
||||||
|
|
||||||
Enable(builtin::Extension::kF16);
|
Enable(builtin::Extension::kF16);
|
||||||
|
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
err << "12:34 error: no matching constructor for mat" << param.columns << "x" << param.rows
|
err << "12:34 error: no matching constructor for mat" << param.columns << "x" << param.rows
|
||||||
<< "(";
|
<< "(";
|
||||||
|
|
||||||
|
@ -2905,7 +2906,7 @@ TEST_P(MatrixConstructorTest, CannotInferElementTypeFromScalars_Mismatch) {
|
||||||
|
|
||||||
Enable(builtin::Extension::kF16);
|
Enable(builtin::Extension::kF16);
|
||||||
|
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
err << "12:34 error: no matching constructor for mat" << param.columns << "x" << param.rows
|
err << "12:34 error: no matching constructor for mat" << param.columns << "x" << param.rows
|
||||||
<< "(";
|
<< "(";
|
||||||
|
|
||||||
|
@ -3073,7 +3074,7 @@ TEST_P(StructConstructorTypeTest, AllTypes) {
|
||||||
auto* tc = Call(ty.Of(s), values);
|
auto* tc = Call(ty.Of(s), values);
|
||||||
WrapInFunction(tc);
|
WrapInFunction(tc);
|
||||||
|
|
||||||
std::stringstream err;
|
utils::StringStream err;
|
||||||
err << "error: type in structure constructor does not match struct member ";
|
err << "error: type in structure constructor does not match struct member ";
|
||||||
err << "type: expected '" << str_params.name() << "', found '" << ctor_params.name() << "'";
|
err << "type: expected '" << str_params.name() << "', found '" << ctor_params.name() << "'";
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
|
|
@ -50,7 +50,7 @@ size_t Distance(std::string_view str_a, std::string_view str_b) {
|
||||||
|
|
||||||
void SuggestAlternatives(std::string_view got,
|
void SuggestAlternatives(std::string_view got,
|
||||||
Slice<char const* const> strings,
|
Slice<char const* const> strings,
|
||||||
std::ostringstream& ss) {
|
utils::StringStream& ss) {
|
||||||
// If the string typed was within kSuggestionDistance of one of the possible enum values,
|
// If the string typed was within kSuggestionDistance of one of the possible enum values,
|
||||||
// suggest that. Don't bother with suggestions if the string was extremely long.
|
// suggest that. Don't bother with suggestions if the string was extremely long.
|
||||||
constexpr size_t kSuggestionDistance = 5;
|
constexpr size_t kSuggestionDistance = 5;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
#include "src/tint/utils/slice.h"
|
#include "src/tint/utils/slice.h"
|
||||||
|
#include "src/tint/utils/string_stream.h"
|
||||||
|
|
||||||
namespace tint::utils {
|
namespace tint::utils {
|
||||||
|
|
||||||
|
@ -74,7 +75,7 @@ size_t Distance(std::string_view a, std::string_view b);
|
||||||
/// @param ss the stream to write the suggest and list of possible values to
|
/// @param ss the stream to write the suggest and list of possible values to
|
||||||
void SuggestAlternatives(std::string_view got,
|
void SuggestAlternatives(std::string_view got,
|
||||||
Slice<char const* const> strings,
|
Slice<char const* const> strings,
|
||||||
std::ostringstream& ss);
|
utils::StringStream& ss);
|
||||||
|
|
||||||
} // namespace tint::utils
|
} // namespace tint::utils
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "src/tint/utils/string.h"
|
#include "src/tint/utils/string.h"
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
#include "src/tint/utils/string_stream.h"
|
||||||
|
|
||||||
namespace tint::utils {
|
namespace tint::utils {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -61,14 +62,14 @@ TEST(StringTest, Distance) {
|
||||||
TEST(StringTest, SuggestAlternatives) {
|
TEST(StringTest, SuggestAlternatives) {
|
||||||
{
|
{
|
||||||
const char* alternatives[] = {"hello world", "Hello World"};
|
const char* alternatives[] = {"hello world", "Hello World"};
|
||||||
std::ostringstream ss;
|
utils::StringStream ss;
|
||||||
SuggestAlternatives("hello wordl", alternatives, ss);
|
SuggestAlternatives("hello wordl", alternatives, ss);
|
||||||
EXPECT_EQ(ss.str(), R"(Did you mean 'hello world'?
|
EXPECT_EQ(ss.str(), R"(Did you mean 'hello world'?
|
||||||
Possible values: 'hello world', 'Hello World')");
|
Possible values: 'hello world', 'Hello World')");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const char* alternatives[] = {"foobar", "something else"};
|
const char* alternatives[] = {"foobar", "something else"};
|
||||||
std::ostringstream ss;
|
utils::StringStream ss;
|
||||||
SuggestAlternatives("hello world", alternatives, ss);
|
SuggestAlternatives("hello world", alternatives, ss);
|
||||||
EXPECT_EQ(ss.str(), R"(Possible values: 'foobar', 'something else')");
|
EXPECT_EQ(ss.str(), R"(Possible values: 'foobar', 'something else')");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue