Import Tint changes from Dawn
Changes:
- 0ea0d4b16eaadac57d35da6e708dbc360e94289d tint/resolver: Test f16 types in materialize unittests by Zhaoming Jiang <zhaoming.jiang@intel.com>
- 6835c8df3e016f4607659bfeaae840483fb1cb24 tint/reader: Parse arrays with no type / size by Ben Clayton <bclayton@google.com>
- 86329e286b23a23d284d213e904869fbfc8a53c1 tint/cmd: Dump disassembly with --verbose by Ben Clayton <bclayton@google.com>
- 92f2cb79b5dc13590353df83da24e023dbadb1f8 tools/gen: clang-format generated .cc, .h and .inl files by Ben Clayton <bclayton@google.com>
- 4aa360db5d36720ae2139ea1e1c84df0a60862b5 tint/resolver: Fix null-deref. by Ben Clayton <bclayton@google.com>
- db5d2ea4f287e8cdc22e719f2182245de1c8c375 tint/writer/wgsl: Emit inferred-type arrays by Ben Clayton <bclayton@google.com>
- 4a6562071605a1a73c14e1b705a8e4f002d03c39 tint/resolver: Handle array() constructors by Ben Clayton <bclayton@google.com>
- 70a43fa5b9ff0ef1f8d31e62f670e0fc86f8b33e tint: Fix doxygen error. by Antonio Maiorano <amaiorano@google.com>
- 239a92d2d00113098cee074a0548a5461c97737d tint: transform::RemovePhonies: skip builtins with no sid... by Antonio Maiorano <amaiorano@google.com>
- 6315a27778728578708d109e5f28c1e0be48aeb8 tint/resolver: Tidy up type_constructor_validation_test.cc by Ben Clayton <bclayton@google.com>
- bf32bd4e961bf82a9246d0e74b863e66073279fe tint/ast: Tighten AST definition of runtime-sized array by Ben Clayton <bclayton@google.com>
- 8c9cc860763f871604ffb77209a167e6f9fe4bea tint/resolver: Simplify / optimize Validator::Call() by Ben Clayton <bclayton@google.com>
- 9c4d0c941038f14c400f99a4952ae0d84ed73817 tint/resolver: Split up the Array resolving logic by Ben Clayton <bclayton@google.com>
GitOrigin-RevId: 0ea0d4b16eaadac57d35da6e708dbc360e94289d
Change-Id: I02c1053b0f39500b16b4559611eea9ffb2551188
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/97800
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/ast/array.cc b/src/tint/ast/array.cc
index cd1fc26..988dfaf 100644
--- a/src/tint/ast/array.cc
+++ b/src/tint/ast/array.cc
@@ -56,11 +56,14 @@
out << "@stride(" << stride->stride << ") ";
}
}
- out << "array<" << type->FriendlyName(symbols);
- if (!IsRuntimeArray()) {
- out << ", " << SizeExprToString(count, symbols);
+ out << "array";
+ if (type) {
+ out << "<" << type->FriendlyName(symbols);
+ if (count) {
+ out << ", " << SizeExprToString(count, symbols);
+ }
+ out << ">";
}
- out << ">";
return out.str();
}
diff --git a/src/tint/ast/array.h b/src/tint/ast/array.h
index ccc31ab..6ad1cbc 100644
--- a/src/tint/ast/array.h
+++ b/src/tint/ast/array.h
@@ -35,9 +35,9 @@
/// @param nid the unique node identifier
/// @param src the source of this node
/// @param subtype the type of the array elements
- /// @param count the number of elements in the array. nullptr represents a
- /// runtime-sized array.
+ /// @param count the number of elements in the array
/// @param attributes the array attributes
+ /// @note a runtime-sized array is represented by a null count and a non-null type
Array(ProgramID pid,
NodeID nid,
const Source& src,
@@ -50,7 +50,7 @@
/// @returns true if this is a runtime array.
/// i.e. the size is determined at runtime
- bool IsRuntimeArray() const { return count == nullptr; }
+ bool IsRuntimeArray() const { return type != nullptr && count == nullptr; }
/// @param symbols the program's symbol table
/// @returns the name for this type that closely resembles how it would be
diff --git a/src/tint/ast/array_test.cc b/src/tint/ast/array_test.cc
index f396e0c..f8d469b 100644
--- a/src/tint/ast/array_test.cc
+++ b/src/tint/ast/array_test.cc
@@ -42,6 +42,14 @@
EXPECT_TRUE(arr->IsRuntimeArray());
}
+TEST_F(AstArrayTest, CreateInferredTypeArray) {
+ auto* arr = create<Array>(nullptr, nullptr, AttributeList{});
+ EXPECT_EQ(arr->type, nullptr);
+ EXPECT_EQ(arr->count, nullptr);
+ EXPECT_TRUE(arr->Is<Array>());
+ EXPECT_FALSE(arr->IsRuntimeArray());
+}
+
TEST_F(AstArrayTest, FriendlyName_RuntimeSized) {
auto* i32 = create<I32>();
auto* arr = create<Array>(i32, nullptr, AttributeList{});
@@ -66,5 +74,15 @@
EXPECT_EQ(arr->FriendlyName(Symbols()), "@stride(32) array<i32, 5>");
}
+TEST_F(AstArrayTest, FriendlyName_InferredTypeAndCount) {
+ auto* arr = create<Array>(nullptr, nullptr, AttributeList{});
+ EXPECT_EQ(arr->FriendlyName(Symbols()), "array");
+}
+
+TEST_F(AstArrayTest, FriendlyName_InferredTypeAndCount_WithStrize) {
+ auto* arr = create<Array>(nullptr, nullptr, AttributeList{create<StrideAttribute>(32u)});
+ EXPECT_EQ(arr->FriendlyName(Symbols()), "@stride(32) array");
+}
+
} // namespace
} // namespace tint::ast
diff --git a/src/tint/ast/storage_class.h b/src/tint/ast/storage_class.h
index cb21115..4da3db0 100644
--- a/src/tint/ast/storage_class.h
+++ b/src/tint/ast/storage_class.h
@@ -37,8 +37,8 @@
kUniform,
kStorage,
kHandle, // Tint-internal enum entry - not parsed
- kIn, // Tint-internal enum entry - not parsed
- kOut, // Tint-internal enum entry - not parsed
+ kIn, // Tint-internal enum entry - not parsed
+ kOut, // Tint-internal enum entry - not parsed
};
/// @param out the std::ostream to write to
diff --git a/src/tint/ast/storage_class_bench.cc b/src/tint/ast/storage_class_bench.cc
index d1232df..d8e9ae9 100644
--- a/src/tint/ast/storage_class_bench.cc
+++ b/src/tint/ast/storage_class_bench.cc
@@ -31,41 +31,12 @@
void StorageClassParser(::benchmark::State& state) {
std::array kStrings{
- "fccnctin",
- "ucti3",
- "functVon",
- "function",
- "1unction",
- "unJtqqon",
- "llun77tion",
- "ppqqivtHH",
- "prcv",
- "bivaGe",
- "private",
- "priviive",
- "8WWivate",
- "pxxvate",
- "wXkgrggup",
- "worXVup",
- "3orkgroup",
- "workgroup",
- "workgroEp",
- "woTTPkroup",
- "ddorkroxxp",
- "u44iform",
- "unSSfoVVm",
- "RniR22m",
- "uniform",
- "uFfo9m",
- "uniorm",
- "VOORRHrm",
- "straye",
- "llntrrr77ge",
- "stor4g00",
- "storage",
- "trooe",
- "zzrage",
- "siioppa1",
+ "fccnctin", "ucti3", "functVon", "function", "1unction", "unJtqqon",
+ "llun77tion", "ppqqivtHH", "prcv", "bivaGe", "private", "priviive",
+ "8WWivate", "pxxvate", "wXkgrggup", "worXVup", "3orkgroup", "workgroup",
+ "workgroEp", "woTTPkroup", "ddorkroxxp", "u44iform", "unSSfoVVm", "RniR22m",
+ "uniform", "uFfo9m", "uniorm", "VOORRHrm", "straye", "llntrrr77ge",
+ "stor4g00", "storage", "trooe", "zzrage", "siioppa1",
};
for (auto _ : state) {
for (auto& str : kStrings) {
diff --git a/src/tint/ast/storage_class_test.cc b/src/tint/ast/storage_class_test.cc
index 2085168..9688236 100644
--- a/src/tint/ast/storage_class_test.cc
+++ b/src/tint/ast/storage_class_test.cc
@@ -42,28 +42,19 @@
}
static constexpr Case kValidCases[] = {
- {"function", StorageClass::kFunction},
- {"private", StorageClass::kPrivate},
- {"workgroup", StorageClass::kWorkgroup},
- {"uniform", StorageClass::kUniform},
+ {"function", StorageClass::kFunction}, {"private", StorageClass::kPrivate},
+ {"workgroup", StorageClass::kWorkgroup}, {"uniform", StorageClass::kUniform},
{"storage", StorageClass::kStorage},
};
static constexpr Case kInvalidCases[] = {
- {"fccnctin", StorageClass::kInvalid},
- {"ucti3", StorageClass::kInvalid},
- {"functVon", StorageClass::kInvalid},
- {"priv1te", StorageClass::kInvalid},
- {"pqiJate", StorageClass::kInvalid},
- {"privat7ll", StorageClass::kInvalid},
- {"workroppqHH", StorageClass::kInvalid},
- {"workru", StorageClass::kInvalid},
- {"wbkgGoup", StorageClass::kInvalid},
- {"unifiivm", StorageClass::kInvalid},
- {"8WWiform", StorageClass::kInvalid},
- {"uxxform", StorageClass::kInvalid},
- {"sXraggg", StorageClass::kInvalid},
- {"traXe", StorageClass::kInvalid},
+ {"fccnctin", StorageClass::kInvalid}, {"ucti3", StorageClass::kInvalid},
+ {"functVon", StorageClass::kInvalid}, {"priv1te", StorageClass::kInvalid},
+ {"pqiJate", StorageClass::kInvalid}, {"privat7ll", StorageClass::kInvalid},
+ {"workroppqHH", StorageClass::kInvalid}, {"workru", StorageClass::kInvalid},
+ {"wbkgGoup", StorageClass::kInvalid}, {"unifiivm", StorageClass::kInvalid},
+ {"8WWiform", StorageClass::kInvalid}, {"uxxform", StorageClass::kInvalid},
+ {"sXraggg", StorageClass::kInvalid}, {"traXe", StorageClass::kInvalid},
{"stor3ge", StorageClass::kInvalid},
};
diff --git a/src/tint/ast/texel_format_bench.cc b/src/tint/ast/texel_format_bench.cc
index 8dde6b2..a17906a 100644
--- a/src/tint/ast/texel_format_bench.cc
+++ b/src/tint/ast/texel_format_bench.cc
@@ -31,118 +31,29 @@
void TexelFormatParser(::benchmark::State& state) {
std::array kStrings{
- "rgbaunccrm",
- "rlbanr3",
- "rVba8unorm",
- "rgba8unorm",
- "rgba1unorm",
- "rgbJqqnorm",
- "rgb7ll8unorm",
- "rgqqappnoHHm",
- "rv8scor",
- "rgbbGsnrm",
- "rgba8snorm",
- "rgba8vniirm",
- "rg8a8snoWWm",
- "Mgbaxxnorm",
- "rXa8uggnt",
- "rgbXVut",
- "3gba8uint",
- "rgba8uint",
- "rgba8uiEt",
- "rgTTPauint",
- "ddgbauixxt",
- "44gba8sint",
- "VVgbaSSsint",
- "rba8si2Rt",
- "rgba8sint",
- "r9bFsint",
- "rgba8int",
- "rgVROOsHnt",
- "ryba1uint",
- "r77ba1nnullrrt",
- "rgb4006uint",
- "rgba16uint",
- "rb1uioot",
- "rga1uzznt",
- "r11b1uppiit",
- "XXgba16sint",
- "IIgb9916nni55t",
- "rYbaSSrrsiHHat",
- "rgba16sint",
- "rbkk6Hit",
- "jgba1sgRR",
- "rgbab6si",
- "rgba16fljat",
- "rgba6float",
- "rbq6float",
- "rgba16float",
- "rgba1NNloat",
- "rgbvv6flot",
- "rgbaQQ6foat",
- "r3ffir",
- "r32uijt",
- "rNNwuin8",
- "r32uint",
- "r32int",
- "rrr2uint",
- "G32uint",
- "r32sinFF",
- "32st",
- "r3rrint",
- "r32sint",
- "2sint",
- "D3siJJt",
- "r38n",
- "r211lk",
- "r32floa",
- "r3flJat",
- "r32float",
- "r32fcoat",
- "r32floOt",
- "r32floKK_vtt",
- "rxx32ui8",
- "Fg3qq__n",
- "rg32iqqt",
- "rg32uint",
- "rg333uin6",
- "rtto62u9QQt",
- "rg366uin",
- "rOx2si6zz",
- "rg3yysint",
- "rHHsint",
- "rg32sint",
- "qWW432snt",
- "rg3OOsnt",
- "g32siYt",
- "g32flo",
- "rg32foaF",
- "rg32fwat",
- "rg32float",
- "G3fKoaff",
- "KKgq2float",
- "rg32mmlo3t",
- "rgba32uit",
- "rqba3uint",
- "rgbabb2uin",
- "rgba32uint",
- "rba32iint",
- "qgba32uiOt",
- "rgba32uiTTvv",
- "rgFFa32sint",
- "rg00Q2sPnt",
- "rgbaP2sint",
- "rgba32sint",
- "rgb77s2sint",
- "rgba32sbbRRC",
- "rgbXX32sint",
- "rOOOba3CCqoat",
- "rgbu32fsLt",
- "rgba3Xfloat",
- "rgba32float",
- "rba32float",
- "qqb3float",
- "rgba32fl22at",
+ "rgbaunccrm", "rlbanr3", "rVba8unorm", "rgba8unorm", "rgba1unorm",
+ "rgbJqqnorm", "rgb7ll8unorm", "rgqqappnoHHm", "rv8scor", "rgbbGsnrm",
+ "rgba8snorm", "rgba8vniirm", "rg8a8snoWWm", "Mgbaxxnorm", "rXa8uggnt",
+ "rgbXVut", "3gba8uint", "rgba8uint", "rgba8uiEt", "rgTTPauint",
+ "ddgbauixxt", "44gba8sint", "VVgbaSSsint", "rba8si2Rt", "rgba8sint",
+ "r9bFsint", "rgba8int", "rgVROOsHnt", "ryba1uint", "r77ba1nnullrrt",
+ "rgb4006uint", "rgba16uint", "rb1uioot", "rga1uzznt", "r11b1uppiit",
+ "XXgba16sint", "IIgb9916nni55t", "rYbaSSrrsiHHat", "rgba16sint", "rbkk6Hit",
+ "jgba1sgRR", "rgbab6si", "rgba16fljat", "rgba6float", "rbq6float",
+ "rgba16float", "rgba1NNloat", "rgbvv6flot", "rgbaQQ6foat", "r3ffir",
+ "r32uijt", "rNNwuin8", "r32uint", "r32int", "rrr2uint",
+ "G32uint", "r32sinFF", "32st", "r3rrint", "r32sint",
+ "2sint", "D3siJJt", "r38n", "r211lk", "r32floa",
+ "r3flJat", "r32float", "r32fcoat", "r32floOt", "r32floKK_vtt",
+ "rxx32ui8", "Fg3qq__n", "rg32iqqt", "rg32uint", "rg333uin6",
+ "rtto62u9QQt", "rg366uin", "rOx2si6zz", "rg3yysint", "rHHsint",
+ "rg32sint", "qWW432snt", "rg3OOsnt", "g32siYt", "g32flo",
+ "rg32foaF", "rg32fwat", "rg32float", "G3fKoaff", "KKgq2float",
+ "rg32mmlo3t", "rgba32uit", "rqba3uint", "rgbabb2uin", "rgba32uint",
+ "rba32iint", "qgba32uiOt", "rgba32uiTTvv", "rgFFa32sint", "rg00Q2sPnt",
+ "rgbaP2sint", "rgba32sint", "rgb77s2sint", "rgba32sbbRRC", "rgbXX32sint",
+ "rOOOba3CCqoat", "rgbu32fsLt", "rgba3Xfloat", "rgba32float", "rba32float",
+ "qqb3float", "rgba32fl22at",
};
for (auto _ : state) {
for (auto& str : kStrings) {
diff --git a/src/tint/ast/texel_format_test.cc b/src/tint/ast/texel_format_test.cc
index 9603961..606d78f 100644
--- a/src/tint/ast/texel_format_test.cc
+++ b/src/tint/ast/texel_format_test.cc
@@ -42,73 +42,41 @@
}
static constexpr Case kValidCases[] = {
- {"rgba8unorm", TexelFormat::kRgba8Unorm},
- {"rgba8snorm", TexelFormat::kRgba8Snorm},
- {"rgba8uint", TexelFormat::kRgba8Uint},
- {"rgba8sint", TexelFormat::kRgba8Sint},
- {"rgba16uint", TexelFormat::kRgba16Uint},
- {"rgba16sint", TexelFormat::kRgba16Sint},
- {"rgba16float", TexelFormat::kRgba16Float},
- {"r32uint", TexelFormat::kR32Uint},
- {"r32sint", TexelFormat::kR32Sint},
- {"r32float", TexelFormat::kR32Float},
- {"rg32uint", TexelFormat::kRg32Uint},
- {"rg32sint", TexelFormat::kRg32Sint},
- {"rg32float", TexelFormat::kRg32Float},
- {"rgba32uint", TexelFormat::kRgba32Uint},
- {"rgba32sint", TexelFormat::kRgba32Sint},
- {"rgba32float", TexelFormat::kRgba32Float},
+ {"rgba8unorm", TexelFormat::kRgba8Unorm}, {"rgba8snorm", TexelFormat::kRgba8Snorm},
+ {"rgba8uint", TexelFormat::kRgba8Uint}, {"rgba8sint", TexelFormat::kRgba8Sint},
+ {"rgba16uint", TexelFormat::kRgba16Uint}, {"rgba16sint", TexelFormat::kRgba16Sint},
+ {"rgba16float", TexelFormat::kRgba16Float}, {"r32uint", TexelFormat::kR32Uint},
+ {"r32sint", TexelFormat::kR32Sint}, {"r32float", TexelFormat::kR32Float},
+ {"rg32uint", TexelFormat::kRg32Uint}, {"rg32sint", TexelFormat::kRg32Sint},
+ {"rg32float", TexelFormat::kRg32Float}, {"rgba32uint", TexelFormat::kRgba32Uint},
+ {"rgba32sint", TexelFormat::kRgba32Sint}, {"rgba32float", TexelFormat::kRgba32Float},
};
static constexpr Case kInvalidCases[] = {
- {"rgbaunccrm", TexelFormat::kInvalid},
- {"rlbanr3", TexelFormat::kInvalid},
- {"rVba8unorm", TexelFormat::kInvalid},
- {"rgba1snorm", TexelFormat::kInvalid},
- {"rgbJqqnorm", TexelFormat::kInvalid},
- {"rgb7ll8snorm", TexelFormat::kInvalid},
- {"rgbauippqHH", TexelFormat::kInvalid},
- {"rgbaun", TexelFormat::kInvalid},
- {"rba8Gint", TexelFormat::kInvalid},
- {"rgvia8sint", TexelFormat::kInvalid},
- {"rgba8WWint", TexelFormat::kInvalid},
- {"rgbasxxMt", TexelFormat::kInvalid},
- {"rXba16ungg", TexelFormat::kInvalid},
- {"rba1XuVt", TexelFormat::kInvalid},
- {"rgba16uin3", TexelFormat::kInvalid},
- {"rgba16sinE", TexelFormat::kInvalid},
- {"TTgba16sPPn", TexelFormat::kInvalid},
- {"rgbad6xxint", TexelFormat::kInvalid},
- {"rgba446float", TexelFormat::kInvalid},
- {"SSVVba16float", TexelFormat::kInvalid},
- {"rgbRR6float", TexelFormat::kInvalid},
- {"rFui9t", TexelFormat::kInvalid},
- {"r32int", TexelFormat::kInvalid},
- {"VOORRHnt", TexelFormat::kInvalid},
- {"r3siyt", TexelFormat::kInvalid},
- {"lln3rrs77nt", TexelFormat::kInvalid},
- {"r32s4n00", TexelFormat::kInvalid},
- {"32ooat", TexelFormat::kInvalid},
- {"r32fzzt", TexelFormat::kInvalid},
- {"r3iippl1a", TexelFormat::kInvalid},
- {"XXg32uint", TexelFormat::kInvalid},
- {"rII39955nnnt", TexelFormat::kInvalid},
- {"aagHH2uinYSS", TexelFormat::kInvalid},
- {"rkk3it", TexelFormat::kInvalid},
- {"gj3sRRn", TexelFormat::kInvalid},
- {"r3bsnt", TexelFormat::kInvalid},
- {"rg32flojt", TexelFormat::kInvalid},
- {"r32floa", TexelFormat::kInvalid},
- {"rg32lot", TexelFormat::kInvalid},
- {"rgb3uit", TexelFormat::kInvalid},
- {"rgjj3uint", TexelFormat::kInvalid},
- {"rgb2urnff", TexelFormat::kInvalid},
- {"rgba32sijt", TexelFormat::kInvalid},
- {"NNgba32ww2t", TexelFormat::kInvalid},
- {"rgba32snt", TexelFormat::kInvalid},
- {"rgba32rrloat", TexelFormat::kInvalid},
- {"rgGa32float", TexelFormat::kInvalid},
- {"FFgba32float", TexelFormat::kInvalid},
+ {"rgbaunccrm", TexelFormat::kInvalid}, {"rlbanr3", TexelFormat::kInvalid},
+ {"rVba8unorm", TexelFormat::kInvalid}, {"rgba1snorm", TexelFormat::kInvalid},
+ {"rgbJqqnorm", TexelFormat::kInvalid}, {"rgb7ll8snorm", TexelFormat::kInvalid},
+ {"rgbauippqHH", TexelFormat::kInvalid}, {"rgbaun", TexelFormat::kInvalid},
+ {"rba8Gint", TexelFormat::kInvalid}, {"rgvia8sint", TexelFormat::kInvalid},
+ {"rgba8WWint", TexelFormat::kInvalid}, {"rgbasxxMt", TexelFormat::kInvalid},
+ {"rXba16ungg", TexelFormat::kInvalid}, {"rba1XuVt", TexelFormat::kInvalid},
+ {"rgba16uin3", TexelFormat::kInvalid}, {"rgba16sinE", TexelFormat::kInvalid},
+ {"TTgba16sPPn", TexelFormat::kInvalid}, {"rgbad6xxint", TexelFormat::kInvalid},
+ {"rgba446float", TexelFormat::kInvalid}, {"SSVVba16float", TexelFormat::kInvalid},
+ {"rgbRR6float", TexelFormat::kInvalid}, {"rFui9t", TexelFormat::kInvalid},
+ {"r32int", TexelFormat::kInvalid}, {"VOORRHnt", TexelFormat::kInvalid},
+ {"r3siyt", TexelFormat::kInvalid}, {"lln3rrs77nt", TexelFormat::kInvalid},
+ {"r32s4n00", TexelFormat::kInvalid}, {"32ooat", TexelFormat::kInvalid},
+ {"r32fzzt", TexelFormat::kInvalid}, {"r3iippl1a", TexelFormat::kInvalid},
+ {"XXg32uint", TexelFormat::kInvalid}, {"rII39955nnnt", TexelFormat::kInvalid},
+ {"aagHH2uinYSS", TexelFormat::kInvalid}, {"rkk3it", TexelFormat::kInvalid},
+ {"gj3sRRn", TexelFormat::kInvalid}, {"r3bsnt", TexelFormat::kInvalid},
+ {"rg32flojt", TexelFormat::kInvalid}, {"r32floa", TexelFormat::kInvalid},
+ {"rg32lot", TexelFormat::kInvalid}, {"rgb3uit", TexelFormat::kInvalid},
+ {"rgjj3uint", TexelFormat::kInvalid}, {"rgb2urnff", TexelFormat::kInvalid},
+ {"rgba32sijt", TexelFormat::kInvalid}, {"NNgba32ww2t", TexelFormat::kInvalid},
+ {"rgba32snt", TexelFormat::kInvalid}, {"rgba32rrloat", TexelFormat::kInvalid},
+ {"rgGa32float", TexelFormat::kInvalid}, {"FFgba32float", TexelFormat::kInvalid},
};
using TexelFormatParseTest = testing::TestWithParam<Case>;
diff --git a/src/tint/cmd/main.cc b/src/tint/cmd/main.cc
index 0c2bcdf..c38e6f9 100644
--- a/src/tint/cmd/main.cc
+++ b/src/tint/cmd/main.cc
@@ -868,9 +868,13 @@
if (options.verbose) {
if (fxc_found && !fxc_res.failed) {
std::cout << "Passed FXC validation" << std::endl;
+ std::cout << fxc_res.output;
+ std::cout << std::endl;
}
if (dxc_found && !dxc_res.failed) {
std::cout << "Passed DXC validation" << std::endl;
+ std::cout << dxc_res.output;
+ std::cout << std::endl;
}
}
}
diff --git a/src/tint/program_builder.h b/src/tint/program_builder.h
index 61954ee..1a3313b 100644
--- a/src/tint/program_builder.h
+++ b/src/tint/program_builder.h
@@ -489,14 +489,35 @@
/// @return the tint AST type for a 2-element vector of `type`.
const ast::Vector* vec2(const ast::Type* type) const { return vec(type, 2u); }
+ /// @param source the vector source
+ /// @param type vector subtype
+ /// @return the tint AST type for a 2-element vector of `type`.
+ const ast::Vector* vec2(const Source& source, const ast::Type* type) const {
+ return vec(source, type, 2u);
+ }
+
/// @param type vector subtype
/// @return the tint AST type for a 3-element vector of `type`.
const ast::Vector* vec3(const ast::Type* type) const { return vec(type, 3u); }
+ /// @param source the vector source
+ /// @param type vector subtype
+ /// @return the tint AST type for a 3-element vector of `type`.
+ const ast::Vector* vec3(const Source& source, const ast::Type* type) const {
+ return vec(source, type, 3u);
+ }
+
/// @param type vector subtype
/// @return the tint AST type for a 4-element vector of `type`.
const ast::Vector* vec4(const ast::Type* type) const { return vec(type, 4u); }
+ /// @param source the vector source
+ /// @param type vector subtype
+ /// @return the tint AST type for a 4-element vector of `type`.
+ const ast::Vector* vec4(const Source& source, const ast::Type* type) const {
+ return vec(source, type, 4u);
+ }
+
/// @param n vector width in elements
/// @return the tint AST type for a `n`-element vector of `type`.
template <typename T>
@@ -510,18 +531,39 @@
return vec2(Of<T>());
}
+ /// @param source the Source of the node
+ /// @return the tint AST type for a 2-element vector of the C type `T`.
+ template <typename T>
+ const ast::Vector* vec2(const Source& source) const {
+ return vec2(source, Of<T>());
+ }
+
/// @return the tint AST type for a 3-element vector of the C type `T`.
template <typename T>
const ast::Vector* vec3() const {
return vec3(Of<T>());
}
+ /// @param source the Source of the node
+ /// @return the tint AST type for a 3-element vector of the C type `T`.
+ template <typename T>
+ const ast::Vector* vec3(const Source& source) const {
+ return vec3(source, Of<T>());
+ }
+
/// @return the tint AST type for a 4-element vector of the C type `T`.
template <typename T>
const ast::Vector* vec4() const {
return vec4(Of<T>());
}
+ /// @param source the Source of the node
+ /// @return the tint AST type for a 4-element vector of the C type `T`.
+ template <typename T>
+ const ast::Vector* vec4(const Source& source) const {
+ return vec4(source, Of<T>());
+ }
+
/// @param type matrix subtype
/// @param columns number of columns for the matrix
/// @param rows number of rows for the matrix
@@ -1245,99 +1287,207 @@
/// @param args the arguments for the vector constructor
/// @return an `ast::CallExpression` of a 2-element vector of type
/// `T`, constructed with the values `args`.
- template <typename T, typename... ARGS>
+ template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
const ast::CallExpression* vec2(ARGS&&... args) {
return Construct(ty.vec2<T>(), std::forward<ARGS>(args)...);
}
+ /// @param source the vector source
+ /// @param args the arguments for the vector constructor
+ /// @return an `ast::CallExpression` of a 2-element vector of type
+ /// `T`, constructed with the values `args`.
+ template <typename T, typename... ARGS>
+ const ast::CallExpression* vec2(const Source& source, ARGS&&... args) {
+ return Construct(source, ty.vec2<T>(), std::forward<ARGS>(args)...);
+ }
+
/// @param args the arguments for the vector constructor
/// @return an `ast::CallExpression` of a 3-element vector of type
/// `T`, constructed with the values `args`.
- template <typename T, typename... ARGS>
+ template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
const ast::CallExpression* vec3(ARGS&&... args) {
return Construct(ty.vec3<T>(), std::forward<ARGS>(args)...);
}
+ /// @param source the vector source
+ /// @param args the arguments for the vector constructor
+ /// @return an `ast::CallExpression` of a 3-element vector of type
+ /// `T`, constructed with the values `args`.
+ template <typename T, typename... ARGS>
+ const ast::CallExpression* vec3(const Source& source, ARGS&&... args) {
+ return Construct(source, ty.vec3<T>(), std::forward<ARGS>(args)...);
+ }
+
/// @param args the arguments for the vector constructor
/// @return an `ast::CallExpression` of a 4-element vector of type
/// `T`, constructed with the values `args`.
- template <typename T, typename... ARGS>
+ template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
const ast::CallExpression* vec4(ARGS&&... args) {
return Construct(ty.vec4<T>(), std::forward<ARGS>(args)...);
}
+ /// @param source the vector source
+ /// @param args the arguments for the vector constructor
+ /// @return an `ast::CallExpression` of a 4-element vector of type
+ /// `T`, constructed with the values `args`.
+ template <typename T, typename... ARGS>
+ const ast::CallExpression* vec4(const Source& source, ARGS&&... args) {
+ return Construct(source, ty.vec4<T>(), std::forward<ARGS>(args)...);
+ }
+
/// @param args the arguments for the matrix constructor
/// @return an `ast::CallExpression` of a 2x2 matrix of type
/// `T`, constructed with the values `args`.
- template <typename T, typename... ARGS>
+ template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
const ast::CallExpression* mat2x2(ARGS&&... args) {
return Construct(ty.mat2x2<T>(), std::forward<ARGS>(args)...);
}
+ /// @param source the matrix source
+ /// @param args the arguments for the matrix constructor
+ /// @return an `ast::CallExpression` of a 2x2 matrix of type
+ /// `T`, constructed with the values `args`.
+ template <typename T, typename... ARGS>
+ const ast::CallExpression* mat2x2(const Source& source, ARGS&&... args) {
+ return Construct(source, ty.mat2x2<T>(), std::forward<ARGS>(args)...);
+ }
+
/// @param args the arguments for the matrix constructor
/// @return an `ast::CallExpression` of a 2x3 matrix of type
/// `T`, constructed with the values `args`.
- template <typename T, typename... ARGS>
+ template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
const ast::CallExpression* mat2x3(ARGS&&... args) {
return Construct(ty.mat2x3<T>(), std::forward<ARGS>(args)...);
}
+ /// @param source the matrix source
+ /// @param args the arguments for the matrix constructor
+ /// @return an `ast::CallExpression` of a 2x3 matrix of type
+ /// `T`, constructed with the values `args`.
+ template <typename T, typename... ARGS>
+ const ast::CallExpression* mat2x3(const Source& source, ARGS&&... args) {
+ return Construct(source, ty.mat2x3<T>(), std::forward<ARGS>(args)...);
+ }
+
/// @param args the arguments for the matrix constructor
/// @return an `ast::CallExpression` of a 2x4 matrix of type
/// `T`, constructed with the values `args`.
- template <typename T, typename... ARGS>
+ template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
const ast::CallExpression* mat2x4(ARGS&&... args) {
return Construct(ty.mat2x4<T>(), std::forward<ARGS>(args)...);
}
+ /// @param source the matrix source
+ /// @param args the arguments for the matrix constructor
+ /// @return an `ast::CallExpression` of a 2x4 matrix of type
+ /// `T`, constructed with the values `args`.
+ template <typename T, typename... ARGS>
+ const ast::CallExpression* mat2x4(const Source& source, ARGS&&... args) {
+ return Construct(source, ty.mat2x4<T>(), std::forward<ARGS>(args)...);
+ }
+
/// @param args the arguments for the matrix constructor
/// @return an `ast::CallExpression` of a 3x2 matrix of type
/// `T`, constructed with the values `args`.
- template <typename T, typename... ARGS>
+ template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
const ast::CallExpression* mat3x2(ARGS&&... args) {
return Construct(ty.mat3x2<T>(), std::forward<ARGS>(args)...);
}
+ /// @param source the matrix source
+ /// @param args the arguments for the matrix constructor
+ /// @return an `ast::CallExpression` of a 3x2 matrix of type
+ /// `T`, constructed with the values `args`.
+ template <typename T, typename... ARGS>
+ const ast::CallExpression* mat3x2(const Source& source, ARGS&&... args) {
+ return Construct(source, ty.mat3x2<T>(), std::forward<ARGS>(args)...);
+ }
+
/// @param args the arguments for the matrix constructor
/// @return an `ast::CallExpression` of a 3x3 matrix of type
/// `T`, constructed with the values `args`.
- template <typename T, typename... ARGS>
+ template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
const ast::CallExpression* mat3x3(ARGS&&... args) {
return Construct(ty.mat3x3<T>(), std::forward<ARGS>(args)...);
}
+ /// @param source the matrix source
+ /// @param args the arguments for the matrix constructor
+ /// @return an `ast::CallExpression` of a 3x3 matrix of type
+ /// `T`, constructed with the values `args`.
+ template <typename T, typename... ARGS>
+ const ast::CallExpression* mat3x3(const Source& source, ARGS&&... args) {
+ return Construct(source, ty.mat3x3<T>(), std::forward<ARGS>(args)...);
+ }
+
/// @param args the arguments for the matrix constructor
/// @return an `ast::CallExpression` of a 3x4 matrix of type
/// `T`, constructed with the values `args`.
- template <typename T, typename... ARGS>
+ template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
const ast::CallExpression* mat3x4(ARGS&&... args) {
return Construct(ty.mat3x4<T>(), std::forward<ARGS>(args)...);
}
+ /// @param source the matrix source
+ /// @param args the arguments for the matrix constructor
+ /// @return an `ast::CallExpression` of a 3x4 matrix of type
+ /// `T`, constructed with the values `args`.
+ template <typename T, typename... ARGS>
+ const ast::CallExpression* mat3x4(const Source& source, ARGS&&... args) {
+ return Construct(source, ty.mat3x4<T>(), std::forward<ARGS>(args)...);
+ }
+
/// @param args the arguments for the matrix constructor
/// @return an `ast::CallExpression` of a 4x2 matrix of type
/// `T`, constructed with the values `args`.
- template <typename T, typename... ARGS>
+ template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
const ast::CallExpression* mat4x2(ARGS&&... args) {
return Construct(ty.mat4x2<T>(), std::forward<ARGS>(args)...);
}
+ /// @param source the matrix source
+ /// @param args the arguments for the matrix constructor
+ /// @return an `ast::CallExpression` of a 4x2 matrix of type
+ /// `T`, constructed with the values `args`.
+ template <typename T, typename... ARGS>
+ const ast::CallExpression* mat4x2(const Source& source, ARGS&&... args) {
+ return Construct(source, ty.mat4x2<T>(), std::forward<ARGS>(args)...);
+ }
+
/// @param args the arguments for the matrix constructor
/// @return an `ast::CallExpression` of a 4x3 matrix of type
/// `T`, constructed with the values `args`.
- template <typename T, typename... ARGS>
+ template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
const ast::CallExpression* mat4x3(ARGS&&... args) {
return Construct(ty.mat4x3<T>(), std::forward<ARGS>(args)...);
}
+ /// @param source the matrix source
+ /// @param args the arguments for the matrix constructor
+ /// @return an `ast::CallExpression` of a 4x3 matrix of type
+ /// `T`, constructed with the values `args`.
+ template <typename T, typename... ARGS>
+ const ast::CallExpression* mat4x3(const Source& source, ARGS&&... args) {
+ return Construct(source, ty.mat4x3<T>(), std::forward<ARGS>(args)...);
+ }
+
/// @param args the arguments for the matrix constructor
/// @return an `ast::CallExpression` of a 4x4 matrix of type
/// `T`, constructed with the values `args`.
- template <typename T, typename... ARGS>
+ template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
const ast::CallExpression* mat4x4(ARGS&&... args) {
return Construct(ty.mat4x4<T>(), std::forward<ARGS>(args)...);
}
+ /// @param source the matrix source
+ /// @param args the arguments for the matrix constructor
+ /// @return an `ast::CallExpression` of a 4x4 matrix of type
+ /// `T`, constructed with the values `args`.
+ template <typename T, typename... ARGS>
+ const ast::CallExpression* mat4x4(const Source& source, ARGS&&... args) {
+ return Construct(source, ty.mat4x4<T>(), std::forward<ARGS>(args)...);
+ }
+
/// @param args the arguments for the array constructor
/// @return an `ast::CallExpression` of an array with element type
/// `T` and size `N`, constructed with the values `args`.
@@ -1346,6 +1496,15 @@
return Construct(ty.array<T, N>(), std::forward<ARGS>(args)...);
}
+ /// @param source the array source
+ /// @param args the arguments for the array constructor
+ /// @return an `ast::CallExpression` of an array with element type
+ /// `T` and size `N`, constructed with the values `args`.
+ template <typename T, int N, typename... ARGS>
+ const ast::CallExpression* array(const Source& source, ARGS&&... args) {
+ return Construct(source, ty.array<T, N>(), std::forward<ARGS>(args)...);
+ }
+
/// @param subtype the array element type
/// @param n the array size. nullptr represents a runtime-array.
/// @param args the arguments for the array constructor
@@ -1356,6 +1515,21 @@
return Construct(ty.array(subtype, std::forward<EXPR>(n)), std::forward<ARGS>(args)...);
}
+ /// @param source the array source
+ /// @param subtype the array element type
+ /// @param n the array size. nullptr represents a runtime-array.
+ /// @param args the arguments for the array constructor
+ /// @return an `ast::CallExpression` of an array with element type
+ /// `subtype`, constructed with the values `args`.
+ template <typename EXPR, typename... ARGS>
+ const ast::CallExpression* array(const Source& source,
+ const ast::Type* subtype,
+ EXPR&& n,
+ ARGS&&... args) {
+ return Construct(source, ty.array(subtype, std::forward<EXPR>(n)),
+ std::forward<ARGS>(args)...);
+ }
+
/// Adds the extension to the list of enable directives at the top of the module.
/// @param ext the extension to enable
/// @return an `ast::Enable` enabling the given extension.
diff --git a/src/tint/reader/wgsl/parser_impl.cc b/src/tint/reader/wgsl/parser_impl.cc
index 3adab59..59f4fac 100644
--- a/src/tint/reader/wgsl/parser_impl.cc
+++ b/src/tint/reader/wgsl/parser_impl.cc
@@ -1175,33 +1175,40 @@
Expect<const ast::Type*> ParserImpl::expect_type_decl_array(const Token& t) {
const char* use = "array declaration";
- const ast::Expression* size = nullptr;
+ struct TypeAndSize {
+ const ast::Type* type = nullptr;
+ const ast::Expression* size = nullptr;
+ };
- auto subtype = expect_lt_gt_block(use, [&]() -> Expect<const ast::Type*> {
+ if (!peek_is(Token::Type::kLessThan)) {
+ return builder_.ty.array(make_source_range_from(t.source()), nullptr, nullptr);
+ }
+
+ auto type_size = expect_lt_gt_block(use, [&]() -> Expect<TypeAndSize> {
auto type = expect_type(use);
if (type.errored) {
return Failure::kErrored;
}
- if (match(Token::Type::kComma)) {
- auto expr = primary_expression();
- if (expr.errored) {
- return Failure::kErrored;
- } else if (!expr.matched) {
- return add_error(peek(), "expected array size expression");
- }
-
- size = std::move(expr.value);
+ if (!match(Token::Type::kComma)) {
+ return TypeAndSize{type.value, nullptr};
}
- return type.value;
+ auto size = primary_expression();
+ if (size.errored) {
+ return Failure::kErrored;
+ } else if (!size.matched) {
+ return add_error(peek(), "expected array size expression");
+ }
+
+ return TypeAndSize{type.value, size.value};
});
- if (subtype.errored) {
+ if (type_size.errored) {
return Failure::kErrored;
}
- return builder_.ty.array(make_source_range_from(t.source()), subtype.value, size);
+ return builder_.ty.array(make_source_range_from(t.source()), type_size->type, type_size->size);
}
Expect<const ast::Type*> ParserImpl::expect_type_decl_matrix(const Token& t) {
diff --git a/src/tint/reader/wgsl/parser_impl_error_msg_test.cc b/src/tint/reader/wgsl/parser_impl_error_msg_test.cc
index 6a825de..81613b4 100644
--- a/src/tint/reader/wgsl/parser_impl_error_msg_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_error_msg_test.cc
@@ -603,8 +603,9 @@
}
TEST_F(ParserImplErrorTest, GlobalDeclLetBadConstLiteral) {
- EXPECT("let i : vec2<i32> = vec2<i32>(!);",
- R"(test.wgsl:1:1 warning: use of deprecated language feature: module-scope 'let' has been replaced with 'const'
+ EXPECT(
+ "let i : vec2<i32> = vec2<i32>(!);",
+ R"(test.wgsl:1:1 warning: use of deprecated language feature: module-scope 'let' has been replaced with 'const'
let i : vec2<i32> = vec2<i32>(!);
^^^
@@ -821,14 +822,6 @@
)");
}
-TEST_F(ParserImplErrorTest, GlobalDeclVarArrayMissingLessThan) {
- EXPECT("var i : array;",
- R"(test.wgsl:1:14 error: expected '<' for array declaration
-var i : array;
- ^
-)");
-}
-
TEST_F(ParserImplErrorTest, GlobalDeclVarArrayMissingGreaterThan) {
EXPECT("var i : array<u32, 3;",
R"(test.wgsl:1:21 error: expected '>' for array declaration
diff --git a/src/tint/reader/wgsl/parser_impl_type_decl_test.cc b/src/tint/reader/wgsl/parser_impl_type_decl_test.cc
index 5459af6..880f87a 100644
--- a/src/tint/reader/wgsl/parser_impl_type_decl_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_type_decl_test.cc
@@ -501,6 +501,22 @@
EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 17u}}));
}
+TEST_F(ParserImplTest, TypeDecl_Array_InferTypeAndSize) {
+ auto p = parser("array");
+ auto t = p->type_decl();
+ EXPECT_TRUE(t.matched);
+ EXPECT_FALSE(t.errored);
+ ASSERT_NE(t.value, nullptr) << p->error();
+ ASSERT_FALSE(p->has_error());
+ ASSERT_TRUE(t.value->Is<ast::Array>());
+
+ auto* a = t.value->As<ast::Array>();
+ EXPECT_FALSE(a->IsRuntimeArray());
+ EXPECT_EQ(a->type, nullptr);
+ EXPECT_EQ(a->count, nullptr);
+ EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 6u}}));
+}
+
TEST_F(ParserImplTest, TypeDecl_Array_BadSize) {
auto p = parser("array<f32, !>");
auto t = p->type_decl();
@@ -521,16 +537,6 @@
ASSERT_EQ(p->error(), "1:11: expected array size expression");
}
-TEST_F(ParserImplTest, TypeDecl_Array_MissingLessThan) {
- auto p = parser("array f32>");
- auto t = p->type_decl();
- EXPECT_TRUE(t.errored);
- EXPECT_FALSE(t.matched);
- ASSERT_EQ(t.value, nullptr);
- ASSERT_TRUE(p->has_error());
- ASSERT_EQ(p->error(), "1:7: expected '<' for array declaration");
-}
-
TEST_F(ParserImplTest, TypeDecl_Array_MissingGreaterThan) {
auto p = parser("array<f32");
auto t = p->type_decl();
diff --git a/src/tint/resolver/attribute_validation_test.cc b/src/tint/resolver/attribute_validation_test.cc
index 2cb8905..36221e2 100644
--- a/src/tint/resolver/attribute_validation_test.cc
+++ b/src/tint/resolver/attribute_validation_test.cc
@@ -895,7 +895,8 @@
<< ", should_pass: " << params.should_pass;
SCOPED_TRACE(ss.str());
- auto* arr = ty.array(Source{{12, 34}}, el_ty, 4_u, params.stride);
+ auto* arr =
+ ty.array(el_ty, 4_u, {create<ast::StrideAttribute>(Source{{12, 34}}, params.stride)});
GlobalVar("myarray", arr, ast::StorageClass::kPrivate);
@@ -906,7 +907,7 @@
EXPECT_EQ(r()->error(),
"12:34 error: arrays decorated with the stride attribute must "
"have a stride that is at least the size of the element type, "
- "and be a multiple of the element type's alignment value.");
+ "and be a multiple of the element type's alignment value");
}
}
diff --git a/src/tint/resolver/materialize_test.cc b/src/tint/resolver/materialize_test.cc
index bd363c1..70985dd 100644
--- a/src/tint/resolver/materialize_test.cc
+++ b/src/tint/resolver/materialize_test.cc
@@ -27,22 +27,28 @@
using AFloatV = builder::vec<3, AFloat>;
using AFloatM = builder::mat<3, 2, AFloat>;
+using AFloatA = builder::array<3, AFloat>;
using AIntV = builder::vec<3, AInt>;
+using AIntA = builder::array<3, AInt>;
using f32V = builder::vec<3, f32>;
using f16V = builder::vec<3, f16>;
using i32V = builder::vec<3, i32>;
using u32V = builder::vec<3, u32>;
using f32M = builder::mat<3, 2, f32>;
-using i32Varr = builder::array<3, i32>;
+using f16M = builder::mat<3, 2, f16>;
+using f32A = builder::array<3, f32>;
+using f16A = builder::array<3, f16>;
+using i32A = builder::array<3, i32>;
+using u32A = builder::array<3, u32>;
constexpr double kTooBigF32 = static_cast<double>(3.5e+38);
-// constexpr double kTooBigF16 = static_cast<double>(6.6e+4);
+constexpr double kTooBigF16 = static_cast<double>(6.6e+4);
constexpr double kPiF64 = 3.141592653589793;
constexpr double kPiF32 = 3.1415927410125732; // kPiF64 quantized to f32
-// constexpr double kPiF16 = 3.140625; // kPiF64 quantized to f16
+constexpr double kPiF16 = 3.140625; // kPiF64 quantized to f16
constexpr double kSubnormalF32 = 0x1.0p-128;
-// constexpr double kSubnormalF16 = 0x1.0p-16;
+constexpr double kSubnormalF16 = 0x1.0p-16;
enum class Expectation {
kMaterialize,
@@ -111,6 +117,14 @@
}
}
},
+ [&](const sem::Array* a) {
+ for (uint32_t i = 0; i < a->Count(); i++) {
+ auto* el = value->Index(i);
+ ASSERT_NE(el, nullptr);
+ EXPECT_TYPE(el->Type(), a->ElemType());
+ EXPECT_EQ(std::get<T>(el->Value()), expected_value);
+ }
+ },
[&](Default) { EXPECT_EQ(std::get<T>(value->Value()), expected_value); });
}
};
@@ -231,7 +245,7 @@
case Method::kWorkgroupSize:
return o << "workgroup-size";
case Method::kRuntimeIndex:
- return o << "dynamic-index";
+ return o << "runtime-index";
}
return o << "<unknown>";
}
@@ -296,8 +310,7 @@
MaterializeTest<std::tuple<Expectation, Method, Data>>;
TEST_P(MaterializeAbstractNumericToConcreteType, Test) {
- // Once built-in and ops using f16 is properly supported, we'll need to enable this:
- // Enable(ast::Extension::kF16);
+ Enable(ast::Extension::kF16);
const auto& param = GetParam();
const auto& expectation = std::get<0>(param);
@@ -435,6 +448,12 @@
Method::kReturn, Method::kArray, Method::kStruct, Method::kBinaryOp,
};
+/// Methods that support array materialization
+constexpr Method kArrayMethods[] = {
+ Method::kLet, Method::kVar, Method::kAssign, Method::kFnArg,
+ Method::kReturn, Method::kArray, Method::kStruct,
+};
+
/// Methods that support materialization for switch cases
constexpr Method kSwitchMethods[] = {
Method::kSwitchCond,
@@ -471,13 +490,13 @@
Types<f32, AFloat>(AFloat(kPiF32), kPiF64), //
Types<f32, AFloat>(AFloat(kSubnormalF32), kSubnormalF32), //
Types<f32, AFloat>(AFloat(-kSubnormalF32), -kSubnormalF32), //
- /* Types<f16, AFloat>(0.0_a, 0.0), */ //
- /* Types<f16, AFloat>(1.0_a, 1.0), */ //
- /* Types<f16, AFloat>(AFloat(kHighestF16), kHighestF16), */ //
- /* Types<f16, AFloat>(AFloat(kLowestF16), kLowestF16), */ //
- /* Types<f16, AFloat>(AFloat(kPiF16), kPiF64), */ //
- /* Types<f16, AFloat>(AFloat(kSubnormalF16), kSubnormalF16), */ //
- /* Types<f16, AFloat>(AFloat(-kSubnormalF16), -kSubnormalF16), */ //
+ Types<f16, AFloat>(0.0_a, 0.0), //
+ Types<f16, AFloat>(1.0_a, 1.0), //
+ Types<f16, AFloat>(AFloat(f16::Highest()), static_cast<double>(f16::Highest())), //
+ Types<f16, AFloat>(AFloat(f16::Lowest()), static_cast<double>(f16::Lowest())), //
+ Types<f16, AFloat>(AFloat(kPiF16), kPiF64), //
+ Types<f16, AFloat>(AFloat(kSubnormalF16), kSubnormalF16), //
+ Types<f16, AFloat>(AFloat(-kSubnormalF16), -kSubnormalF16), //
})));
INSTANTIATE_TEST_SUITE_P(
@@ -504,14 +523,14 @@
Types<f32V, AFloatV>(AFloat(kPiF32), kPiF64), //
Types<f32V, AFloatV>(AFloat(kSubnormalF32), kSubnormalF32), //
Types<f32V, AFloatV>(AFloat(-kSubnormalF32), -kSubnormalF32), //
- /* Types<f16V, AFloatV>(0.0_a, 0.0), */ //
- /* Types<f16V, AFloatV>(1.0_a, 1.0), */ //
- /* Types<f16V, AFloatV>(-1.0_a, -1.0), */ //
- /* Types<f16V, AFloatV>(AFloat(kHighestF16), kHighestF16), */ //
- /* Types<f16V, AFloatV>(AFloat(kLowestF16), kLowestF16), */ //
- /* Types<f16V, AFloatV>(AFloat(kPiF16), kPiF64), */ //
- /* Types<f16V, AFloatV>(AFloat(kSubnormalF16), kSubnormalF16), */ //
- /* Types<f16V, AFloatV>(AFloat(-kSubnormalF16), -kSubnormalF16), */ //
+ Types<f16V, AFloatV>(0.0_a, 0.0), //
+ Types<f16V, AFloatV>(1.0_a, 1.0), //
+ Types<f16V, AFloatV>(-1.0_a, -1.0), //
+ Types<f16V, AFloatV>(AFloat(f16::Highest()), static_cast<double>(f16::Highest())), //
+ Types<f16V, AFloatV>(AFloat(f16::Lowest()), static_cast<double>(f16::Lowest())), //
+ Types<f16V, AFloatV>(AFloat(kPiF16), kPiF64), //
+ Types<f16V, AFloatV>(AFloat(kSubnormalF16), kSubnormalF16), //
+ Types<f16V, AFloatV>(AFloat(-kSubnormalF16), -kSubnormalF16), //
})));
INSTANTIATE_TEST_SUITE_P(
@@ -551,14 +570,14 @@
Types<f32M, AFloatM>(AFloat(kPiF32), kPiF64), //
Types<f32M, AFloatM>(AFloat(kSubnormalF32), kSubnormalF32), //
Types<f32M, AFloatM>(AFloat(-kSubnormalF32), -kSubnormalF32), //
- /* Types<f16M, AFloatM>(0.0_a, 0.0), */ //
- /* Types<f16M, AFloatM>(1.0_a, 1.0), */ //
- /* Types<f16M, AFloatM>(-1.0_a, -1.0), */ //
- /* Types<f16M, AFloatM>(AFloat(kHighestF16), kHighestF16), */ //
- /* Types<f16M, AFloatM>(AFloat(kLowestF16), kLowestF16), */ //
- /* Types<f16M, AFloatM>(AFloat(kPiF16), kPiF64), */ //
- /* Types<f16M, AFloatM>(AFloat(kSubnormalF16), kSubnormalF16), */ //
- /* Types<f16M, AFloatM>(AFloat(-kSubnormalF16), -kSubnormalF16), */ //
+ Types<f16M, AFloatM>(0.0_a, 0.0), //
+ Types<f16M, AFloatM>(1.0_a, 1.0), //
+ Types<f16M, AFloatM>(-1.0_a, -1.0), //
+ Types<f16M, AFloatM>(AFloat(f16::Highest()), static_cast<double>(f16::Highest())), //
+ Types<f16M, AFloatM>(AFloat(f16::Lowest()), static_cast<double>(f16::Lowest())), //
+ Types<f16M, AFloatM>(AFloat(kPiF16), kPiF64), //
+ Types<f16M, AFloatM>(AFloat(kSubnormalF16), kSubnormalF16), //
+ Types<f16M, AFloatM>(AFloat(-kSubnormalF16), -kSubnormalF16), //
})));
INSTANTIATE_TEST_SUITE_P(
@@ -595,6 +614,57 @@
Types<u32, AInt>(AInt(u32::Lowest()), u32::Lowest()), //
})));
+INSTANTIATE_TEST_SUITE_P(
+ MaterializeArray,
+ MaterializeAbstractNumericToConcreteType,
+ testing::Combine(
+ testing::Values(Expectation::kMaterialize),
+ testing::ValuesIn(kArrayMethods),
+ testing::ValuesIn(std::vector<Data>{
+ Types<i32A, AIntA>(0_a, 0.0), //
+ Types<i32A, AIntA>(1_a, 1.0), //
+ Types<i32A, AIntA>(-1_a, -1.0), //
+ Types<i32A, AIntA>(AInt(i32::Highest()), i32::Highest()), //
+ Types<i32A, AIntA>(AInt(i32::Lowest()), i32::Lowest()), //
+ Types<u32A, AIntA>(0_a, 0.0), //
+ Types<u32A, AIntA>(1_a, 1.0), //
+ Types<u32A, AIntA>(AInt(u32::Highest()), u32::Highest()), //
+ Types<u32A, AIntA>(AInt(u32::Lowest()), u32::Lowest()), //
+ Types<f32A, AFloatA>(0.0_a, 0.0), //
+ Types<f32A, AFloatA>(1.0_a, 1.0), //
+ Types<f32A, AFloatA>(-1.0_a, -1.0), //
+ Types<f32A, AFloatA>(AFloat(f32::Highest()), static_cast<double>(f32::Highest())), //
+ Types<f32A, AFloatA>(AFloat(f32::Lowest()), static_cast<double>(f32::Lowest())), //
+ Types<f32A, AFloatA>(AFloat(kPiF32), kPiF64), //
+ Types<f32A, AFloatA>(AFloat(kSubnormalF32), kSubnormalF32), //
+ Types<f32A, AFloatA>(AFloat(-kSubnormalF32), -kSubnormalF32), //
+ Types<f16A, AFloatA>(0.0_a, 0.0), //
+ Types<f16A, AFloatA>(1.0_a, 1.0), //
+ Types<f16A, AFloatA>(-1.0_a, -1.0), //
+ Types<f16A, AFloatA>(AFloat(f16::Highest()), static_cast<double>(f16::Highest())), //
+ Types<f16A, AFloatA>(AFloat(f16::Lowest()), static_cast<double>(f16::Lowest())), //
+ Types<f16A, AFloatA>(AFloat(kPiF16), kPiF64), //
+ Types<f16A, AFloatA>(AFloat(kSubnormalF16), kSubnormalF16), //
+ Types<f16A, AFloatA>(AFloat(-kSubnormalF16), -kSubnormalF16), //
+ })));
+
+INSTANTIATE_TEST_SUITE_P(
+ MaterializeArrayRuntimeIndex,
+ MaterializeAbstractNumericToConcreteType,
+ testing::Combine(
+ testing::Values(Expectation::kMaterialize),
+ testing::Values(Method::kRuntimeIndex),
+ testing::ValuesIn(std::vector<Data>{
+ Types<f32A, AFloatA>(0.0_a, 0.0), //
+ Types<f32A, AFloatA>(1.0_a, 1.0), //
+ Types<f32A, AFloatA>(-1.0_a, -1.0), //
+ Types<f32A, AFloatA>(AFloat(f32::Highest()), static_cast<double>(f32::Highest())), //
+ Types<f32A, AFloatA>(AFloat(f32::Lowest()), static_cast<double>(f32::Lowest())), //
+ Types<f32A, AFloatA>(AFloat(kPiF32), kPiF64), //
+ Types<f32A, AFloatA>(AFloat(kSubnormalF32), kSubnormalF32), //
+ Types<f32A, AFloatA>(AFloat(-kSubnormalF32), -kSubnormalF32), //
+ })));
+
INSTANTIATE_TEST_SUITE_P(MaterializeWorkgroupSize,
MaterializeAbstractNumericToConcreteType,
testing::Combine(testing::Values(Expectation::kMaterialize),
@@ -625,14 +695,14 @@
testing::Combine(testing::Values(Expectation::kInvalidConversion),
testing::ValuesIn(kScalarMethods),
testing::ValuesIn(std::vector<Data>{
- Types<i32, AFloat>(), //
- Types<u32, AFloat>(), //
- Types<i32V, AFloatV>(), //
- Types<u32V, AFloatV>(), //
- Types<i32Varr, AInt>(), //
- Types<i32Varr, AIntV>(), //
- Types<i32Varr, AFloat>(), //
- Types<i32Varr, AFloatV>(), //
+ Types<i32, AFloat>(), //
+ Types<u32, AFloat>(), //
+ Types<i32V, AFloatV>(), //
+ Types<u32V, AFloatV>(), //
+ Types<i32A, AInt>(), //
+ Types<i32A, AIntV>(), //
+ Types<i32A, AFloat>(), //
+ Types<i32A, AFloatV>(), //
})));
INSTANTIATE_TEST_SUITE_P(
@@ -647,8 +717,8 @@
Types<u32, AInt>(0_a, static_cast<double>(u32::kLowestValue) - 1), //
Types<f32, AFloat>(0.0_a, kTooBigF32), //
Types<f32, AFloat>(0.0_a, -kTooBigF32), //
- /* Types<f16, AFloat>(0.0_a, kTooBigF16), */ //
- /* Types<f16, AFloat>(0.0_a, -kTooBigF16), */ //
+ Types<f16, AFloat>(0.0_a, kTooBigF16), //
+ Types<f16, AFloat>(0.0_a, -kTooBigF16), //
})));
INSTANTIATE_TEST_SUITE_P(
@@ -663,8 +733,8 @@
Types<u32V, AIntV>(0_a, static_cast<double>(u32::kLowestValue) - 1), //
Types<f32V, AFloatV>(0.0_a, kTooBigF32), //
Types<f32V, AFloatV>(0.0_a, -kTooBigF32), //
- /* Types<f16V, AFloatV>(0.0_a, kTooBigF16), */ //
- /* Types<f16V, AFloatV>(0.0_a, -kTooBigF16), */ //
+ Types<f16V, AFloatV>(0.0_a, kTooBigF16), //
+ Types<f16V, AFloatV>(0.0_a, -kTooBigF16), //
})));
INSTANTIATE_TEST_SUITE_P(MatrixValueCannotBeRepresented,
@@ -672,10 +742,10 @@
testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
testing::ValuesIn(kMatrixMethods),
testing::ValuesIn(std::vector<Data>{
- Types<f32M, AFloatM>(0.0_a, kTooBigF32), //
- Types<f32M, AFloatM>(0.0_a, -kTooBigF32), //
- /* Types<f16M, AFloatM>(0.0_a, kTooBigF16), */ //
- /* Types<f16M, AFloatM>(0.0_a, -kTooBigF16), */ //
+ Types<f32M, AFloatM>(0.0_a, kTooBigF32), //
+ Types<f32M, AFloatM>(0.0_a, -kTooBigF32), //
+ Types<f16M, AFloatM>(0.0_a, kTooBigF16), //
+ Types<f16M, AFloatM>(0.0_a, -kTooBigF16), //
})));
} // namespace materialize_abstract_numeric_to_concrete_type
@@ -719,6 +789,9 @@
// arr[abstract_expr]
kIndex,
+
+ // abstract_expr[runtime-index]
+ kRuntimeIndex,
};
static std::ostream& operator<<(std::ostream& o, Method m) {
@@ -741,6 +814,8 @@
return o << "workgroup-size";
case Method::kIndex:
return o << "index";
+ case Method::kRuntimeIndex:
+ return o << "runtime-index";
}
return o << "<unknown>";
}
@@ -826,6 +901,10 @@
GlobalVar("arr", ty.array<i32, 4>(), ast::StorageClass::kPrivate);
WrapInFunction(IndexAccessor("arr", abstract_expr()));
break;
+ case Method::kRuntimeIndex:
+ auto* runtime_index = Var("runtime_index", nullptr, Expr(1_i));
+ WrapInFunction(runtime_index, IndexAccessor(abstract_expr(), runtime_index));
+ break;
}
switch (expectation) {
@@ -883,10 +962,8 @@
/// Methods that support vector materialization
constexpr Method kVectorMethods[] = {
- Method::kLet,
- Method::kVar,
- Method::kBuiltinArg,
- Method::kBitcastVec3F32Arg,
+ Method::kLet, Method::kVar, Method::kBuiltinArg, Method::kBitcastVec3F32Arg,
+ Method::kRuntimeIndex,
};
/// Methods that support matrix materialization
@@ -895,6 +972,12 @@
Method::kVar,
};
+/// Methods that support array materialization
+constexpr Method kArrayMethods[] = {
+ Method::kLet,
+ Method::kVar,
+};
+
INSTANTIATE_TEST_SUITE_P(
MaterializeScalar,
MaterializeAbstractNumericToDefaultType,
@@ -967,6 +1050,28 @@
})));
INSTANTIATE_TEST_SUITE_P(
+ MaterializeArray,
+ MaterializeAbstractNumericToDefaultType,
+ testing::Combine(
+ testing::Values(Expectation::kMaterialize),
+ testing::ValuesIn(kArrayMethods),
+ testing::ValuesIn(std::vector<Data>{
+ Types<i32A, AIntA>(0_a, 0.0), //
+ Types<i32A, AIntA>(1_a, 1.0), //
+ Types<i32A, AIntA>(-1_a, -1.0), //
+ Types<i32A, AIntA>(AInt(i32::Highest()), i32::Highest()), //
+ Types<i32A, AIntA>(AInt(i32::Lowest()), i32::Lowest()), //
+ Types<f32A, AFloatA>(0.0_a, 0.0), //
+ Types<f32A, AFloatA>(1.0_a, 1.0), //
+ Types<f32A, AFloatA>(-1.0_a, -1.0), //
+ Types<f32A, AFloatA>(AFloat(f32::Highest()), static_cast<double>(f32::Highest())), //
+ Types<f32A, AFloatA>(AFloat(f32::Lowest()), static_cast<double>(f32::Lowest())), //
+ Types<f32A, AFloatA>(AFloat(kPiF32), kPiF64), //
+ Types<f32A, AFloatA>(AFloat(kSubnormalF32), kSubnormalF32), //
+ Types<f32A, AFloatA>(AFloat(-kSubnormalF32), -kSubnormalF32), //
+ })));
+
+INSTANTIATE_TEST_SUITE_P(
MaterializeArrayLength,
MaterializeAbstractNumericToDefaultType,
testing::Combine(testing::Values(Expectation::kMaterialize),
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index b1961c3..097d591 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -1316,7 +1316,9 @@
return nullptr;
}
-const sem::Type* Resolver::ConcreteType(const sem::Type* ty, const sem::Type* target_ty) {
+const sem::Type* Resolver::ConcreteType(const sem::Type* ty,
+ const sem::Type* target_ty,
+ const Source& source) {
auto i32 = [&] { return builder_->create<sem::I32>(); };
auto f32 = [&] { return builder_->create<sem::F32>(); };
auto i32v = [&](uint32_t width) { return builder_->create<sem::Vector>(i32(), width); };
@@ -1342,6 +1344,16 @@
[&](const sem::AbstractFloat*) {
return target_ty ? target_ty : f32m(m->columns(), m->rows());
});
+ },
+ [&](const sem::Array* a) -> const sem::Type* {
+ const sem::Type* target_el_ty = nullptr;
+ if (auto* target_arr_ty = As<sem::Array>(target_ty)) {
+ target_el_ty = target_arr_ty->ElemType();
+ }
+ if (auto* el_ty = ConcreteType(a->ElemType(), target_el_ty, source)) {
+ return Array(source, el_ty, a->Count(), /* explicit_stride */ 0);
+ }
+ return nullptr;
});
}
@@ -1354,7 +1366,7 @@
auto* decl = expr->Declaration();
- auto* concrete_ty = ConcreteType(expr->Type(), target_type);
+ auto* concrete_ty = ConcreteType(expr->Type(), target_type, decl->source);
if (!concrete_ty) {
return expr; // Does not require materialization
}
@@ -1422,6 +1434,9 @@
// vec2(1, 2)[runtime-index]
obj = Materialize(obj);
}
+ if (!obj) {
+ return nullptr;
+ }
auto* obj_raw_ty = obj->Type();
auto* obj_ty = obj_raw_ty->UnwrapRef();
auto* ty = Switch(
@@ -1579,20 +1594,28 @@
auto* call_target = utils::GetOrCreate(
array_ctors_, ArrayConstructorSig{{arr, args.Length(), args_stage}},
[&]() -> sem::TypeConstructor* {
- utils::Vector<const sem::Parameter*, 8> params;
- params.Reserve(args.Length());
- for (size_t i = 0; i < args.Length(); i++) {
- params.Push(builder_->create<sem::Parameter>(
- nullptr, // declaration
- static_cast<uint32_t>(i), // index
- arr->ElemType(), // type
- ast::StorageClass::kNone, // storage_class
- ast::Access::kUndefined)); // access
- }
+ auto params = utils::Transform(args, [&](auto, size_t i) {
+ return builder_->create<sem::Parameter>(
+ nullptr, // declaration
+ static_cast<uint32_t>(i), // index
+ arr->ElemType(), // type
+ ast::StorageClass::kNone, // storage_class
+ ast::Access::kUndefined);
+ });
return builder_->create<sem::TypeConstructor>(arr, std::move(params),
args_stage);
});
- return arr_or_str_ctor(arr, call_target);
+
+ auto* call = arr_or_str_ctor(arr, call_target);
+ if (!call) {
+ return nullptr;
+ }
+
+ // Validation must occur after argument materialization in arr_or_str_ctor().
+ if (!validator_.ArrayConstructor(expr, arr)) {
+ return nullptr;
+ }
+ return call;
},
[&](const sem::Struct* str) -> sem::Call* {
auto* call_target = utils::GetOrCreate(
@@ -1611,7 +1634,17 @@
return builder_->create<sem::TypeConstructor>(str, std::move(params),
args_stage);
});
- return arr_or_str_ctor(str, call_target);
+
+ auto* call = arr_or_str_ctor(str, call_target);
+ if (!call) {
+ return nullptr;
+ }
+
+ // Validation must occur after argument materialization in arr_or_str_ctor().
+ if (!validator_.StructureConstructor(expr, str)) {
+ return nullptr;
+ }
+ return call;
},
[&](Default) {
AddError("type is not constructible", expr->source);
@@ -1659,6 +1692,59 @@
}
return nullptr;
},
+ [&](const ast::Array* a) -> sem::Call* {
+ Mark(a);
+ // array element type must be inferred if it was not specified.
+ auto el_count = static_cast<uint32_t>(args.Length());
+ const sem::Type* el_ty = nullptr;
+ if (a->type) {
+ el_ty = Type(a->type);
+ if (!el_ty) {
+ return nullptr;
+ }
+ if (!a->count) {
+ AddError("cannot construct a runtime-sized array", expr->source);
+ return nullptr;
+ }
+ if (auto count = ArrayCount(a->count)) {
+ el_count = count.Get();
+ } else {
+ return nullptr;
+ }
+ // Note: validation later will detect any mismatches between explicit array
+ // size and number of constructor expressions.
+ } else {
+ auto arg_tys =
+ utils::Transform(args, [](auto* arg) { return arg->Type()->UnwrapRef(); });
+ el_ty = sem::Type::Common(arg_tys);
+ if (!el_ty) {
+ AddError(
+ "cannot infer common array element type from constructor arguments",
+ expr->source);
+ std::unordered_set<const sem::Type*> types;
+ for (size_t i = 0; i < args.Length(); i++) {
+ if (types.emplace(args[i]->Type()).second) {
+ AddNote("argument " + std::to_string(i) + " is of type '" +
+ sem_.TypeNameOf(args[i]->Type()) + "'",
+ args[i]->Declaration()->source);
+ }
+ }
+ return nullptr;
+ }
+ }
+ uint32_t explicit_stride = 0;
+ if (!ArrayAttributes(a->attributes, el_ty, explicit_stride)) {
+ return nullptr;
+ }
+
+ auto* arr = Array(a->source, el_ty, el_count, explicit_stride);
+ if (!arr) {
+ return nullptr;
+ }
+ builder_->Sem().Add(a, arr);
+
+ return ty_ctor_or_conv(arr);
+ },
[&](const ast::Type* ast) -> sem::Call* {
// Handler for AST types that do not have an optional element type.
if (auto* ty = Type(ast)) {
@@ -2259,102 +2345,128 @@
}
sem::Array* Resolver::Array(const ast::Array* arr) {
- auto source = arr->source;
-
- auto* elem_type = Type(arr->type);
- if (!elem_type) {
+ if (!arr->type) {
+ AddError("missing array element type", arr->source.End());
return nullptr;
}
- if (!validator_.IsPlain(elem_type)) { // Check must come before GetDefaultAlignAndSize()
- AddError(sem_.TypeNameOf(elem_type) + " cannot be used as an element type of an array",
- source);
- return nullptr;
- }
-
- uint32_t el_align = elem_type->Align();
- uint32_t el_size = elem_type->Size();
-
- if (!validator_.NoDuplicateAttributes(arr->attributes)) {
+ auto* el_ty = Type(arr->type);
+ if (!el_ty) {
return nullptr;
}
// Look for explicit stride via @stride(n) attribute
uint32_t explicit_stride = 0;
- for (auto* attr : arr->attributes) {
+ if (!ArrayAttributes(arr->attributes, el_ty, explicit_stride)) {
+ return nullptr;
+ }
+
+ uint32_t el_count = 0; // sem::Array uses a size of 0 for a runtime-sized array.
+
+ // Evaluate the constant array size expression.
+ if (auto* count_expr = arr->count) {
+ if (auto count = ArrayCount(count_expr)) {
+ el_count = count.Get();
+ } else {
+ return nullptr;
+ }
+ }
+
+ auto* out = Array(arr->source, el_ty, el_count, explicit_stride);
+ if (out == nullptr) {
+ return nullptr;
+ }
+
+ if (el_ty->Is<sem::Atomic>()) {
+ atomic_composite_info_.emplace(out, arr->type->source);
+ } else {
+ auto found = atomic_composite_info_.find(el_ty);
+ if (found != atomic_composite_info_.end()) {
+ atomic_composite_info_.emplace(out, found->second);
+ }
+ }
+
+ return out;
+}
+
+utils::Result<uint32_t> Resolver::ArrayCount(const ast::Expression* count_expr) {
+ // Evaluate the constant array size expression.
+ const auto* count_sem = Materialize(Expression(count_expr));
+ if (!count_sem) {
+ return utils::Failure;
+ }
+
+ auto* count_val = count_sem->ConstantValue();
+ if (!count_val) {
+ AddError("array size must evaluate to a constant integer expression", count_expr->source);
+ return utils::Failure;
+ }
+
+ if (auto* ty = count_val->Type(); !ty->is_integer_scalar()) {
+ AddError("array size must evaluate to a constant integer expression, but is type '" +
+ builder_->FriendlyName(ty) + "'",
+ count_expr->source);
+ return utils::Failure;
+ }
+
+ int64_t count = count_val->As<AInt>();
+ if (count < 1) {
+ AddError("array size (" + std::to_string(count) + ") must be greater than 0",
+ count_expr->source);
+ return utils::Failure;
+ }
+
+ return static_cast<uint32_t>(count);
+}
+
+bool Resolver::ArrayAttributes(const ast::AttributeList& attributes,
+ const sem::Type* el_ty,
+ uint32_t& explicit_stride) {
+ if (!validator_.NoDuplicateAttributes(attributes)) {
+ return false;
+ }
+
+ for (auto* attr : attributes) {
Mark(attr);
if (auto* sd = attr->As<ast::StrideAttribute>()) {
explicit_stride = sd->stride;
- if (!validator_.ArrayStrideAttribute(sd, el_size, el_align, source)) {
- return nullptr;
+ if (!validator_.ArrayStrideAttribute(sd, el_ty->Size(), el_ty->Align())) {
+ return false;
}
continue;
}
AddError("attribute is not valid for array types", attr->source);
- return nullptr;
+ return false;
}
- // Calculate implicit stride
- uint64_t implicit_stride = utils::RoundUp<uint64_t>(el_align, el_size);
+ return true;
+}
+sem::Array* Resolver::Array(const Source& source,
+ const sem::Type* el_ty,
+ uint32_t el_count,
+ uint32_t explicit_stride) {
+ uint32_t el_align = el_ty->Align();
+ uint32_t el_size = el_ty->Size();
+ uint64_t implicit_stride = el_size ? utils::RoundUp<uint64_t>(el_align, el_size) : 0;
uint64_t stride = explicit_stride ? explicit_stride : implicit_stride;
- int64_t count = 0; // sem::Array uses a size of 0 for a runtime-sized array.
-
- // Evaluate the constant array size expression.
- if (auto* count_expr = arr->count) {
- const auto* count_sem = Materialize(Expression(count_expr));
- if (!count_sem) {
- return nullptr;
- }
-
- auto* count_val = count_sem->ConstantValue();
- if (!count_val) {
- AddError("array size must evaluate to a constant integer expression",
- count_expr->source);
- return nullptr;
- }
-
- if (auto* ty = count_val->Type(); !ty->is_integer_scalar()) {
- AddError("array size must evaluate to a constant integer expression, but is type '" +
- builder_->FriendlyName(ty) + "'",
- count_expr->source);
- return nullptr;
- }
-
- count = count_val->As<AInt>();
- if (count < 1) {
- AddError("array size (" + std::to_string(count) + ") must be greater than 0",
- count_expr->source);
- return nullptr;
- }
- }
-
- auto size = std::max<uint64_t>(static_cast<uint32_t>(count), 1u) * stride;
+ auto size = std::max<uint64_t>(el_count, 1u) * stride;
if (size > std::numeric_limits<uint32_t>::max()) {
std::stringstream msg;
msg << "array size (0x" << std::hex << size << ") must not exceed 0xffffffff bytes";
- AddError(msg.str(), arr->source);
+ AddError(msg.str(), source);
return nullptr;
}
- auto* out = builder_->create<sem::Array>(
- elem_type, static_cast<uint32_t>(count), el_align, static_cast<uint32_t>(size),
- static_cast<uint32_t>(stride), static_cast<uint32_t>(implicit_stride));
+ auto* out = builder_->create<sem::Array>(el_ty, el_count, el_align, static_cast<uint32_t>(size),
+ static_cast<uint32_t>(stride),
+ static_cast<uint32_t>(implicit_stride));
if (!validator_.Array(out, source)) {
return nullptr;
}
- if (elem_type->Is<sem::Atomic>()) {
- atomic_composite_info_.emplace(out, arr->type->source);
- } else {
- auto found = atomic_composite_info_.find(elem_type);
- if (found != atomic_composite_info_.end()) {
- atomic_composite_info_.emplace(out, found->second);
- }
- }
-
return out;
}
diff --git a/src/tint/resolver/resolver.h b/src/tint/resolver/resolver.h
index ccd3895..fa5a569 100644
--- a/src/tint/resolver/resolver.h
+++ b/src/tint/resolver/resolver.h
@@ -233,9 +233,12 @@
/// @param ty the type that may hold abstract numeric types
/// @param target_ty the target type for the expression (variable type, parameter type, etc).
/// May be nullptr.
+ /// @param source the source of the expression requiring materialization
/// @returns the concrete (materialized) type for the given type, or nullptr if the type is
/// already concrete.
- const sem::Type* ConcreteType(const sem::Type* ty, const sem::Type* target_ty);
+ const sem::Type* ConcreteType(const sem::Type* ty,
+ const sem::Type* target_ty,
+ const Source& source);
// Statement resolving methods
// Each return true on success, false on failure.
@@ -286,14 +289,38 @@
/// @returns the resolved semantic type
sem::Type* TypeDecl(const ast::TypeDecl* named_type);
- /// Builds and returns the semantic information for the array `arr`.
- /// This method does not mark the ast::Array node, nor attach the generated
- /// semantic information to the AST node.
- /// @returns the semantic Array information, or nullptr if an error is
- /// raised.
+ /// Builds and returns the semantic information for the AST array `arr`.
+ /// This method does not mark the ast::Array node, nor attach the generated semantic information
+ /// to the AST node.
+ /// @returns the semantic Array information, or nullptr if an error is raised.
/// @param arr the Array to get semantic information for
sem::Array* Array(const ast::Array* arr);
+ /// Resolves and validates the expression used as the count parameter of an array.
+ /// @param count_expr the expression used as the second template parameter to an array<>.
+ /// @returns the number of elements in the array.
+ utils::Result<uint32_t> ArrayCount(const ast::Expression* count_expr);
+
+ /// Resolves and validates the attributes on an array.
+ /// @param attributes the attributes on the array type.
+ /// @param el_ty the element type of the array.
+ /// @param explicit_stride assigned the specified stride of the array in bytes.
+ /// @returns true on success, false on failure
+ bool ArrayAttributes(const ast::AttributeList& attributes,
+ const sem::Type* el_ty,
+ uint32_t& explicit_stride);
+
+ /// Builds and returns the semantic information for an array.
+ /// @returns the semantic Array information, or nullptr if an error is raised.
+ /// @param source the source of the array declaration
+ /// @param el_ty the Array element type
+ /// @param el_count the number of elements in the array. Zero means runtime-sized.
+ /// @param explicit_stride the explicit byte stride of the array. Zero means implicit stride.
+ sem::Array* Array(const Source& source,
+ const sem::Type* el_ty,
+ uint32_t el_count,
+ uint32_t explicit_stride);
+
/// Builds and returns the semantic information for the alias `alias`.
/// This method does not mark the ast::Alias node, nor attach the generated
/// semantic information to the AST node.
diff --git a/src/tint/resolver/resolver_test_helper.h b/src/tint/resolver/resolver_test_helper.h
index f56d822..efb215b 100644
--- a/src/tint/resolver/resolver_test_helper.h
+++ b/src/tint/resolver/resolver_test_helper.h
@@ -538,7 +538,10 @@
/// @param b the ProgramBuilder
/// @return a new AST array type
static inline const ast::Type* AST(ProgramBuilder& b) {
- return b.ty.array(DataType<T>::AST(b), u32(N));
+ if (auto* ast = DataType<T>::AST(b)) {
+ return b.ty.array(ast, u32(N));
+ }
+ return b.ty.array(nullptr, nullptr);
}
/// @param b the ProgramBuilder
/// @return the semantic array type
@@ -548,7 +551,7 @@
/* element */ el,
/* count */ N,
/* align */ el->Align(),
- /* size */ el->Size(),
+ /* size */ N * el->Size(),
/* stride */ el->Align(),
/* implicit_stride */ el->Align());
}
diff --git a/src/tint/resolver/type_constructor_validation_test.cc b/src/tint/resolver/type_constructor_validation_test.cc
index 0fb01bc..fe1973b 100644
--- a/src/tint/resolver/type_constructor_validation_test.cc
+++ b/src/tint/resolver/type_constructor_validation_test.cc
@@ -486,7 +486,7 @@
namespace ArrayConstructor {
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Array_ZeroValue_Pass) {
+TEST_F(ResolverTypeConstructorValidationTest, Array_ZeroValue_Pass) {
// array<u32, 10u>();
auto* tc = array<u32, 10>();
WrapInFunction(tc);
@@ -502,9 +502,9 @@
ASSERT_EQ(ctor->Parameters().Length(), 0u);
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Array_type_match) {
- // array<u32, 3u>(0u, 10u. 20u);
- auto* tc = array<u32, 3>(Expr(0_u), Expr(10_u), Expr(20_u));
+TEST_F(ResolverTypeConstructorValidationTest, Array_U32U32U32) {
+ // array<u32, 3u>(0u, 10u, 20u);
+ auto* tc = array<u32, 3>(0_u, 10_u, 20_u);
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -521,112 +521,330 @@
EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::U32>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Array_type_Mismatch_U32F32) {
+TEST_F(ResolverTypeConstructorValidationTest, InferredArray_U32U32U32) {
+ // array(0u, 10u, 20u);
+ auto* tc = array(Source{{12, 34}}, nullptr, nullptr, 0_u, 10_u, 20_u);
+ WrapInFunction(tc);
+
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+
+ auto* call = Sem().Get<sem::Call>(tc);
+ ASSERT_NE(call, nullptr);
+ EXPECT_TRUE(call->Type()->Is<sem::Array>());
+ auto* ctor = call->Target()->As<sem::TypeConstructor>();
+ ASSERT_NE(ctor, nullptr);
+ EXPECT_EQ(call->Type(), ctor->ReturnType());
+ ASSERT_EQ(ctor->Parameters().Length(), 3u);
+ EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::U32>());
+ EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::U32>());
+ EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::U32>());
+}
+
+TEST_F(ResolverTypeConstructorValidationTest, Array_U32AIU32) {
+ // array<u32, 3u>(0u, 10, 20u);
+ auto* tc = array<u32, 3>(0_u, 10_a, 20_u);
+ WrapInFunction(tc);
+
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+
+ auto* call = Sem().Get<sem::Call>(tc);
+ ASSERT_NE(call, nullptr);
+ EXPECT_TRUE(call->Type()->Is<sem::Array>());
+ auto* ctor = call->Target()->As<sem::TypeConstructor>();
+ ASSERT_NE(ctor, nullptr);
+ EXPECT_EQ(call->Type(), ctor->ReturnType());
+ ASSERT_EQ(ctor->Parameters().Length(), 3u);
+ EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::U32>());
+ EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::U32>());
+ EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::U32>());
+}
+
+TEST_F(ResolverTypeConstructorValidationTest, InferredArray_U32AIU32) {
+ // array(0u, 10u, 20u);
+ auto* tc = array(Source{{12, 34}}, nullptr, nullptr, 0_u, 10_a, 20_u);
+ WrapInFunction(tc);
+
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+
+ auto* call = Sem().Get<sem::Call>(tc);
+ ASSERT_NE(call, nullptr);
+ EXPECT_TRUE(call->Type()->Is<sem::Array>());
+ auto* ctor = call->Target()->As<sem::TypeConstructor>();
+ ASSERT_NE(ctor, nullptr);
+ EXPECT_EQ(call->Type(), ctor->ReturnType());
+ ASSERT_EQ(ctor->Parameters().Length(), 3u);
+ EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::U32>());
+ EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::U32>());
+ EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::U32>());
+}
+
+TEST_F(ResolverTypeConstructorValidationTest, ArrayU32_AIAIAI) {
+ // array<u32, 3u>(0, 10, 20);
+ auto* tc = array<u32, 3>(0_a, 10_a, 20_a);
+ WrapInFunction(tc);
+
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+
+ auto* call = Sem().Get<sem::Call>(tc);
+ ASSERT_NE(call, nullptr);
+ EXPECT_TRUE(call->Type()->Is<sem::Array>());
+ auto* ctor = call->Target()->As<sem::TypeConstructor>();
+ ASSERT_NE(ctor, nullptr);
+ EXPECT_EQ(call->Type(), ctor->ReturnType());
+ ASSERT_EQ(ctor->Parameters().Length(), 3u);
+ EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::U32>());
+ EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::U32>());
+ EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::U32>());
+}
+
+TEST_F(ResolverTypeConstructorValidationTest, InferredArray_AIAIAI) {
+ // const c = array(0, 10, 20);
+ auto* tc = array(Source{{12, 34}}, nullptr, nullptr, 0_a, 10_a, 20_a);
+ WrapInFunction(Decl(Const("C", nullptr, tc)));
+
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+
+ auto* call = Sem().Get<sem::Call>(tc);
+ ASSERT_NE(call, nullptr);
+ EXPECT_TRUE(call->Type()->Is<sem::Array>());
+ auto* ctor = call->Target()->As<sem::TypeConstructor>();
+ ASSERT_NE(ctor, nullptr);
+ EXPECT_EQ(call->Type(), ctor->ReturnType());
+ ASSERT_EQ(ctor->Parameters().Length(), 3u);
+ EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::AbstractInt>());
+ EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::AbstractInt>());
+ EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::AbstractInt>());
+}
+
+TEST_F(ResolverTypeConstructorValidationTest, InferredArrayU32_VecI32_VecAI) {
+ // array(vec2(10i), vec2(20));
+ auto* tc = array(Source{{12, 34}}, nullptr, nullptr, //
+ Construct(ty.vec(nullptr, 2), 20_i), //
+ Construct(ty.vec(nullptr, 2), 20_a));
+ WrapInFunction(tc);
+
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+
+ auto* call = Sem().Get<sem::Call>(tc);
+ ASSERT_NE(call, nullptr);
+ EXPECT_TRUE(call->Type()->Is<sem::Array>());
+ auto* ctor = call->Target()->As<sem::TypeConstructor>();
+ ASSERT_NE(ctor, nullptr);
+ EXPECT_EQ(call->Type(), ctor->ReturnType());
+ ASSERT_EQ(ctor->Parameters().Length(), 2u);
+ ASSERT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::Vector>());
+ EXPECT_TRUE(ctor->Parameters()[0]->Type()->As<sem::Vector>()->type()->Is<sem::I32>());
+ ASSERT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::Vector>());
+ EXPECT_TRUE(ctor->Parameters()[1]->Type()->As<sem::Vector>()->type()->Is<sem::I32>());
+}
+
+TEST_F(ResolverTypeConstructorValidationTest, InferredArrayU32_VecAI_VecF32) {
+ // array(vec2(20), vec2(10f));
+ auto* tc = array(Source{{12, 34}}, nullptr, nullptr, //
+ Construct(ty.vec(nullptr, 2), 20_a), //
+ Construct(ty.vec(nullptr, 2), 20_f));
+ WrapInFunction(tc);
+
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+
+ auto* call = Sem().Get<sem::Call>(tc);
+ ASSERT_NE(call, nullptr);
+ EXPECT_TRUE(call->Type()->Is<sem::Array>());
+ auto* ctor = call->Target()->As<sem::TypeConstructor>();
+ ASSERT_NE(ctor, nullptr);
+ EXPECT_EQ(call->Type(), ctor->ReturnType());
+ ASSERT_EQ(ctor->Parameters().Length(), 2u);
+ ASSERT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::Vector>());
+ EXPECT_TRUE(ctor->Parameters()[0]->Type()->As<sem::Vector>()->type()->Is<sem::F32>());
+ ASSERT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::Vector>());
+ EXPECT_TRUE(ctor->Parameters()[1]->Type()->As<sem::Vector>()->type()->Is<sem::F32>());
+}
+
+TEST_F(ResolverTypeConstructorValidationTest, ArrayArgumentTypeMismatch_U32F32) {
// array<u32, 3u>(0u, 1.0f, 20u);
- auto* tc = array<u32, 3>(Expr(0_u), Expr(Source{{12, 34}}, 1_f), Expr(20_u));
+ auto* tc = array<u32, 3>(0_u, Expr(Source{{12, 34}}, 1_f), 20_u);
+ WrapInFunction(tc);
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), R"(12:34 error: 'f32' cannot be used to construct an array of 'u32')");
+}
+
+TEST_F(ResolverTypeConstructorValidationTest, InferredArrayArgumentTypeMismatch_U32F32) {
+ // array(0u, 1.0f, 20u);
+ auto* tc = array(Source{{12, 34}}, nullptr, nullptr, 0_u, 1_f, 20_u);
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- "12:34 error: type in array constructor does not match array type: "
- "expected 'u32', found 'f32'");
+ R"(12:34 error: cannot infer common array element type from constructor arguments
+note: argument 0 is of type 'u32'
+note: argument 1 is of type 'f32')");
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Array_ScalarArgumentTypeMismatch_F32I32) {
+TEST_F(ResolverTypeConstructorValidationTest, ArrayArgumentTypeMismatch_F32I32) {
// array<f32, 1u>(1i);
auto* tc = array<f32, 1>(Expr(Source{{12, 34}}, 1_i));
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(),
- "12:34 error: type in array constructor does not match array type: "
- "expected 'f32', found 'i32'");
+ EXPECT_EQ(r()->error(), R"(12:34 error: 'i32' cannot be used to construct an array of 'f32')");
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Array_ScalarArgumentTypeMismatch_U32I32) {
+TEST_F(ResolverTypeConstructorValidationTest, InferredArrayArgumentTypeMismatch_F32I32) {
+ // array(1f, 1i);
+ auto* tc = array(Source{{12, 34}}, nullptr, nullptr, 1_f, 1_i);
+ WrapInFunction(tc);
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(),
+ R"(12:34 error: cannot infer common array element type from constructor arguments
+note: argument 0 is of type 'f32'
+note: argument 1 is of type 'i32')");
+}
+
+TEST_F(ResolverTypeConstructorValidationTest, ArrayArgumentTypeMismatch_U32I32) {
// array<u32, 1u>(1i, 0u, 0u, 0u, 0u, 0u);
- auto* tc =
- array<u32, 1>(Expr(Source{{12, 34}}, 1_i), Expr(0_u), Expr(0_u), Expr(0_u), Expr(0_u));
+ auto* tc = array<u32, 1>(Expr(Source{{12, 34}}, 1_i), 0_u, 0_u, 0_u, 0_u);
+ WrapInFunction(tc);
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), R"(12:34 error: 'i32' cannot be used to construct an array of 'u32')");
+}
+
+TEST_F(ResolverTypeConstructorValidationTest, InferredArrayArgumentTypeMismatch_U32I32) {
+ // array(1i, 0u, 0u, 0u, 0u, 0u);
+ auto* tc = array(Source{{12, 34}}, nullptr, nullptr, 1_i, 0_u, 0_u, 0_u, 0_u);
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- "12:34 error: type in array constructor does not match array type: "
- "expected 'u32', found 'i32'");
+ R"(12:34 error: cannot infer common array element type from constructor arguments
+note: argument 0 is of type 'i32'
+note: argument 1 is of type 'u32')");
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Array_ScalarArgumentTypeMismatch_Vec2) {
+TEST_F(ResolverTypeConstructorValidationTest, ArrayArgumentTypeMismatch_I32Vec2) {
// array<i32, 3u>(1i, vec2<i32>());
- auto* tc = array<i32, 3>(Expr(1_i), Construct(Source{{12, 34}}, ty.vec2<i32>()));
+ auto* tc = array<i32, 3>(1_i, vec2<i32>(Source{{12, 34}}));
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- "12:34 error: type in array constructor does not match array type: "
- "expected 'i32', found 'vec2<i32>'");
+ R"(12:34 error: 'vec2<i32>' cannot be used to construct an array of 'i32')");
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_ArrayOfVector_SubElemTypeMismatch_I32U32) {
- // array<vec3<i32>, 2u>(vec3<i32>(), vec3<u32>());
- auto* e0 = vec3<i32>();
- SetSource(Source::Location({12, 34}));
- auto* e1 = vec3<u32>();
- auto* t = Construct(ty.array(ty.vec3<i32>(), 2_i), e0, e1);
+TEST_F(ResolverTypeConstructorValidationTest, InferredArrayArgumentTypeMismatch_I32Vec2) {
+ // array(1i, vec2<i32>());
+ auto* tc = array(Source{{12, 34}}, nullptr, nullptr, 1_i, vec2<i32>());
+ WrapInFunction(tc);
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(),
+ R"(12:34 error: cannot infer common array element type from constructor arguments
+note: argument 0 is of type 'i32'
+note: argument 1 is of type 'vec2<i32>')");
+}
+
+TEST_F(ResolverTypeConstructorValidationTest, ArrayArgumentTypeMismatch_Vec3i32_Vec3u32) {
+ // array<vec3<i32>, 2u>(vec3<u32>(), vec3<u32>());
+ auto* t = array(ty.vec3<i32>(), 2_u, vec3<u32>(Source{{12, 34}}), vec3<u32>());
WrapInFunction(t);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- "12:34 error: type in array constructor does not match array type: "
- "expected 'vec3<i32>', found 'vec3<u32>'");
+ R"(12:34 error: 'vec3<u32>' cannot be used to construct an array of 'vec3<i32>')");
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_ArrayOfVector_SubElemTypeMismatch_I32Bool) {
- // array<vec3<i32>, 2u>(vec3<i32>(), vec3<bool>(true, true, false));
- SetSource(Source::Location({12, 34}));
- auto* e0 = vec3<bool>(true, true, false);
- auto* e1 = vec3<i32>();
- auto* t = Construct(ty.array(ty.vec3<i32>(), 2_i), e0, e1);
+TEST_F(ResolverTypeConstructorValidationTest, InferredArrayArgumentTypeMismatch_Vec3i32_Vec3u32) {
+ // array(vec3<i32>(), vec3<u32>());
+ auto* t = array(Source{{12, 34}}, nullptr, nullptr, vec3<i32>(), vec3<u32>());
WrapInFunction(t);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- "12:34 error: type in array constructor does not match array type: "
- "expected 'vec3<i32>', found 'vec3<bool>'");
+ R"(12:34 error: cannot infer common array element type from constructor arguments
+note: argument 0 is of type 'vec3<i32>'
+note: argument 1 is of type 'vec3<u32>')");
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_ArrayOfArray_SubElemSizeMismatch) {
+TEST_F(ResolverTypeConstructorValidationTest, InferredArrayArgumentTypeMismatch_Vec3i32_Vec3AF) {
+ // array(vec3<i32>(), vec3(1.0));
+ auto* t =
+ array(Source{{12, 34}}, nullptr, nullptr, vec3<i32>(), Construct(ty.vec3(nullptr), 1._a));
+ WrapInFunction(t);
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(),
+ R"(12:34 error: cannot infer common array element type from constructor arguments
+note: argument 0 is of type 'vec3<i32>'
+note: argument 1 is of type 'vec3<abstract-float>')");
+}
+
+TEST_F(ResolverTypeConstructorValidationTest, ArrayArgumentTypeMismatch_Vec3i32_Vec3bool) {
+ // array<vec3<i32>, 2u>(vec3<i32>(), vec3<bool>());
+ auto* t = array(ty.vec3<i32>(), 2_u, vec3<i32>(), vec3<bool>());
+ WrapInFunction(t);
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(),
+ R"(error: 'vec3<bool>' cannot be used to construct an array of 'vec3<i32>')");
+}
+
+TEST_F(ResolverTypeConstructorValidationTest, InferredArrayArgumentTypeMismatch_Vec3i32_Vec3bool) {
+ // array(vec3<i32>(), vec3<bool>());
+ auto* t = array(Source{{12, 34}}, nullptr, nullptr, vec3<i32>(), vec3<bool>());
+ WrapInFunction(t);
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(),
+ R"(12:34 error: cannot infer common array element type from constructor arguments
+note: argument 0 is of type 'vec3<i32>'
+note: argument 1 is of type 'vec3<bool>')");
+}
+
+TEST_F(ResolverTypeConstructorValidationTest, ArrayOfArray_SubElemSizeMismatch) {
// array<array<i32, 2u>, 2u>(array<i32, 3u>(), array<i32, 2u>());
- SetSource(Source::Location({12, 34}));
- auto* e0 = array<i32, 3>();
- auto* e1 = array<i32, 2>();
- auto* t = Construct(ty.array(ty.array<i32, 2>(), 2_i), e0, e1);
+ auto* t = array(Source{{12, 34}}, ty.array<i32, 2>(), 2_i, array<i32, 3>(), array<i32, 2>());
WrapInFunction(t);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- "12:34 error: type in array constructor does not match array type: "
- "expected 'array<i32, 2>', found 'array<i32, 3>'");
+ R"(error: 'array<i32, 3>' cannot be used to construct an array of 'array<i32, 2>')");
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_ArrayOfArray_SubElemTypeMismatch) {
+TEST_F(ResolverTypeConstructorValidationTest, InferredArrayOfArray_SubElemSizeMismatch) {
+ // array<array<i32, 2u>, 2u>(array<i32, 3u>(), array<i32, 2u>());
+ auto* t = array(Source{{12, 34}}, nullptr, nullptr, array<i32, 3>(), array<i32, 2>());
+ WrapInFunction(t);
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(),
+ R"(12:34 error: cannot infer common array element type from constructor arguments
+note: argument 0 is of type 'array<i32, 3>'
+note: argument 1 is of type 'array<i32, 2>')");
+}
+
+TEST_F(ResolverTypeConstructorValidationTest, ArrayOfArray_SubElemTypeMismatch) {
// array<array<i32, 2u>, 2u>(array<i32, 2u>(), array<u32, 2u>());
- auto* e0 = array<i32, 2>();
- SetSource(Source::Location({12, 34}));
- auto* e1 = array<u32, 2>();
- auto* t = Construct(ty.array(ty.array<i32, 2>(), 2_i), e0, e1);
+ auto* t = array(Source{{12, 34}}, ty.array<i32, 2>(), 2_i, array<i32, 2>(), array<u32, 2>());
WrapInFunction(t);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- "12:34 error: type in array constructor does not match array type: "
- "expected 'array<i32, 2>', found 'array<u32, 2>'");
+ R"(error: 'array<u32, 2>' cannot be used to construct an array of 'array<i32, 2>')");
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Array_TooFewElements) {
+TEST_F(ResolverTypeConstructorValidationTest, InferredArrayOfArray_SubElemTypeMismatch) {
+ // array<array<i32, 2u>, 2u>(array<i32, 2u>(), array<u32, 2u>());
+ auto* t = array(Source{{12, 34}}, nullptr, nullptr, array<i32, 2>(), array<u32, 2>());
+ WrapInFunction(t);
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(),
+ R"(12:34 error: cannot infer common array element type from constructor arguments
+note: argument 0 is of type 'array<i32, 2>'
+note: argument 1 is of type 'array<u32, 2>')");
+}
+
+TEST_F(ResolverTypeConstructorValidationTest, Array_TooFewElements) {
// array<i32, 4u>(1i, 2i, 3i);
SetSource(Source::Location({12, 34}));
auto* tc = array<i32, 4>(Expr(1_i), Expr(2_i), Expr(3_i));
@@ -637,7 +855,7 @@
"12:34 error: array constructor has too few elements: expected 4, found 3");
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Array_TooManyElements) {
+TEST_F(ResolverTypeConstructorValidationTest, Array_TooManyElements) {
// array<i32, 4u>(1i, 2i, 3i, 4i, 5i);
SetSource(Source::Location({12, 34}));
auto* tc = array<i32, 4>(Expr(1_i), Expr(2_i), Expr(3_i), Expr(4_i), Expr(5_i));
@@ -650,29 +868,29 @@
"found 5");
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Array_Runtime) {
+TEST_F(ResolverTypeConstructorValidationTest, Array_Runtime) {
// array<i32>(1i);
- auto* tc = array(ty.i32(), nullptr, Expr(Source{{12, 34}}, 1_i));
+ auto* tc = array(Source{{12, 34}}, ty.i32(), nullptr, Expr(1_i));
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "error: cannot init a runtime-sized array");
+ EXPECT_EQ(r()->error(), "12:34 error: cannot construct a runtime-sized array");
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Array_RuntimeZeroValue) {
+TEST_F(ResolverTypeConstructorValidationTest, Array_RuntimeZeroValue) {
// array<i32>();
- auto* tc = array(ty.i32(), nullptr);
+ auto* tc = array(Source{{12, 34}}, ty.i32(), nullptr);
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "error: cannot init a runtime-sized array");
+ EXPECT_EQ(r()->error(), "12:34 error: cannot construct a runtime-sized array");
}
} // namespace ArrayConstructor
namespace ScalarConstructor {
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Construct_i32_Success) {
+TEST_F(ResolverTypeConstructorValidationTest, I32_Success) {
auto* expr = Construct<i32>(Expr(123_i));
WrapInFunction(expr);
@@ -690,7 +908,7 @@
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::I32>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Construct_u32_Success) {
+TEST_F(ResolverTypeConstructorValidationTest, U32_Success) {
auto* expr = Construct<u32>(Expr(123_u));
WrapInFunction(expr);
@@ -708,7 +926,7 @@
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::U32>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Construct_f32_Success) {
+TEST_F(ResolverTypeConstructorValidationTest, F32_Success) {
auto* expr = Construct<f32>(Expr(1.23_f));
WrapInFunction(expr);
@@ -726,7 +944,7 @@
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::F32>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Construct_f16_Success) {
+TEST_F(ResolverTypeConstructorValidationTest, F16_Success) {
Enable(ast::Extension::kF16);
auto* expr = Construct<f16>(Expr(1.5_h));
@@ -746,7 +964,7 @@
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::F16>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Convert_f32_to_i32_Success) {
+TEST_F(ResolverTypeConstructorValidationTest, Convert_f32_to_i32_Success) {
auto* expr = Construct<i32>(1.23_f);
WrapInFunction(expr);
@@ -764,7 +982,7 @@
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::F32>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Convert_i32_to_u32_Success) {
+TEST_F(ResolverTypeConstructorValidationTest, Convert_i32_to_u32_Success) {
auto* expr = Construct<u32>(123_i);
WrapInFunction(expr);
@@ -782,7 +1000,7 @@
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::I32>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Convert_u32_to_f16_Success) {
+TEST_F(ResolverTypeConstructorValidationTest, Convert_u32_to_f16_Success) {
Enable(ast::Extension::kF16);
auto* expr = Construct<f16>(123_u);
@@ -802,7 +1020,7 @@
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::U32>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Convert_f16_to_f32_Success) {
+TEST_F(ResolverTypeConstructorValidationTest, Convert_f16_to_f32_Success) {
Enable(ast::Extension::kF16);
auto* expr = Construct<f32>(123_h);
@@ -826,81 +1044,74 @@
namespace VectorConstructor {
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec2F32_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec2<f32>(), 1_i, 2_f));
+TEST_F(ResolverTypeConstructorValidationTest, Vec2F32_Error_ScalarArgumentTypeMismatch) {
+ WrapInFunction(vec2<f32>(Source{{12, 34}}, 1_i, 2_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec2<f32>(i32, f32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec2F16_Error_ScalarArgumentTypeMismatch) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec2F16_Error_ScalarArgumentTypeMismatch) {
Enable(ast::Extension::kF16);
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec2<f16>(), 1_h, 2_f));
+ WrapInFunction(vec2<f16>(Source{{12, 34}}, 1_h, 2_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec2<f16>(f16, f32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec2U32_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec2<u32>(), 1_u, 2_i));
+TEST_F(ResolverTypeConstructorValidationTest, Vec2U32_Error_ScalarArgumentTypeMismatch) {
+ WrapInFunction(vec2<u32>(Source{{12, 34}}, 1_u, 2_i));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec2<u32>(u32, i32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec2I32_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec2<i32>(), 1_u, 2_i));
+TEST_F(ResolverTypeConstructorValidationTest, Vec2I32_Error_ScalarArgumentTypeMismatch) {
+ WrapInFunction(vec2<i32>(Source{{12, 34}}, 1_u, 2_i));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec2<i32>(u32, i32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec2Bool_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec2<bool>(), true, 1_i));
+TEST_F(ResolverTypeConstructorValidationTest, Vec2Bool_Error_ScalarArgumentTypeMismatch) {
+ WrapInFunction(vec2<bool>(Source{{12, 34}}, true, 1_i));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec2<bool>(bool, i32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec2_Error_Vec3ArgumentCardinalityTooLarge) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec2<f32>(), vec3<f32>()));
+TEST_F(ResolverTypeConstructorValidationTest, Vec2_Error_Vec3ArgumentCardinalityTooLarge) {
+ WrapInFunction(vec2<f32>(Source{{12, 34}}, vec3<f32>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec2<f32>(vec3<f32>)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec2_Error_Vec4ArgumentCardinalityTooLarge) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec2<f32>(), vec4<f32>()));
+TEST_F(ResolverTypeConstructorValidationTest, Vec2_Error_Vec4ArgumentCardinalityTooLarge) {
+ WrapInFunction(vec2<f32>(Source{{12, 34}}, vec4<f32>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec2<f32>(vec4<f32>)"));
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec2_Error_TooManyArgumentsScalar) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec2<f32>(), 1_f, 2_f, 3_f));
+TEST_F(ResolverTypeConstructorValidationTest, Vec2_Error_TooManyArgumentsScalar) {
+ WrapInFunction(vec2<f32>(Source{{12, 34}}, 1_f, 2_f, 3_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec2<f32>(f32, f32, f32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec2_Error_TooManyArgumentsVector) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec2<f32>(), vec2<f32>(), vec2<f32>()));
+TEST_F(ResolverTypeConstructorValidationTest, Vec2_Error_TooManyArgumentsVector) {
+ WrapInFunction(vec2<f32>(Source{{12, 34}}, vec2<f32>(), vec2<f32>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -908,24 +1119,23 @@
HasSubstr("12:34 error: no matching constructor for vec2<f32>(vec2<f32>, vec2<f32>)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec2_Error_TooManyArgumentsVectorAndScalar) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec2<f32>(), vec2<f32>(), 1_f));
+TEST_F(ResolverTypeConstructorValidationTest, Vec2_Error_TooManyArgumentsVectorAndScalar) {
+ WrapInFunction(vec2<f32>(Source{{12, 34}}, vec2<f32>(), 1_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec2<f32>(vec2<f32>, f32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec2_Error_InvalidArgumentType) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec2<f32>(), mat2x2<f32>()));
+TEST_F(ResolverTypeConstructorValidationTest, Vec2_Error_InvalidArgumentType) {
+ WrapInFunction(vec2<f32>(Source{{12, 34}}, mat2x2<f32>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec2<f32>(mat2x2<f32>)"));
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec2_Success_ZeroValue) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec2_Success_ZeroValue) {
auto* tc = vec2<f32>();
WrapInFunction(tc);
@@ -944,7 +1154,7 @@
ASSERT_EQ(ctor->Parameters().Length(), 0u);
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec2F32_Success_Scalar) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec2F32_Success_Scalar) {
auto* tc = vec2<f32>(1_f, 1_f);
WrapInFunction(tc);
@@ -965,7 +1175,7 @@
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::F32>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec2F16_Success_Scalar) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec2F16_Success_Scalar) {
Enable(ast::Extension::kF16);
auto* tc = vec2<f16>(1_h, 1_h);
@@ -988,7 +1198,7 @@
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::F16>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec2U32_Success_Scalar) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec2U32_Success_Scalar) {
auto* tc = vec2<u32>(1_u, 1_u);
WrapInFunction(tc);
@@ -1009,7 +1219,7 @@
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::U32>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec2I32_Success_Scalar) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec2I32_Success_Scalar) {
auto* tc = vec2<i32>(1_i, 1_i);
WrapInFunction(tc);
@@ -1030,7 +1240,7 @@
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::I32>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec2Bool_Success_Scalar) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec2Bool_Success_Scalar) {
auto* tc = vec2<bool>(true, false);
WrapInFunction(tc);
@@ -1051,7 +1261,7 @@
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::Bool>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec2_Success_Identity) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec2_Success_Identity) {
auto* tc = vec2<f32>(vec2<f32>());
WrapInFunction(tc);
@@ -1071,7 +1281,7 @@
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::Vector>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec2_Success_Vec2TypeConversion) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec2_Success_Vec2TypeConversion) {
auto* tc = vec2<f32>(vec2<i32>());
WrapInFunction(tc);
@@ -1091,72 +1301,66 @@
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::Vector>());
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec3F32_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec3<f32>(), 1_f, 2_f, 3_i));
+TEST_F(ResolverTypeConstructorValidationTest, Vec3F32_Error_ScalarArgumentTypeMismatch) {
+ WrapInFunction(vec3<f32>(Source{{12, 34}}, 1_f, 2_f, 3_i));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec3<f32>(f32, f32, i32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec3F16_Error_ScalarArgumentTypeMismatch) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec3F16_Error_ScalarArgumentTypeMismatch) {
Enable(ast::Extension::kF16);
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec3<f16>(), 1_h, 2_h, 3_f));
+ WrapInFunction(vec3<f16>(Source{{12, 34}}, 1_h, 2_h, 3_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec3<f16>(f16, f16, f32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec3U32_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec3<u32>(), 1_u, 2_i, 3_u));
+TEST_F(ResolverTypeConstructorValidationTest, Vec3U32_Error_ScalarArgumentTypeMismatch) {
+ WrapInFunction(vec3<u32>(Source{{12, 34}}, 1_u, 2_i, 3_u));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec3<u32>(u32, i32, u32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec3I32_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec3<i32>(), 1_i, 2_u, 3_i));
+TEST_F(ResolverTypeConstructorValidationTest, Vec3I32_Error_ScalarArgumentTypeMismatch) {
+ WrapInFunction(vec3<i32>(Source{{12, 34}}, 1_i, 2_u, 3_i));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec3<i32>(i32, u32, i32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec3Bool_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec3<bool>(), false, 1_i, true));
+TEST_F(ResolverTypeConstructorValidationTest, Vec3Bool_Error_ScalarArgumentTypeMismatch) {
+ WrapInFunction(vec3<bool>(Source{{12, 34}}, false, 1_i, true));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec3<bool>(bool, i32, bool)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec3_Error_Vec4ArgumentCardinalityTooLarge) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec3<f32>(), vec4<f32>()));
+TEST_F(ResolverTypeConstructorValidationTest, Vec3_Error_Vec4ArgumentCardinalityTooLarge) {
+ WrapInFunction(vec3<f32>(Source{{12, 34}}, vec4<f32>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec3<f32>(vec4<f32>)"));
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3_Error_TooFewArgumentsScalar) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec3<f32>(), 1_f, 2_f));
+TEST_F(ResolverTypeConstructorValidationTest, Vec3_Error_TooFewArgumentsScalar) {
+ WrapInFunction(vec3<f32>(Source{{12, 34}}, 1_f, 2_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec3<f32>(f32, f32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3_Error_TooManyArgumentsScalar) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec3<f32>(), 1_f, 2_f, 3_f, 4_f));
+TEST_F(ResolverTypeConstructorValidationTest, Vec3_Error_TooManyArgumentsScalar) {
+ WrapInFunction(vec3<f32>(Source{{12, 34}}, 1_f, 2_f, 3_f, 4_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1164,16 +1368,16 @@
HasSubstr("12:34 error: no matching constructor for vec3<f32>(f32, f32, f32, f32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3_Error_TooFewArgumentsVec2) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec3<f32>(), vec2<f32>()));
+TEST_F(ResolverTypeConstructorValidationTest, Vec3_Error_TooFewArgumentsVec2) {
+ WrapInFunction(vec3<f32>(Source{{12, 34}}, vec2<f32>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec3<f32>(vec2<f32>)"));
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3_Error_TooManyArgumentsVec2) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec3<f32>(), vec2<f32>(), vec2<f32>()));
+TEST_F(ResolverTypeConstructorValidationTest, Vec3_Error_TooManyArgumentsVec2) {
+ WrapInFunction(vec3<f32>(Source{{12, 34}}, vec2<f32>(), vec2<f32>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1181,9 +1385,8 @@
HasSubstr("12:34 error: no matching constructor for vec3<f32>(vec2<f32>, vec2<f32>)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec3_Error_TooManyArgumentsVec2AndScalar) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec3<f32>(), vec2<f32>(), 1_f, 1_f));
+TEST_F(ResolverTypeConstructorValidationTest, Vec3_Error_TooManyArgumentsVec2AndScalar) {
+ WrapInFunction(vec3<f32>(Source{{12, 34}}, vec2<f32>(), 1_f, 1_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1191,23 +1394,23 @@
HasSubstr("12:34 error: no matching constructor for vec3<f32>(vec2<f32>, f32, f32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3_Error_TooManyArgumentsVec3) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec3<f32>(), vec3<f32>(), 1_f));
+TEST_F(ResolverTypeConstructorValidationTest, Vec3_Error_TooManyArgumentsVec3) {
+ WrapInFunction(vec3<f32>(Source{{12, 34}}, vec3<f32>(), 1_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec3<f32>(vec3<f32>, f32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3_Error_InvalidArgumentType) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec3<f32>(), mat2x2<f32>()));
+TEST_F(ResolverTypeConstructorValidationTest, Vec3_Error_InvalidArgumentType) {
+ WrapInFunction(vec3<f32>(Source{{12, 34}}, mat2x2<f32>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec3<f32>(mat2x2<f32>)"));
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3_Success_ZeroValue) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec3_Success_ZeroValue) {
auto* tc = vec3<f32>();
WrapInFunction(tc);
@@ -1226,7 +1429,7 @@
ASSERT_EQ(ctor->Parameters().Length(), 0u);
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3F32_Success_Scalar) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec3F32_Success_Scalar) {
auto* tc = vec3<f32>(1_f, 1_f, 1_f);
WrapInFunction(tc);
@@ -1248,7 +1451,7 @@
EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::F32>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3F16_Success_Scalar) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec3F16_Success_Scalar) {
Enable(ast::Extension::kF16);
auto* tc = vec3<f16>(1_h, 1_h, 1_h);
@@ -1272,7 +1475,7 @@
EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::F16>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3U32_Success_Scalar) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec3U32_Success_Scalar) {
auto* tc = vec3<u32>(1_u, 1_u, 1_u);
WrapInFunction(tc);
@@ -1294,7 +1497,7 @@
EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::U32>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3I32_Success_Scalar) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec3I32_Success_Scalar) {
auto* tc = vec3<i32>(1_i, 1_i, 1_i);
WrapInFunction(tc);
@@ -1316,7 +1519,7 @@
EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::I32>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3Bool_Success_Scalar) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec3Bool_Success_Scalar) {
auto* tc = vec3<bool>(true, false, true);
WrapInFunction(tc);
@@ -1338,7 +1541,7 @@
EXPECT_TRUE(ctor->Parameters()[2]->Type()->Is<sem::Bool>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3_Success_Vec2AndScalar) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec3_Success_Vec2AndScalar) {
auto* tc = vec3<f32>(vec2<f32>(), 1_f);
WrapInFunction(tc);
@@ -1359,7 +1562,7 @@
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::F32>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3_Success_ScalarAndVec2) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec3_Success_ScalarAndVec2) {
auto* tc = vec3<f32>(1_f, vec2<f32>());
WrapInFunction(tc);
@@ -1380,7 +1583,7 @@
EXPECT_TRUE(ctor->Parameters()[1]->Type()->Is<sem::Vector>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3_Success_Identity) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec3_Success_Identity) {
auto* tc = vec3<f32>(vec3<f32>());
WrapInFunction(tc);
@@ -1400,7 +1603,7 @@
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::Vector>());
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec3_Success_Vec3TypeConversion) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec3_Success_Vec3TypeConversion) {
auto* tc = vec3<f32>(vec3<i32>());
WrapInFunction(tc);
@@ -1420,9 +1623,8 @@
EXPECT_TRUE(ctor->Parameters()[0]->Type()->Is<sem::Vector>());
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec4F32_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec4<f32>(), 1_f, 1_f, 1_i, 1_f));
+TEST_F(ResolverTypeConstructorValidationTest, Vec4F32_Error_ScalarArgumentTypeMismatch) {
+ WrapInFunction(vec4<f32>(Source{{12, 34}}, 1_f, 1_f, 1_i, 1_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1430,11 +1632,10 @@
HasSubstr("12:34 error: no matching constructor for vec4<f32>(f32, f32, i32, f32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec4F16_Error_ScalarArgumentTypeMismatch) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec4F16_Error_ScalarArgumentTypeMismatch) {
Enable(ast::Extension::kF16);
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec4<f16>(), 1_h, 1_h, 1_f, 1_h));
+ WrapInFunction(vec4<f16>(Source{{12, 34}}, 1_h, 1_h, 1_f, 1_h));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1442,9 +1643,8 @@
HasSubstr("12:34 error: no matching constructor for vec4<f16>(f16, f16, f32, f16)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec4U32_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec4<u32>(), 1_u, 1_u, 1_i, 1_u));
+TEST_F(ResolverTypeConstructorValidationTest, Vec4U32_Error_ScalarArgumentTypeMismatch) {
+ WrapInFunction(vec4<u32>(Source{{12, 34}}, 1_u, 1_u, 1_i, 1_u));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1452,9 +1652,8 @@
HasSubstr("12:34 error: no matching constructor for vec4<u32>(u32, u32, i32, u32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec4I32_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec4<i32>(), 1_i, 1_i, 1_u, 1_i));
+TEST_F(ResolverTypeConstructorValidationTest, Vec4I32_Error_ScalarArgumentTypeMismatch) {
+ WrapInFunction(vec4<i32>(Source{{12, 34}}, 1_i, 1_i, 1_u, 1_i));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1462,9 +1661,8 @@
HasSubstr("12:34 error: no matching constructor for vec4<i32>(i32, i32, u32, i32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec4Bool_Error_ScalarArgumentTypeMismatch) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec4<bool>(), true, false, 1_i, true));
+TEST_F(ResolverTypeConstructorValidationTest, Vec4Bool_Error_ScalarArgumentTypeMismatch) {
+ WrapInFunction(vec4<bool>(Source{{12, 34}}, true, false, 1_i, true));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1472,16 +1670,16 @@
HasSubstr("12:34 error: no matching constructor for vec4<bool>(bool, bool, i32, bool)"));
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec4_Error_TooFewArgumentsScalar) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec4<f32>(), 1_f, 2_f, 3_f));
+TEST_F(ResolverTypeConstructorValidationTest, Vec4_Error_TooFewArgumentsScalar) {
+ WrapInFunction(vec4<f32>(Source{{12, 34}}, 1_f, 2_f, 3_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec4<f32>(f32, f32, f32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec4_Error_TooManyArgumentsScalar) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec4<f32>(), 1_f, 2_f, 3_f, 4_f, 5_f));
+TEST_F(ResolverTypeConstructorValidationTest, Vec4_Error_TooManyArgumentsScalar) {
+ WrapInFunction(vec4<f32>(Source{{12, 34}}, 1_f, 2_f, 3_f, 4_f, 5_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1489,18 +1687,16 @@
HasSubstr("12:34 error: no matching constructor for vec4<f32>(f32, f32, f32, f32, f32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec4_Error_TooFewArgumentsVec2AndScalar) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec4<f32>(), vec2<f32>(), 1_f));
+TEST_F(ResolverTypeConstructorValidationTest, Vec4_Error_TooFewArgumentsVec2AndScalar) {
+ WrapInFunction(vec4<f32>(Source{{12, 34}}, vec2<f32>(), 1_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec4<f32>(vec2<f32>, f32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec4_Error_TooManyArgumentsVec2AndScalars) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec4<f32>(), vec2<f32>(), 1_f, 2_f, 3_f));
+TEST_F(ResolverTypeConstructorValidationTest, Vec4_Error_TooManyArgumentsVec2AndScalars) {
+ WrapInFunction(vec4<f32>(Source{{12, 34}}, vec2<f32>(), 1_f, 2_f, 3_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1508,9 +1704,8 @@
HasSubstr("12:34 error: no matching constructor for vec4<f32>(vec2<f32>, f32, f32, f32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec4_Error_TooManyArgumentsVec2Vec2Scalar) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec4<f32>(), vec2<f32>(), vec2<f32>(), 1_f));
+TEST_F(ResolverTypeConstructorValidationTest, Vec4_Error_TooManyArgumentsVec2Vec2Scalar) {
+ WrapInFunction(vec4<f32>(Source{{12, 34}}, vec2<f32>(), vec2<f32>(), 1_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1518,10 +1713,8 @@
HasSubstr("12:34 error: no matching constructor for vec4<f32>(vec2<f32>, vec2<f32>, f32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec4_Error_TooManyArgumentsVec2Vec2Vec2) {
- WrapInFunction(
- Construct(Source{{12, 34}}, ty.vec4<f32>(), vec2<f32>(), vec2<f32>(), vec2<f32>()));
+TEST_F(ResolverTypeConstructorValidationTest, Vec4_Error_TooManyArgumentsVec2Vec2Vec2) {
+ WrapInFunction(vec4<f32>(Source{{12, 34}}, vec2<f32>(), vec2<f32>(), vec2<f32>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1530,17 +1723,16 @@
"12:34 error: no matching constructor for vec4<f32>(vec2<f32>, vec2<f32>, vec2<f32>)"));
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec4_Error_TooFewArgumentsVec3) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec4<f32>(), vec3<f32>()));
+TEST_F(ResolverTypeConstructorValidationTest, Vec4_Error_TooFewArgumentsVec3) {
+ WrapInFunction(vec4<f32>(Source{{12, 34}}, vec3<f32>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec4<f32>(vec3<f32>)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec4_Error_TooManyArgumentsVec3AndScalars) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec4<f32>(), vec3<f32>(), 1_f, 2_f));
+TEST_F(ResolverTypeConstructorValidationTest, Vec4_Error_TooManyArgumentsVec3AndScalars) {
+ WrapInFunction(vec4<f32>(Source{{12, 34}}, vec3<f32>(), 1_f, 2_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1548,9 +1740,8 @@
HasSubstr("12:34 error: no matching constructor for vec4<f32>(vec3<f32>, f32, f32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec4_Error_TooManyArgumentsVec3AndVec2) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec4<f32>(), vec3<f32>(), vec2<f32>()));
+TEST_F(ResolverTypeConstructorValidationTest, Vec4_Error_TooManyArgumentsVec3AndVec2) {
+ WrapInFunction(vec4<f32>(Source{{12, 34}}, vec3<f32>(), vec2<f32>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1558,9 +1749,8 @@
HasSubstr("12:34 error: no matching constructor for vec4<f32>(vec3<f32>, vec2<f32>)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec4_Error_TooManyArgumentsVec2AndVec3) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec4<f32>(), vec2<f32>(), vec3<f32>()));
+TEST_F(ResolverTypeConstructorValidationTest, Vec4_Error_TooManyArgumentsVec2AndVec3) {
+ WrapInFunction(vec4<f32>(Source{{12, 34}}, vec2<f32>(), vec3<f32>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1568,9 +1758,8 @@
HasSubstr("12:34 error: no matching constructor for vec4<f32>(vec2<f32>, vec3<f32>)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vec4_Error_TooManyArgumentsVec3AndVec3) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec4<f32>(), vec3<f32>(), vec3<f32>()));
+TEST_F(ResolverTypeConstructorValidationTest, Vec4_Error_TooManyArgumentsVec3AndVec3) {
+ WrapInFunction(vec4<f32>(Source{{12, 34}}, vec3<f32>(), vec3<f32>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(
@@ -1578,15 +1767,15 @@
HasSubstr("12:34 error: no matching constructor for vec4<f32>(vec3<f32>, vec3<f32>)"));
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec4_Error_InvalidArgumentType) {
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec4<f32>(), mat2x2<f32>()));
+TEST_F(ResolverTypeConstructorValidationTest, Vec4_Error_InvalidArgumentType) {
+ WrapInFunction(vec4<f32>(Source{{12, 34}}, mat2x2<f32>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec4<f32>(mat2x2<f32>)"));
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec4_Success_ZeroValue) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec4_Success_ZeroValue) {
auto* tc = vec4<f32>();
WrapInFunction(tc);
@@ -1598,7 +1787,7 @@
EXPECT_EQ(TypeOf(tc)->As<sem::Vector>()->Width(), 4u);
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec4F32_Success_Scalar) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec4F32_Success_Scalar) {
auto* tc = vec4<f32>(1_f, 1_f, 1_f, 1_f);
WrapInFunction(tc);
@@ -1610,7 +1799,7 @@
EXPECT_EQ(TypeOf(tc)->As<sem::Vector>()->Width(), 4u);
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec4F16_Success_Scalar) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec4F16_Success_Scalar) {
Enable(ast::Extension::kF16);
auto* tc = vec4<f16>(1_h, 1_h, 1_h, 1_h);
@@ -1624,7 +1813,7 @@
EXPECT_EQ(TypeOf(tc)->As<sem::Vector>()->Width(), 4u);
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec4U32_Success_Scalar) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec4U32_Success_Scalar) {
auto* tc = vec4<u32>(1_u, 1_u, 1_u, 1_u);
WrapInFunction(tc);
@@ -1636,7 +1825,7 @@
EXPECT_EQ(TypeOf(tc)->As<sem::Vector>()->Width(), 4u);
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec4I32_Success_Scalar) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec4I32_Success_Scalar) {
auto* tc = vec4<i32>(1_i, 1_i, 1_i, 1_i);
WrapInFunction(tc);
@@ -1648,7 +1837,7 @@
EXPECT_EQ(TypeOf(tc)->As<sem::Vector>()->Width(), 4u);
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec4Bool_Success_Scalar) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec4Bool_Success_Scalar) {
auto* tc = vec4<bool>(true, false, true, false);
WrapInFunction(tc);
@@ -1660,7 +1849,7 @@
EXPECT_EQ(TypeOf(tc)->As<sem::Vector>()->Width(), 4u);
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec4_Success_Vec2ScalarScalar) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec4_Success_Vec2ScalarScalar) {
auto* tc = vec4<f32>(vec2<f32>(), 1_f, 1_f);
WrapInFunction(tc);
@@ -1672,7 +1861,7 @@
EXPECT_EQ(TypeOf(tc)->As<sem::Vector>()->Width(), 4u);
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec4_Success_ScalarVec2Scalar) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec4_Success_ScalarVec2Scalar) {
auto* tc = vec4<f32>(1_f, vec2<f32>(), 1_f);
WrapInFunction(tc);
@@ -1684,7 +1873,7 @@
EXPECT_EQ(TypeOf(tc)->As<sem::Vector>()->Width(), 4u);
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec4_Success_ScalarScalarVec2) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec4_Success_ScalarScalarVec2) {
auto* tc = vec4<f32>(1_f, 1_f, vec2<f32>());
WrapInFunction(tc);
@@ -1696,7 +1885,7 @@
EXPECT_EQ(TypeOf(tc)->As<sem::Vector>()->Width(), 4u);
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec4_Success_Vec2AndVec2) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec4_Success_Vec2AndVec2) {
auto* tc = vec4<f32>(vec2<f32>(), vec2<f32>());
WrapInFunction(tc);
@@ -1708,7 +1897,7 @@
EXPECT_EQ(TypeOf(tc)->As<sem::Vector>()->Width(), 4u);
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec4_Success_Vec3AndScalar) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec4_Success_Vec3AndScalar) {
auto* tc = vec4<f32>(vec3<f32>(), 1_f);
WrapInFunction(tc);
@@ -1720,7 +1909,7 @@
EXPECT_EQ(TypeOf(tc)->As<sem::Vector>()->Width(), 4u);
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec4_Success_ScalarAndVec3) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec4_Success_ScalarAndVec3) {
auto* tc = vec4<f32>(1_f, vec3<f32>());
WrapInFunction(tc);
@@ -1732,7 +1921,7 @@
EXPECT_EQ(TypeOf(tc)->As<sem::Vector>()->Width(), 4u);
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec4_Success_Identity) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec4_Success_Identity) {
auto* tc = vec4<f32>(vec4<f32>());
WrapInFunction(tc);
@@ -1744,7 +1933,7 @@
EXPECT_EQ(TypeOf(tc)->As<sem::Vector>()->Width(), 4u);
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vec4_Success_Vec4TypeConversion) {
+TEST_F(ResolverTypeConstructorValidationTest, Vec4_Success_Vec4TypeConversion) {
auto* tc = vec4<f32>(vec4<i32>());
WrapInFunction(tc);
@@ -1756,10 +1945,9 @@
EXPECT_EQ(TypeOf(tc)->As<sem::Vector>()->Width(), 4u);
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_NestedVectorConstructors_InnerError) {
+TEST_F(ResolverTypeConstructorValidationTest, NestedVectorConstructors_InnerError) {
WrapInFunction(vec4<f32>(vec4<f32>(1_f, 1_f, //
- Construct(Source{{12, 34}}, ty.vec3<f32>(), 1_f, 1_f)),
+ vec3<f32>(Source{{12, 34}}, 1_f, 1_f)),
1_f));
EXPECT_FALSE(r()->Resolve());
@@ -1767,7 +1955,7 @@
HasSubstr("12:34 error: no matching constructor for vec3<f32>(f32, f32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_NestedVectorConstructors_Success) {
+TEST_F(ResolverTypeConstructorValidationTest, NestedVectorConstructors_Success) {
auto* tc = vec4<f32>(vec3<f32>(vec2<f32>(1_f, 1_f), 1_f), 1_f);
WrapInFunction(tc);
@@ -1779,18 +1967,18 @@
EXPECT_EQ(TypeOf(tc)->As<sem::Vector>()->Width(), 4u);
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vector_Alias_Argument_Error) {
+TEST_F(ResolverTypeConstructorValidationTest, Vector_Alias_Argument_Error) {
auto* alias = Alias("UnsignedInt", ty.u32());
GlobalVar("uint_var", ty.Of(alias), ast::StorageClass::kPrivate);
- auto* tc = Construct(Source{{12, 34}}, ty.vec2<f32>(), "uint_var");
+ auto* tc = vec2<f32>(Source{{12, 34}}, "uint_var");
WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), HasSubstr("12:34 error: no matching constructor for vec2<f32>(u32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vector_Alias_Argument_Success) {
+TEST_F(ResolverTypeConstructorValidationTest, Vector_Alias_Argument_Success) {
auto* f32_alias = Alias("Float32", ty.f32());
auto* vec2_alias = Alias("VectorFloat2", ty.vec2<f32>());
GlobalVar("my_f32", ty.Of(f32_alias), ast::StorageClass::kPrivate);
@@ -1801,7 +1989,7 @@
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vector_ElementTypeAlias_Error) {
+TEST_F(ResolverTypeConstructorValidationTest, Vector_ElementTypeAlias_Error) {
auto* f32_alias = Alias("Float32", ty.f32());
// vec2<Float32>(1.0f, 1u)
@@ -1813,7 +2001,7 @@
HasSubstr("12:34 error: no matching constructor for vec2<f32>(f32, u32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Vector_ElementTypeAlias_Success) {
+TEST_F(ResolverTypeConstructorValidationTest, Vector_ElementTypeAlias_Success) {
auto* f32_alias = Alias("Float32", ty.f32());
// vec2<Float32>(1.0f, 1.0f)
@@ -1824,21 +2012,19 @@
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vector_ArgumentElementTypeAlias_Error) {
+TEST_F(ResolverTypeConstructorValidationTest, Vector_ArgumentElementTypeAlias_Error) {
auto* f32_alias = Alias("Float32", ty.f32());
// vec3<u32>(vec<Float32>(), 1.0f)
auto* vec_type = ty.vec(ty.Of(f32_alias), 2);
- WrapInFunction(Construct(Source{{12, 34}}, ty.vec3<u32>(), Construct(vec_type), 1_f));
+ WrapInFunction(vec3<u32>(Source{{12, 34}}, Construct(vec_type), 1_f));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(),
HasSubstr("12:34 error: no matching constructor for vec3<u32>(vec2<f32>, f32)"));
}
-TEST_F(ResolverTypeConstructorValidationTest,
- Expr_Constructor_Vector_ArgumentElementTypeAlias_Success) {
+TEST_F(ResolverTypeConstructorValidationTest, Vector_ArgumentElementTypeAlias_Success) {
auto* f32_alias = Alias("Float32", ty.f32());
// vec3<f32>(vec<Float32>(), 1.0f)
@@ -2278,7 +2464,7 @@
using MatrixConstructorTest = ResolverTestWithParam<MatrixParams>;
-TEST_P(MatrixConstructorTest, Expr_ColumnConstructor_Error_TooFewArguments) {
+TEST_P(MatrixConstructorTest, ColumnConstructor_Error_TooFewArguments) {
// matNxM<f32>(vecM<f32>(), ...); with N - 1 arguments
// matNxM<f16>(vecM<f16>(), ...); with N - 1 arguments
@@ -2307,7 +2493,7 @@
MatrixStr(param) + "(" + args_tys.str() + ")"));
}
-TEST_P(MatrixConstructorTest, Expr_ElementConstructor_Error_TooFewArguments) {
+TEST_P(MatrixConstructorTest, ElementConstructor_Error_TooFewArguments) {
// matNxM<f32>(f32,...,f32); with N*M - 1 arguments
// matNxM<f16>(f16,...,f16); with N*M - 1 arguments
@@ -2335,7 +2521,7 @@
MatrixStr(param) + "(" + args_tys.str() + ")"));
}
-TEST_P(MatrixConstructorTest, Expr_ColumnConstructor_Error_TooManyArguments) {
+TEST_P(MatrixConstructorTest, ColumnConstructor_Error_TooManyArguments) {
// matNxM<f32>(vecM<f32>(), ...); with N + 1 arguments
// matNxM<f16>(vecM<f16>(), ...); with N + 1 arguments
@@ -2364,7 +2550,7 @@
MatrixStr(param) + "(" + args_tys.str() + ")"));
}
-TEST_P(MatrixConstructorTest, Expr_ElementConstructor_Error_TooManyArguments) {
+TEST_P(MatrixConstructorTest, ElementConstructor_Error_TooManyArguments) {
// matNxM<f32>(f32,...,f32); with N*M + 1 arguments
// matNxM<f16>(f16,...,f16); with N*M + 1 arguments
@@ -2392,7 +2578,7 @@
MatrixStr(param) + "(" + args_tys.str() + ")"));
}
-TEST_P(MatrixConstructorTest, Expr_ColumnConstructor_Error_InvalidArgumentType) {
+TEST_P(MatrixConstructorTest, ColumnConstructor_Error_InvalidArgumentType) {
// matNxM<f32>(vec<u32>, vec<u32>, ...); N arguments
// matNxM<f16>(vec<u32>, vec<u32>, ...); N arguments
@@ -2420,7 +2606,7 @@
MatrixStr(param) + "(" + args_tys.str() + ")"));
}
-TEST_P(MatrixConstructorTest, Expr_ElementConstructor_Error_InvalidArgumentType) {
+TEST_P(MatrixConstructorTest, ElementConstructor_Error_InvalidArgumentType) {
// matNxM<f32>(u32, u32, ...); N*M arguments
// matNxM<f16>(u32, u32, ...); N*M arguments
@@ -2447,7 +2633,7 @@
MatrixStr(param) + "(" + args_tys.str() + ")"));
}
-TEST_P(MatrixConstructorTest, Expr_ColumnConstructor_Error_TooFewRowsInVectorArgument) {
+TEST_P(MatrixConstructorTest, ColumnConstructor_Error_TooFewRowsInVectorArgument) {
// matNxM<f32>(vecM<f32>(),...,vecM-1<f32>());
// matNxM<f16>(vecM<f16>(),...,vecM-1<f32>());
@@ -2485,7 +2671,7 @@
MatrixStr(param) + "(" + args_tys.str() + ")"));
}
-TEST_P(MatrixConstructorTest, Expr_ColumnConstructor_Error_TooManyRowsInVectorArgument) {
+TEST_P(MatrixConstructorTest, ColumnConstructor_Error_TooManyRowsInVectorArgument) {
// matNxM<f32>(vecM<f32>(),...,vecM+1<f32>());
// matNxM<f16>(vecM<f16>(),...,vecM+1<f16>());
@@ -2522,7 +2708,7 @@
MatrixStr(param) + "(" + args_tys.str() + ")"));
}
-TEST_P(MatrixConstructorTest, Expr_Constructor_ZeroValue_Success) {
+TEST_P(MatrixConstructorTest, ZeroValue_Success) {
// matNxM<f32>();
// matNxM<f16>();
@@ -2537,7 +2723,7 @@
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
-TEST_P(MatrixConstructorTest, Expr_Constructor_WithColumns_Success) {
+TEST_P(MatrixConstructorTest, WithColumns_Success) {
// matNxM<f32>(vecM<f32>(), ...); with N arguments
// matNxM<f16>(vecM<f16>(), ...); with N arguments
@@ -2558,7 +2744,7 @@
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
-TEST_P(MatrixConstructorTest, Expr_Constructor_WithElements_Success) {
+TEST_P(MatrixConstructorTest, WithElements_Success) {
// matNxM<f32>(f32,...,f32); with N*M arguments
// matNxM<f16>(f16,...,f16); with N*M arguments
@@ -2578,7 +2764,7 @@
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
-TEST_P(MatrixConstructorTest, Expr_Constructor_ElementTypeAlias_Error) {
+TEST_P(MatrixConstructorTest, ElementTypeAlias_Error) {
// matNxM<Float32>(vecM<u32>(), ...); with N arguments
// matNxM<Float16>(vecM<u32>(), ...); with N arguments
@@ -2608,7 +2794,7 @@
MatrixStr(param) + "(" + args_tys.str() + ")"));
}
-TEST_P(MatrixConstructorTest, Expr_Constructor_ElementTypeAlias_Success) {
+TEST_P(MatrixConstructorTest, ElementTypeAlias_Success) {
// matNxM<Float32>(vecM<f32>(), ...); with N arguments
// matNxM<Float16>(vecM<f16>(), ...); with N arguments
@@ -2631,7 +2817,7 @@
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_MatrixConstructor_ArgumentTypeAlias_Error) {
+TEST_F(ResolverTypeConstructorValidationTest, MatrixConstructor_ArgumentTypeAlias_Error) {
auto* alias = Alias("VectorUnsigned2", ty.vec2<u32>());
auto* tc = Construct(Source{{12, 34}}, ty.mat2x2<f32>(), Construct(ty.Of(alias)), vec2<f32>());
WrapInFunction(tc);
@@ -2642,7 +2828,7 @@
HasSubstr("12:34 error: no matching constructor for mat2x2<f32>(vec2<u32>, vec2<f32>)"));
}
-TEST_P(MatrixConstructorTest, Expr_Constructor_ArgumentTypeAlias_Success) {
+TEST_P(MatrixConstructorTest, ArgumentTypeAlias_Success) {
const auto param = GetParam();
Enable(ast::Extension::kF16);
@@ -2662,7 +2848,7 @@
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
-TEST_P(MatrixConstructorTest, Expr_Constructor_ArgumentElementTypeAlias_Error) {
+TEST_P(MatrixConstructorTest, ArgumentElementTypeAlias_Error) {
const auto param = GetParam();
Enable(ast::Extension::kF16);
@@ -2689,7 +2875,7 @@
MatrixStr(param) + "(" + args_tys.str() + ")"));
}
-TEST_P(MatrixConstructorTest, Expr_Constructor_ArgumentElementTypeAlias_Success) {
+TEST_P(MatrixConstructorTest, ArgumentElementTypeAlias_Success) {
const auto param = GetParam();
Enable(ast::Extension::kF16);
@@ -2961,7 +3147,7 @@
testing::ValuesIn(all_types),
number_of_members));
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Struct_Nested) {
+TEST_F(ResolverTypeConstructorValidationTest, Struct_Nested) {
auto* inner_m = Member("m", ty.i32());
auto* inner_s = Structure("inner_s", {inner_m});
@@ -2978,7 +3164,7 @@
"type: expected 'inner_s', found 'i32'");
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Struct) {
+TEST_F(ResolverTypeConstructorValidationTest, Struct) {
auto* m = Member("m", ty.i32());
auto* s = Structure("MyInputs", {m});
auto* tc = Construct(Source{{12, 34}}, ty.Of(s));
@@ -2986,7 +3172,7 @@
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
-TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Struct_Empty) {
+TEST_F(ResolverTypeConstructorValidationTest, Struct_Empty) {
auto* str = Structure("S", {
Member("a", ty.i32()),
Member("b", ty.f32()),
@@ -3030,7 +3216,7 @@
}
TEST_F(ResolverTypeConstructorValidationTest, TypeConstructorAsStatement) {
- WrapInFunction(CallStmt(Construct(Source{{12, 34}}, ty.vec2<f32>(), 1_f, 2_f)));
+ WrapInFunction(CallStmt(vec2<f32>(Source{{12, 34}}, 1_f, 2_f)));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: type constructor evaluated but not used");
diff --git a/src/tint/resolver/validator.cc b/src/tint/resolver/validator.cc
index 940e154..ec858c4 100644
--- a/src/tint/resolver/validator.cc
+++ b/src/tint/resolver/validator.cc
@@ -1495,28 +1495,21 @@
bool is_call_stmt =
current_statement && Is<ast::CallStatement>(current_statement->Declaration(),
[&](auto* stmt) { return stmt->expr == expr; });
-
- return Switch(
- call->Target(), //
- [&](const sem::TypeConversion*) {
- if (is_call_stmt) {
+ if (is_call_stmt) {
+ return Switch(
+ call->Target(), //
+ [&](const sem::TypeConversion*) {
AddError("type conversion evaluated but not used", call->Declaration()->source);
return false;
- }
- return true;
- },
- [&](const sem::TypeConstructor* ctor) {
- if (is_call_stmt) {
+ },
+ [&](const sem::TypeConstructor*) {
AddError("type constructor evaluated but not used", call->Declaration()->source);
return false;
- }
- return Switch(
- ctor->ReturnType(), //
- [&](const sem::Array* arr) { return ArrayConstructor(expr, arr); },
- [&](const sem::Struct* str) { return StructureConstructor(expr, str); },
- [&](Default) { return true; });
- },
- [&](Default) { return true; });
+ },
+ [&](Default) { return true; });
+ }
+
+ return true;
}
bool Validator::DiscardStatement(const sem::Statement* stmt,
@@ -1874,18 +1867,17 @@
auto* elem_ty = array_type->ElemType();
for (auto* value : values) {
auto* value_ty = sem_.TypeOf(value)->UnwrapRef();
- if (value_ty != elem_ty) {
- AddError(
- "type in array constructor does not match array type: "
- "expected '" +
- sem_.TypeNameOf(elem_ty) + "', found '" + sem_.TypeNameOf(value_ty) + "'",
- value->source);
+ if (sem::Type::ConversionRank(value_ty, elem_ty) == sem::Type::kNoConversion) {
+ AddError("'" + sem_.TypeNameOf(value_ty) +
+ "' cannot be used to construct an array of '" + sem_.TypeNameOf(elem_ty) +
+ "'",
+ value->source);
return false;
}
}
if (array_type->IsRuntimeSized()) {
- AddError("cannot init a runtime-sized array", ctor->source);
+ AddError("cannot construct a runtime-sized array", ctor->source);
return false;
} else if (!elem_ty->IsConstructible()) {
AddError("array constructor has non-constructible element type", ctor->source);
@@ -2011,6 +2003,11 @@
bool Validator::Array(const sem::Array* arr, const Source& source) const {
auto* el_ty = arr->ElemType();
+ if (!IsPlain(el_ty)) {
+ AddError(sem_.TypeNameOf(el_ty) + " cannot be used as an element type of an array", source);
+ return false;
+ }
+
if (!IsFixedFootprint(el_ty)) {
AddError("an array element type cannot contain a runtime-sized array", source);
return false;
@@ -2020,8 +2017,7 @@
bool Validator::ArrayStrideAttribute(const ast::StrideAttribute* attr,
uint32_t el_size,
- uint32_t el_align,
- const Source& source) const {
+ uint32_t el_align) const {
auto stride = attr->stride;
bool is_valid_stride = (stride >= el_size) && (stride >= el_align) && (stride % el_align == 0);
if (!is_valid_stride) {
@@ -2032,8 +2028,8 @@
AddError(
"arrays decorated with the stride attribute must have a stride "
"that is at least the size of the element type, and be a multiple "
- "of the element type's alignment value.",
- source);
+ "of the element type's alignment value",
+ attr->source);
return false;
}
return true;
diff --git a/src/tint/resolver/validator.h b/src/tint/resolver/validator.h
index e9f9cea..385e020 100644
--- a/src/tint/resolver/validator.h
+++ b/src/tint/resolver/validator.h
@@ -131,12 +131,10 @@
/// @param attr the stride attribute to validate
/// @param el_size the element size
/// @param el_align the element alignment
- /// @param source the source of the attribute
/// @returns true on success, false otherwise
bool ArrayStrideAttribute(const ast::StrideAttribute* attr,
uint32_t el_size,
- uint32_t el_align,
- const Source& source) const;
+ uint32_t el_align) const;
/// Validates an atomic
/// @param a the atomic ast node to validate
diff --git a/src/tint/sem/abstract_numeric.cc b/src/tint/sem/abstract_numeric.cc
index 6481a43..e7d1846 100644
--- a/src/tint/sem/abstract_numeric.cc
+++ b/src/tint/sem/abstract_numeric.cc
@@ -31,7 +31,7 @@
}
bool AbstractNumeric::IsConstructible() const {
- return false;
+ return true;
}
} // namespace tint::sem
diff --git a/src/tint/sem/abstract_numeric.h b/src/tint/sem/abstract_numeric.h
index 0b38448..620c528 100644
--- a/src/tint/sem/abstract_numeric.h
+++ b/src/tint/sem/abstract_numeric.h
@@ -38,7 +38,7 @@
/// @returns 0, as the type is abstract.
uint32_t Align() const override;
- /// @returns 0, as the type is abstract.
+ /// @returns true.
bool IsConstructible() const override;
};
diff --git a/src/tint/symbol.h b/src/tint/symbol.h
index e344341..fc0a0df 100644
--- a/src/tint/symbol.h
+++ b/src/tint/symbol.h
@@ -41,7 +41,7 @@
#if TINT_SYMBOL_STORE_DEBUG_NAME
/// Constructor
/// @param val the symbol value
- /// @param program_id the identifier of the program that owns this Symbol
+ /// @param pid the identifier of the program that owns this Symbol
/// @param debug_name name of symbols used only for debugging
Symbol(uint32_t val, tint::ProgramID pid, std::string debug_name);
#endif
diff --git a/src/tint/transform/remove_phonies.cc b/src/tint/transform/remove_phonies.cc
index 1cac0b7..7ba109a 100644
--- a/src/tint/transform/remove_phonies.cc
+++ b/src/tint/transform/remove_phonies.cc
@@ -97,7 +97,8 @@
// Just skip.
return ast::TraverseAction::Skip;
}
- if (call->Target()->IsAnyOf<sem::Function, sem::Builtin>()) {
+ if (call->Target()->IsAnyOf<sem::Function, sem::Builtin>() &&
+ call->HasSideEffects()) {
side_effects.push_back(expr);
return ast::TraverseAction::Skip;
}
diff --git a/src/tint/transform/remove_phonies_test.cc b/src/tint/transform/remove_phonies_test.cc
index 220f1db..dc91b5a 100644
--- a/src/tint/transform/remove_phonies_test.cc
+++ b/src/tint/transform/remove_phonies_test.cc
@@ -65,6 +65,8 @@
_ = vec2<f32>(5.0);
_ = vec3<i32>(6, 7, 8);
_ = mat2x2<f32>(9.0, 10.0, 11.0, 12.0);
+ _ = atan2(1.0, 2.0);
+ _ = clamp(1.0, 2.0, 3.0);
}
)";
diff --git a/src/tint/val/hlsl.cc b/src/tint/val/hlsl.cc
index 18bded6..f1cfb05 100644
--- a/src/tint/val/hlsl.cc
+++ b/src/tint/val/hlsl.cc
@@ -114,13 +114,21 @@
return result;
}
- pD3DCompile d3dCompile = reinterpret_cast<pD3DCompile>(
+ auto* d3dCompile = reinterpret_cast<pD3DCompile>(
reinterpret_cast<void*>(GetProcAddress(fxcLib, "D3DCompile")));
+ auto* d3dDisassemble = reinterpret_cast<pD3DDisassemble>(
+ reinterpret_cast<void*>(GetProcAddress(fxcLib, "D3DDisassemble")));
+
if (d3dCompile == nullptr) {
result.output = "Couldn't load D3DCompile from FXC";
result.failed = true;
return result;
}
+ if (d3dDisassemble == nullptr) {
+ result.output = "Couldn't load D3DDisassemble from FXC";
+ result.failed = true;
+ return result;
+ }
for (auto ep : entry_points) {
const char* profile = "";
@@ -147,21 +155,30 @@
ComPtr<ID3DBlob> compiledShader;
ComPtr<ID3DBlob> errors;
- HRESULT cr = d3dCompile(source.c_str(), // pSrcData
- source.length(), // SrcDataSize
- nullptr, // pSourceName
- nullptr, // pDefines
- nullptr, // pInclude
- ep.first.c_str(), // pEntrypoint
- profile, // pTarget
- compileFlags, // Flags1
- 0, // Flags2
- &compiledShader, // ppCode
- &errors); // ppErrorMsgs
- if (FAILED(cr)) {
+ HRESULT res = d3dCompile(source.c_str(), // pSrcData
+ source.length(), // SrcDataSize
+ nullptr, // pSourceName
+ nullptr, // pDefines
+ nullptr, // pInclude
+ ep.first.c_str(), // pEntrypoint
+ profile, // pTarget
+ compileFlags, // Flags1
+ 0, // Flags2
+ &compiledShader, // ppCode
+ &errors); // ppErrorMsgs
+ if (FAILED(res)) {
result.output = static_cast<char*>(errors->GetBufferPointer());
result.failed = true;
return result;
+ } else {
+ ComPtr<ID3DBlob> disassembly;
+ res = d3dDisassemble(compiledShader->GetBufferPointer(),
+ compiledShader->GetBufferSize(), 0, "", &disassembly);
+ if (FAILED(res)) {
+ result.output = "failed to disassemble shader";
+ } else {
+ result.output = static_cast<char*>(disassembly->GetBufferPointer());
+ }
}
}
diff --git a/src/tint/writer/wgsl/generator_impl.cc b/src/tint/writer/wgsl/generator_impl.cc
index 6ca7083..f3129c0 100644
--- a/src/tint/writer/wgsl/generator_impl.cc
+++ b/src/tint/writer/wgsl/generator_impl.cc
@@ -382,19 +382,22 @@
}
}
- out << "array<";
- if (!EmitType(out, ary->type)) {
- return false;
- }
+ out << "array";
+ if (ary->type) {
+ out << "<";
+ TINT_DEFER(out << ">");
- if (!ary->IsRuntimeArray()) {
- out << ", ";
- if (!EmitExpression(out, ary->count)) {
+ if (!EmitType(out, ary->type)) {
return false;
}
- }
- out << ">";
+ if (!ary->IsRuntimeArray()) {
+ out << ", ";
+ if (!EmitExpression(out, ary->count)) {
+ return false;
+ }
+ }
+ }
return true;
},
[&](const ast::Bool*) {
diff --git a/src/tint/writer/wgsl/generator_impl_constructor_test.cc b/src/tint/writer/wgsl/generator_impl_constructor_test.cc
index 07b10ad..40bf393 100644
--- a/src/tint/writer/wgsl/generator_impl_constructor_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_constructor_test.cc
@@ -174,5 +174,17 @@
"vec3<f32>(4.0f, 5.0f, 6.0f), vec3<f32>(7.0f, 8.0f, 9.0f))"));
}
+TEST_F(WgslGeneratorImplTest, EmitConstructor_Type_ImplicitArray) {
+ WrapInFunction(Construct(ty.array(nullptr, nullptr), vec3<f32>(1_f, 2_f, 3_f),
+ vec3<f32>(4_f, 5_f, 6_f), vec3<f32>(7_f, 8_f, 9_f)));
+
+ GeneratorImpl& gen = Build();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ EXPECT_THAT(gen.result(),
+ HasSubstr("array(vec3<f32>(1.0f, 2.0f, 3.0f), "
+ "vec3<f32>(4.0f, 5.0f, 6.0f), vec3<f32>(7.0f, 8.0f, 9.0f))"));
+}
+
} // namespace
} // namespace tint::writer::wgsl