Import Tint changes from Dawn
Changes:
- 6d4b35a14b589a1ac821b9ff4be2f13a8345ea80 ClampFragDepth: switch params to a struct. by Stephen White <senorblanco@chromium.org>
- a2ca09a571f432c7ce1a068b356a28ee201568c2 Fix issue with break inside switch inside continuing. by dan sinclair <dsinclair@chromium.org>
- b87d6571e934ca2a5c647312d98a1da56f20d0a0 [tint][utils] Add more comparison operators for Source::L... by Ben Clayton <bclayton@google.com>
- 023f2ae8175ea5164b50fc7e1daef18687e178f3 [tint][core] Expose intrinsic::PrintOverload() by Ben Clayton <bclayton@google.com>
- 82d62aa377a6d01c09c890138798f58b2aee5cf0 [tint][wgsl] Expand ast::Function source to include whole... by Ben Clayton <bclayton@google.com>
- 7c8832ac22c07df7451b7c7774849d94d590ee4f [tint][sem] Store OverloadInfo on BuiltinFn by Ben Clayton <bclayton@google.com>
GitOrigin-RevId: 6d4b35a14b589a1ac821b9ff4be2f13a8345ea80
Change-Id: I592e4b0e397a9009f5d4b86b8ab78bfd8ca3403e
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/174940
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/api/options/BUILD.bazel b/src/tint/api/options/BUILD.bazel
index 9a16e95..c7eba70 100644
--- a/src/tint/api/options/BUILD.bazel
+++ b/src/tint/api/options/BUILD.bazel
@@ -44,6 +44,7 @@
hdrs = [
"array_length_from_uniform.h",
"binding_remapper.h",
+ "depth_range_offsets.h",
"external_texture.h",
"pixel_local.h",
"texture_builtins_from_uniform.h",
diff --git a/src/tint/api/options/BUILD.cmake b/src/tint/api/options/BUILD.cmake
index 045323e..1f0fffa 100644
--- a/src/tint/api/options/BUILD.cmake
+++ b/src/tint/api/options/BUILD.cmake
@@ -41,6 +41,7 @@
tint_add_target(tint_api_options lib
api/options/array_length_from_uniform.h
api/options/binding_remapper.h
+ api/options/depth_range_offsets.h
api/options/external_texture.h
api/options/options.cc
api/options/pixel_local.h
diff --git a/src/tint/api/options/BUILD.gn b/src/tint/api/options/BUILD.gn
index f9f9b46..cc35c71 100644
--- a/src/tint/api/options/BUILD.gn
+++ b/src/tint/api/options/BUILD.gn
@@ -46,6 +46,7 @@
sources = [
"array_length_from_uniform.h",
"binding_remapper.h",
+ "depth_range_offsets.h",
"external_texture.h",
"options.cc",
"pixel_local.h",
diff --git a/src/tint/api/options/depth_range_offsets.h b/src/tint/api/options/depth_range_offsets.h
new file mode 100644
index 0000000..1abe2a5
--- /dev/null
+++ b/src/tint/api/options/depth_range_offsets.h
@@ -0,0 +1,49 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SRC_TINT_API_OPTIONS_DEPTH_RANGE_OFFSETS_H_
+#define SRC_TINT_API_OPTIONS_DEPTH_RANGE_OFFSETS_H_
+
+#include <unordered_map>
+
+#include "src/tint/api/common/binding_point.h"
+
+namespace tint {
+
+/// Options used to specify the offsets of the min_depth and max_depth push constants.
+struct DepthRangeOffsets {
+ /// A map of old binding point to new binding point
+ uint32_t min = 0;
+ uint32_t max = 0;
+
+ /// Reflect the fields of this class so that it can be used by tint::ForeachField()
+ TINT_REFLECT(DepthRangeOffsets, min, max);
+};
+
+} // namespace tint
+
+#endif // SRC_TINT_API_OPTIONS_DEPTH_RANGE_OFFSETS_H_
diff --git a/src/tint/cmd/tint/main.cc b/src/tint/cmd/tint/main.cc
index 1601a76..8db9a64 100644
--- a/src/tint/cmd/tint/main.cc
+++ b/src/tint/cmd/tint/main.cc
@@ -1089,8 +1089,7 @@
offset += 4;
}
if (entry_point.frag_depth_used) {
- gen_options.min_depth_offset = offset + 0;
- gen_options.max_depth_offset = offset + 4;
+ gen_options.depth_range_offsets = {offset + 0, offset + 4};
offset += 8;
}
diff --git a/src/tint/lang/core/intrinsic/table.cc b/src/tint/lang/core/intrinsic/table.cc
index a8ee926..b81fde7 100644
--- a/src/tint/lang/core/intrinsic/table.cc
+++ b/src/tint/lang/core/intrinsic/table.cc
@@ -161,12 +161,6 @@
const NumberMatcherIndex* number_matcher_indices,
EvaluationStage earliest_eval_stage);
-// Prints the overload for emitting diagnostics
-void PrintOverload(StringStream& ss,
- Context& context,
- const OverloadInfo& overload,
- std::string_view intrinsic_name);
-
// Prints the list of candidates for emitting diagnostics
void PrintCandidates(StringStream& ss,
Context& context,
@@ -464,6 +458,57 @@
number_matcher_indices, earliest_eval_stage};
}
+void PrintCandidates(StringStream& ss,
+ Context& context,
+ VectorRef<Candidate> candidates,
+ std::string_view intrinsic_name) {
+ for (auto& candidate : candidates) {
+ ss << " ";
+ PrintOverload(ss, context, *candidate.overload, intrinsic_name);
+ ss << std::endl;
+ }
+}
+
+std::string ErrAmbiguousOverload(Context& context,
+ std::string_view intrinsic_name,
+ VectorRef<const core::type::Type*> args,
+ TemplateState templates,
+ VectorRef<Candidate> candidates) {
+ StringStream ss;
+ ss << "ambiguous overload while attempting to match " << intrinsic_name;
+ for (size_t i = 0; i < std::numeric_limits<size_t>::max(); i++) {
+ if (auto* ty = templates.Type(i)) {
+ ss << ((i == 0) ? "<" : ", ") << ty->FriendlyName();
+ } else {
+ if (i > 0) {
+ ss << ">";
+ }
+ break;
+ }
+ }
+ ss << "(";
+ bool first = true;
+ for (auto* arg : args) {
+ if (!first) {
+ ss << ", ";
+ }
+ first = false;
+ ss << arg->FriendlyName();
+ }
+ ss << "):\n";
+ for (auto& candidate : candidates) {
+ if (candidate.score == 0) {
+ ss << " ";
+ PrintOverload(ss, context, *candidate.overload, intrinsic_name);
+ ss << std::endl;
+ }
+ }
+ TINT_ICE() << ss.str();
+ return ss.str();
+}
+
+} // namespace
+
void PrintOverload(StringStream& ss,
Context& context,
const OverloadInfo& overload,
@@ -545,57 +590,6 @@
}
}
-void PrintCandidates(StringStream& ss,
- Context& context,
- VectorRef<Candidate> candidates,
- std::string_view intrinsic_name) {
- for (auto& candidate : candidates) {
- ss << " ";
- PrintOverload(ss, context, *candidate.overload, intrinsic_name);
- ss << std::endl;
- }
-}
-
-std::string ErrAmbiguousOverload(Context& context,
- std::string_view intrinsic_name,
- VectorRef<const core::type::Type*> args,
- TemplateState templates,
- VectorRef<Candidate> candidates) {
- StringStream ss;
- ss << "ambiguous overload while attempting to match " << intrinsic_name;
- for (size_t i = 0; i < std::numeric_limits<size_t>::max(); i++) {
- if (auto* ty = templates.Type(i)) {
- ss << ((i == 0) ? "<" : ", ") << ty->FriendlyName();
- } else {
- if (i > 0) {
- ss << ">";
- }
- break;
- }
- }
- ss << "(";
- bool first = true;
- for (auto* arg : args) {
- if (!first) {
- ss << ", ";
- }
- first = false;
- ss << arg->FriendlyName();
- }
- ss << "):\n";
- for (auto& candidate : candidates) {
- if (candidate.score == 0) {
- ss << " ";
- PrintOverload(ss, context, *candidate.overload, intrinsic_name);
- ss << std::endl;
- }
- }
- TINT_ICE() << ss.str();
- return ss.str();
-}
-
-} // namespace
-
Result<Overload, std::string> LookupFn(Context& context,
std::string_view intrinsic_name,
size_t function_id,
diff --git a/src/tint/lang/core/intrinsic/table.h b/src/tint/lang/core/intrinsic/table.h
index c1cbfcc..8228c1f 100644
--- a/src/tint/lang/core/intrinsic/table.h
+++ b/src/tint/lang/core/intrinsic/table.h
@@ -106,6 +106,12 @@
SymbolTable& symbols;
};
+// Prints the overload for emitting diagnostics
+void PrintOverload(StringStream& ss,
+ Context& context,
+ const OverloadInfo& overload,
+ std::string_view intrinsic_name);
+
/// Lookup looks for the builtin overload with the given signature, raising an error diagnostic
/// if the builtin was not found.
/// @param context the intrinsic context
diff --git a/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc b/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
index 764b779..5020b17 100644
--- a/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
@@ -254,8 +254,8 @@
data.Add<ast::transform::OffsetFirstIndex::Config>(std::nullopt, options.first_instance_offset);
- data.Add<ast::transform::ClampFragDepth::Config>(options.min_depth_offset,
- options.max_depth_offset);
+ data.Add<ast::transform::ClampFragDepth::Config>(options.depth_range_offsets);
+
SanitizedResult result;
ast::transform::DataMap outputs;
result.program = manager.Run(in, data, outputs);
diff --git a/src/tint/lang/glsl/writer/common/options.h b/src/tint/lang/glsl/writer/common/options.h
index 62cd80c..19aa11d 100644
--- a/src/tint/lang/glsl/writer/common/options.h
+++ b/src/tint/lang/glsl/writer/common/options.h
@@ -33,6 +33,7 @@
#include <unordered_map>
#include "src/tint/api/options/binding_remapper.h"
+#include "src/tint/api/options/depth_range_offsets.h"
#include "src/tint/api/options/external_texture.h"
#include "src/tint/api/options/texture_builtins_from_uniform.h"
#include "src/tint/lang/glsl/writer/common/version.h"
@@ -82,11 +83,8 @@
/// Offset of the firstInstance push constant.
std::optional<int32_t> first_instance_offset;
- /// Offset of the minDepth push constant.
- std::optional<uint32_t> min_depth_offset;
-
- /// Offset of the maxDepth push constant.
- std::optional<uint32_t> max_depth_offset;
+ /// Offsets of the minDepth and maxDepth push constants.
+ std::optional<DepthRangeOffsets> depth_range_offsets;
/// Options used to map WGSL textureNumLevels/textureNumSamples builtins to internal uniform
/// buffer values. If not specified, emits corresponding GLSL builtins
@@ -104,8 +102,7 @@
binding_remapper_options,
external_texture_options,
first_instance_offset,
- min_depth_offset,
- max_depth_offset,
+ depth_range_offsets,
texture_builtins_from_uniform);
};
diff --git a/src/tint/lang/spirv/writer/ast_printer/ast_printer.cc b/src/tint/lang/spirv/writer/ast_printer/ast_printer.cc
index c782db5..1d75ad5 100644
--- a/src/tint/lang/spirv/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/spirv/writer/ast_printer/ast_printer.cc
@@ -66,7 +66,7 @@
if (options.clamp_frag_depth) {
manager.Add<ast::transform::ClampFragDepth>();
- data.Add<ast::transform::ClampFragDepth::Config>(0, 4);
+ data.Add<ast::transform::ClampFragDepth::Config>(tint::DepthRangeOffsets{0, 4});
}
manager.Add<ast::transform::DisableUniformityAnalysis>();
diff --git a/src/tint/lang/wgsl/ast/transform/clamp_frag_depth.cc b/src/tint/lang/wgsl/ast/transform/clamp_frag_depth.cc
index 2b5e6a2..66bf672 100644
--- a/src/tint/lang/wgsl/ast/transform/clamp_frag_depth.cc
+++ b/src/tint/lang/wgsl/ast/transform/clamp_frag_depth.cc
@@ -67,7 +67,7 @@
/// @returns the new program or SkipTransform if the transform is not required
Transform::ApplyResult Run(const DataMap& inputs) {
const Config* cfg = inputs.Get<Config>();
- if (!cfg || !cfg->min_depth_offset.has_value() || !cfg->max_depth_offset.has_value()) {
+ if (!cfg || !cfg->offsets.has_value()) {
return SkipTransform;
}
@@ -87,8 +87,8 @@
// return clamp(v, push_constants.min, push_constants.max_depth);
// }
- push_constant_helper.InsertMember("min_depth", b.ty.f32(), *cfg->min_depth_offset);
- push_constant_helper.InsertMember("max_depth", b.ty.f32(), *cfg->max_depth_offset);
+ push_constant_helper.InsertMember("min_depth", b.ty.f32(), cfg->offsets->min);
+ push_constant_helper.InsertMember("max_depth", b.ty.f32(), cfg->offsets->max);
Symbol buffer_name = push_constant_helper.Run();
@@ -221,9 +221,7 @@
return State{src}.Run(inputs);
}
-ClampFragDepth::Config::Config(std::optional<uint32_t> min_depth_off,
- std::optional<uint32_t> max_depth_off)
- : min_depth_offset(min_depth_off), max_depth_offset(max_depth_off) {}
+ClampFragDepth::Config::Config(std::optional<tint::DepthRangeOffsets> off) : offsets(off) {}
ClampFragDepth::Config::~Config() = default;
diff --git a/src/tint/lang/wgsl/ast/transform/clamp_frag_depth.h b/src/tint/lang/wgsl/ast/transform/clamp_frag_depth.h
index 599b91c..03972a0 100644
--- a/src/tint/lang/wgsl/ast/transform/clamp_frag_depth.h
+++ b/src/tint/lang/wgsl/ast/transform/clamp_frag_depth.h
@@ -28,6 +28,7 @@
#ifndef SRC_TINT_LANG_WGSL_AST_TRANSFORM_CLAMP_FRAG_DEPTH_H_
#define SRC_TINT_LANG_WGSL_AST_TRANSFORM_CLAMP_FRAG_DEPTH_H_
+#include "src/tint/api/options/depth_range_offsets.h"
#include "src/tint/lang/wgsl/ast/transform/transform.h"
namespace tint::ast::transform {
@@ -72,18 +73,14 @@
/// Transform configuration options
struct Config final : public Castable<Config, ast::transform::Data> {
/// Constructor
- /// @param min_depth_off Offset of the minDepth push constant
- /// @param max_depth_off Offset of the maxDepth push constant
- Config(std::optional<uint32_t> min_depth_off, std::optional<uint32_t> max_depth_off);
+ /// @param off Offsets of the min_depth and max_depth push constants
+ explicit Config(std::optional<tint::DepthRangeOffsets> off);
/// Destructor
~Config() override;
- /// Offset of the min_depth push constant
- std::optional<uint32_t> min_depth_offset;
-
- /// Offset of the min_depth push constant
- std::optional<uint32_t> max_depth_offset;
+ /// Offsets of the min_depth and max_depth push constants
+ std::optional<tint::DepthRangeOffsets> offsets;
};
/// @copydoc ast::transform::Transform::Apply
diff --git a/src/tint/lang/wgsl/ast/transform/clamp_frag_depth_test.cc b/src/tint/lang/wgsl/ast/transform/clamp_frag_depth_test.cc
index 97f1f31..027c19d 100644
--- a/src/tint/lang/wgsl/ast/transform/clamp_frag_depth_test.cc
+++ b/src/tint/lang/wgsl/ast/transform/clamp_frag_depth_test.cc
@@ -50,19 +50,6 @@
EXPECT_FALSE(ShouldRun<ClampFragDepth>(src));
}
-TEST_F(ClampFragDepthTest, ShouldRunNoMin) {
- auto* src = R"(
- @fragment fn main() -> @builtin(frag_depth) f32 {
- return 0.0;
- }
- )";
-
- DataMap config;
- config.Add<ClampFragDepth::Config>(std::nullopt, 4);
-
- EXPECT_FALSE(ShouldRun<ClampFragDepth>(src, config));
-}
-
TEST_F(ClampFragDepthTest, ShouldRunNoMinNoMax) {
auto* src = R"(
@fragment fn main() -> @builtin(frag_depth) f32 {
@@ -71,7 +58,7 @@
)";
DataMap config;
- config.Add<ClampFragDepth::Config>(0, std::nullopt);
+ config.Add<ClampFragDepth::Config>(std::nullopt);
EXPECT_FALSE(ShouldRun<ClampFragDepth>(src, config));
}
@@ -84,7 +71,7 @@
)";
DataMap config;
- config.Add<ClampFragDepth::Config>(0, 4);
+ config.Add<ClampFragDepth::Config>(tint::DepthRangeOffsets{0, 4});
EXPECT_TRUE(ShouldRun<ClampFragDepth>(src, config));
}
@@ -132,7 +119,7 @@
)";
DataMap config;
- config.Add<ClampFragDepth::Config>(4, 8);
+ config.Add<ClampFragDepth::Config>(tint::DepthRangeOffsets{4, 8});
auto got = Run<ClampFragDepth>(src, config);
EXPECT_EQ(expect, str(got));
@@ -146,7 +133,7 @@
)";
DataMap config;
- config.Add<ClampFragDepth::Config>(0, 4);
+ config.Add<ClampFragDepth::Config>(tint::DepthRangeOffsets{0, 4});
EXPECT_TRUE(ShouldRun<ClampFragDepth>(src, config));
}
@@ -164,7 +151,7 @@
)";
DataMap config;
- config.Add<ClampFragDepth::Config>(0, 4);
+ config.Add<ClampFragDepth::Config>(tint::DepthRangeOffsets{0, 4});
EXPECT_TRUE(ShouldRun<ClampFragDepth>(src, config));
}
@@ -199,7 +186,7 @@
)";
DataMap config;
- config.Add<ClampFragDepth::Config>(0, 4);
+ config.Add<ClampFragDepth::Config>(tint::DepthRangeOffsets{0, 4});
auto got = Run<ClampFragDepth>(src, config);
EXPECT_EQ(expect, str(got));
}
@@ -240,7 +227,7 @@
)";
DataMap config;
- config.Add<ClampFragDepth::Config>(0, 4);
+ config.Add<ClampFragDepth::Config>(tint::DepthRangeOffsets{0, 4});
auto got = Run<ClampFragDepth>(src, config);
EXPECT_EQ(expect, str(got));
}
@@ -283,7 +270,7 @@
)";
DataMap config;
- config.Add<ClampFragDepth::Config>(0, 4);
+ config.Add<ClampFragDepth::Config>(tint::DepthRangeOffsets{0, 4});
auto got = Run<ClampFragDepth>(src, config);
EXPECT_EQ(expect, str(got));
}
@@ -331,7 +318,7 @@
)";
DataMap config;
- config.Add<ClampFragDepth::Config>(0, 4);
+ config.Add<ClampFragDepth::Config>(tint::DepthRangeOffsets{0, 4});
auto got = Run<ClampFragDepth>(src, config);
EXPECT_EQ(expect, str(got));
}
@@ -409,7 +396,7 @@
)";
DataMap config;
- config.Add<ClampFragDepth::Config>(0, 4);
+ config.Add<ClampFragDepth::Config>(tint::DepthRangeOffsets{0, 4});
auto got = Run<ClampFragDepth>(src, config);
EXPECT_EQ(expect, str(got));
}
@@ -469,7 +456,7 @@
)";
DataMap config;
- config.Add<ClampFragDepth::Config>(0, 4);
+ config.Add<ClampFragDepth::Config>(tint::DepthRangeOffsets{0, 4});
auto got = Run<ClampFragDepth>(src, config);
EXPECT_EQ(expect, str(got));
}
diff --git a/src/tint/lang/wgsl/reader/parser/function_decl_test.cc b/src/tint/lang/wgsl/reader/parser/function_decl_test.cc
index 99aa00f..212e5b9 100644
--- a/src/tint/lang/wgsl/reader/parser/function_decl_test.cc
+++ b/src/tint/lang/wgsl/reader/parser/function_decl_test.cc
@@ -45,6 +45,9 @@
EXPECT_TRUE(f.matched);
ASSERT_NE(f.value, nullptr);
+ EXPECT_EQ(f->source.range.begin, (Source::Location{1, 1}));
+ EXPECT_EQ(f->source.range.end, (Source::Location{1, 38}));
+
EXPECT_EQ(f->name->symbol, p->builder().Symbols().Get("main"));
EXPECT_EQ(f->return_type, nullptr);
@@ -88,6 +91,9 @@
EXPECT_TRUE(f.matched);
ASSERT_NE(f.value, nullptr);
+ EXPECT_EQ(f->source.range.begin, (Source::Location{1, 1}));
+ EXPECT_EQ(f->source.range.end, (Source::Location{1, 114}));
+
EXPECT_EQ(f->name->symbol, p->builder().Symbols().Get(function_ident));
EXPECT_EQ(f->return_type, nullptr);
@@ -114,6 +120,9 @@
EXPECT_TRUE(f.matched);
ASSERT_NE(f.value, nullptr);
+ EXPECT_EQ(f->source.range.begin, (Source::Location{1, 26}));
+ EXPECT_EQ(f->source.range.end, (Source::Location{1, 47}));
+
EXPECT_EQ(f->name->symbol, p->builder().Symbols().Get("main"));
EXPECT_EQ(f->return_type, nullptr);
ASSERT_EQ(f->params.Length(), 0u);
@@ -158,6 +167,9 @@
EXPECT_TRUE(f.matched);
ASSERT_NE(f.value, nullptr);
+ EXPECT_EQ(f->source.range.begin, (Source::Location{3, 1}));
+ EXPECT_EQ(f->source.range.end, (Source::Location{3, 22}));
+
EXPECT_EQ(f->name->symbol, p->builder().Symbols().Get("main"));
EXPECT_EQ(f->return_type, nullptr);
ASSERT_EQ(f->params.Length(), 0u);
@@ -206,6 +218,9 @@
EXPECT_TRUE(f.matched);
ASSERT_NE(f.value, nullptr);
+ EXPECT_EQ(f->source.range.begin, (Source::Location{4, 1}));
+ EXPECT_EQ(f->source.range.end, (Source::Location{4, 22}));
+
EXPECT_EQ(f->name->symbol, p->builder().Symbols().Get("main"));
EXPECT_EQ(f->return_type, nullptr);
ASSERT_EQ(f->params.Length(), 0u);
@@ -251,6 +266,9 @@
EXPECT_TRUE(f.matched);
ASSERT_NE(f.value, nullptr);
+ EXPECT_EQ(f->source.range.begin, (Source::Location{1, 1}));
+ EXPECT_EQ(f->source.range.end, (Source::Location{1, 46}));
+
EXPECT_EQ(f->name->symbol, p->builder().Symbols().Get("main"));
ASSERT_NE(f->return_type, nullptr);
@@ -287,6 +305,9 @@
EXPECT_TRUE(f.matched);
ASSERT_NE(f.value, nullptr);
+ EXPECT_EQ(f->source.range.begin, (Source::Location{1, 11}));
+ EXPECT_EQ(f->source.range.end, (Source::Location{1, 32}));
+
auto& attributes = f->attributes;
ASSERT_EQ(attributes.Length(), 1u);
ASSERT_TRUE(attributes[0]->Is<ast::MustUseAttribute>());
diff --git a/src/tint/lang/wgsl/reader/parser/parser.cc b/src/tint/lang/wgsl/reader/parser/parser.cc
index 3a05f2d..0781f66 100644
--- a/src/tint/lang/wgsl/reader/parser/parser.cc
+++ b/src/tint/lang/wgsl/reader/parser/parser.cc
@@ -1060,6 +1060,8 @@
// function_decl
// : function_header compound_statement
Maybe<const ast::Function*> Parser::function_decl(AttributeList& attrs) {
+ MultiTokenSource source(this);
+
auto header = function_header();
if (header.errored) {
if (sync_to(Token::Type::kBraceLeft, /* consume: */ false)) {
@@ -1090,8 +1092,8 @@
TINT_DEFER(attrs.Clear());
- return builder_.Func(header->source, header->name, header->params, header->return_type,
- body.value, std::move(attrs), header->return_type_attributes);
+ return builder_.Func(source, header->name, header->params, header->return_type, body.value,
+ std::move(attrs), header->return_type_attributes);
}
// function_header
diff --git a/src/tint/lang/wgsl/resolver/resolver.cc b/src/tint/lang/wgsl/resolver/resolver.cc
index 76b9ff9..29d313d 100644
--- a/src/tint/lang/wgsl/resolver/resolver.cc
+++ b/src/tint/lang/wgsl/resolver/resolver.cc
@@ -2415,9 +2415,8 @@
}
auto eval_stage = overload->const_eval_fn ? core::EvaluationStage::kConstant
: core::EvaluationStage::kRuntime;
- return b.create<sem::BuiltinFn>(
- fn, overload->return_type, std::move(params), eval_stage, supported_stages,
- flags.Contains(OverloadFlag::kIsDeprecated), flags.Contains(OverloadFlag::kMustUse));
+ return b.create<sem::BuiltinFn>(fn, overload->return_type, std::move(params), eval_stage,
+ supported_stages, *overload->info);
});
if (fn == wgsl::BuiltinFn::kTintMaterialize) {
diff --git a/src/tint/lang/wgsl/resolver/validation_test.cc b/src/tint/lang/wgsl/resolver/validation_test.cc
index 6bc6fc2..ba5da4a 100644
--- a/src/tint/lang/wgsl/resolver/validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/validation_test.cc
@@ -994,6 +994,22 @@
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
+TEST_F(ResolverValidationTest, Stmt_BreakInSwitchInContinuing) {
+ // loop {
+ // continuing {
+ // switch(1) {
+ // default:
+ // break;
+ // }
+ // }
+ // }
+
+ auto* cont = Block(Switch(1_i, DefaultCase(Block(Break()))));
+
+ WrapInFunction(Loop(Block(Break()), cont));
+ EXPECT_TRUE(r()->Resolve()) << r()->error();
+}
+
TEST_F(ResolverValidationTest, Stmt_BreakInIfTrueInContinuing) {
auto* cont = Block( // continuing {
If(true, Block( // if(true) {
diff --git a/src/tint/lang/wgsl/resolver/validator.cc b/src/tint/lang/wgsl/resolver/validator.cc
index 8e54a74..3cf40c0 100644
--- a/src/tint/lang/wgsl/resolver/validator.cc
+++ b/src/tint/lang/wgsl/resolver/validator.cc
@@ -266,11 +266,15 @@
}
const ast::Statement* Validator::ClosestContinuing(bool stop_at_loop,
+ bool stop_at_switch,
sem::Statement* current_statement) const {
for (const auto* s = current_statement; s != nullptr; s = s->Parent()) {
if (stop_at_loop && s->Is<sem::LoopStatement>()) {
break;
}
+ if (stop_at_switch && s->Is<sem::SwitchStatement>()) {
+ break;
+ }
if (s->Is<sem::LoopContinuingBlockStatement>()) {
return s->Declaration();
}
@@ -1583,7 +1587,8 @@
AddError("break statement must be in a loop or switch case", stmt->Declaration()->source);
return false;
}
- if (ClosestContinuing(/*stop_at_loop*/ true, current_statement) != nullptr) {
+ if (ClosestContinuing(/*stop_at_loop*/ true, /* stop_at_switch */ true, current_statement) !=
+ nullptr) {
AddError(
"`break` must not be used to exit from a continuing block. Use `break-if` instead.",
stmt->Declaration()->source);
@@ -1594,7 +1599,8 @@
bool Validator::ContinueStatement(const sem::Statement* stmt,
sem::Statement* current_statement) const {
- if (auto* continuing = ClosestContinuing(/*stop_at_loop*/ true, current_statement)) {
+ if (auto* continuing = ClosestContinuing(/*stop_at_loop*/ true, /* stop_at_switch */ false,
+ current_statement)) {
AddError("continuing blocks must not contain a continue statement",
stmt->Declaration()->source);
if (continuing != stmt->Declaration() && continuing != stmt->Parent()->Declaration()) {
@@ -2463,7 +2469,8 @@
}
auto* sem = sem_.Get(ret);
- if (auto* continuing = ClosestContinuing(/*stop_at_loop*/ false, current_statement)) {
+ if (auto* continuing = ClosestContinuing(/*stop_at_loop*/ false, /* stop_at_switch */ false,
+ current_statement)) {
AddError("continuing blocks must not contain a return statement", ret->source);
if (continuing != sem->Declaration() && continuing != sem->Parent()->Declaration()) {
AddNote("see continuing block here", continuing->source);
diff --git a/src/tint/lang/wgsl/resolver/validator.h b/src/tint/lang/wgsl/resolver/validator.h
index 92ccf7c..fc42824 100644
--- a/src/tint/lang/wgsl/resolver/validator.h
+++ b/src/tint/lang/wgsl/resolver/validator.h
@@ -579,8 +579,11 @@
/// (transitively) owns the current statement.
/// @param stop_at_loop if true then the function will return nullptr if a
/// loop or for-loop was found before the continuing.
+ /// @param stop_at_switch if true then the function will return nullptr if a switch was found
+ /// before continuing.
/// @param current_statement the current statement being resolved
const ast::Statement* ClosestContinuing(bool stop_at_loop,
+ bool stop_at_switch,
sem::Statement* current_statement) const;
/// Returns a human-readable string representation of the vector type name
diff --git a/src/tint/lang/wgsl/sem/BUILD.bazel b/src/tint/lang/wgsl/sem/BUILD.bazel
index 75399ed..37b8323 100644
--- a/src/tint/lang/wgsl/sem/BUILD.bazel
+++ b/src/tint/lang/wgsl/sem/BUILD.bazel
@@ -113,6 +113,7 @@
"//src/tint/api/common",
"//src/tint/lang/core",
"//src/tint/lang/core/constant",
+ "//src/tint/lang/core/intrinsic",
"//src/tint/lang/core/type",
"//src/tint/lang/wgsl",
"//src/tint/lang/wgsl/ast",
diff --git a/src/tint/lang/wgsl/sem/BUILD.cmake b/src/tint/lang/wgsl/sem/BUILD.cmake
index eba7340..6120b90 100644
--- a/src/tint/lang/wgsl/sem/BUILD.cmake
+++ b/src/tint/lang/wgsl/sem/BUILD.cmake
@@ -112,6 +112,7 @@
tint_api_common
tint_lang_core
tint_lang_core_constant
+ tint_lang_core_intrinsic
tint_lang_core_type
tint_lang_wgsl
tint_lang_wgsl_ast
diff --git a/src/tint/lang/wgsl/sem/BUILD.gn b/src/tint/lang/wgsl/sem/BUILD.gn
index 715f3a6..e6b2b06 100644
--- a/src/tint/lang/wgsl/sem/BUILD.gn
+++ b/src/tint/lang/wgsl/sem/BUILD.gn
@@ -116,6 +116,7 @@
"${tint_src_dir}/api/common",
"${tint_src_dir}/lang/core",
"${tint_src_dir}/lang/core/constant",
+ "${tint_src_dir}/lang/core/intrinsic",
"${tint_src_dir}/lang/core/type",
"${tint_src_dir}/lang/wgsl",
"${tint_src_dir}/lang/wgsl/ast",
diff --git a/src/tint/lang/wgsl/sem/builtin_fn.cc b/src/tint/lang/wgsl/sem/builtin_fn.cc
index 0e48dfc..b0218eb 100644
--- a/src/tint/lang/wgsl/sem/builtin_fn.cc
+++ b/src/tint/lang/wgsl/sem/builtin_fn.cc
@@ -33,6 +33,7 @@
#include <utility>
#include <vector>
+#include "src/tint/lang/core/intrinsic/table.h"
#include "src/tint/utils/containers/transform.h"
TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinFn);
@@ -48,15 +49,21 @@
VectorRef<Parameter*> parameters,
core::EvaluationStage eval_stage,
PipelineStageSet supported_stages,
- bool is_deprecated,
- bool must_use)
- : Base(return_type, std::move(parameters), eval_stage, must_use),
+ const core::intrinsic::OverloadInfo& overload)
+ : Base(return_type,
+ std::move(parameters),
+ eval_stage,
+ overload.flags.Contains(core::intrinsic::OverloadFlag::kMustUse)),
fn_(type),
supported_stages_(supported_stages),
- is_deprecated_(is_deprecated) {}
+ overload_(overload) {}
BuiltinFn::~BuiltinFn() = default;
+bool BuiltinFn::IsDeprecated() const {
+ return overload_.flags.Contains(core::intrinsic::OverloadFlag::kIsDeprecated);
+}
+
bool BuiltinFn::IsCoarseDerivative() const {
return wgsl::IsCoarseDerivative(fn_);
}
diff --git a/src/tint/lang/wgsl/sem/builtin_fn.h b/src/tint/lang/wgsl/sem/builtin_fn.h
index bcac245..18684cc 100644
--- a/src/tint/lang/wgsl/sem/builtin_fn.h
+++ b/src/tint/lang/wgsl/sem/builtin_fn.h
@@ -38,6 +38,11 @@
#include "src/tint/lang/wgsl/sem/pipeline_stage_set.h"
#include "src/tint/utils/math/hash.h"
+// Forward declarations
+namespace tint::core::intrinsic {
+struct OverloadInfo;
+}
+
namespace tint::sem {
/// BuiltinFn holds the semantic information for a builtin function.
@@ -49,15 +54,13 @@
/// @param parameters the parameters for the builtin overload
/// @param eval_stage the earliest evaluation stage for a call to the builtin
/// @param supported_stages the pipeline stages that this builtin can be used in
- /// @param is_deprecated true if the particular overload is considered deprecated
- /// @param must_use true if the builtin was annotated with `@must_use`
+ /// @param overload the builtin table overload
BuiltinFn(wgsl::BuiltinFn type,
const core::type::Type* return_type,
VectorRef<Parameter*> parameters,
core::EvaluationStage eval_stage,
PipelineStageSet supported_stages,
- bool is_deprecated,
- bool must_use);
+ const core::intrinsic::OverloadInfo& overload);
/// Destructor
~BuiltinFn() override;
@@ -69,7 +72,7 @@
PipelineStageSet SupportedStages() const { return supported_stages_; }
/// @return true if the builtin overload is considered deprecated
- bool IsDeprecated() const { return is_deprecated_; }
+ bool IsDeprecated() const;
/// @returns the name of the builtin function type. The spelling, including
/// case, matches the name in the WGSL spec.
@@ -122,6 +125,9 @@
/// wgsl::LanguageFeature::kUndefined if no language feature is required.
wgsl::LanguageFeature RequiredLanguageFeature() const;
+ /// @returns the builtin table overload info
+ const core::intrinsic::OverloadInfo& Overload() const { return overload_; }
+
/// @return the hash code for this object
tint::HashCode HashCode() const {
return Hash(Fn(), SupportedStages(), ReturnType(), Parameters(), IsDeprecated());
@@ -130,7 +136,7 @@
private:
const wgsl::BuiltinFn fn_;
const PipelineStageSet supported_stages_;
- const bool is_deprecated_;
+ const core::intrinsic::OverloadInfo& overload_;
};
/// Constant value used by the degrees() builtin
diff --git a/src/tint/utils/diagnostic/source.h b/src/tint/utils/diagnostic/source.h
index 8400921..afef58c 100644
--- a/src/tint/utils/diagnostic/source.h
+++ b/src/tint/utils/diagnostic/source.h
@@ -97,10 +97,31 @@
/// Returns true if `this` location is lexicographically less than `rhs`
/// @param rhs location to compare against
/// @returns true if `this` < `rhs`
- inline bool operator<(const Source::Location& rhs) {
+ inline bool operator<(const Source::Location& rhs) const {
return std::tie(line, column) < std::tie(rhs.line, rhs.column);
}
+ /// Returns true if `this` location is lexicographically less than or equal to `rhs`
+ /// @param rhs location to compare against
+ /// @returns true if `this` <= `rhs`
+ inline bool operator<=(const Source::Location& rhs) const {
+ return std::tie(line, column) <= std::tie(rhs.line, rhs.column);
+ }
+
+ /// Returns true if `this` location is lexicographically greater than `rhs`
+ /// @param rhs location to compare against
+ /// @returns true if `this` > `rhs`
+ inline bool operator>(const Source::Location& rhs) const {
+ return std::tie(line, column) > std::tie(rhs.line, rhs.column);
+ }
+
+ /// Returns true if `this` location is lexicographically greater than or equal to `rhs`
+ /// @param rhs location to compare against
+ /// @returns true if `this` >= `rhs`
+ inline bool operator>=(const Source::Location& rhs) const {
+ return std::tie(line, column) >= std::tie(rhs.line, rhs.column);
+ }
+
/// Returns true of `this` location is equal to `rhs`
/// @param rhs location to compare against
/// @returns true if `this` == `rhs`