Import Tint changes from Dawn
Changes:
- 6cc183c85a24e8dafbba87fd0f242ede0810f478 Generic template and forward in stringstream. by dan sinclair <dsinclair@chromium.org>
- 03de0e83aeb62e8282c3a7b31d2ba01155ebae30 Move tint::transform::Robustness to a santizier transform by Ben Clayton <bclayton@google.com>
- d7ee9c1510dc7b90457fd77c1cc4359492d416fa tint/sem: Add Declaration() override for IndexAccessorExp... by Ben Clayton <bclayton@google.com>
- 1edc2729049705022c6aff1188bc32d2164af84a tint/transform: Implement CreateASTTypeFor() for pointers by Ben Clayton <bclayton@google.com>
- 57be2ff2eb03eba86fb4b3e0b1bd9cc1869969fa tint: Change CloneContext::Replace() to replace the map e... by Ben Clayton <bclayton@google.com>
- 26157557e86d8aa80e152660e4c0410a455d7a12 tint/transform/utils: Add HoistToDeclBefore::Replace() by Ben Clayton <bclayton@google.com>
- c0c8abc56978905bf05fccafeeb406709d885366 tint/resolver: Add missing ResolvedIdentifier case for 'l... by Ben Clayton <bclayton@google.com>
- 3cde73cb1a07f8dc88974ddd7324011956f592f1 tint/transform/utils: Correctly scope for-loop init by Ben Clayton <bclayton@google.com>
GitOrigin-RevId: 6cc183c85a24e8dafbba87fd0f242ede0810f478
Change-Id: Iac8248e5d7f6906ff486082f43466207fc64f6c4
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/122500
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/include/tint/tint.h b/include/tint/tint.h
index cdda85c..c405175 100644
--- a/include/tint/tint.h
+++ b/include/tint/tint.h
@@ -32,7 +32,6 @@
#include "src/tint/transform/manager.h"
#include "src/tint/transform/multiplanar_external_texture.h"
#include "src/tint/transform/renamer.h"
-#include "src/tint/transform/robustness.h"
#include "src/tint/transform/single_entry_point.h"
#include "src/tint/transform/substitute_override.h"
#include "src/tint/transform/vertex_pulling.h"
diff --git a/src/tint/ast/binary_expression.h b/src/tint/ast/binary_expression.h
index 35ca308..b314250 100644
--- a/src/tint/ast/binary_expression.h
+++ b/src/tint/ast/binary_expression.h
@@ -297,10 +297,10 @@
return "<invalid>";
}
-/// @param out the std::ostream to write to
+/// @param out the stream to write to
/// @param op the BinaryOp
-/// @return the std::ostream so calls can be chained
-inline std::ostream& operator<<(std::ostream& out, BinaryOp op) {
+/// @return the stream so calls can be chained
+inline utils::StringStream& operator<<(utils::StringStream& out, BinaryOp op) {
out << FriendlyName(op);
return out;
}
diff --git a/src/tint/ast/builtin_texture_helper_test.cc b/src/tint/ast/builtin_texture_helper_test.cc
index 6451bfe..658b650 100644
--- a/src/tint/ast/builtin_texture_helper_test.cc
+++ b/src/tint/ast/builtin_texture_helper_test.cc
@@ -23,6 +23,45 @@
using namespace tint::number_suffixes; // NOLINT
namespace tint::ast::builtin::test {
+namespace {
+
+utils::StringStream& operator<<(utils::StringStream& out, const TextureKind& kind) {
+ switch (kind) {
+ case TextureKind::kRegular:
+ out << "regular";
+ break;
+ case TextureKind::kDepth:
+ out << "depth";
+ break;
+ case TextureKind::kDepthMultisampled:
+ out << "depth-multisampled";
+ break;
+ case TextureKind::kMultisampled:
+ out << "multisampled";
+ break;
+ case TextureKind::kStorage:
+ out << "storage";
+ break;
+ }
+ return out;
+}
+
+utils::StringStream& operator<<(utils::StringStream& out, const TextureDataType& ty) {
+ switch (ty) {
+ case TextureDataType::kF32:
+ out << "f32";
+ break;
+ case TextureDataType::kU32:
+ out << "u32";
+ break;
+ case TextureDataType::kI32:
+ out << "i32";
+ break;
+ }
+ return out;
+}
+
+} // namespace
TextureOverloadCase::TextureOverloadCase(ValidTextureOverload o,
const char* desc,
@@ -80,57 +119,24 @@
TextureOverloadCase::TextureOverloadCase(const TextureOverloadCase&) = default;
TextureOverloadCase::~TextureOverloadCase() = default;
-std::ostream& operator<<(std::ostream& out, const TextureKind& kind) {
- switch (kind) {
- case TextureKind::kRegular:
- out << "regular";
- break;
- case TextureKind::kDepth:
- out << "depth";
- break;
- case TextureKind::kDepthMultisampled:
- out << "depth-multisampled";
- break;
- case TextureKind::kMultisampled:
- out << "multisampled";
- break;
- case TextureKind::kStorage:
- out << "storage";
- break;
- }
- return out;
-}
-
-std::ostream& operator<<(std::ostream& out, const TextureDataType& ty) {
- switch (ty) {
- case TextureDataType::kF32:
- out << "f32";
- break;
- case TextureDataType::kU32:
- out << "u32";
- break;
- case TextureDataType::kI32:
- out << "i32";
- break;
- }
- return out;
-}
-
std::ostream& operator<<(std::ostream& out, const TextureOverloadCase& data) {
- out << "TextureOverloadCase " << static_cast<int>(data.overload) << "\n";
- out << data.description << "\n";
- out << "texture_kind: " << data.texture_kind << "\n";
- out << "sampler_kind: ";
+ utils::StringStream str;
+ str << "TextureOverloadCase " << static_cast<int>(data.overload) << "\n";
+ str << data.description << "\n";
+ str << "texture_kind: " << data.texture_kind << "\n";
+ str << "sampler_kind: ";
if (data.texture_kind != TextureKind::kStorage) {
- out << data.sampler_kind;
+ str << data.sampler_kind;
} else {
- out << "<unused>";
+ str << "<unused>";
}
- out << "\n";
- out << "access: " << data.access << "\n";
- out << "texel_format: " << data.texel_format << "\n";
- out << "texture_dimension: " << data.texture_dimension << "\n";
- out << "texture_data_type: " << data.texture_data_type << "\n";
+ str << "\n";
+ str << "access: " << data.access << "\n";
+ str << "texel_format: " << data.texel_format << "\n";
+ str << "texture_dimension: " << data.texture_dimension << "\n";
+ str << "texture_data_type: " << data.texture_data_type << "\n";
+
+ out << str.str();
return out;
}
diff --git a/src/tint/ast/diagnostic_control.h b/src/tint/ast/diagnostic_control.h
index 3a5cd1f..a0f5a9d 100644
--- a/src/tint/ast/diagnostic_control.h
+++ b/src/tint/ast/diagnostic_control.h
@@ -15,7 +15,6 @@
#ifndef SRC_TINT_AST_DIAGNOSTIC_CONTROL_H_
#define SRC_TINT_AST_DIAGNOSTIC_CONTROL_H_
-#include <ostream>
#include <string>
#include <unordered_map>
diff --git a/src/tint/ast/float_literal_expression.cc b/src/tint/ast/float_literal_expression.cc
index 524b56e..5de8821 100644
--- a/src/tint/ast/float_literal_expression.cc
+++ b/src/tint/ast/float_literal_expression.cc
@@ -37,7 +37,7 @@
return ctx->dst->create<FloatLiteralExpression>(src, value, suffix);
}
-std::ostream& operator<<(std::ostream& out, FloatLiteralExpression::Suffix suffix) {
+utils::StringStream& operator<<(utils::StringStream& out, FloatLiteralExpression::Suffix suffix) {
switch (suffix) {
default:
return out;
diff --git a/src/tint/ast/float_literal_expression.h b/src/tint/ast/float_literal_expression.h
index 7f3cd12..7920c78 100644
--- a/src/tint/ast/float_literal_expression.h
+++ b/src/tint/ast/float_literal_expression.h
@@ -56,11 +56,11 @@
const Suffix suffix;
};
-/// Writes the float literal suffix to the std::ostream.
-/// @param out the std::ostream to write to
+/// Writes the float literal suffix to the stream.
+/// @param out the stream to write to
/// @param suffix the suffix to write
/// @returns out so calls can be chained
-std::ostream& operator<<(std::ostream& out, FloatLiteralExpression::Suffix suffix);
+utils::StringStream& operator<<(utils::StringStream& out, FloatLiteralExpression::Suffix suffix);
} // namespace tint::ast
diff --git a/src/tint/ast/int_literal_expression.cc b/src/tint/ast/int_literal_expression.cc
index 502ea9d..b659bbb 100644
--- a/src/tint/ast/int_literal_expression.cc
+++ b/src/tint/ast/int_literal_expression.cc
@@ -35,7 +35,7 @@
return ctx->dst->create<IntLiteralExpression>(src, value, suffix);
}
-std::ostream& operator<<(std::ostream& out, IntLiteralExpression::Suffix suffix) {
+utils::StringStream& operator<<(utils::StringStream& out, IntLiteralExpression::Suffix suffix) {
switch (suffix) {
default:
return out;
diff --git a/src/tint/ast/int_literal_expression.h b/src/tint/ast/int_literal_expression.h
index 10cbbee..0f50ad3 100644
--- a/src/tint/ast/int_literal_expression.h
+++ b/src/tint/ast/int_literal_expression.h
@@ -55,11 +55,11 @@
const Suffix suffix;
};
-/// Writes the integer literal suffix to the std::ostream.
-/// @param out the std::ostream to write to
+/// Writes the integer literal suffix to the stream.
+/// @param out the stream to write to
/// @param suffix the suffix to write
/// @returns out so calls can be chained
-std::ostream& operator<<(std::ostream& out, IntLiteralExpression::Suffix suffix);
+utils::StringStream& operator<<(utils::StringStream& out, IntLiteralExpression::Suffix suffix);
} // namespace tint::ast
diff --git a/src/tint/ast/interpolate_attribute.h b/src/tint/ast/interpolate_attribute.h
index e50d8dd..b3177ed 100644
--- a/src/tint/ast/interpolate_attribute.h
+++ b/src/tint/ast/interpolate_attribute.h
@@ -15,7 +15,6 @@
#ifndef SRC_TINT_AST_INTERPOLATE_ATTRIBUTE_H_
#define SRC_TINT_AST_INTERPOLATE_ATTRIBUTE_H_
-#include <ostream>
#include <string>
#include "src/tint/ast/attribute.h"
diff --git a/src/tint/ast/pipeline_stage.cc b/src/tint/ast/pipeline_stage.cc
index 79157da..72d3aca 100644
--- a/src/tint/ast/pipeline_stage.cc
+++ b/src/tint/ast/pipeline_stage.cc
@@ -16,7 +16,7 @@
namespace tint::ast {
-std::ostream& operator<<(std::ostream& out, PipelineStage stage) {
+utils::StringStream& operator<<(utils::StringStream& out, PipelineStage stage) {
switch (stage) {
case PipelineStage::kNone: {
out << "none";
diff --git a/src/tint/ast/pipeline_stage.h b/src/tint/ast/pipeline_stage.h
index a1b9c0c..5344afd 100644
--- a/src/tint/ast/pipeline_stage.h
+++ b/src/tint/ast/pipeline_stage.h
@@ -15,17 +15,17 @@
#ifndef SRC_TINT_AST_PIPELINE_STAGE_H_
#define SRC_TINT_AST_PIPELINE_STAGE_H_
-#include <ostream>
+#include "src/tint/utils/string_stream.h"
namespace tint::ast {
/// The pipeline stage
enum class PipelineStage { kNone = -1, kVertex, kFragment, kCompute };
-/// @param out the std::ostream to write to
+/// @param out the stream to write to
/// @param stage the PipelineStage
-/// @return the std::ostream so calls can be chained
-std::ostream& operator<<(std::ostream& out, PipelineStage stage);
+/// @return the stream so calls can be chained
+utils::StringStream& operator<<(utils::StringStream& out, PipelineStage stage);
} // namespace tint::ast
diff --git a/src/tint/ast/unary_op.cc b/src/tint/ast/unary_op.cc
index e0afe8d..34d15f7 100644
--- a/src/tint/ast/unary_op.cc
+++ b/src/tint/ast/unary_op.cc
@@ -16,7 +16,7 @@
namespace tint::ast {
-std::ostream& operator<<(std::ostream& out, UnaryOp mod) {
+utils::StringStream& operator<<(utils::StringStream& out, UnaryOp mod) {
switch (mod) {
case UnaryOp::kAddressOf: {
out << "address-of";
diff --git a/src/tint/ast/unary_op.h b/src/tint/ast/unary_op.h
index a861af3..368803d 100644
--- a/src/tint/ast/unary_op.h
+++ b/src/tint/ast/unary_op.h
@@ -15,7 +15,7 @@
#ifndef SRC_TINT_AST_UNARY_OP_H_
#define SRC_TINT_AST_UNARY_OP_H_
-#include <ostream>
+#include "src/tint/utils/string_stream.h"
namespace tint::ast {
@@ -28,10 +28,10 @@
kNot, // !EXPR
};
-/// @param out the std::ostream to write to
+/// @param out the stream to write to
/// @param mod the UnaryOp
-/// @return the std::ostream so calls can be chained
-std::ostream& operator<<(std::ostream& out, UnaryOp mod);
+/// @return the stream so calls can be chained
+utils::StringStream& operator<<(utils::StringStream& out, UnaryOp mod);
} // namespace tint::ast
diff --git a/src/tint/bench/benchmark.cc b/src/tint/bench/benchmark.cc
index 6b072db..5a28e95 100644
--- a/src/tint/bench/benchmark.cc
+++ b/src/tint/bench/benchmark.cc
@@ -15,7 +15,7 @@
#include "src/tint/bench/benchmark.h"
#include <filesystem>
-#include <sstream>
+#include <iostream>
#include <utility>
#include <vector>
diff --git a/src/tint/builtin/access.cc b/src/tint/builtin/access.cc
index 56b326c..15bf700 100644
--- a/src/tint/builtin/access.cc
+++ b/src/tint/builtin/access.cc
@@ -40,7 +40,7 @@
return Access::kUndefined;
}
-std::ostream& operator<<(std::ostream& out, Access value) {
+utils::StringStream& operator<<(utils::StringStream& out, Access value) {
switch (value) {
case Access::kUndefined:
return out << "undefined";
diff --git a/src/tint/builtin/access.h b/src/tint/builtin/access.h
index f59f50e..afc0867 100644
--- a/src/tint/builtin/access.h
+++ b/src/tint/builtin/access.h
@@ -23,7 +23,7 @@
#ifndef SRC_TINT_BUILTIN_ACCESS_H_
#define SRC_TINT_BUILTIN_ACCESS_H_
-#include <ostream>
+#include "src/tint/utils/string_stream.h"
namespace tint::builtin {
@@ -35,10 +35,10 @@
kWrite,
};
-/// @param out the std::ostream to write to
+/// @param out the stream to write to
/// @param value the Access
/// @returns `out` so calls can be chained
-std::ostream& operator<<(std::ostream& out, Access value);
+utils::StringStream& operator<<(utils::StringStream& out, Access value);
/// ParseAccess parses a Access from a string.
/// @param str the string to parse
diff --git a/src/tint/builtin/access.h.tmpl b/src/tint/builtin/access.h.tmpl
index 6e4587a..3b45390 100644
--- a/src/tint/builtin/access.h.tmpl
+++ b/src/tint/builtin/access.h.tmpl
@@ -17,7 +17,7 @@
#ifndef SRC_TINT_BUILTIN_ACCESS_H_
#define SRC_TINT_BUILTIN_ACCESS_H_
-#include <ostream>
+#include "src/tint/utils/string_stream.h"
namespace tint::builtin {
diff --git a/src/tint/builtin/address_space.cc b/src/tint/builtin/address_space.cc
index 3b386b8..545d97a 100644
--- a/src/tint/builtin/address_space.cc
+++ b/src/tint/builtin/address_space.cc
@@ -55,7 +55,7 @@
return AddressSpace::kUndefined;
}
-std::ostream& operator<<(std::ostream& out, AddressSpace value) {
+utils::StringStream& operator<<(utils::StringStream& out, AddressSpace value) {
switch (value) {
case AddressSpace::kUndefined:
return out << "undefined";
diff --git a/src/tint/builtin/address_space.h b/src/tint/builtin/address_space.h
index 55b1557..5334301 100644
--- a/src/tint/builtin/address_space.h
+++ b/src/tint/builtin/address_space.h
@@ -23,7 +23,7 @@
#ifndef SRC_TINT_BUILTIN_ADDRESS_SPACE_H_
#define SRC_TINT_BUILTIN_ADDRESS_SPACE_H_
-#include <ostream>
+#include "src/tint/utils/string_stream.h"
namespace tint::builtin {
@@ -41,10 +41,10 @@
kWorkgroup,
};
-/// @param out the std::ostream to write to
+/// @param out the stream to write to
/// @param value the AddressSpace
/// @returns `out` so calls can be chained
-std::ostream& operator<<(std::ostream& out, AddressSpace value);
+utils::StringStream& operator<<(utils::StringStream& out, AddressSpace value);
/// ParseAddressSpace parses a AddressSpace from a string.
/// @param str the string to parse
diff --git a/src/tint/builtin/address_space.h.tmpl b/src/tint/builtin/address_space.h.tmpl
index 1dd7d35..42103c3 100644
--- a/src/tint/builtin/address_space.h.tmpl
+++ b/src/tint/builtin/address_space.h.tmpl
@@ -17,7 +17,7 @@
#ifndef SRC_TINT_BUILTIN_ADDRESS_SPACE_H_
#define SRC_TINT_BUILTIN_ADDRESS_SPACE_H_
-#include <ostream>
+#include "src/tint/utils/string_stream.h"
namespace tint::builtin {
diff --git a/src/tint/builtin/attribute.cc b/src/tint/builtin/attribute.cc
index d20b77c..33a5171 100644
--- a/src/tint/builtin/attribute.cc
+++ b/src/tint/builtin/attribute.cc
@@ -76,7 +76,7 @@
return Attribute::kUndefined;
}
-std::ostream& operator<<(std::ostream& out, Attribute value) {
+utils::StringStream& operator<<(utils::StringStream& out, Attribute value) {
switch (value) {
case Attribute::kUndefined:
return out << "undefined";
diff --git a/src/tint/builtin/attribute.h b/src/tint/builtin/attribute.h
index bf95458..c975267 100644
--- a/src/tint/builtin/attribute.h
+++ b/src/tint/builtin/attribute.h
@@ -23,7 +23,7 @@
#ifndef SRC_TINT_BUILTIN_ATTRIBUTE_H_
#define SRC_TINT_BUILTIN_ATTRIBUTE_H_
-#include <ostream>
+#include "src/tint/utils/string_stream.h"
/// \cond DO_NOT_DOCUMENT
/// There is a bug in doxygen where this enum conflicts with the ast::Attribute
@@ -50,10 +50,10 @@
kWorkgroupSize,
};
-/// @param out the std::ostream to write to
+/// @param out the stream to write to
/// @param value the Attribute
/// @returns `out` so calls can be chained
-std::ostream& operator<<(std::ostream& out, Attribute value);
+utils::StringStream& operator<<(utils::StringStream& out, Attribute value);
/// ParseAttribute parses a Attribute from a string.
/// @param str the string to parse
diff --git a/src/tint/builtin/attribute.h.tmpl b/src/tint/builtin/attribute.h.tmpl
index 32ca6a3..ca7443d 100644
--- a/src/tint/builtin/attribute.h.tmpl
+++ b/src/tint/builtin/attribute.h.tmpl
@@ -17,7 +17,7 @@
#ifndef SRC_TINT_BUILTIN_ATTRIBUTE_H_
#define SRC_TINT_BUILTIN_ATTRIBUTE_H_
-#include <ostream>
+#include "src/tint/utils/string_stream.h"
/// \cond DO_NOT_DOCUMENT
/// There is a bug in doxygen where this enum conflicts with the ast::Attribute
diff --git a/src/tint/builtin/builtin.cc b/src/tint/builtin/builtin.cc
index dc608d0..085a266 100644
--- a/src/tint/builtin/builtin.cc
+++ b/src/tint/builtin/builtin.cc
@@ -241,7 +241,7 @@
return Builtin::kUndefined;
}
-std::ostream& operator<<(std::ostream& out, Builtin value) {
+utils::StringStream& operator<<(utils::StringStream& out, Builtin value) {
switch (value) {
case Builtin::kUndefined:
return out << "undefined";
diff --git a/src/tint/builtin/builtin.h b/src/tint/builtin/builtin.h
index 25bac8b..da5226d 100644
--- a/src/tint/builtin/builtin.h
+++ b/src/tint/builtin/builtin.h
@@ -23,7 +23,7 @@
#ifndef SRC_TINT_BUILTIN_BUILTIN_H_
#define SRC_TINT_BUILTIN_BUILTIN_H_
-#include <ostream>
+#include "src/tint/utils/string_stream.h"
namespace tint::builtin {
@@ -102,10 +102,10 @@
kVec4U,
};
-/// @param out the std::ostream to write to
+/// @param out the stream to write to
/// @param value the Builtin
/// @returns `out` so calls can be chained
-std::ostream& operator<<(std::ostream& out, Builtin value);
+utils::StringStream& operator<<(utils::StringStream& out, Builtin value);
/// ParseBuiltin parses a Builtin from a string.
/// @param str the string to parse
diff --git a/src/tint/builtin/builtin.h.tmpl b/src/tint/builtin/builtin.h.tmpl
index 4fce648..f63b20d 100644
--- a/src/tint/builtin/builtin.h.tmpl
+++ b/src/tint/builtin/builtin.h.tmpl
@@ -18,7 +18,7 @@
#ifndef SRC_TINT_BUILTIN_BUILTIN_H_
#define SRC_TINT_BUILTIN_BUILTIN_H_
-#include <ostream>
+#include "src/tint/utils/string_stream.h"
namespace tint::builtin {
diff --git a/src/tint/builtin/builtin_value.cc b/src/tint/builtin/builtin_value.cc
index 150ac7b..5e06c50 100644
--- a/src/tint/builtin/builtin_value.cc
+++ b/src/tint/builtin/builtin_value.cc
@@ -70,7 +70,7 @@
return BuiltinValue::kUndefined;
}
-std::ostream& operator<<(std::ostream& out, BuiltinValue value) {
+utils::StringStream& operator<<(utils::StringStream& out, BuiltinValue value) {
switch (value) {
case BuiltinValue::kUndefined:
return out << "undefined";
diff --git a/src/tint/builtin/builtin_value.h b/src/tint/builtin/builtin_value.h
index 4f8753f..fc1f39b 100644
--- a/src/tint/builtin/builtin_value.h
+++ b/src/tint/builtin/builtin_value.h
@@ -23,7 +23,7 @@
#ifndef SRC_TINT_BUILTIN_BUILTIN_VALUE_H_
#define SRC_TINT_BUILTIN_BUILTIN_VALUE_H_
-#include <ostream>
+#include "src/tint/utils/string_stream.h"
namespace tint::builtin {
@@ -45,10 +45,10 @@
kWorkgroupId,
};
-/// @param out the std::ostream to write to
+/// @param out the stream to write to
/// @param value the BuiltinValue
/// @returns `out` so calls can be chained
-std::ostream& operator<<(std::ostream& out, BuiltinValue value);
+utils::StringStream& operator<<(utils::StringStream& out, BuiltinValue value);
/// ParseBuiltinValue parses a BuiltinValue from a string.
/// @param str the string to parse
diff --git a/src/tint/builtin/builtin_value.h.tmpl b/src/tint/builtin/builtin_value.h.tmpl
index 46e806e..dae642a 100644
--- a/src/tint/builtin/builtin_value.h.tmpl
+++ b/src/tint/builtin/builtin_value.h.tmpl
@@ -14,7 +14,7 @@
#ifndef SRC_TINT_BUILTIN_BUILTIN_VALUE_H_
#define SRC_TINT_BUILTIN_BUILTIN_VALUE_H_
-#include <ostream>
+#include "src/tint/utils/string_stream.h"
namespace tint::builtin {
diff --git a/src/tint/builtin/diagnostic_rule.cc b/src/tint/builtin/diagnostic_rule.cc
index 7b020d5..69650cb 100644
--- a/src/tint/builtin/diagnostic_rule.cc
+++ b/src/tint/builtin/diagnostic_rule.cc
@@ -22,9 +22,10 @@
#include "src/tint/builtin/diagnostic_rule.h"
-#include <ostream>
#include <string>
+#include "src/tint/utils/string_stream.h"
+
namespace tint::builtin {
/// ParseDiagnosticRule parses a DiagnosticRule from a string.
@@ -40,7 +41,7 @@
return DiagnosticRule::kUndefined;
}
-std::ostream& operator<<(std::ostream& out, DiagnosticRule value) {
+utils::StringStream& operator<<(utils::StringStream& out, DiagnosticRule value) {
switch (value) {
case DiagnosticRule::kUndefined:
return out << "undefined";
diff --git a/src/tint/builtin/diagnostic_rule.cc.tmpl b/src/tint/builtin/diagnostic_rule.cc.tmpl
index 4cf05a4..8705485 100644
--- a/src/tint/builtin/diagnostic_rule.cc.tmpl
+++ b/src/tint/builtin/diagnostic_rule.cc.tmpl
@@ -12,9 +12,10 @@
#include "src/tint/builtin/diagnostic_rule.h"
-#include <ostream>
#include <string>
+#include "src/tint/utils/string_stream.h"
+
namespace tint::builtin {
{{ Eval "ParseEnum" (Sem.Enum "diagnostic_rule")}}
diff --git a/src/tint/builtin/diagnostic_rule.h b/src/tint/builtin/diagnostic_rule.h
index 55a6aab..6b6d094 100644
--- a/src/tint/builtin/diagnostic_rule.h
+++ b/src/tint/builtin/diagnostic_rule.h
@@ -25,6 +25,8 @@
#include <string>
+#include "src/tint/utils/string_stream.h"
+
namespace tint::builtin {
/// The diagnostic rule.
@@ -34,10 +36,10 @@
kDerivativeUniformity,
};
-/// @param out the std::ostream to write to
+/// @param out the stream to write to
/// @param value the DiagnosticRule
/// @returns `out` so calls can be chained
-std::ostream& operator<<(std::ostream& out, DiagnosticRule value);
+utils::StringStream& operator<<(utils::StringStream& out, DiagnosticRule value);
/// ParseDiagnosticRule parses a DiagnosticRule from a string.
/// @param str the string to parse
diff --git a/src/tint/builtin/diagnostic_rule.h.tmpl b/src/tint/builtin/diagnostic_rule.h.tmpl
index 2e6f7f9..ba823e3 100644
--- a/src/tint/builtin/diagnostic_rule.h.tmpl
+++ b/src/tint/builtin/diagnostic_rule.h.tmpl
@@ -15,6 +15,8 @@
#include <string>
+#include "src/tint/utils/string_stream.h"
+
namespace tint::builtin {
/// The diagnostic rule.
diff --git a/src/tint/builtin/diagnostic_severity.cc b/src/tint/builtin/diagnostic_severity.cc
index 8c14a9a..5d68992 100644
--- a/src/tint/builtin/diagnostic_severity.cc
+++ b/src/tint/builtin/diagnostic_severity.cc
@@ -58,7 +58,7 @@
return DiagnosticSeverity::kUndefined;
}
-std::ostream& operator<<(std::ostream& out, DiagnosticSeverity value) {
+utils::StringStream& operator<<(utils::StringStream& out, DiagnosticSeverity value) {
switch (value) {
case DiagnosticSeverity::kUndefined:
return out << "undefined";
diff --git a/src/tint/builtin/diagnostic_severity.h b/src/tint/builtin/diagnostic_severity.h
index daef0f7..44a3b41 100644
--- a/src/tint/builtin/diagnostic_severity.h
+++ b/src/tint/builtin/diagnostic_severity.h
@@ -23,12 +23,12 @@
#ifndef SRC_TINT_BUILTIN_DIAGNOSTIC_SEVERITY_H_
#define SRC_TINT_BUILTIN_DIAGNOSTIC_SEVERITY_H_
-#include <ostream>
#include <string>
#include <unordered_map>
#include "src/tint/builtin/diagnostic_rule.h"
#include "src/tint/diagnostic/diagnostic.h"
+#include "src/tint/utils/string_stream.h"
namespace tint::builtin {
@@ -41,10 +41,10 @@
kWarning,
};
-/// @param out the std::ostream to write to
+/// @param out the stream to write to
/// @param value the DiagnosticSeverity
/// @returns `out` so calls can be chained
-std::ostream& operator<<(std::ostream& out, DiagnosticSeverity value);
+utils::StringStream& operator<<(utils::StringStream& out, DiagnosticSeverity value);
/// ParseDiagnosticSeverity parses a DiagnosticSeverity from a string.
/// @param str the string to parse
diff --git a/src/tint/builtin/diagnostic_severity.h.tmpl b/src/tint/builtin/diagnostic_severity.h.tmpl
index 7580b2c..7773d6c 100644
--- a/src/tint/builtin/diagnostic_severity.h.tmpl
+++ b/src/tint/builtin/diagnostic_severity.h.tmpl
@@ -13,10 +13,10 @@
#ifndef SRC_TINT_BUILTIN_DIAGNOSTIC_SEVERITY_H_
#define SRC_TINT_BUILTIN_DIAGNOSTIC_SEVERITY_H_
-#include <ostream>
#include <string>
#include <unordered_map>
+#include "src/tint/utils/string_stream.h"
#include "src/tint/builtin/diagnostic_rule.h"
#include "src/tint/diagnostic/diagnostic.h"
diff --git a/src/tint/builtin/extension.cc b/src/tint/builtin/extension.cc
index 36171db..aca6220 100644
--- a/src/tint/builtin/extension.cc
+++ b/src/tint/builtin/extension.cc
@@ -49,7 +49,7 @@
return Extension::kUndefined;
}
-std::ostream& operator<<(std::ostream& out, Extension value) {
+utils::StringStream& operator<<(utils::StringStream& out, Extension value) {
switch (value) {
case Extension::kUndefined:
return out << "undefined";
diff --git a/src/tint/builtin/extension.h b/src/tint/builtin/extension.h
index aace504..6beeda3 100644
--- a/src/tint/builtin/extension.h
+++ b/src/tint/builtin/extension.h
@@ -23,8 +23,7 @@
#ifndef SRC_TINT_BUILTIN_EXTENSION_H_
#define SRC_TINT_BUILTIN_EXTENSION_H_
-#include <ostream>
-
+#include "src/tint/utils/string_stream.h"
#include "src/tint/utils/unique_vector.h"
namespace tint::builtin {
@@ -41,10 +40,10 @@
kF16,
};
-/// @param out the std::ostream to write to
+/// @param out the stream to write to
/// @param value the Extension
/// @returns `out` so calls can be chained
-std::ostream& operator<<(std::ostream& out, Extension value);
+utils::StringStream& operator<<(utils::StringStream& out, Extension value);
/// ParseExtension parses a Extension from a string.
/// @param str the string to parse
diff --git a/src/tint/builtin/extension.h.tmpl b/src/tint/builtin/extension.h.tmpl
index 3051ad4..07f3ee4 100644
--- a/src/tint/builtin/extension.h.tmpl
+++ b/src/tint/builtin/extension.h.tmpl
@@ -14,8 +14,7 @@
#ifndef SRC_TINT_BUILTIN_EXTENSION_H_
#define SRC_TINT_BUILTIN_EXTENSION_H_
-#include <ostream>
-
+#include "src/tint/utils/string_stream.h"
#include "src/tint/utils/unique_vector.h"
namespace tint::builtin {
diff --git a/src/tint/builtin/interpolation_sampling.cc b/src/tint/builtin/interpolation_sampling.cc
index 8b39930..30d925a 100644
--- a/src/tint/builtin/interpolation_sampling.cc
+++ b/src/tint/builtin/interpolation_sampling.cc
@@ -43,7 +43,7 @@
return InterpolationSampling::kUndefined;
}
-std::ostream& operator<<(std::ostream& out, InterpolationSampling value) {
+utils::StringStream& operator<<(utils::StringStream& out, InterpolationSampling value) {
switch (value) {
case InterpolationSampling::kUndefined:
return out << "undefined";
diff --git a/src/tint/builtin/interpolation_sampling.h b/src/tint/builtin/interpolation_sampling.h
index a3fc357..78a9d51 100644
--- a/src/tint/builtin/interpolation_sampling.h
+++ b/src/tint/builtin/interpolation_sampling.h
@@ -23,9 +23,10 @@
#ifndef SRC_TINT_BUILTIN_INTERPOLATION_SAMPLING_H_
#define SRC_TINT_BUILTIN_INTERPOLATION_SAMPLING_H_
-#include <ostream>
#include <string>
+#include "src/tint/utils/string_stream.h"
+
namespace tint::builtin {
/// The interpolation sampling.
@@ -36,10 +37,10 @@
kSample,
};
-/// @param out the std::ostream to write to
+/// @param out the stream to write to
/// @param value the InterpolationSampling
/// @returns `out` so calls can be chained
-std::ostream& operator<<(std::ostream& out, InterpolationSampling value);
+utils::StringStream& operator<<(utils::StringStream& out, InterpolationSampling value);
/// ParseInterpolationSampling parses a InterpolationSampling from a string.
/// @param str the string to parse
diff --git a/src/tint/builtin/interpolation_sampling.h.tmpl b/src/tint/builtin/interpolation_sampling.h.tmpl
index 24b3b02..eacc2a1 100644
--- a/src/tint/builtin/interpolation_sampling.h.tmpl
+++ b/src/tint/builtin/interpolation_sampling.h.tmpl
@@ -13,9 +13,10 @@
#ifndef SRC_TINT_BUILTIN_INTERPOLATION_SAMPLING_H_
#define SRC_TINT_BUILTIN_INTERPOLATION_SAMPLING_H_
-#include <ostream>
#include <string>
+#include "src/tint/utils/string_stream.h"
+
namespace tint::builtin {
/// The interpolation sampling.
diff --git a/src/tint/builtin/interpolation_type.cc b/src/tint/builtin/interpolation_type.cc
index ee3f68b..349d3e9 100644
--- a/src/tint/builtin/interpolation_type.cc
+++ b/src/tint/builtin/interpolation_type.cc
@@ -42,7 +42,7 @@
return InterpolationType::kUndefined;
}
-std::ostream& operator<<(std::ostream& out, InterpolationType value) {
+utils::StringStream& operator<<(utils::StringStream& out, InterpolationType value) {
switch (value) {
case InterpolationType::kUndefined:
return out << "undefined";
diff --git a/src/tint/builtin/interpolation_type.h b/src/tint/builtin/interpolation_type.h
index ee54964..bd32923 100644
--- a/src/tint/builtin/interpolation_type.h
+++ b/src/tint/builtin/interpolation_type.h
@@ -23,9 +23,10 @@
#ifndef SRC_TINT_BUILTIN_INTERPOLATION_TYPE_H_
#define SRC_TINT_BUILTIN_INTERPOLATION_TYPE_H_
-#include <ostream>
#include <string>
+#include "src/tint/utils/string_stream.h"
+
namespace tint::builtin {
/// The interpolation type.
@@ -36,10 +37,10 @@
kPerspective,
};
-/// @param out the std::ostream to write to
+/// @param out the stream to write to
/// @param value the InterpolationType
/// @returns `out` so calls can be chained
-std::ostream& operator<<(std::ostream& out, InterpolationType value);
+utils::StringStream& operator<<(utils::StringStream& out, InterpolationType value);
/// ParseInterpolationType parses a InterpolationType from a string.
/// @param str the string to parse
diff --git a/src/tint/builtin/interpolation_type.h.tmpl b/src/tint/builtin/interpolation_type.h.tmpl
index c869a96..7114fd1 100644
--- a/src/tint/builtin/interpolation_type.h.tmpl
+++ b/src/tint/builtin/interpolation_type.h.tmpl
@@ -13,9 +13,10 @@
#ifndef SRC_TINT_BUILTIN_INTERPOLATION_TYPE_H_
#define SRC_TINT_BUILTIN_INTERPOLATION_TYPE_H_
-#include <ostream>
#include <string>
+#include "src/tint/utils/string_stream.h"
+
namespace tint::builtin {
/// The interpolation type.
diff --git a/src/tint/builtin/texel_format.cc b/src/tint/builtin/texel_format.cc
index dc4bbfe..4e1b8b7 100644
--- a/src/tint/builtin/texel_format.cc
+++ b/src/tint/builtin/texel_format.cc
@@ -82,7 +82,7 @@
return TexelFormat::kUndefined;
}
-std::ostream& operator<<(std::ostream& out, TexelFormat value) {
+utils::StringStream& operator<<(utils::StringStream& out, TexelFormat value) {
switch (value) {
case TexelFormat::kUndefined:
return out << "undefined";
diff --git a/src/tint/builtin/texel_format.h b/src/tint/builtin/texel_format.h
index 9611e62..6643523 100644
--- a/src/tint/builtin/texel_format.h
+++ b/src/tint/builtin/texel_format.h
@@ -23,7 +23,7 @@
#ifndef SRC_TINT_BUILTIN_TEXEL_FORMAT_H_
#define SRC_TINT_BUILTIN_TEXEL_FORMAT_H_
-#include <ostream>
+#include "src/tint/utils/string_stream.h"
namespace tint::builtin {
@@ -49,10 +49,10 @@
kRgba8Unorm,
};
-/// @param out the std::ostream to write to
+/// @param out the stream to write to
/// @param value the TexelFormat
/// @returns `out` so calls can be chained
-std::ostream& operator<<(std::ostream& out, TexelFormat value);
+utils::StringStream& operator<<(utils::StringStream& out, TexelFormat value);
/// ParseTexelFormat parses a TexelFormat from a string.
/// @param str the string to parse
diff --git a/src/tint/builtin/texel_format.h.tmpl b/src/tint/builtin/texel_format.h.tmpl
index a3a9e31..b00e1f8 100644
--- a/src/tint/builtin/texel_format.h.tmpl
+++ b/src/tint/builtin/texel_format.h.tmpl
@@ -14,7 +14,7 @@
#ifndef SRC_TINT_BUILTIN_TEXEL_FORMAT_H_
#define SRC_TINT_BUILTIN_TEXEL_FORMAT_H_
-#include <ostream>
+#include "src/tint/utils/string_stream.h"
namespace tint::builtin {
diff --git a/src/tint/clone_context.h b/src/tint/clone_context.h
index 188ee25..8e0e2ff 100644
--- a/src/tint/clone_context.h
+++ b/src/tint/clone_context.h
@@ -359,7 +359,7 @@
CloneContext& Replace(const WHAT* what, const WITH* with) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, what);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, dst, with);
- replacements_.Add(what, [with]() -> const Cloneable* { return with; });
+ replacements_.Replace(what, [with]() -> const Cloneable* { return with; });
return *this;
}
@@ -379,7 +379,7 @@
template <typename WHAT, typename WITH, typename = std::invoke_result_t<WITH>>
CloneContext& Replace(const WHAT* what, WITH&& with) {
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(Clone, src, what);
- replacements_.Add(what, with);
+ replacements_.Replace(what, with);
return *this;
}
diff --git a/src/tint/clone_context_test.cc b/src/tint/clone_context_test.cc
index f2ed247..59c47c0 100644
--- a/src/tint/clone_context_test.cc
+++ b/src/tint/clone_context_test.cc
@@ -339,6 +339,45 @@
EXPECT_EQ(cloned_root->c->name, cloned.Symbols().Get("c"));
}
+TEST_F(CloneContextNodeTest, CloneWithRepeatedImmediateReplacePointer) {
+ Allocator a;
+
+ ProgramBuilder builder;
+ auto* original_root = a.Create<Node>(builder.Symbols().New("root"));
+ original_root->a = a.Create<Node>(builder.Symbols().New("a"));
+ original_root->b = a.Create<Node>(builder.Symbols().New("b"));
+ original_root->c = a.Create<Node>(builder.Symbols().New("c"));
+ Program original(std::move(builder));
+
+ ProgramBuilder cloned;
+
+ CloneContext ctx(&cloned, &original);
+
+ // Demonstrate that ctx.Replace() can be called multiple times to update the replacement of a
+ // node.
+
+ auto* replacement_x =
+ a.Create<Node>(cloned.Symbols().New("replacement_x"), ctx.Clone(original_root->b));
+ ctx.Replace(original_root->b, replacement_x);
+
+ auto* replacement_y =
+ a.Create<Node>(cloned.Symbols().New("replacement_y"), ctx.Clone(original_root->b));
+ ctx.Replace(original_root->b, replacement_y);
+
+ auto* replacement_z =
+ a.Create<Node>(cloned.Symbols().New("replacement_z"), ctx.Clone(original_root->b));
+ ctx.Replace(original_root->b, replacement_z);
+
+ auto* cloned_root = ctx.Clone(original_root);
+
+ EXPECT_NE(cloned_root->a, replacement_z);
+ EXPECT_EQ(cloned_root->b, replacement_z);
+ EXPECT_NE(cloned_root->c, replacement_z);
+
+ EXPECT_EQ(replacement_z->a, replacement_y);
+ EXPECT_EQ(replacement_y->a, replacement_x);
+}
+
TEST_F(CloneContextNodeTest, CloneWithReplaceFunction) {
Allocator a;
@@ -371,6 +410,45 @@
EXPECT_EQ(cloned_root->c->name, cloned.Symbols().Get("c"));
}
+TEST_F(CloneContextNodeTest, CloneWithRepeatedImmediateReplaceFunction) {
+ Allocator a;
+
+ ProgramBuilder builder;
+ auto* original_root = a.Create<Node>(builder.Symbols().New("root"));
+ original_root->a = a.Create<Node>(builder.Symbols().New("a"));
+ original_root->b = a.Create<Node>(builder.Symbols().New("b"));
+ original_root->c = a.Create<Node>(builder.Symbols().New("c"));
+ Program original(std::move(builder));
+
+ ProgramBuilder cloned;
+
+ CloneContext ctx(&cloned, &original);
+
+ // Demonstrate that ctx.Replace() can be called multiple times to update the replacement of a
+ // node.
+
+ Node* replacement_x =
+ a.Create<Node>(cloned.Symbols().New("replacement_x"), ctx.Clone(original_root->b));
+ ctx.Replace(original_root->b, [&] { return replacement_x; });
+
+ Node* replacement_y =
+ a.Create<Node>(cloned.Symbols().New("replacement_y"), ctx.Clone(original_root->b));
+ ctx.Replace(original_root->b, [&] { return replacement_y; });
+
+ Node* replacement_z =
+ a.Create<Node>(cloned.Symbols().New("replacement_z"), ctx.Clone(original_root->b));
+ ctx.Replace(original_root->b, [&] { return replacement_z; });
+
+ auto* cloned_root = ctx.Clone(original_root);
+
+ EXPECT_NE(cloned_root->a, replacement_z);
+ EXPECT_EQ(cloned_root->b, replacement_z);
+ EXPECT_NE(cloned_root->c, replacement_z);
+
+ EXPECT_EQ(replacement_z->a, replacement_y);
+ EXPECT_EQ(replacement_y->a, replacement_x);
+}
+
TEST_F(CloneContextNodeTest, CloneWithRemove) {
Allocator a;
diff --git a/src/tint/cmd/helper.cc b/src/tint/cmd/helper.cc
index f3760da..c31178d 100644
--- a/src/tint/cmd/helper.cc
+++ b/src/tint/cmd/helper.cc
@@ -14,6 +14,7 @@
#include "src/tint/cmd/helper.h"
+#include <iostream>
#include <utility>
#include <vector>
diff --git a/src/tint/cmd/info.cc b/src/tint/cmd/info.cc
index 6c244ad..c31095c 100644
--- a/src/tint/cmd/info.cc
+++ b/src/tint/cmd/info.cc
@@ -13,6 +13,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <iostream>
+
#if TINT_BUILD_SPV_READER
#include "spirv-tools/libspirv.hpp"
#endif // TINT_BUILD_SPV_READER
diff --git a/src/tint/cmd/main.cc b/src/tint/cmd/main.cc
index 12d5b8c..0b2aad2 100644
--- a/src/tint/cmd/main.cc
+++ b/src/tint/cmd/main.cc
@@ -79,6 +79,7 @@
bool print_hash = false;
bool demangle = false;
bool dump_inspector_bindings = false;
+ bool enable_robustness = false;
std::unordered_set<uint32_t> skip_hash;
@@ -533,6 +534,7 @@
#if TINT_BUILD_SPV_WRITER
// TODO(jrprice): Provide a way for the user to set non-default options.
tint::writer::spirv::Options gen_options;
+ gen_options.disable_robustness = !options.enable_robustness;
gen_options.disable_workgroup_init = options.disable_workgroup_init;
gen_options.generate_external_texture_bindings = true;
auto result = tint::writer::spirv::Generate(program, gen_options);
@@ -639,6 +641,7 @@
// TODO(jrprice): Provide a way for the user to set non-default options.
tint::writer::msl::Options gen_options;
+ gen_options.disable_robustness = !options.enable_robustness;
gen_options.disable_workgroup_init = options.disable_workgroup_init;
gen_options.generate_external_texture_bindings = true;
auto result = tint::writer::msl::Generate(input_program, gen_options);
@@ -699,6 +702,7 @@
#if TINT_BUILD_HLSL_WRITER
// TODO(jrprice): Provide a way for the user to set non-default options.
tint::writer::hlsl::Options gen_options;
+ gen_options.disable_robustness = !options.enable_robustness;
gen_options.disable_workgroup_init = options.disable_workgroup_init;
gen_options.generate_external_texture_bindings = true;
gen_options.root_constant_binding_point = options.hlsl_root_constant_binding_point;
@@ -838,6 +842,7 @@
auto generate = [&](const tint::Program* prg, const std::string entry_point_name) -> bool {
tint::writer::glsl::Options gen_options;
+ gen_options.disable_robustness = !options.enable_robustness;
gen_options.generate_external_texture_bindings = true;
auto result = tint::writer::glsl::Generate(prg, gen_options, entry_point_name);
if (!result.success) {
@@ -946,8 +951,9 @@
return true;
}},
{"robustness",
- [](tint::inspector::Inspector&, tint::transform::Manager& m, tint::transform::DataMap&) {
- m.Add<tint::transform::Robustness>();
+ [&](tint::inspector::Inspector&, tint::transform::Manager&,
+ tint::transform::DataMap&) { // enabled via writer option
+ options.enable_robustness = true;
return true;
}},
{"substitute_override",
diff --git a/src/tint/diagnostic/formatter.cc b/src/tint/diagnostic/formatter.cc
index 18520fc..9752838 100644
--- a/src/tint/diagnostic/formatter.cc
+++ b/src/tint/diagnostic/formatter.cc
@@ -16,6 +16,7 @@
#include <algorithm>
#include <iterator>
+#include <utility>
#include <vector>
#include "src/tint/diagnostic/diagnostic.h"
@@ -85,8 +86,8 @@
/// @param msg the value or string to write to the printer
/// @returns this State so that calls can be chained
template <typename T>
- State& operator<<(const T& msg) {
- stream << msg;
+ State& operator<<(T&& msg) {
+ stream << std::forward<T>(msg);
return *this;
}
diff --git a/src/tint/diagnostic/printer.h b/src/tint/diagnostic/printer.h
index 9e4ce7c..5e7752c 100644
--- a/src/tint/diagnostic/printer.h
+++ b/src/tint/diagnostic/printer.h
@@ -16,7 +16,6 @@
#define SRC_TINT_DIAGNOSTIC_PRINTER_H_
#include <memory>
-#include <sstream>
#include <string>
#include "src/tint/utils/string_stream.h"
diff --git a/src/tint/fuzzers/tint_common_fuzzer.cc b/src/tint/fuzzers/tint_common_fuzzer.cc
index 11cdf76..c4f1fd1 100644
--- a/src/tint/fuzzers/tint_common_fuzzer.cc
+++ b/src/tint/fuzzers/tint_common_fuzzer.cc
@@ -17,6 +17,7 @@
#include <cassert>
#include <cstring>
#include <fstream>
+#include <iostream>
#include <memory>
#include <sstream>
#include <string>
diff --git a/src/tint/fuzzers/tint_reader_writer_fuzzer.h b/src/tint/fuzzers/tint_reader_writer_fuzzer.h
index 0104c9d..b5d0a95 100644
--- a/src/tint/fuzzers/tint_reader_writer_fuzzer.h
+++ b/src/tint/fuzzers/tint_reader_writer_fuzzer.h
@@ -43,16 +43,14 @@
CommonFuzzer::SetTransformManager(tm, inputs);
}
- /// Pass through to the CommonFuzzer implementation, but will setup a
- /// robustness transform, if no other transforms have been set.
- /// @param data buffer of data that will interpreted as a byte array or string
- /// depending on the shader input format.
+ /// Pass through to the CommonFuzzer implementation.
+ /// @param data buffer of data that will interpreted as a byte array or string depending on the
+ /// shader input format.
/// @param size number of elements in buffer
/// @returns 0, this is what libFuzzer expects
int Run(const uint8_t* data, size_t size) {
if (!tm_set_) {
tb_ = std::make_unique<TransformBuilder>(data, size);
- tb_->AddTransform<tint::transform::Robustness>();
SetTransformManager(tb_->manager(), tb_->data_map());
}
diff --git a/src/tint/fuzzers/tint_robustness_fuzzer.cc b/src/tint/fuzzers/tint_robustness_fuzzer.cc
index dfc9a03..4b5eaa6 100644
--- a/src/tint/fuzzers/tint_robustness_fuzzer.cc
+++ b/src/tint/fuzzers/tint_robustness_fuzzer.cc
@@ -15,6 +15,7 @@
#include "src/tint/fuzzers/fuzzer_init.h"
#include "src/tint/fuzzers/tint_common_fuzzer.h"
#include "src/tint/fuzzers/transform_builder.h"
+#include "src/tint/transform/robustness.h"
namespace tint::fuzzers {
diff --git a/src/tint/fuzzers/transform_builder.h b/src/tint/fuzzers/transform_builder.h
index 73b5b51..787abb9 100644
--- a/src/tint/fuzzers/transform_builder.h
+++ b/src/tint/fuzzers/transform_builder.h
@@ -22,6 +22,7 @@
#include "src/tint/fuzzers/data_builder.h"
#include "src/tint/fuzzers/shuffle_transform.h"
+#include "src/tint/transform/robustness.h"
namespace tint::fuzzers {
@@ -61,7 +62,6 @@
/// Helper that invokes Add*Transform for all of the platform independent
/// passes.
void AddPlatformIndependentPasses() {
- AddTransform<transform::Robustness>();
AddTransform<transform::FirstIndexOffset>();
AddTransform<transform::BindingRemapper>();
AddTransform<transform::Renamer>();
diff --git a/src/tint/inspector/test_inspector_builder.cc b/src/tint/inspector/test_inspector_builder.cc
index ad576b9..9f92d6d 100644
--- a/src/tint/inspector/test_inspector_builder.cc
+++ b/src/tint/inspector/test_inspector_builder.cc
@@ -273,7 +273,11 @@
case type::TextureDimension::kCubeArray:
return ty.vec3(scalar);
default:
- [=]() { FAIL() << "Unsupported texture dimension: " << dim; }();
+ [=]() {
+ utils::StringStream str;
+ str << dim;
+ FAIL() << "Unsupported texture dimension: " << str.str();
+ }();
}
return ast::Type{};
}
diff --git a/src/tint/intrinsics.def b/src/tint/intrinsics.def
index 7a5334f..45d77c8 100644
--- a/src/tint/intrinsics.def
+++ b/src/tint/intrinsics.def
@@ -544,8 +544,8 @@
@must_use @const fn abs<N: num, T: fia_fiu32_f16>(vec<N, T>) -> vec<N, T>
@must_use @const fn acos<T: fa_f32_f16>(@test_value(0.96891242171) T) -> T
@must_use @const fn acos<N: num, T: fa_f32_f16>(@test_value(0.96891242171) vec<N, T>) -> vec<N, T>
-@must_use @const fn acosh<T: fa_f32_f16>(@test_value(2.0) T) -> T
-@must_use @const fn acosh<N: num, T: fa_f32_f16>(@test_value(2.0) vec<N, T>) -> vec<N, T>
+@must_use @const fn acosh<T: fa_f32_f16>(@test_value(1.5430806348) T) -> T
+@must_use @const fn acosh<N: num, T: fa_f32_f16>(@test_value(1.5430806348) vec<N, T>) -> vec<N, T>
@must_use @const fn all(bool) -> bool
@must_use @const fn all<N: num>(vec<N, bool>) -> bool
@must_use @const fn any(bool) -> bool
@@ -658,8 +658,8 @@
@must_use @const fn refract<N: num, T: fa_f32_f16>(vec<N, T>, vec<N, T>, T) -> vec<N, T>
@must_use @const fn reverseBits<T: iu32>(T) -> T
@must_use @const fn reverseBits<N: num, T: iu32>(vec<N, T>) -> vec<N, T>
-@must_use @const fn round<T: fa_f32_f16>(@test_value(3.4) T) -> T
-@must_use @const fn round<N: num, T: fa_f32_f16>(@test_value(3.4) vec<N, T>) -> vec<N, T>
+@must_use @const fn round<T: fa_f32_f16>(@test_value(3.5) T) -> T
+@must_use @const fn round<N: num, T: fa_f32_f16>(@test_value(3.5) vec<N, T>) -> vec<N, T>
@must_use @const fn saturate<T: fa_f32_f16>(@test_value(2) T) -> T
@must_use @const fn saturate<T: fa_f32_f16, N: num>(@test_value(2) vec<N, T>) -> vec<N, T>
@must_use @const("select_bool") fn select<T: scalar>(T, T, bool) -> T
diff --git a/src/tint/ir/binary.h b/src/tint/ir/binary.h
index be5d243..063bc93 100644
--- a/src/tint/ir/binary.h
+++ b/src/tint/ir/binary.h
@@ -15,8 +15,6 @@
#ifndef SRC_TINT_IR_BINARY_H_
#define SRC_TINT_IR_BINARY_H_
-#include <ostream>
-
#include "src/tint/castable.h"
#include "src/tint/ir/instruction.h"
#include "src/tint/symbol_table.h"
diff --git a/src/tint/ir/binary_test.cc b/src/tint/ir/binary_test.cc
index 103719c..9f4ba19 100644
--- a/src/tint/ir/binary_test.cc
+++ b/src/tint/ir/binary_test.cc
@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include <sstream>
-
#include "src/tint/ir/instruction.h"
#include "src/tint/ir/test_helper.h"
#include "src/tint/utils/string_stream.h"
diff --git a/src/tint/ir/bitcast.h b/src/tint/ir/bitcast.h
index 16d62f8..0178066 100644
--- a/src/tint/ir/bitcast.h
+++ b/src/tint/ir/bitcast.h
@@ -15,8 +15,6 @@
#ifndef SRC_TINT_IR_BITCAST_H_
#define SRC_TINT_IR_BITCAST_H_
-#include <ostream>
-
#include "src/tint/castable.h"
#include "src/tint/ir/instruction.h"
#include "src/tint/symbol_table.h"
diff --git a/src/tint/ir/bitcast_test.cc b/src/tint/ir/bitcast_test.cc
index d190abb..38ae9b2 100644
--- a/src/tint/ir/bitcast_test.cc
+++ b/src/tint/ir/bitcast_test.cc
@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include <sstream>
-
#include "src/tint/ir/instruction.h"
#include "src/tint/ir/test_helper.h"
#include "src/tint/utils/string_stream.h"
diff --git a/src/tint/ir/builder_impl_test.cc b/src/tint/ir/builder_impl_test.cc
index b70c059..9af481b 100644
--- a/src/tint/ir/builder_impl_test.cc
+++ b/src/tint/ir/builder_impl_test.cc
@@ -1836,8 +1836,8 @@
EXPECT_EQ(d.AsString(), R"(%1 (u32) = 3 >> 4
%2 (u32) = %1 (u32) + 9
%3 (bool) = 1 < %2 (u32)
-%4 (f32) = 2.299999952 * 5.5
-%5 (f32) = 6.699999809 / %4 (f32)
+%4 (f32) = 2.29999995231628417969 * 5.5
+%5 (f32) = 6.69999980926513671875 / %4 (f32)
%6 (bool) = 2.5 > %5 (f32)
%7 (bool) = %3 (bool) && %6 (bool)
)");
diff --git a/src/tint/ir/constant.h b/src/tint/ir/constant.h
index e7d66a4..1c4088f 100644
--- a/src/tint/ir/constant.h
+++ b/src/tint/ir/constant.h
@@ -15,8 +15,6 @@
#ifndef SRC_TINT_IR_CONSTANT_H_
#define SRC_TINT_IR_CONSTANT_H_
-#include <ostream>
-
#include "src/tint/constant/value.h"
#include "src/tint/ir/value.h"
#include "src/tint/symbol_table.h"
diff --git a/src/tint/ir/constant_test.cc b/src/tint/ir/constant_test.cc
index 745ec54..f3a1dc0 100644
--- a/src/tint/ir/constant_test.cc
+++ b/src/tint/ir/constant_test.cc
@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include <sstream>
-
#include "src/tint/ir/test_helper.h"
#include "src/tint/ir/value.h"
#include "src/tint/utils/string_stream.h"
@@ -34,7 +32,7 @@
EXPECT_EQ(1.2_f, c->value->As<constant::Scalar<f32>>()->ValueAs<f32>());
c->ToString(str, b.builder.ir.symbols);
- EXPECT_EQ("1.200000048", str.str());
+ EXPECT_EQ("1.20000004768371582031", str.str());
EXPECT_TRUE(c->value->Is<constant::Scalar<f32>>());
EXPECT_FALSE(c->value->Is<constant::Scalar<f16>>());
diff --git a/src/tint/ir/debug.cc b/src/tint/ir/debug.cc
index b541236..290aaeb8 100644
--- a/src/tint/ir/debug.cc
+++ b/src/tint/ir/debug.cc
@@ -14,7 +14,6 @@
#include "src/tint/ir/debug.h"
-#include <sstream>
#include <unordered_map>
#include <unordered_set>
diff --git a/src/tint/ir/disassembler.h b/src/tint/ir/disassembler.h
index 1ed822c..eee6b76 100644
--- a/src/tint/ir/disassembler.h
+++ b/src/tint/ir/disassembler.h
@@ -15,7 +15,6 @@
#ifndef SRC_TINT_IR_DISASSEMBLER_H_
#define SRC_TINT_IR_DISASSEMBLER_H_
-#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
diff --git a/src/tint/ir/instruction.h b/src/tint/ir/instruction.h
index abd5179..9d09fcb 100644
--- a/src/tint/ir/instruction.h
+++ b/src/tint/ir/instruction.h
@@ -15,8 +15,6 @@
#ifndef SRC_TINT_IR_INSTRUCTION_H_
#define SRC_TINT_IR_INSTRUCTION_H_
-#include <ostream>
-
#include "src/tint/castable.h"
#include "src/tint/ir/value.h"
#include "src/tint/symbol_table.h"
diff --git a/src/tint/ir/temp.h b/src/tint/ir/temp.h
index 989e416..8532a45 100644
--- a/src/tint/ir/temp.h
+++ b/src/tint/ir/temp.h
@@ -15,8 +15,6 @@
#ifndef SRC_TINT_IR_TEMP_H_
#define SRC_TINT_IR_TEMP_H_
-#include <ostream>
-
#include "src/tint/ir/value.h"
#include "src/tint/symbol_table.h"
#include "src/tint/utils/string_stream.h"
diff --git a/src/tint/ir/temp_test.cc b/src/tint/ir/temp_test.cc
index 1a33769..e73dd34 100644
--- a/src/tint/ir/temp_test.cc
+++ b/src/tint/ir/temp_test.cc
@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include <sstream>
-
#include "src/tint/ir/temp.h"
#include "src/tint/ir/test_helper.h"
#include "src/tint/utils/string_stream.h"
diff --git a/src/tint/ir/value.h b/src/tint/ir/value.h
index 983eae0..b3ec7ef 100644
--- a/src/tint/ir/value.h
+++ b/src/tint/ir/value.h
@@ -15,8 +15,6 @@
#ifndef SRC_TINT_IR_VALUE_H_
#define SRC_TINT_IR_VALUE_H_
-#include <ostream>
-
#include "src/tint/castable.h"
#include "src/tint/symbol_table.h"
#include "src/tint/type/type.h"
diff --git a/src/tint/number.cc b/src/tint/number.cc
index 629091b..8b85670 100644
--- a/src/tint/number.cc
+++ b/src/tint/number.cc
@@ -17,10 +17,10 @@
#include <algorithm>
#include <cmath>
#include <cstring>
-#include <ostream>
#include "src/tint/debug.h"
#include "src/tint/utils/bitcast.h"
+#include "src/tint/utils/string_stream.h"
namespace tint {
namespace {
@@ -50,7 +50,7 @@
} // namespace
-std::ostream& operator<<(std::ostream& out, ConversionFailure failure) {
+utils::StringStream& operator<<(utils::StringStream& out, ConversionFailure failure) {
switch (failure) {
case ConversionFailure::kExceedsPositiveLimit:
return out << "value exceeds positive limit for type";
diff --git a/src/tint/number.h b/src/tint/number.h
index 82a9963..69df284 100644
--- a/src/tint/number.h
+++ b/src/tint/number.h
@@ -20,11 +20,11 @@
#include <functional>
#include <limits>
#include <optional>
-#include <ostream>
#include "src/tint/traits.h"
#include "src/tint/utils/compiler_macros.h"
#include "src/tint/utils/result.h"
+#include "src/tint/utils/string_stream.h"
// Forward declaration
namespace tint {
@@ -175,11 +175,11 @@
};
/// Writes the number to the ostream.
-/// @param out the std::ostream to write to
+/// @param out the stream to write to
/// @param num the Number
-/// @return the std::ostream so calls can be chained
+/// @return the stream so calls can be chained
template <typename T>
-inline std::ostream& operator<<(std::ostream& out, Number<T> num) {
+inline utils::StringStream& operator<<(utils::StringStream& out, Number<T> num) {
return out << num.value;
}
@@ -314,10 +314,10 @@
};
/// Writes the conversion failure message to the ostream.
-/// @param out the std::ostream to write to
+/// @param out the stream to write to
/// @param failure the ConversionFailure
-/// @return the std::ostream so calls can be chained
-std::ostream& operator<<(std::ostream& out, ConversionFailure failure);
+/// @return the stream so calls can be chained
+utils::StringStream& operator<<(utils::StringStream& out, ConversionFailure failure);
/// Converts a number from one type to another, checking that the value fits in the target type.
/// @returns the resulting value of the conversion, or a failure reason.
diff --git a/src/tint/program_id.h b/src/tint/program_id.h
index c018543..4169ba1 100644
--- a/src/tint/program_id.h
+++ b/src/tint/program_id.h
@@ -16,10 +16,10 @@
#define SRC_TINT_PROGRAM_ID_H_
#include <stdint.h>
-#include <iostream>
#include <utility>
#include "src/tint/debug.h"
+#include "src/tint/utils/string_stream.h"
namespace tint {
@@ -71,11 +71,11 @@
return id;
}
-/// Writes the ProgramID to the std::ostream.
-/// @param out the std::ostream to write to
+/// Writes the ProgramID to the stream.
+/// @param out the stream to write to
/// @param id the program identifier to write
/// @returns out so calls can be chained
-inline std::ostream& operator<<(std::ostream& out, ProgramID id) {
+inline utils::StringStream& operator<<(utils::StringStream& out, ProgramID id) {
out << "Program<" << id.Value() << ">";
return out;
}
diff --git a/src/tint/reader/spirv/construct.h b/src/tint/reader/spirv/construct.h
index 06ae450..7377d83 100644
--- a/src/tint/reader/spirv/construct.h
+++ b/src/tint/reader/spirv/construct.h
@@ -16,7 +16,6 @@
#define SRC_TINT_READER_SPIRV_CONSTRUCT_H_
#include <memory>
-#include <sstream>
#include <string>
#include "src/tint/utils/string_stream.h"
diff --git a/src/tint/reader/spirv/fail_stream.h b/src/tint/reader/spirv/fail_stream.h
index 6530eae..0a154f7 100644
--- a/src/tint/reader/spirv/fail_stream.h
+++ b/src/tint/reader/spirv/fail_stream.h
@@ -19,7 +19,7 @@
namespace tint::reader::spirv {
-/// A FailStream object accumulates values onto a given std::ostream,
+/// A FailStream object accumulates values onto a given stream,
/// and can be used to record failure by writing the false value
/// to given a pointer-to-bool.
class FailStream {
diff --git a/src/tint/reader/spirv/function.h b/src/tint/reader/spirv/function.h
index a07309d..718e8e3 100644
--- a/src/tint/reader/spirv/function.h
+++ b/src/tint/reader/spirv/function.h
@@ -28,6 +28,7 @@
#include "src/tint/reader/spirv/attributes.h"
#include "src/tint/reader/spirv/construct.h"
#include "src/tint/reader/spirv/parser_impl.h"
+#include "src/tint/utils/string_stream.h"
namespace tint::reader::spirv {
@@ -178,11 +179,11 @@
utils::Vector<uint32_t, 4> phis_needing_state_vars;
};
-/// Writes the BlockInfo to the ostream
-/// @param o the ostream
+/// Writes the BlockInfo to the stream
+/// @param o the stream
/// @param bi the BlockInfo
-/// @returns the ostream so calls can be chained
-inline std::ostream& operator<<(std::ostream& o, const BlockInfo& bi) {
+/// @returns the stream so calls can be chained
+inline utils::StringStream& operator<<(utils::StringStream& o, const BlockInfo& bi) {
o << "BlockInfo{"
<< " id: " << bi.id << " pos: " << bi.pos << " merge_for_header: " << bi.merge_for_header
<< " continue_for_header: " << bi.continue_for_header
@@ -353,11 +354,11 @@
SkipReason skip = SkipReason::kDontSkip;
};
-/// Writes the DefInfo to the ostream
-/// @param o the ostream
+/// Writes the DefInfo to the stream
+/// @param o the stream
/// @param di the DefInfo
-/// @returns the ostream so calls can be chained
-inline std::ostream& operator<<(std::ostream& o, const DefInfo& di) {
+/// @returns the stream so calls can be chained
+inline utils::StringStream& operator<<(utils::StringStream& o, const DefInfo& di) {
o << "DefInfo{"
<< " inst.result_id: " << di.inst.result_id();
if (di.local.has_value()) {
diff --git a/src/tint/reader/spirv/function_cfg_test.cc b/src/tint/reader/spirv/function_cfg_test.cc
index f4f1ce5..36d085a 100644
--- a/src/tint/reader/spirv/function_cfg_test.cc
+++ b/src/tint/reader/spirv/function_cfg_test.cc
@@ -2598,10 +2598,11 @@
fe.ComputeBlockOrderAndPositions();
fe.RegisterMerges();
EXPECT_FALSE(fe.VerifyHeaderContinueMergeOrder());
+
+ utils::StringStream result;
+ result << *fe.GetBlockInfo(50) << std::endl << *fe.GetBlockInfo(20) << std::endl;
EXPECT_THAT(p->error(), Eq("Header 50 does not strictly dominate its merge block 20"))
- << *fe.GetBlockInfo(50) << std::endl
- << *fe.GetBlockInfo(20) << std::endl
- << Dump(fe.block_order());
+ << result.str() << Dump(fe.block_order());
}
TEST_F(SpvParserCFGTest,
@@ -2634,10 +2635,10 @@
fe.ComputeBlockOrderAndPositions();
fe.RegisterMerges();
EXPECT_FALSE(fe.VerifyHeaderContinueMergeOrder());
+ utils::StringStream str;
+ str << *fe.GetBlockInfo(50) << std::endl << *fe.GetBlockInfo(20) << std::endl;
EXPECT_THAT(p->error(), Eq("Loop header 50 does not dominate its continue target 20"))
- << *fe.GetBlockInfo(50) << std::endl
- << *fe.GetBlockInfo(20) << std::endl
- << Dump(fe.block_order());
+ << str.str() << Dump(fe.block_order());
}
TEST_F(SpvParserCFGTest, VerifyHeaderContinueMergeOrder_MergeInsideContinueTarget) {
@@ -2752,10 +2753,15 @@
EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 2u);
+
+ utils::StringStream str;
+ str << constructs;
+
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,4) begin_id:10 end_id:0 depth:0 parent:null }
Construct{ IfSelection [0,3) begin_id:10 end_id:99 depth:1 parent:Function@10 }
-})")) << constructs;
+})")) << str.str();
+
// The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[1].get());
@@ -2798,10 +2804,15 @@
EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 2u);
+
+ utils::StringStream str;
+ str << constructs;
+
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,6) begin_id:5 end_id:0 depth:0 parent:null }
Construct{ IfSelection [1,4) begin_id:10 end_id:99 depth:1 parent:Function@5 }
-})")) << constructs;
+})")) << str.str();
+
// The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(5)->construct, constructs[0].get());
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get());
@@ -2842,10 +2853,15 @@
EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 2u);
+
+ utils::StringStream str;
+ str << constructs;
+
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,5) begin_id:10 end_id:0 depth:0 parent:null }
Construct{ SwitchSelection [0,4) begin_id:10 end_id:99 depth:1 parent:Function@10 in-c-l-s:SwitchSelection@10 }
-})")) << constructs;
+})")) << str.str();
+
// The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[1].get());
@@ -2879,12 +2895,17 @@
EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 2u);
+
+ utils::StringStream str;
+ str << constructs;
+
// A single-block loop consists *only* of a continue target with one block in
// it.
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,3) begin_id:10 end_id:0 depth:0 parent:null }
Construct{ Continue [1,2) begin_id:20 end_id:99 depth:1 parent:Function@10 in-c:Continue@20 }
-})")) << constructs;
+})")) << str.str();
+
// The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[1].get());
@@ -2925,11 +2946,16 @@
fe.RegisterMerges();
EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs();
+
+ utils::StringStream str;
+ str << constructs;
+
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,6) begin_id:10 end_id:0 depth:0 parent:null }
Construct{ Continue [3,5) begin_id:40 end_id:99 depth:1 parent:Function@10 in-c:Continue@40 }
Construct{ Loop [1,3) begin_id:20 end_id:40 depth:1 parent:Function@10 scope:[1,5) in-l:Loop@20 }
-})")) << constructs;
+})")) << str.str();
+
// The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[2].get());
@@ -2973,10 +2999,14 @@
fe.RegisterMerges();
EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs();
+
+ utils::StringStream str;
+ str << constructs;
+
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,6) begin_id:10 end_id:0 depth:0 parent:null }
Construct{ Continue [1,5) begin_id:20 end_id:99 depth:1 parent:Function@10 in-c:Continue@20 }
-})")) << constructs;
+})")) << str.str();
// The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[1].get());
@@ -3020,13 +3050,18 @@
EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 3u);
+
+ utils::StringStream str;
+ str << constructs;
+
// A single-block loop consists *only* of a continue target with one block in
// it.
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,4) begin_id:10 end_id:0 depth:0 parent:null }
Construct{ IfSelection [0,2) begin_id:10 end_id:50 depth:1 parent:Function@10 }
Construct{ Continue [2,3) begin_id:50 end_id:99 depth:1 parent:Function@10 in-c:Continue@50 }
-})")) << constructs;
+})")) << str.str();
+
// The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[1].get());
@@ -3068,12 +3103,17 @@
EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 4u);
+
+ utils::StringStream str;
+ str << constructs;
+
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,5) begin_id:10 end_id:0 depth:0 parent:null }
Construct{ IfSelection [0,2) begin_id:10 end_id:50 depth:1 parent:Function@10 }
Construct{ Continue [3,4) begin_id:60 end_id:99 depth:1 parent:Function@10 in-c:Continue@60 }
Construct{ Loop [2,3) begin_id:50 end_id:60 depth:1 parent:Function@10 scope:[2,4) in-l:Loop@50 }
-})")) << constructs;
+})")) << str.str();
+
// The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[1].get());
@@ -3127,12 +3167,17 @@
EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 4u);
+
+ utils::StringStream str;
+ str << constructs;
+
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,9) begin_id:10 end_id:0 depth:0 parent:null }
Construct{ IfSelection [0,8) begin_id:10 end_id:99 depth:1 parent:Function@10 }
Construct{ IfSelection [1,3) begin_id:20 end_id:40 depth:2 parent:IfSelection@10 }
Construct{ IfSelection [5,7) begin_id:50 end_id:89 depth:2 parent:IfSelection@10 }
-})")) << constructs;
+})")) << str.str();
+
// The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[2].get());
@@ -3187,13 +3232,18 @@
EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 4u);
+
+ utils::StringStream str;
+ str << constructs;
+
// The ordering among siblings depends on the computed block order.
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,8) begin_id:10 end_id:0 depth:0 parent:null }
Construct{ SwitchSelection [0,7) begin_id:10 end_id:99 depth:1 parent:Function@10 in-c-l-s:SwitchSelection@10 }
Construct{ IfSelection [1,3) begin_id:50 end_id:89 depth:2 parent:SwitchSelection@10 in-c-l-s:SwitchSelection@10 }
Construct{ IfSelection [4,6) begin_id:20 end_id:49 depth:2 parent:SwitchSelection@10 in-c-l-s:SwitchSelection@10 }
-})")) << constructs;
+})")) << str.str();
+
// The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[3].get());
@@ -3237,11 +3287,16 @@
EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 3u);
+
+ utils::StringStream str;
+ str << constructs;
+
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,5) begin_id:10 end_id:0 depth:0 parent:null }
Construct{ IfSelection [0,4) begin_id:10 end_id:99 depth:1 parent:Function@10 }
Construct{ SwitchSelection [1,3) begin_id:20 end_id:89 depth:2 parent:IfSelection@10 in-c-l-s:SwitchSelection@20 }
-})")) << constructs;
+})")) << str.str();
+
// The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[2].get());
@@ -3291,12 +3346,17 @@
EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 4u);
+
+ utils::StringStream str;
+ str << constructs;
+
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,8) begin_id:10 end_id:0 depth:0 parent:null }
Construct{ Continue [4,6) begin_id:50 end_id:89 depth:1 parent:Function@10 in-c:Continue@50 }
Construct{ Loop [1,4) begin_id:20 end_id:50 depth:1 parent:Function@10 scope:[1,6) in-l:Loop@20 }
Construct{ Continue [2,3) begin_id:30 end_id:40 depth:2 parent:Loop@20 in-l:Loop@20 in-c:Continue@30 }
-})")) << constructs;
+})")) << str.str();
+
// The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[2].get());
@@ -3346,12 +3406,17 @@
EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 4u);
+
+ utils::StringStream str;
+ str << constructs;
+
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,7) begin_id:10 end_id:0 depth:0 parent:null }
Construct{ Continue [5,6) begin_id:80 end_id:99 depth:1 parent:Function@10 in-c:Continue@80 }
Construct{ Loop [1,5) begin_id:20 end_id:80 depth:1 parent:Function@10 scope:[1,6) in-l:Loop@20 }
Construct{ IfSelection [2,4) begin_id:30 end_id:49 depth:2 parent:Loop@20 in-l:Loop@20 }
-})")) << constructs;
+})")) << str.str();
+
// The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[2].get());
@@ -3397,12 +3462,16 @@
EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 4u);
+
+ utils::StringStream str;
+ str << constructs;
+
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,6) begin_id:10 end_id:0 depth:0 parent:null }
Construct{ Continue [2,5) begin_id:30 end_id:99 depth:1 parent:Function@10 in-c:Continue@30 }
Construct{ Loop [1,2) begin_id:20 end_id:30 depth:1 parent:Function@10 scope:[1,5) in-l:Loop@20 }
Construct{ IfSelection [2,4) begin_id:30 end_id:49 depth:2 parent:Continue@30 in-c:Continue@30 }
-})")) << constructs;
+})")) << str.str();
// The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[2].get());
@@ -3441,11 +3510,15 @@
EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 3u);
+
+ utils::StringStream str;
+ str << constructs;
+
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,4) begin_id:10 end_id:0 depth:0 parent:null }
Construct{ IfSelection [0,3) begin_id:10 end_id:99 depth:1 parent:Function@10 }
Construct{ Continue [1,2) begin_id:20 end_id:89 depth:2 parent:IfSelection@10 in-c:Continue@20 }
-})")) << constructs;
+})")) << str.str();
// The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[2].get());
@@ -3490,12 +3563,17 @@
EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 4u);
+
+ utils::StringStream str;
+ str << constructs;
+
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,7) begin_id:10 end_id:0 depth:0 parent:null }
Construct{ IfSelection [0,6) begin_id:10 end_id:99 depth:1 parent:Function@10 }
Construct{ Continue [3,5) begin_id:40 end_id:89 depth:2 parent:IfSelection@10 in-c:Continue@40 }
Construct{ Loop [1,3) begin_id:20 end_id:40 depth:2 parent:IfSelection@10 scope:[1,5) in-l:Loop@20 }
-})")) << constructs;
+})")) << str.str();
+
// The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[3].get());
@@ -3540,12 +3618,17 @@
ASSERT_TRUE(FlowLabelControlFlowConstructs(&fe)) << p->error();
const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 4u);
+
+ utils::StringStream str;
+ str << constructs;
+
ASSERT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,6) begin_id:10 end_id:0 depth:0 parent:null }
Construct{ Continue [4,5) begin_id:90 end_id:99 depth:1 parent:Function@10 in-c:Continue@90 }
Construct{ Loop [1,4) begin_id:20 end_id:90 depth:1 parent:Function@10 scope:[1,5) in-l:Loop@20 }
Construct{ IfSelection [1,4) begin_id:20 end_id:90 depth:2 parent:Loop@20 in-l:Loop@20 }
-})")) << constructs;
+})")) << str.str();
+
// The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[3].get());
diff --git a/src/tint/reader/spirv/function_logical_test.cc b/src/tint/reader/spirv/function_logical_test.cc
index a9ccf7d..2d362c4 100644
--- a/src/tint/reader/spirv/function_logical_test.cc
+++ b/src/tint/reader/spirv/function_logical_test.cc
@@ -532,9 +532,10 @@
auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error();
auto ast_body = fe.ast_body();
- EXPECT_THAT(test::ToString(p->program(), ast_body),
- HasSubstr("let x_1 : vec2<bool> = "
- "!((vec2<f32>(50.0f, 60.0f) != vec2<f32>(60.0f, 50.0f)));"));
+ EXPECT_THAT(
+ test::ToString(p->program(), ast_body),
+ HasSubstr(
+ "let x_1 : vec2<bool> = !((vec2<f32>(50.0f, 60.0f) != vec2<f32>(60.0f, 50.0f)));"));
}
TEST_F(SpvFUnordTest, FUnordNotEqual_Scalar) {
@@ -567,9 +568,10 @@
auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error();
auto ast_body = fe.ast_body();
- EXPECT_THAT(test::ToString(p->program(), ast_body),
- HasSubstr("let x_1 : vec2<bool> = "
- "!((vec2<f32>(50.0f, 60.0f) == vec2<f32>(60.0f, 50.0f)));"));
+ EXPECT_THAT(
+ test::ToString(p->program(), ast_body),
+ HasSubstr(
+ "let x_1 : vec2<bool> = !((vec2<f32>(50.0f, 60.0f) == vec2<f32>(60.0f, 50.0f)));"));
}
TEST_F(SpvFUnordTest, FUnordLessThan_Scalar) {
@@ -602,9 +604,10 @@
auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error();
auto ast_body = fe.ast_body();
- EXPECT_THAT(test::ToString(p->program(), ast_body),
- HasSubstr("let x_1 : vec2<bool> = "
- "!((vec2<f32>(50.0f, 60.0f) >= vec2<f32>(60.0f, 50.0f)));"));
+ EXPECT_THAT(
+ test::ToString(p->program(), ast_body),
+ HasSubstr(
+ "let x_1 : vec2<bool> = !((vec2<f32>(50.0f, 60.0f) >= vec2<f32>(60.0f, 50.0f)));"));
}
TEST_F(SpvFUnordTest, FUnordLessThanEqual_Scalar) {
@@ -637,9 +640,10 @@
auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error();
auto ast_body = fe.ast_body();
- EXPECT_THAT(test::ToString(p->program(), ast_body),
- HasSubstr("let x_1 : vec2<bool> = "
- "!((vec2<f32>(50.0f, 60.0f) > vec2<f32>(60.0f, 50.0f)));"));
+ EXPECT_THAT(
+ test::ToString(p->program(), ast_body),
+ HasSubstr(
+ "let x_1 : vec2<bool> = !((vec2<f32>(50.0f, 60.0f) > vec2<f32>(60.0f, 50.0f)));"));
}
TEST_F(SpvFUnordTest, FUnordGreaterThan_Scalar) {
@@ -672,9 +676,10 @@
auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error();
auto ast_body = fe.ast_body();
- EXPECT_THAT(test::ToString(p->program(), ast_body),
- HasSubstr("let x_1 : vec2<bool> = "
- "!((vec2<f32>(50.0f, 60.0f) <= vec2<f32>(60.0f, 50.0f)));"));
+ EXPECT_THAT(
+ test::ToString(p->program(), ast_body),
+ HasSubstr(
+ "let x_1 : vec2<bool> = !((vec2<f32>(50.0f, 60.0f) <= vec2<f32>(60.0f, 50.0f)));"));
}
TEST_F(SpvFUnordTest, FUnordGreaterThanEqual_Scalar) {
@@ -707,10 +712,10 @@
auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error();
auto ast_body = fe.ast_body();
- EXPECT_THAT(test::ToString(p->program(), ast_body),
- HasSubstr("let x_1 : vec2<bool> = !(("
- "vec2<f32>(50.0f, 60.0f) < vec2<f32>(60.0f, 50.0f)"
- "));"));
+ EXPECT_THAT(
+ test::ToString(p->program(), ast_body),
+ HasSubstr(
+ "let x_1 : vec2<bool> = !((vec2<f32>(50.0f, 60.0f) < vec2<f32>(60.0f, 50.0f)));"));
}
using SpvLogicalTest = SpvParserTestBase<::testing::Test>;
diff --git a/src/tint/reader/spirv/namer.cc b/src/tint/reader/spirv/namer.cc
index 378e133..6c73a34 100644
--- a/src/tint/reader/spirv/namer.cc
+++ b/src/tint/reader/spirv/namer.cc
@@ -15,7 +15,6 @@
#include "src/tint/reader/spirv/namer.h"
#include <algorithm>
-#include <sstream>
#include <unordered_set>
#include "src/tint/debug.h"
diff --git a/src/tint/reader/spirv/parser_impl_handle_test.cc b/src/tint/reader/spirv/parser_impl_handle_test.cc
index 17e6ed6..39d5498 100644
--- a/src/tint/reader/spirv/parser_impl_handle_test.cc
+++ b/src/tint/reader/spirv/parser_impl_handle_test.cc
@@ -1645,7 +1645,7 @@
R"(@group(0) @binding(0) var x_10 : sampler_comparison;
@group(2) @binding(1) var x_20 : texture_depth_2d;)",
- "textureGatherCompare(x_20, x_10, coords12, 0.200000003f)"},
+ "textureGatherCompare(x_20, x_10, coords12, 0.20000000298023223877f)"},
// OpImageDrefGather 2DDepth ConstOffset signed
ImageAccessCase{"%float 2D 1 0 0 1 Unknown",
"%result = OpImageDrefGather "
@@ -1653,7 +1653,7 @@
R"(@group(0) @binding(0) var x_10 : sampler_comparison;
@group(2) @binding(1) var x_20 : texture_depth_2d;)",
- "textureGatherCompare(x_20, x_10, coords12, 0.200000003f, "
+ "textureGatherCompare(x_20, x_10, coords12, 0.20000000298023223877f, "
"vec2<i32>(3i, 4i))"},
// OpImageDrefGather 2DDepth ConstOffset unsigned
ImageAccessCase{"%float 2D 1 0 0 1 Unknown",
@@ -1663,7 +1663,7 @@
R"(@group(0) @binding(0) var x_10 : sampler_comparison;
@group(2) @binding(1) var x_20 : texture_depth_2d;)",
- "textureGatherCompare(x_20, x_10, coords12, 0.200000003f, "
+ "textureGatherCompare(x_20, x_10, coords12, 0.20000000298023223877f, "
"vec2<i32>(vec2<u32>(3u, 4u)))"},
// OpImageDrefGather 2DDepth Array
ImageAccessCase{"%float 2D 1 1 0 1 Unknown",
@@ -1673,7 +1673,7 @@
@group(2) @binding(1) var x_20 : texture_depth_2d_array;)",
"textureGatherCompare(x_20, x_10, coords123.xy, "
- "i32(round(coords123.z)), 0.200000003f)"},
+ "i32(round(coords123.z)), 0.20000000298023223877f)"},
// OpImageDrefGather 2DDepth Array ConstOffset signed
ImageAccessCase{"%float 2D 1 1 0 1 Unknown",
"%result = OpImageDrefGather "
@@ -1682,7 +1682,7 @@
@group(2) @binding(1) var x_20 : texture_depth_2d_array;)",
"textureGatherCompare(x_20, x_10, coords123.xy, "
- "i32(round(coords123.z)), 0.200000003f, vec2<i32>(3i, 4i))"},
+ "i32(round(coords123.z)), 0.20000000298023223877f, vec2<i32>(3i, 4i))"},
// OpImageDrefGather 2DDepth Array ConstOffset unsigned
ImageAccessCase{"%float 2D 1 1 0 1 Unknown",
"%result = OpImageDrefGather "
@@ -1692,7 +1692,7 @@
@group(2) @binding(1) var x_20 : texture_depth_2d_array;)",
"textureGatherCompare(x_20, x_10, coords123.xy, "
- "i32(round(coords123.z)), 0.200000003f, "
+ "i32(round(coords123.z)), 0.20000000298023223877f, "
"vec2<i32>(vec2<u32>(3u, 4u)))"},
// OpImageDrefGather DepthCube
ImageAccessCase{"%float Cube 1 0 0 1 Unknown",
@@ -1701,7 +1701,7 @@
R"(@group(0) @binding(0) var x_10 : sampler_comparison;
@group(2) @binding(1) var x_20 : texture_depth_cube;)",
- "textureGatherCompare(x_20, x_10, coords123, 0.200000003f)"},
+ "textureGatherCompare(x_20, x_10, coords123, 0.20000000298023223877f)"},
// OpImageDrefGather DepthCube Array
ImageAccessCase{"%float Cube 1 1 0 1 Unknown",
"%result = OpImageDrefGather "
@@ -1710,7 +1710,7 @@
@group(2) @binding(1) var x_20 : texture_depth_cube_array;)",
"textureGatherCompare(x_20, x_10, coords1234.xyz, "
- "i32(round(coords1234.w)), 0.200000003f)"}}));
+ "i32(round(coords1234.w)), 0.20000000298023223877f)"}}));
INSTANTIATE_TEST_SUITE_P(
ImageSampleImplicitLod,
@@ -1829,7 +1829,7 @@
)",
R"(
let x_200 : vec4<f32> = vec4<f32>(textureSample(x_20, x_10, coords12), 0.0f, 0.0f, 0.0f);
- let x_210 : f32 = textureSampleCompare(x_20, x_30, coords12, 0.200000003f);
+ let x_210 : f32 = textureSampleCompare(x_20, x_30, coords12, 0.20000000298023223877f);
)"}));
INSTANTIATE_TEST_SUITE_P(
@@ -1844,7 +1844,7 @@
@group(2) @binding(1) var x_20 : texture_depth_2d;
)",
- R"(textureSampleCompare(x_20, x_10, coords12, 0.200000003f))"},
+ R"(textureSampleCompare(x_20, x_10, coords12, 0.20000000298023223877f))"},
// ImageSampleDrefImplicitLod - arrayed
ImageAccessCase{
"%float 2D 0 1 0 1 Unknown",
@@ -1853,7 +1853,7 @@
R"(@group(0) @binding(0) var x_10 : sampler_comparison;
@group(2) @binding(1) var x_20 : texture_depth_2d_array;)",
- R"(textureSampleCompare(x_20, x_10, coords123.xy, i32(round(coords123.z)), 0.200000003f))"},
+ R"(textureSampleCompare(x_20, x_10, coords123.xy, i32(round(coords123.z)), 0.20000000298023223877f))"},
// ImageSampleDrefImplicitLod with ConstOffset
ImageAccessCase{
"%float 2D 0 0 0 1 Unknown",
@@ -1863,7 +1863,7 @@
@group(2) @binding(1) var x_20 : texture_depth_2d;
)",
- R"(textureSampleCompare(x_20, x_10, coords12, 0.200000003f, vec2<i32>(3i, 4i)))"},
+ R"(textureSampleCompare(x_20, x_10, coords12, 0.20000000298023223877f, vec2<i32>(3i, 4i)))"},
// ImageSampleDrefImplicitLod arrayed with ConstOffset
ImageAccessCase{
"%float 2D 0 1 0 1 Unknown",
@@ -1872,7 +1872,7 @@
R"(@group(0) @binding(0) var x_10 : sampler_comparison;
@group(2) @binding(1) var x_20 : texture_depth_2d_array;)",
- R"(textureSampleCompare(x_20, x_10, coords123.xy, i32(round(coords123.z)), 0.200000003f, vec2<i32>(3i, 4i)))"}));
+ R"(textureSampleCompare(x_20, x_10, coords123.xy, i32(round(coords123.z)), 0.20000000298023223877f, vec2<i32>(3i, 4i)))"}));
INSTANTIATE_TEST_SUITE_P(
ImageSampleDrefExplicitLod,
@@ -1881,14 +1881,15 @@
// Another test checks cases where the Lod is not float constant 0.
::testing::Values(
// 2D
- ImageAccessCase{"%float 2D 1 0 0 1 Unknown",
- "%result = OpImageSampleDrefExplicitLod "
- "%float %sampled_image %coords12 %depth Lod %float_0",
- R"(@group(0) @binding(0) var x_10 : sampler_comparison;
+ ImageAccessCase{
+ "%float 2D 1 0 0 1 Unknown",
+ "%result = OpImageSampleDrefExplicitLod "
+ "%float %sampled_image %coords12 %depth Lod %float_0",
+ R"(@group(0) @binding(0) var x_10 : sampler_comparison;
@group(2) @binding(1) var x_20 : texture_depth_2d;
)",
- R"(textureSampleCompareLevel(x_20, x_10, coords12, 0.200000003f))"},
+ R"(textureSampleCompareLevel(x_20, x_10, coords12, 0.20000000298023223877f))"},
// 2D array
ImageAccessCase{
"%float 2D 1 1 0 1 Unknown",
@@ -1897,7 +1898,7 @@
R"(@group(0) @binding(0) var x_10 : sampler_comparison;
@group(2) @binding(1) var x_20 : texture_depth_2d_array;)",
- R"(textureSampleCompareLevel(x_20, x_10, coords123.xy, i32(round(coords123.z)), 0.200000003f))"},
+ R"(textureSampleCompareLevel(x_20, x_10, coords123.xy, i32(round(coords123.z)), 0.20000000298023223877f))"},
// 2D, ConstOffset
ImageAccessCase{
"%float 2D 1 0 0 1 Unknown",
@@ -1908,7 +1909,7 @@
@group(2) @binding(1) var x_20 : texture_depth_2d;
)",
- R"(textureSampleCompareLevel(x_20, x_10, coords12, 0.200000003f, vec2<i32>(3i, 4i)))"},
+ R"(textureSampleCompareLevel(x_20, x_10, coords12, 0.20000000298023223877f, vec2<i32>(3i, 4i)))"},
// 2D array, ConstOffset
ImageAccessCase{
"%float 2D 1 1 0 1 Unknown",
@@ -1918,15 +1919,16 @@
R"(@group(0) @binding(0) var x_10 : sampler_comparison;
@group(2) @binding(1) var x_20 : texture_depth_2d_array;)",
- R"(textureSampleCompareLevel(x_20, x_10, coords123.xy, i32(round(coords123.z)), 0.200000003f, vec2<i32>(3i, 4i)))"},
+ R"(textureSampleCompareLevel(x_20, x_10, coords123.xy, i32(round(coords123.z)), 0.20000000298023223877f, vec2<i32>(3i, 4i)))"},
// Cube
- ImageAccessCase{"%float Cube 1 0 0 1 Unknown",
- "%result = OpImageSampleDrefExplicitLod "
- "%float %sampled_image %coords123 %depth Lod %float_0",
- R"(@group(0) @binding(0) var x_10 : sampler_comparison;
+ ImageAccessCase{
+ "%float Cube 1 0 0 1 Unknown",
+ "%result = OpImageSampleDrefExplicitLod "
+ "%float %sampled_image %coords123 %depth Lod %float_0",
+ R"(@group(0) @binding(0) var x_10 : sampler_comparison;
@group(2) @binding(1) var x_20 : texture_depth_cube;)",
- R"(textureSampleCompareLevel(x_20, x_10, coords123, 0.200000003f))"},
+ R"(textureSampleCompareLevel(x_20, x_10, coords123, 0.20000000298023223877f))"},
// Cube array
ImageAccessCase{
"%float Cube 1 1 0 1 Unknown",
@@ -1935,7 +1937,7 @@
R"(@group(0) @binding(0) var x_10 : sampler_comparison;
@group(2) @binding(1) var x_20 : texture_depth_cube_array;)",
- R"(textureSampleCompareLevel(x_20, x_10, coords1234.xyz, i32(round(coords1234.w)), 0.200000003f))"}));
+ R"(textureSampleCompareLevel(x_20, x_10, coords1234.xyz, i32(round(coords1234.w)), 0.20000000298023223877f))"}));
INSTANTIATE_TEST_SUITE_P(
ImageSampleExplicitLod_UsingLod,
@@ -2308,7 +2310,7 @@
@group(2) @binding(1) var x_20 : texture_depth_2d;
)",
- R"(textureSampleCompare(x_20, x_10, (coords123.xy / coords123.z), 0.200000003f, 0.0f))"},
+ R"(textureSampleCompare(x_20, x_10, (coords123.xy / coords123.z), 0.20000000298023223877f, 0.0f))"},
// OpImageSampleProjDrefImplicitLod 2D depth-texture, Lod ConstOffset
ImageAccessCase{
@@ -2320,7 +2322,7 @@
@group(2) @binding(1) var x_20 : texture_depth_2d;
)",
- R"(textureSampleCompareLevel(x_20, x_10, (coords123.xy / coords123.z), 0.200000003f, 0.0f, vec2<i32>(3i, 4i)))"}));
+ R"(textureSampleCompareLevel(x_20, x_10, (coords123.xy / coords123.z), 0.20000000298023223877f, 0.0f, vec2<i32>(3i, 4i)))"}));
/////
// End projection sampling
diff --git a/src/tint/reader/spirv/usage.cc b/src/tint/reader/spirv/usage.cc
index 5256d4f..add944b 100644
--- a/src/tint/reader/spirv/usage.cc
+++ b/src/tint/reader/spirv/usage.cc
@@ -14,8 +14,6 @@
#include "src/tint/reader/spirv/usage.h"
-#include <sstream>
-
#include "src/tint/utils/string_stream.h"
namespace tint::reader::spirv {
@@ -24,7 +22,7 @@
Usage::Usage(const Usage& other) = default;
Usage::~Usage() = default;
-std::ostream& Usage::operator<<(std::ostream& out) const {
+utils::StringStream& Usage::operator<<(utils::StringStream& out) const {
out << "Usage(";
if (IsSampler()) {
out << "Sampler(";
diff --git a/src/tint/reader/spirv/usage.h b/src/tint/reader/spirv/usage.h
index 4c2ccbb..63902ef 100644
--- a/src/tint/reader/spirv/usage.h
+++ b/src/tint/reader/spirv/usage.h
@@ -17,6 +17,8 @@
#include <string>
+#include "src/tint/utils/string_stream.h"
+
namespace tint::reader::spirv {
/// Records the properties of a sampler or texture based on how it's used
@@ -73,7 +75,7 @@
/// Emits this usage to the given stream
/// @param out the output stream.
/// @returns the modified stream.
- std::ostream& operator<<(std::ostream& out) const;
+ utils::StringStream& operator<<(utils::StringStream& out) const;
/// Equality operator
/// @param other the RHS of the equality test.
@@ -122,11 +124,11 @@
bool is_storage_write_ = false;
};
-/// Writes the Usage to the ostream
-/// @param out the ostream
+/// Writes the Usage to the stream
+/// @param out the stream
/// @param u the Usage
-/// @returns the ostream so calls can be chained
-inline std::ostream& operator<<(std::ostream& out, const Usage& u) {
+/// @returns the stream so calls can be chained
+inline utils::StringStream& operator<<(utils::StringStream& out, const Usage& u) {
return u.operator<<(out);
}
diff --git a/src/tint/reader/wgsl/parser_impl_expression_test.cc b/src/tint/reader/wgsl/parser_impl_expression_test.cc
index 9a6c917..000a24b 100644
--- a/src/tint/reader/wgsl/parser_impl_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_expression_test.cc
@@ -468,7 +468,7 @@
static bool ParsedAsTemplateArgumentList(BinaryOperatorInfo lhs_op, BinaryOperatorInfo rhs_op) {
return lhs_op.bit == kOpLt && rhs_op.bit & (kOpGt | kOpGe | kOpShr);
}
-static std::ostream& operator<<(std::ostream& o, const Case& c) {
+static utils::StringStream& operator<<(utils::StringStream& o, const Case& c) {
return o << "a " << c.lhs_op.symbol << " b " << c.rhs_op.symbol << " c ";
}
diff --git a/src/tint/reader/wgsl/token.h b/src/tint/reader/wgsl/token.h
index 222f28e..43f6831 100644
--- a/src/tint/reader/wgsl/token.h
+++ b/src/tint/reader/wgsl/token.h
@@ -353,7 +353,7 @@
std::variant<int64_t, double, std::string, std::string_view> value_;
};
-inline std::ostream& operator<<(std::ostream& out, Token::Type type) {
+inline utils::StringStream& operator<<(utils::StringStream& out, Token::Type type) {
out << Token::TypeToName(type);
return out;
}
diff --git a/src/tint/resolver/builtin_test.cc b/src/tint/resolver/builtin_test.cc
index 0108e89..4e9e4bd 100644
--- a/src/tint/resolver/builtin_test.cc
+++ b/src/tint/resolver/builtin_test.cc
@@ -2070,7 +2070,7 @@
namespace texture_builtin_tests {
enum class Texture { kF32, kI32, kU32 };
-inline std::ostream& operator<<(std::ostream& out, Texture data) {
+inline utils::StringStream& operator<<(utils::StringStream& out, Texture data) {
if (data == Texture::kF32) {
out << "f32";
} else if (data == Texture::kI32) {
@@ -2087,7 +2087,9 @@
builtin::TexelFormat format = builtin::TexelFormat::kR32Float;
};
inline std::ostream& operator<<(std::ostream& out, TextureTestParams data) {
- out << data.dim << "_" << data.type;
+ utils::StringStream str;
+ str << data.dim << "_" << data.type;
+ out << str.str();
return out;
}
@@ -2110,7 +2112,11 @@
case type::TextureDimension::kCubeArray:
return ty.vec3(scalar);
default:
- [=]() { FAIL() << "Unsupported texture dimension: " << dim; }();
+ [=]() {
+ utils::StringStream str;
+ str << dim;
+ FAIL() << "Unsupported texture dimension: " << str.str();
+ }();
}
return ast::Type{};
}
@@ -2448,8 +2454,11 @@
if (std::string(param.function) == "textureDimensions") {
switch (param.texture_dimension) {
- default:
- FAIL() << "invalid texture dimensions: " << param.texture_dimension;
+ default: {
+ utils::StringStream str;
+ str << param.texture_dimension;
+ FAIL() << "invalid texture dimensions: " << str.str();
+ }
case type::TextureDimension::k1d:
EXPECT_TRUE(TypeOf(call)->Is<type::U32>());
break;
diff --git a/src/tint/resolver/const_eval_binary_op_test.cc b/src/tint/resolver/const_eval_binary_op_test.cc
index ff50a24..76441cd 100644
--- a/src/tint/resolver/const_eval_binary_op_test.cc
+++ b/src/tint/resolver/const_eval_binary_op_test.cc
@@ -1607,7 +1607,7 @@
"179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558"
"632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245"
"490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168"
- "738177180919299881250404026184124858368.000000000 cannot be represented as 'f32'");
+ "738177180919299881250404026184124858368.0 cannot be represented as 'f32'");
}
TEST_F(ResolverConstEvalTest, ShortCircuit_And_Error_Materialize) {
@@ -1658,7 +1658,7 @@
"179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558"
"632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245"
"490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168"
- "738177180919299881250404026184124858368.000000000 cannot be represented as 'f32'");
+ "738177180919299881250404026184124858368.0 cannot be represented as 'f32'");
}
TEST_F(ResolverConstEvalTest, ShortCircuit_Or_Error_Materialize) {
diff --git a/src/tint/resolver/const_eval_builtin_test.cc b/src/tint/resolver/const_eval_builtin_test.cc
index 6f53af1..bd32779 100644
--- a/src/tint/resolver/const_eval_builtin_test.cc
+++ b/src/tint/resolver/const_eval_builtin_test.cc
@@ -2025,10 +2025,10 @@
C({Vec(f32(10), f32(-10.5))}, Val(u32(0xc940'4900))),
E({Vec(f32(0), f32::Highest())},
- "12:34 error: value 340282346638528859811704183484516925440.000000000 cannot be "
+ "12:34 error: value 340282346638528859811704183484516925440.0 cannot be "
"represented as 'f16'"),
E({Vec(f32::Lowest(), f32(0))},
- "12:34 error: value -340282346638528859811704183484516925440.000000000 cannot be "
+ "12:34 error: value -340282346638528859811704183484516925440.0 cannot be "
"represented as 'f16'"),
};
}
@@ -2850,16 +2850,15 @@
Vec(0x0.034p-14_f, -0x0.034p-14_f, 0x0.068p-14_f, -0x0.068p-14_f)),
// Value out of f16 range
- E({65504.003_f}, "12:34 error: value 65504.003906250 cannot be represented as 'f16'"),
- E({-65504.003_f}, "12:34 error: value -65504.003906250 cannot be represented as 'f16'"),
- E({0x1.234p56_f},
- "12:34 error: value 81979586966978560.000000000 cannot be represented as 'f16'"),
+ E({65504.003_f}, "12:34 error: value 65504.00390625 cannot be represented as 'f16'"),
+ E({-65504.003_f}, "12:34 error: value -65504.00390625 cannot be represented as 'f16'"),
+ E({0x1.234p56_f}, "12:34 error: value 81979586966978560.0 cannot be represented as 'f16'"),
E({0x4.321p65_f},
- "12:34 error: value 154788719192723947520.000000000 cannot be represented as 'f16'"),
+ "12:34 error: value 154788719192723947520.0 cannot be represented as 'f16'"),
E({Vec(65504.003_f, 0_f)},
- "12:34 error: value 65504.003906250 cannot be represented as 'f16'"),
+ "12:34 error: value 65504.00390625 cannot be represented as 'f16'"),
E({Vec(0_f, -0x4.321p65_f)},
- "12:34 error: value -154788719192723947520.000000000 cannot be represented as 'f16'"),
+ "12:34 error: value -154788719192723947520.0 cannot be represented as 'f16'"),
};
}
INSTANTIATE_TEST_SUITE_P( //
diff --git a/src/tint/resolver/const_eval_conversion_test.cc b/src/tint/resolver/const_eval_conversion_test.cc
index b6bcc56..92af2de 100644
--- a/src/tint/resolver/const_eval_conversion_test.cc
+++ b/src/tint/resolver/const_eval_conversion_test.cc
@@ -431,8 +431,7 @@
WrapInFunction(expr);
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(),
- "12:34 error: value 10000000000.000000000 cannot be represented as 'f16'");
+ EXPECT_EQ(r()->error(), "12:34 error: value 10000000000.0 cannot be represented as 'f16'");
}
TEST_F(ResolverConstEvalTest, Vec3_Convert_Small_f32_to_f16) {
diff --git a/src/tint/resolver/const_eval_runtime_semantics_test.cc b/src/tint/resolver/const_eval_runtime_semantics_test.cc
index 347e41d..eb0cf52 100644
--- a/src/tint/resolver/const_eval_runtime_semantics_test.cc
+++ b/src/tint/resolver/const_eval_runtime_semantics_test.cc
@@ -363,7 +363,7 @@
auto result = const_eval.exp(a->Type(), utils::Vector{a}, {});
ASSERT_TRUE(result);
EXPECT_EQ(result.Get()->ValueAs<f32>(), 0.f);
- EXPECT_EQ(error(), R"(warning: e^1000.000000000 cannot be represented as 'f32')");
+ EXPECT_EQ(error(), R"(warning: e^1000.0 cannot be represented as 'f32')");
}
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Exp2_F32_Overflow) {
@@ -371,7 +371,7 @@
auto result = const_eval.exp2(a->Type(), utils::Vector{a}, {});
ASSERT_TRUE(result);
EXPECT_EQ(result.Get()->ValueAs<f32>(), 0.f);
- EXPECT_EQ(error(), R"(warning: 2^1000.000000000 cannot be represented as 'f32')");
+ EXPECT_EQ(error(), R"(warning: 2^1000.0 cannot be represented as 'f32')");
}
TEST_F(ResolverConstEvalRuntimeSemanticsTest, ExtractBits_I32_TooManyBits) {
@@ -476,7 +476,7 @@
auto result = const_eval.pack2x16float(create<type::U32>(), utils::Vector{vec}, {});
ASSERT_TRUE(result);
EXPECT_EQ(result.Get()->ValueAs<u32>(), 0x51430000);
- EXPECT_EQ(error(), R"(warning: value 75250.000000000 cannot be represented as 'f16')");
+ EXPECT_EQ(error(), R"(warning: value 75250.0 cannot be represented as 'f16')");
}
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Pow_F32_Overflow) {
@@ -502,7 +502,7 @@
auto result = const_eval.quantizeToF16(create<type::U32>(), utils::Vector{a}, {});
ASSERT_TRUE(result);
EXPECT_EQ(result.Get()->ValueAs<u32>(), 0);
- EXPECT_EQ(error(), R"(warning: value 75250.000000000 cannot be represented as 'f16')");
+ EXPECT_EQ(error(), R"(warning: value 75250.0 cannot be represented as 'f16')");
}
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Sqrt_F32_OutOfRange) {
@@ -536,7 +536,7 @@
EXPECT_EQ(result.Get()->ValueAs<f32>(), f32::kHighestValue);
EXPECT_EQ(
error(),
- R"(warning: value 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000000 cannot be represented as 'f32')");
+ R"(warning: value 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0 cannot be represented as 'f32')");
}
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Convert_F32_TooLow) {
@@ -546,7 +546,7 @@
EXPECT_EQ(result.Get()->ValueAs<f32>(), f32::kLowestValue);
EXPECT_EQ(
error(),
- R"(warning: value -179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000000 cannot be represented as 'f32')");
+ R"(warning: value -179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0 cannot be represented as 'f32')");
}
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Convert_F16_TooHigh) {
@@ -554,7 +554,7 @@
auto result = const_eval.Convert(create<type::F16>(), a, {});
ASSERT_TRUE(result);
EXPECT_EQ(result.Get()->ValueAs<f32>(), f16::kHighestValue);
- EXPECT_EQ(error(), R"(warning: value 1000000.000000000 cannot be represented as 'f16')");
+ EXPECT_EQ(error(), R"(warning: value 1000000.0 cannot be represented as 'f16')");
}
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Convert_F16_TooLow) {
@@ -562,7 +562,7 @@
auto result = const_eval.Convert(create<type::F16>(), a, {});
ASSERT_TRUE(result);
EXPECT_EQ(result.Get()->ValueAs<f32>(), f16::kLowestValue);
- EXPECT_EQ(error(), R"(warning: value -1000000.000000000 cannot be represented as 'f16')");
+ EXPECT_EQ(error(), R"(warning: value -1000000.0 cannot be represented as 'f16')");
}
TEST_F(ResolverConstEvalRuntimeSemanticsTest, Vec_Overflow_SingleComponent) {
diff --git a/src/tint/resolver/dependency_graph.cc b/src/tint/resolver/dependency_graph.cc
index 9b6d471..8292adb 100644
--- a/src/tint/resolver/dependency_graph.cc
+++ b/src/tint/resolver/dependency_graph.cc
@@ -37,6 +37,7 @@
#include "src/tint/ast/internal_attribute.h"
#include "src/tint/ast/interpolate_attribute.h"
#include "src/tint/ast/invariant_attribute.h"
+#include "src/tint/ast/let.h"
#include "src/tint/ast/location_attribute.h"
#include "src/tint/ast/loop_statement.h"
#include "src/tint/ast/must_use_attribute.h"
@@ -810,6 +811,9 @@
[&](const ast::Var* n) { //
return "var '" + symbols.NameFor(n->name->symbol) + "'";
},
+ [&](const ast::Let* n) { //
+ return "let '" + symbols.NameFor(n->name->symbol) + "'";
+ },
[&](const ast::Const* n) { //
return "const '" + symbols.NameFor(n->name->symbol) + "'";
},
diff --git a/src/tint/resolver/intrinsic_table.inl b/src/tint/resolver/intrinsic_table.inl
index 9aa0b76..c383265 100644
--- a/src/tint/resolver/intrinsic_table.inl
+++ b/src/tint/resolver/intrinsic_table.inl
@@ -14092,8 +14092,8 @@
},
{
/* [2] */
- /* fn acosh<T : fa_f32_f16>(@test_value(2) T) -> T */
- /* fn acosh<N : num, T : fa_f32_f16>(@test_value(2) vec<N, T>) -> vec<N, T> */
+ /* fn acosh<T : fa_f32_f16>(@test_value(1.5430806348) T) -> T */
+ /* fn acosh<N : num, T : fa_f32_f16>(@test_value(1.5430806348) vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
/* overloads */ &kOverloads[287],
},
@@ -14526,8 +14526,8 @@
},
{
/* [66] */
- /* fn round<T : fa_f32_f16>(@test_value(3.4) T) -> T */
- /* fn round<N : num, T : fa_f32_f16>(@test_value(3.4) vec<N, T>) -> vec<N, T> */
+ /* fn round<T : fa_f32_f16>(@test_value(3.5) T) -> T */
+ /* fn round<N : num, T : fa_f32_f16>(@test_value(3.5) vec<N, T>) -> vec<N, T> */
/* num overloads */ 2,
/* overloads */ &kOverloads[383],
},
diff --git a/src/tint/resolver/uniformity.cc b/src/tint/resolver/uniformity.cc
index 93402b6..bc4ac1d 100644
--- a/src/tint/resolver/uniformity.cc
+++ b/src/tint/resolver/uniformity.cc
@@ -15,7 +15,6 @@
#include "src/tint/resolver/uniformity.h"
#include <limits>
-#include <sstream>
#include <string>
#include <utility>
#include <vector>
diff --git a/src/tint/resolver/uniformity_test.cc b/src/tint/resolver/uniformity_test.cc
index 0a79058..51608bd 100644
--- a/src/tint/resolver/uniformity_test.cc
+++ b/src/tint/resolver/uniformity_test.cc
@@ -13,7 +13,6 @@
// limitations under the License.
#include <memory>
-#include <sstream>
#include <string>
#include <tuple>
#include <utility>
diff --git a/src/tint/sem/behavior.cc b/src/tint/sem/behavior.cc
index 670cc1d..b2c7897 100644
--- a/src/tint/sem/behavior.cc
+++ b/src/tint/sem/behavior.cc
@@ -16,7 +16,7 @@
namespace tint::sem {
-std::ostream& operator<<(std::ostream& out, Behavior behavior) {
+utils::StringStream& operator<<(utils::StringStream& out, Behavior behavior) {
switch (behavior) {
case Behavior::kReturn:
return out << "Return";
diff --git a/src/tint/sem/behavior.h b/src/tint/sem/behavior.h
index 011ca72..27eba3f 100644
--- a/src/tint/sem/behavior.h
+++ b/src/tint/sem/behavior.h
@@ -31,11 +31,11 @@
/// Behaviors is a set of Behavior
using Behaviors = utils::EnumSet<Behavior>;
-/// Writes the Behavior to the std::ostream.
-/// @param out the std::ostream to write to
+/// Writes the Behavior to the stream.
+/// @param out the stream to write to
/// @param behavior the Behavior to write
/// @returns out so calls can be chained
-std::ostream& operator<<(std::ostream& out, Behavior behavior);
+utils::StringStream& operator<<(utils::StringStream& out, Behavior behavior);
} // namespace tint::sem
diff --git a/src/tint/sem/binding_point.h b/src/tint/sem/binding_point.h
index 78403ab..6837310 100644
--- a/src/tint/sem/binding_point.h
+++ b/src/tint/sem/binding_point.h
@@ -18,10 +18,10 @@
#include <stdint.h>
#include <functional>
-#include <ostream>
#include "src/tint/reflection.h"
#include "src/tint/utils/hash.h"
+#include "src/tint/utils/string_stream.h"
namespace tint::sem {
@@ -49,10 +49,10 @@
};
/// Prints the BindingPoint @p bp to @p o
-/// @param o the std::ostream to write to
+/// @param o the stream to write to
/// @param bp the BindingPoint
-/// @return the std::ostream so calls can be chained
-inline std::ostream& operator<<(std::ostream& o, const BindingPoint& bp) {
+/// @return the stream so calls can be chained
+inline utils::StringStream& operator<<(utils::StringStream& o, const BindingPoint& bp) {
return o << "[group: " << bp.group << ", binding: " << bp.binding << "]";
}
diff --git a/src/tint/sem/builtin_type.cc b/src/tint/sem/builtin_type.cc
index d9cb0c2..8abcec0 100644
--- a/src/tint/sem/builtin_type.cc
+++ b/src/tint/sem/builtin_type.cc
@@ -22,8 +22,6 @@
#include "src/tint/sem/builtin_type.h"
-#include <sstream>
-
namespace tint::sem {
BuiltinType ParseBuiltinType(const std::string& name) {
@@ -608,7 +606,7 @@
return "<unknown>";
}
-std::ostream& operator<<(std::ostream& out, BuiltinType i) {
+utils::StringStream& operator<<(utils::StringStream& out, BuiltinType i) {
out << str(i);
return out;
}
diff --git a/src/tint/sem/builtin_type.cc.tmpl b/src/tint/sem/builtin_type.cc.tmpl
index af3b1fa..86a8623 100644
--- a/src/tint/sem/builtin_type.cc.tmpl
+++ b/src/tint/sem/builtin_type.cc.tmpl
@@ -13,8 +13,6 @@
#include "src/tint/sem/builtin_type.h"
-#include <sstream>
-
namespace tint::sem {
BuiltinType ParseBuiltinType(const std::string& name) {
@@ -38,7 +36,7 @@
return "<unknown>";
}
-std::ostream& operator<<(std::ostream& out, BuiltinType i) {
+utils::StringStream& operator<<(utils::StringStream& out, BuiltinType i) {
out << str(i);
return out;
}
diff --git a/src/tint/sem/builtin_type.h b/src/tint/sem/builtin_type.h
index 114afb6..23f3749 100644
--- a/src/tint/sem/builtin_type.h
+++ b/src/tint/sem/builtin_type.h
@@ -23,9 +23,10 @@
#ifndef SRC_TINT_SEM_BUILTIN_TYPE_H_
#define SRC_TINT_SEM_BUILTIN_TYPE_H_
-#include <sstream>
#include <string>
+#include "src/tint/utils/string_stream.h"
+
namespace tint::sem {
/// Enumerator of all builtin functions
@@ -159,7 +160,7 @@
/// Emits the name of the builtin function type. The spelling, including case,
/// matches the name in the WGSL spec.
-std::ostream& operator<<(std::ostream& out, BuiltinType i);
+utils::StringStream& operator<<(utils::StringStream& out, BuiltinType i);
/// All builtin function
constexpr BuiltinType kBuiltinTypes[] = {
diff --git a/src/tint/sem/builtin_type.h.tmpl b/src/tint/sem/builtin_type.h.tmpl
index 7e574f5..366db95 100644
--- a/src/tint/sem/builtin_type.h.tmpl
+++ b/src/tint/sem/builtin_type.h.tmpl
@@ -14,9 +14,10 @@
#ifndef SRC_TINT_SEM_BUILTIN_TYPE_H_
#define SRC_TINT_SEM_BUILTIN_TYPE_H_
-#include <sstream>
#include <string>
+#include "src/tint/utils/string_stream.h"
+
namespace tint::sem {
/// Enumerator of all builtin functions
@@ -39,7 +40,7 @@
/// Emits the name of the builtin function type. The spelling, including case,
/// matches the name in the WGSL spec.
-std::ostream& operator<<(std::ostream& out, BuiltinType i);
+utils::StringStream& operator<<(utils::StringStream& out, BuiltinType i);
/// All builtin function
constexpr BuiltinType kBuiltinTypes[] = {
diff --git a/src/tint/sem/index_accessor_expression.h b/src/tint/sem/index_accessor_expression.h
index 2375a9d..8118659 100644
--- a/src/tint/sem/index_accessor_expression.h
+++ b/src/tint/sem/index_accessor_expression.h
@@ -17,13 +17,9 @@
#include <vector>
+#include "src/tint/ast/index_accessor_expression.h"
#include "src/tint/sem/value_expression.h"
-// Forward declarations
-namespace tint::ast {
-class IndexAccessorExpression;
-} // namespace tint::ast
-
namespace tint::sem {
/// IndexAccessorExpression holds the semantic information for a ast::IndexAccessorExpression node.
@@ -52,6 +48,11 @@
/// Destructor
~IndexAccessorExpression() override;
+ /// @returns the AST node
+ const ast::IndexAccessorExpression* Declaration() const {
+ return static_cast<const ast::IndexAccessorExpression*>(declaration_);
+ }
+
/// @returns the object expression that is being indexed
ValueExpression const* Object() const { return object_; }
diff --git a/src/tint/sem/sampler_texture_pair.h b/src/tint/sem/sampler_texture_pair.h
index b3cf4f2..b0199bb 100644
--- a/src/tint/sem/sampler_texture_pair.h
+++ b/src/tint/sem/sampler_texture_pair.h
@@ -17,9 +17,9 @@
#include <cstdint>
#include <functional>
-#include <ostream>
#include "src/tint/sem/binding_point.h"
+#include "src/tint/utils/string_stream.h"
namespace tint::sem {
@@ -45,10 +45,10 @@
};
/// Prints the SamplerTexturePair @p stp to @p o
-/// @param o the std::ostream to write to
+/// @param o the stream to write to
/// @param stp the SamplerTexturePair
-/// @return the std::ostream so calls can be chained
-inline std::ostream& operator<<(std::ostream& o, const SamplerTexturePair& stp) {
+/// @return the stream so calls can be chained
+inline utils::StringStream& operator<<(utils::StringStream& o, const SamplerTexturePair& stp) {
return o << "[sampler: " << stp.sampler_binding_point
<< ", texture: " << stp.sampler_binding_point << "]";
}
diff --git a/src/tint/source.cc b/src/tint/source.cc
index 6a10de5..3f3ec7c 100644
--- a/src/tint/source.cc
+++ b/src/tint/source.cc
@@ -15,7 +15,6 @@
#include "src/tint/source.h"
#include <algorithm>
-#include <sstream>
#include <string_view>
#include <utility>
@@ -122,7 +121,7 @@
Source::File::~File() = default;
-std::ostream& operator<<(std::ostream& out, const Source& source) {
+utils::StringStream& operator<<(utils::StringStream& out, const Source& source) {
auto rng = source.range;
if (source.file) {
diff --git a/src/tint/source.h b/src/tint/source.h
index 7bf9735..cc13c5f 100644
--- a/src/tint/source.h
+++ b/src/tint/source.h
@@ -16,12 +16,13 @@
#ifndef SRC_TINT_SOURCE_H_
#define SRC_TINT_SOURCE_H_
-#include <iostream>
#include <string>
#include <string_view>
#include <tuple>
#include <vector>
+#include "src/tint/utils/string_stream.h"
+
namespace tint {
/// Source describes a range of characters within a source file.
@@ -191,35 +192,36 @@
const File* file = nullptr;
};
-/// Writes the Source::Location to the std::ostream.
-/// @param out the std::ostream to write to
+/// Writes the Source::Location to the stream.
+/// @param out the stream to write to
/// @param loc the location to write
/// @returns out so calls can be chained
-inline std::ostream& operator<<(std::ostream& out, const Source::Location& loc) {
+inline utils::StringStream& operator<<(utils::StringStream& out, const Source::Location& loc) {
out << loc.line << ":" << loc.column;
return out;
}
-/// Writes the Source::Range to the std::ostream.
-/// @param out the std::ostream to write to
+/// Writes the Source::Range to the stream.
+/// @param out the stream to write to
/// @param range the range to write
/// @returns out so calls can be chained
-inline std::ostream& operator<<(std::ostream& out, const Source::Range& range) {
+inline utils::StringStream& operator<<(utils::StringStream& out, const Source::Range& range) {
out << "[" << range.begin << ", " << range.end << "]";
return out;
}
-/// Writes the Source to the std::ostream.
-/// @param out the std::ostream to write to
+/// Writes the Source to the stream.
+/// @param out the stream to write to
/// @param source the source to write
/// @returns out so calls can be chained
-std::ostream& operator<<(std::ostream& out, const Source& source);
+utils::StringStream& operator<<(utils::StringStream& out, const Source& source);
-/// Writes the Source::FileContent to the std::ostream.
-/// @param out the std::ostream to write to
+/// Writes the Source::FileContent to the stream.
+/// @param out the stream to write to
/// @param content the file content to write
/// @returns out so calls can be chained
-inline std::ostream& operator<<(std::ostream& out, const Source::FileContent& content) {
+inline utils::StringStream& operator<<(utils::StringStream& out,
+ const Source::FileContent& content) {
out << content.data;
return out;
}
diff --git a/src/tint/templates/enums.tmpl.inc b/src/tint/templates/enums.tmpl.inc
index ab08163..ad46942 100644
--- a/src/tint/templates/enums.tmpl.inc
+++ b/src/tint/templates/enums.tmpl.inc
@@ -47,10 +47,10 @@
{{- end }}
};
-/// @param out the std::ostream to write to
+/// @param out the stream to write to
/// @param value the {{$enum}}
/// @returns `out` so calls can be chained
-std::ostream& operator<<(std::ostream& out, {{$enum}} value);
+utils::StringStream& operator<<(utils::StringStream& out, {{$enum}} value);
/// Parse{{$enum}} parses a {{$enum}} from a string.
/// @param str the string to parse
@@ -90,11 +90,11 @@
{{- /* ------------------------------------------------------------------ */ -}}
{{- define "EnumOStream" -}}
-{{- /* Implements the std::ostream 'operator<<()' function to print the */ -}}
+{{- /* Implements the stream 'operator<<()' function to print the */ -}}
{{- /* provided sem.Enum. */ -}}
{{- /* ------------------------------------------------------------------ */ -}}
{{- $enum := Eval "EnumName" $ -}}
-std::ostream& operator<<(std::ostream& out, {{$enum}} value) {
+ utils::StringStream& operator<<(utils::StringStream& out, {{$enum}} value) {
switch (value) {
case {{$enum}}::kUndefined:
return out << "undefined";
diff --git a/src/tint/text/unicode.cc b/src/tint/text/unicode.cc
index cc9a9d1..ee3092b 100644
--- a/src/tint/text/unicode.cc
+++ b/src/tint/text/unicode.cc
@@ -330,30 +330,6 @@
kXIDContinueRanges + kNumXIDContinueRanges, *this);
}
-std::ostream& operator<<(std::ostream& out, CodePoint code_point) {
- if (code_point < 0x7f) {
- // See https://en.cppreference.com/w/cpp/language/escape
- switch (code_point) {
- case '\a':
- return out << R"('\a')";
- case '\b':
- return out << R"('\b')";
- case '\f':
- return out << R"('\f')";
- case '\n':
- return out << R"('\n')";
- case '\r':
- return out << R"('\r')";
- case '\t':
- return out << R"('\t')";
- case '\v':
- return out << R"('\v')";
- }
- return out << "'" << static_cast<char>(code_point) << "'";
- }
- return out << "'U+" << std::hex << code_point.value << "'";
-}
-
namespace utf8 {
std::pair<CodePoint, size_t> Decode(const uint8_t* ptr, size_t len) {
diff --git a/src/tint/text/unicode.h b/src/tint/text/unicode.h
index 0594d31..493cdf2 100644
--- a/src/tint/text/unicode.h
+++ b/src/tint/text/unicode.h
@@ -17,7 +17,7 @@
#include <cstddef>
#include <cstdint>
-#include <ostream>
+#include <string_view>
#include <utility>
namespace tint::text {
@@ -54,12 +54,6 @@
uint32_t value = 0;
};
-/// Writes the CodePoint to the std::ostream.
-/// @param out the std::ostream to write to
-/// @param codepoint the CodePoint to write
-/// @returns out so calls can be chained
-std::ostream& operator<<(std::ostream& out, CodePoint codepoint);
-
namespace utf8 {
/// Decodes the first code point in the utf8 string.
diff --git a/src/tint/transform/direct_variable_access_test.cc b/src/tint/transform/direct_variable_access_test.cc
index f017662..cc77748 100644
--- a/src/tint/transform/direct_variable_access_test.cc
+++ b/src/tint/transform/direct_variable_access_test.cc
@@ -436,16 +436,32 @@
}
fn b() {
- let ptr_index_save = first();
- for(let p1 = &(U[ptr_index_save]); true; ) {
- a_U_X_X(10, U_X_X(u32(ptr_index_save), u32(second())), 20);
+ {
+ let ptr_index_save = first();
+ let p1 = &(U[ptr_index_save]);
+ loop {
+ if (!(true)) {
+ break;
+ }
+ {
+ a_U_X_X(10, U_X_X(u32(ptr_index_save), u32(second())), 20);
+ }
+ }
}
}
fn c_U() {
- let ptr_index_save_1 = first();
- for(let p1 = &(U[ptr_index_save_1]); true; ) {
- a_U_X_X(10, U_X_X(u32(ptr_index_save_1), u32(second())), 20);
+ {
+ let ptr_index_save_1 = first();
+ let p1 = &(U[ptr_index_save_1]);
+ loop {
+ if (!(true)) {
+ break;
+ }
+ {
+ a_U_X_X(10, U_X_X(u32(ptr_index_save_1), u32(second())), 20);
+ }
+ }
}
}
diff --git a/src/tint/transform/expand_compound_assignment_test.cc b/src/tint/transform/expand_compound_assignment_test.cc
index 6b18b40..c227398 100644
--- a/src/tint/transform/expand_compound_assignment_test.cc
+++ b/src/tint/transform/expand_compound_assignment_test.cc
@@ -391,10 +391,15 @@
}
fn main() {
- let tint_symbol = &(a[idx1()]);
- let tint_symbol_1 = idx2();
- for((*(tint_symbol))[tint_symbol_1] = ((*(tint_symbol))[tint_symbol_1] + 1); ; ) {
- break;
+ {
+ let tint_symbol = &(a[idx1()]);
+ let tint_symbol_1 = idx2();
+ (*(tint_symbol))[tint_symbol_1] = ((*(tint_symbol))[tint_symbol_1] + 1);
+ loop {
+ {
+ break;
+ }
+ }
}
}
)";
diff --git a/src/tint/transform/packed_vec3_test.cc b/src/tint/transform/packed_vec3_test.cc
index 670bc05..dbc28f7 100644
--- a/src/tint/transform/packed_vec3_test.cc
+++ b/src/tint/transform/packed_vec3_test.cc
@@ -289,7 +289,7 @@
@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
fn f() {
- v = __packed_vec3<f32>(vec3(1.23));
+ v = __packed_vec3<f32>(vec3(1.22999999999999998224));
}
)";
@@ -342,7 +342,7 @@
@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
fn f() {
- v.y = 1.23;
+ v.y = 1.22999999999999998224;
}
)";
@@ -367,7 +367,7 @@
@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
fn f() {
- v[1] = 1.23;
+ v[1] = 1.22999999999999998224;
}
)";
@@ -596,7 +596,7 @@
@group(0) @binding(0) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 4u>;
fn f() {
- arr[0].elements = __packed_vec3<f32>(vec3(1.23));
+ arr[0].elements = __packed_vec3<f32>(vec3(1.22999999999999998224));
}
)";
@@ -664,7 +664,7 @@
@group(0) @binding(0) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 4u>;
fn f() {
- arr[0].elements.y = 1.23;
+ arr[0].elements.y = 1.22999999999999998224;
}
)";
@@ -694,7 +694,7 @@
@group(0) @binding(0) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 4u>;
fn f() {
- arr[0].elements[1] = 1.23;
+ arr[0].elements[1] = 1.22999999999999998224;
}
)";
@@ -923,7 +923,7 @@
@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
fn f() {
- m[1].elements = __packed_vec3<f32>(vec3(1.23));
+ m[1].elements = __packed_vec3<f32>(vec3(1.22999999999999998224));
}
)";
@@ -991,7 +991,7 @@
@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
fn f() {
- m[1].elements.y = 1.23;
+ m[1].elements.y = 1.22999999999999998224;
}
)";
@@ -1021,7 +1021,7 @@
@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
fn f() {
- m[1].elements[2] = 1.23;
+ m[1].elements[2] = 1.22999999999999998224;
}
)";
@@ -1312,7 +1312,7 @@
@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
fn f() {
- arr[0] = tint_pack_vec3_in_composite(mat3x3(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9));
+ arr[0] = tint_pack_vec3_in_composite(mat3x3(1.10000000000000008882, 2.20000000000000017764, 3.29999999999999982236, 4.40000000000000035527, 5.5, 6.59999999999999964473, 7.70000000000000017764, 8.80000000000000071054, 9.90000000000000035527));
}
)";
@@ -1380,7 +1380,7 @@
@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
fn f() {
- arr[0][1].elements = __packed_vec3<f32>(vec3(1.23));
+ arr[0][1].elements = __packed_vec3<f32>(vec3(1.22999999999999998224));
}
)";
@@ -1453,7 +1453,7 @@
@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
fn f() {
- arr[0][1].elements.y = 1.23;
+ arr[0][1].elements.y = 1.22999999999999998224;
}
)";
@@ -1483,7 +1483,7 @@
@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
fn f() {
- arr[0][1].elements[2] = 1.23;
+ arr[0][1].elements[2] = 1.22999999999999998224;
}
)";
@@ -1685,7 +1685,7 @@
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
- P = tint_pack_vec3_in_composite(S(vec3(1.23)));
+ P = tint_pack_vec3_in_composite(S(vec3(1.22999999999999998224)));
}
)";
@@ -1764,7 +1764,7 @@
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
- P.v = __packed_vec3<f32>(vec3(1.23));
+ P.v = __packed_vec3<f32>(vec3(1.22999999999999998224));
}
)";
@@ -1852,7 +1852,7 @@
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
- P.v.y = 1.23;
+ P.v.y = 1.22999999999999998224;
}
)";
@@ -1890,7 +1890,7 @@
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
- P.v[1] = 1.23;
+ P.v[1] = 1.22999999999999998224;
}
)";
@@ -2380,7 +2380,7 @@
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
- P.arr[0].elements = __packed_vec3<f32>(vec3(1.23));
+ P.arr[0].elements = __packed_vec3<f32>(vec3(1.22999999999999998224));
}
)";
@@ -2479,7 +2479,7 @@
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
- P.arr[0].elements.y = 1.23;
+ P.arr[0].elements.y = 1.22999999999999998224;
}
)";
@@ -2522,7 +2522,7 @@
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
- P.arr[0].elements[1] = 1.23;
+ P.arr[0].elements[1] = 1.22999999999999998224;
}
)";
@@ -3012,7 +3012,7 @@
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
- P.m[1].elements = __packed_vec3<f32>(vec3(1.23));
+ P.m[1].elements = __packed_vec3<f32>(vec3(1.22999999999999998224));
}
)";
@@ -3111,7 +3111,7 @@
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
- P.m[1].elements.y = 1.23;
+ P.m[1].elements.y = 1.22999999999999998224;
}
)";
@@ -3154,7 +3154,7 @@
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
- P.m[1].elements[2] = 1.23;
+ P.m[1].elements[2] = 1.22999999999999998224;
}
)";
@@ -3834,7 +3834,7 @@
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
- P.arr[0][1].elements = __packed_vec3<f32>(vec3(1.23));
+ P.arr[0][1].elements = __packed_vec3<f32>(vec3(1.22999999999999998224));
}
)";
@@ -3938,7 +3938,7 @@
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
- P.arr[0][1].elements.y = 1.23;
+ P.arr[0][1].elements.y = 1.22999999999999998224;
}
)";
@@ -3981,7 +3981,7 @@
@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
fn f() {
- P.arr[0][1].elements[2] = 1.23;
+ P.arr[0][1].elements[2] = 1.22999999999999998224;
}
)";
diff --git a/src/tint/transform/pad_structs.h b/src/tint/transform/pad_structs.h
index e9996d4..1add1d6 100644
--- a/src/tint/transform/pad_structs.h
+++ b/src/tint/transform/pad_structs.h
@@ -22,6 +22,8 @@
/// This transform turns all explicit alignment and sizing into padding
/// members of structs. This is required for GLSL ES, since it not support
/// the offset= decoration.
+///
+/// @note This transform requires the CanonicalizeEntryPointIO transform to have been run first.
class PadStructs final : public Castable<PadStructs, Transform> {
public:
/// Constructor
diff --git a/src/tint/transform/promote_initializers_to_let_test.cc b/src/tint/transform/promote_initializers_to_let_test.cc
index 539f513..fc593d5 100644
--- a/src/tint/transform/promote_initializers_to_let_test.cc
+++ b/src/tint/transform/promote_initializers_to_let_test.cc
@@ -272,9 +272,14 @@
auto* expect = R"(
fn f() {
var insert_after = 1;
- let tint_symbol : array<f32, 4u> = array<f32, 4u>(0.0, 1.0, 2.0, 3.0);
- for(var i = tint_symbol[insert_after]; ; ) {
- break;
+ {
+ let tint_symbol : array<f32, 4u> = array<f32, 4u>(0.0, 1.0, 2.0, 3.0);
+ var i = tint_symbol[insert_after];
+ loop {
+ {
+ break;
+ }
+ }
}
}
)";
@@ -301,9 +306,14 @@
const arr = array<f32, 4u>(0.0, 1.0, 2.0, 3.0);
let runtime_value = 1;
var insert_after = 1;
- let tint_symbol : array<f32, 4u> = arr;
- for(var i = tint_symbol[runtime_value]; ; ) {
- break;
+ {
+ let tint_symbol : array<f32, 4u> = arr;
+ var i = tint_symbol[runtime_value];
+ loop {
+ {
+ break;
+ }
+ }
}
}
)";
@@ -332,9 +342,14 @@
fn f() {
let runtime_value = 1;
var insert_after = 1;
- let tint_symbol : array<f32, 4u> = arr;
- for(var i = tint_symbol[runtime_value]; ; ) {
- break;
+ {
+ let tint_symbol : array<f32, 4u> = arr;
+ var i = tint_symbol[runtime_value];
+ loop {
+ {
+ break;
+ }
+ }
}
}
)";
@@ -377,9 +392,14 @@
fn f() {
var insert_after = 1;
- let tint_symbol : S = S(1, 2.0, vec3<f32>());
- for(var x = get_b_runtime(tint_symbol); ; ) {
- break;
+ {
+ let tint_symbol : S = S(1, 2.0, vec3<f32>());
+ var x = get_b_runtime(tint_symbol);
+ loop {
+ {
+ break;
+ }
+ }
}
}
)";
@@ -412,9 +432,14 @@
auto* expect = R"(
fn f() {
var insert_after = 1;
- let tint_symbol : S = S(1, 2.0, vec3<f32>());
- for(var x = get_b_runtime(tint_symbol); ; ) {
- break;
+ {
+ let tint_symbol : S = S(1, 2.0, vec3<f32>());
+ var x = get_b_runtime(tint_symbol);
+ loop {
+ {
+ break;
+ }
+ }
}
}
@@ -683,8 +708,8 @@
auto* expect = R"(
fn f() {
let runtime_value = 0;
- let tint_symbol : array<f32, 1u> = array<f32, 1u>(0.0);
{
+ let tint_symbol : array<f32, 1u> = array<f32, 1u>(0.0);
var f = tint_symbol[runtime_value];
loop {
let tint_symbol_1 : array<f32, 1u> = array<f32, 1u>(1.0);
@@ -728,8 +753,8 @@
const arr_a = array<f32, 1u>(0.0);
const arr_b = array<f32, 1u>(1.0);
const arr_c = array<f32, 1u>(2.0);
- let tint_symbol : array<f32, 1u> = arr_a;
{
+ let tint_symbol : array<f32, 1u> = arr_a;
var f = tint_symbol[runtime_value];
loop {
let tint_symbol_1 : array<f32, 1u> = arr_b;
@@ -1301,9 +1326,21 @@
fn Z() {
var i = 10;
- let tint_symbol_2 : array<i32, 1u> = array<i32, 1u>(i);
- for(var f = tint_symbol_2[0]; (f < 10); f = (f + 1)) {
- var i = 20;
+ {
+ let tint_symbol_2 : array<i32, 1u> = array<i32, 1u>(i);
+ var f = tint_symbol_2[0];
+ loop {
+ if (!((f < 10))) {
+ break;
+ }
+ {
+ var i = 20;
+ }
+
+ continuing {
+ f = (f + 1);
+ }
+ }
}
}
)";
diff --git a/src/tint/transform/promote_side_effects_to_decl_test.cc b/src/tint/transform/promote_side_effects_to_decl_test.cc
index f064834..6ed4b27 100644
--- a/src/tint/transform/promote_side_effects_to_decl_test.cc
+++ b/src/tint/transform/promote_side_effects_to_decl_test.cc
@@ -848,10 +848,15 @@
fn f() {
var b = 1;
- let tint_symbol = a(0);
- for(var r = (tint_symbol + b); ; ) {
- var marker = 0;
- break;
+ {
+ let tint_symbol = a(0);
+ var r = (tint_symbol + b);
+ loop {
+ {
+ var marker = 0;
+ break;
+ }
+ }
}
}
)";
@@ -2169,13 +2174,18 @@
fn f() {
var b = true;
- var tint_symbol = a(0);
- if (tint_symbol) {
- tint_symbol = b;
- }
- for(var r = tint_symbol; ; ) {
- var marker = 0;
- break;
+ {
+ var tint_symbol = a(0);
+ if (tint_symbol) {
+ tint_symbol = b;
+ }
+ var r = tint_symbol;
+ loop {
+ {
+ var marker = 0;
+ break;
+ }
+ }
}
}
)";
diff --git a/src/tint/transform/robustness.h b/src/tint/transform/robustness.h
index 14c5fe1..780eab9 100644
--- a/src/tint/transform/robustness.h
+++ b/src/tint/transform/robustness.h
@@ -31,6 +31,7 @@
/// the bounds of the array. Any access before the start of the array will clamp
/// to zero and any access past the end of the array will clamp to
/// (array length - 1).
+/// @note This transform must come before the BuiltinPolyfill transform
class Robustness final : public Castable<Robustness, Transform> {
public:
/// Address space to be skipped in the transform
diff --git a/src/tint/transform/substitute_override_test.cc b/src/tint/transform/substitute_override_test.cc
index abc67f5..1b4646f 100644
--- a/src/tint/transform/substitute_override_test.cc
+++ b/src/tint/transform/substitute_override_test.cc
@@ -110,9 +110,9 @@
const i_height = 11i;
-const f_width : f32 = 22.299999237f;
+const f_width : f32 = 22.299999237060546875f;
-const f_height = 12.399999619f;
+const f_height = 12.3999996185302734375f;
const b_width : bool = true;
@@ -175,9 +175,9 @@
const i_height = 11i;
-const f_width : f32 = 22.299999237f;
+const f_width : f32 = 22.299999237060546875f;
-const f_height = 12.399999619f;
+const f_height = 12.3999996185302734375f;
const b_width : bool = true;
diff --git a/src/tint/transform/texture_1d_to_2d_test.cc b/src/tint/transform/texture_1d_to_2d_test.cc
index 0196951..b68b51e 100644
--- a/src/tint/transform/texture_1d_to_2d_test.cc
+++ b/src/tint/transform/texture_1d_to_2d_test.cc
@@ -226,7 +226,7 @@
@group(0) @binding(1) var samp : sampler;
fn f(t : texture_2d<f32>, s : sampler) -> vec4<f32> {
- return textureSample(t, s, vec2<f32>(0.7, 0.5));
+ return textureSample(t, s, vec2<f32>(0.69999999999999995559, 0.5));
}
fn main() -> vec4<f32> {
diff --git a/src/tint/transform/transform.cc b/src/tint/transform/transform.cc
index ad954ee..73ee3ae 100644
--- a/src/tint/transform/transform.cc
+++ b/src/tint/transform/transform.cc
@@ -173,6 +173,15 @@
if (auto* s = ty->As<type::Sampler>()) {
return ctx.dst->ty.sampler(s->kind());
}
+ if (auto* p = ty->As<type::Pointer>()) {
+ // Note: type::Pointer always has an inferred access, but WGSL only allows an explicit
+ // access in the 'storage' address space.
+ auto address_space = p->AddressSpace();
+ auto access = address_space == builtin::AddressSpace::kStorage
+ ? p->Access()
+ : builtin::Access::kUndefined;
+ return ctx.dst->ty.pointer(CreateASTTypeFor(ctx, p->StoreType()), address_space, access);
+ }
TINT_UNREACHABLE(Transform, ctx.dst->Diagnostics())
<< "Unhandled type: " << ty->TypeInfo().name;
return ast::Type{};
diff --git a/src/tint/transform/transform_test.cc b/src/tint/transform/transform_test.cc
index f27a990..deffae3 100644
--- a/src/tint/transform/transform_test.cc
+++ b/src/tint/transform/transform_test.cc
@@ -127,5 +127,24 @@
ast::CheckIdentifier(ast_type_builder.Symbols(), str, "S");
}
+TEST_F(CreateASTTypeForTest, PrivatePointer) {
+ auto ptr = create([](ProgramBuilder& b) {
+ return b.create<type::Pointer>(b.create<type::I32>(), builtin::AddressSpace::kPrivate,
+ builtin::Access::kReadWrite);
+ });
+
+ ast::CheckIdentifier(ast_type_builder.Symbols(), ptr, ast::Template("ptr", "private", "i32"));
+}
+
+TEST_F(CreateASTTypeForTest, StorageReadWritePointer) {
+ auto ptr = create([](ProgramBuilder& b) {
+ return b.create<type::Pointer>(b.create<type::I32>(), builtin::AddressSpace::kStorage,
+ builtin::Access::kReadWrite);
+ });
+
+ ast::CheckIdentifier(ast_type_builder.Symbols(), ptr,
+ ast::Template("ptr", "storage", "i32", "read_write"));
+}
+
} // namespace
} // namespace tint::transform
diff --git a/src/tint/transform/utils/hoist_to_decl_before.cc b/src/tint/transform/utils/hoist_to_decl_before.cc
index 0c2c6eb..5fa00c4 100644
--- a/src/tint/transform/utils/hoist_to_decl_before.cc
+++ b/src/tint/transform/utils/hoist_to_decl_before.cc
@@ -99,6 +99,21 @@
return InsertBeforeImpl(before_stmt, std::move(builder));
}
+ /// @copydoc HoistToDeclBefore::Replace(const sem::Statement* what, const ast::Statement* with)
+ bool Replace(const sem::Statement* what, const ast::Statement* with) {
+ auto builder = [with] { return with; };
+ return Replace(what, std::move(builder));
+ }
+
+ /// @copydoc HoistToDeclBefore::Replace(const sem::Statement* what, const StmtBuilder& with)
+ bool Replace(const sem::Statement* what, const StmtBuilder& with) {
+ if (!InsertBeforeImpl(what, Decompose{})) {
+ return false;
+ }
+ ctx.Replace(what->Declaration(), with);
+ return true;
+ }
+
/// @copydoc HoistToDeclBefore::Prepare()
bool Prepare(const sem::ValueExpression* before_expr) {
return InsertBefore(before_expr->Stmt(), nullptr);
@@ -112,6 +127,7 @@
/// loop, so that declaration statements can be inserted before the
/// condition expression or continuing statement.
struct LoopInfo {
+ utils::Vector<StmtBuilder, 8> init_decls;
utils::Vector<StmtBuilder, 8> cond_decls;
utils::Vector<StmtBuilder, 8> cont_decls;
};
@@ -198,7 +214,7 @@
// Next emit the for-loop body
body_stmts.Push(ctx.Clone(for_loop->body));
- // Finally create the continuing block if there was one.
+ // Create the continuing block if there was one.
const ast::BlockStatement* continuing = nullptr;
if (auto* cont = for_loop->continuing) {
// Continuing block starts with any let declarations used by
@@ -210,8 +226,17 @@
auto* body = b.Block(body_stmts);
auto* loop = b.Loop(body, continuing);
- if (auto* init = for_loop->initializer) {
- return b.Block(ctx.Clone(init), loop);
+
+ // If the loop has no initializer statements, then we're done.
+ // Otherwise, wrap loop with another block, prefixed with the initializer
+ // statements
+ if (!info->init_decls.IsEmpty() || for_loop->initializer) {
+ auto stmts = Build(info->init_decls);
+ if (auto* init = for_loop->initializer) {
+ stmts.Push(ctx.Clone(init));
+ }
+ stmts.Push(loop);
+ return b.Block(std::move(stmts));
}
return loop;
}
@@ -299,7 +324,7 @@
// Need to convert 'else if' to 'else { if }'.
auto else_if_info = ElseIf(else_if->Declaration());
- // Index the map to convert this else if, even if `stmt` is nullptr.
+ // Index the map to decompose this else if, even if `stmt` is nullptr.
auto& decls = else_if_info->cond_decls;
if constexpr (!std::is_same_v<BUILDER, Decompose>) {
decls.Push(std::forward<BUILDER>(builder));
@@ -311,7 +336,7 @@
// Insertion point is a for-loop condition.
// For-loop needs to be decomposed to a loop.
- // Index the map to convert this for-loop, even if `stmt` is nullptr.
+ // Index the map to decompose this for-loop, even if `stmt` is nullptr.
auto& decls = ForLoop(fl)->cond_decls;
if constexpr (!std::is_same_v<BUILDER, Decompose>) {
decls.Push(std::forward<BUILDER>(builder));
@@ -323,7 +348,7 @@
// Insertion point is a while condition.
// While needs to be decomposed to a loop.
- // Index the map to convert this while, even if `stmt` is nullptr.
+ // Index the map to decompose this while, even if `stmt` is nullptr.
auto& decls = WhileLoop(w)->cond_decls;
if constexpr (!std::is_same_v<BUILDER, Decompose>) {
decls.Push(std::forward<BUILDER>(builder));
@@ -348,11 +373,14 @@
// These require special care.
if (fl->Declaration()->initializer == ip) {
// Insertion point is a for-loop initializer.
- // Insert the new statement above the for-loop.
+ // For-loop needs to be decomposed to a loop.
+
+ // Index the map to decompose this for-loop, even if `stmt` is nullptr.
+ auto& decls = ForLoop(fl)->init_decls;
if constexpr (!std::is_same_v<BUILDER, Decompose>) {
- ctx.InsertBefore(fl->Block()->Declaration()->statements, fl->Declaration(),
- std::forward<BUILDER>(builder));
+ decls.Push(std::forward<BUILDER>(builder));
}
+
return true;
}
@@ -360,11 +388,12 @@
// Insertion point is a for-loop continuing statement.
// For-loop needs to be decomposed to a loop.
- // Index the map to convert this for-loop, even if `stmt` is nullptr.
+ // Index the map to decompose this for-loop, even if `stmt` is nullptr.
auto& decls = ForLoop(fl)->cont_decls;
if constexpr (!std::is_same_v<BUILDER, Decompose>) {
decls.Push(std::forward<BUILDER>(builder));
}
+
return true;
}
@@ -399,6 +428,14 @@
return state_->InsertBefore(before_stmt, builder);
}
+bool HoistToDeclBefore::Replace(const sem::Statement* what, const ast::Statement* with) {
+ return state_->Replace(what, with);
+}
+
+bool HoistToDeclBefore::Replace(const sem::Statement* what, const StmtBuilder& with) {
+ return state_->Replace(what, with);
+}
+
bool HoistToDeclBefore::Prepare(const sem::ValueExpression* before_expr) {
return state_->Prepare(before_expr);
}
diff --git a/src/tint/transform/utils/hoist_to_decl_before.h b/src/tint/transform/utils/hoist_to_decl_before.h
index 81c255f..c662b1e 100644
--- a/src/tint/transform/utils/hoist_to_decl_before.h
+++ b/src/tint/transform/utils/hoist_to_decl_before.h
@@ -76,6 +76,20 @@
/// @return true on success
bool InsertBefore(const sem::Statement* before_stmt, const StmtBuilder& builder);
+ /// Replaces the statement @p what with the statement @p stmt, possibly converting 'for-loop's
+ /// to 'loop's if necessary.
+ /// @param what the statement to replace
+ /// @param with the replacement statement
+ /// @return true on success
+ bool Replace(const sem::Statement* what, const ast::Statement* with);
+
+ /// Replaces the statement @p what with the statement returned by @p stmt, possibly converting
+ /// 'for-loop's to 'loop's if necessary.
+ /// @param what the statement to replace
+ /// @param with the replacement statement builder
+ /// @return true on success
+ bool Replace(const sem::Statement* what, const StmtBuilder& with);
+
/// Use to signal that we plan on hoisting a decl before `before_expr`. This
/// will convert 'for-loop's to 'loop's and 'else-if's to 'else {if}'s if
/// needed.
diff --git a/src/tint/transform/utils/hoist_to_decl_before_test.cc b/src/tint/transform/utils/hoist_to_decl_before_test.cc
index e8d92ed..0abb809 100644
--- a/src/tint/transform/utils/hoist_to_decl_before_test.cc
+++ b/src/tint/transform/utils/hoist_to_decl_before_test.cc
@@ -82,8 +82,16 @@
auto* expect = R"(
fn f() {
- var tint_symbol : i32 = 1i;
- for(var a = tint_symbol; true; ) {
+ {
+ var tint_symbol : i32 = 1i;
+ var a = tint_symbol;
+ loop {
+ if (!(true)) {
+ break;
+ }
+ {
+ }
+ }
}
}
)";
@@ -545,8 +553,16 @@
}
fn f() {
- foo();
- for(var a = 1i; true; ) {
+ {
+ foo();
+ var a = 1i;
+ loop {
+ if (!(true)) {
+ break;
+ }
+ {
+ }
+ }
}
}
)";
@@ -584,8 +600,16 @@
}
fn f() {
- foo();
- for(var a = 1i; true; ) {
+ {
+ foo();
+ var a = 1i;
+ loop {
+ if (!(true)) {
+ break;
+ }
+ {
+ }
+ }
}
}
)";
@@ -853,5 +877,264 @@
EXPECT_EQ(expect, str(cloned));
}
+TEST_F(HoistToDeclBeforeTest, Replace_Block) {
+ // fn foo() {
+ // }
+ // fn f() {
+ // var a = 1i;
+ // }
+ ProgramBuilder b;
+ b.Func("foo", utils::Empty, b.ty.void_(), utils::Empty);
+ auto* var = b.Decl(b.Var("a", b.Expr(1_i)));
+ b.Func("f", utils::Empty, b.ty.void_(), utils::Vector{var});
+
+ Program original(std::move(b));
+ ProgramBuilder cloned_b;
+ CloneContext ctx(&cloned_b, &original);
+
+ HoistToDeclBefore hoistToDeclBefore(ctx);
+ auto* target_stmt = ctx.src->Sem().Get(var);
+ auto* new_stmt = ctx.dst->CallStmt(ctx.dst->Call("foo"));
+ hoistToDeclBefore.Replace(target_stmt, new_stmt);
+
+ ctx.Clone();
+ Program cloned(std::move(cloned_b));
+
+ auto* expect = R"(
+fn foo() {
+}
+
+fn f() {
+ foo();
+}
+)";
+
+ EXPECT_EQ(expect, str(cloned));
+}
+
+TEST_F(HoistToDeclBeforeTest, Replace_Block_Function) {
+ // fn foo() {
+ // }
+ // fn f() {
+ // var a = 1i;
+ // }
+ ProgramBuilder b;
+ b.Func("foo", utils::Empty, b.ty.void_(), utils::Empty);
+ auto* var = b.Decl(b.Var("a", b.Expr(1_i)));
+ b.Func("f", utils::Empty, b.ty.void_(), utils::Vector{var});
+
+ Program original(std::move(b));
+ ProgramBuilder cloned_b;
+ CloneContext ctx(&cloned_b, &original);
+
+ HoistToDeclBefore hoistToDeclBefore(ctx);
+ auto* target_stmt = ctx.src->Sem().Get(var);
+ hoistToDeclBefore.Replace(target_stmt, [&] { return ctx.dst->CallStmt(ctx.dst->Call("foo")); });
+
+ ctx.Clone();
+ Program cloned(std::move(cloned_b));
+
+ auto* expect = R"(
+fn foo() {
+}
+
+fn f() {
+ foo();
+}
+)";
+
+ EXPECT_EQ(expect, str(cloned));
+}
+
+TEST_F(HoistToDeclBeforeTest, Replace_ForLoopInit) {
+ // fn foo() {
+ // }
+ // fn f() {
+ // for(var a = 1i; true;) {
+ // }
+ // }
+ ProgramBuilder b;
+ b.Func("foo", utils::Empty, b.ty.void_(), utils::Empty);
+ auto* var = b.Decl(b.Var("a", b.Expr(1_i)));
+ auto* s = b.For(var, b.Expr(true), nullptr, b.Block());
+ b.Func("f", utils::Empty, b.ty.void_(), utils::Vector{s});
+
+ Program original(std::move(b));
+ ProgramBuilder cloned_b;
+ CloneContext ctx(&cloned_b, &original);
+
+ HoistToDeclBefore hoistToDeclBefore(ctx);
+ auto* target_stmt = ctx.src->Sem().Get(var);
+ auto* new_stmt = ctx.dst->CallStmt(ctx.dst->Call("foo"));
+ hoistToDeclBefore.Replace(target_stmt, new_stmt);
+
+ ctx.Clone();
+ Program cloned(std::move(cloned_b));
+
+ auto* expect = R"(
+fn foo() {
+}
+
+fn f() {
+ {
+ foo();
+ loop {
+ if (!(true)) {
+ break;
+ }
+ {
+ }
+ }
+ }
+}
+)";
+
+ EXPECT_EQ(expect, str(cloned));
+}
+
+TEST_F(HoistToDeclBeforeTest, Replace_ForLoopInit_Function) {
+ // fn foo() {
+ // }
+ // fn f() {
+ // for(var a = 1i; true;) {
+ // }
+ // }
+ ProgramBuilder b;
+ b.Func("foo", utils::Empty, b.ty.void_(), utils::Empty);
+ auto* var = b.Decl(b.Var("a", b.Expr(1_i)));
+ auto* s = b.For(var, b.Expr(true), nullptr, b.Block());
+ b.Func("f", utils::Empty, b.ty.void_(), utils::Vector{s});
+
+ Program original(std::move(b));
+ ProgramBuilder cloned_b;
+ CloneContext ctx(&cloned_b, &original);
+
+ HoistToDeclBefore hoistToDeclBefore(ctx);
+ auto* target_stmt = ctx.src->Sem().Get(var);
+ hoistToDeclBefore.Replace(target_stmt, [&] { return ctx.dst->CallStmt(ctx.dst->Call("foo")); });
+
+ ctx.Clone();
+ Program cloned(std::move(cloned_b));
+
+ auto* expect = R"(
+fn foo() {
+}
+
+fn f() {
+ {
+ foo();
+ loop {
+ if (!(true)) {
+ break;
+ }
+ {
+ }
+ }
+ }
+}
+)";
+
+ EXPECT_EQ(expect, str(cloned));
+}
+
+TEST_F(HoistToDeclBeforeTest, Replace_ForLoopCont) {
+ // fn foo() {
+ // }
+ // fn f() {
+ // var a = 1i;
+ // for(; true; a+=1i) {
+ // }
+ // }
+ ProgramBuilder b;
+ b.Func("foo", utils::Empty, b.ty.void_(), utils::Empty);
+ auto* var = b.Decl(b.Var("a", b.Expr(1_i)));
+ auto* cont = b.CompoundAssign("a", b.Expr(1_i), ast::BinaryOp::kAdd);
+ auto* s = b.For(nullptr, b.Expr(true), cont, b.Block());
+ b.Func("f", utils::Empty, b.ty.void_(), utils::Vector{var, s});
+
+ Program original(std::move(b));
+ ProgramBuilder cloned_b;
+ CloneContext ctx(&cloned_b, &original);
+
+ HoistToDeclBefore hoistToDeclBefore(ctx);
+ auto* target_stmt = ctx.src->Sem().Get(cont->As<ast::Statement>());
+ auto* new_stmt = ctx.dst->CallStmt(ctx.dst->Call("foo"));
+ hoistToDeclBefore.Replace(target_stmt, new_stmt);
+
+ ctx.Clone();
+ Program cloned(std::move(cloned_b));
+
+ auto* expect = R"(
+fn foo() {
+}
+
+fn f() {
+ var a = 1i;
+ loop {
+ if (!(true)) {
+ break;
+ }
+ {
+ }
+
+ continuing {
+ foo();
+ }
+ }
+}
+)";
+
+ EXPECT_EQ(expect, str(cloned));
+}
+
+TEST_F(HoistToDeclBeforeTest, Replace_ForLoopCont_Function) {
+ // fn foo() {
+ // }
+ // fn f() {
+ // var a = 1i;
+ // for(; true; a+=1i) {
+ // }
+ // }
+ ProgramBuilder b;
+ b.Func("foo", utils::Empty, b.ty.void_(), utils::Empty);
+ auto* var = b.Decl(b.Var("a", b.Expr(1_i)));
+ auto* cont = b.CompoundAssign("a", b.Expr(1_i), ast::BinaryOp::kAdd);
+ auto* s = b.For(nullptr, b.Expr(true), cont, b.Block());
+ b.Func("f", utils::Empty, b.ty.void_(), utils::Vector{var, s});
+
+ Program original(std::move(b));
+ ProgramBuilder cloned_b;
+ CloneContext ctx(&cloned_b, &original);
+
+ HoistToDeclBefore hoistToDeclBefore(ctx);
+ auto* target_stmt = ctx.src->Sem().Get(cont->As<ast::Statement>());
+ hoistToDeclBefore.Replace(target_stmt, [&] { return ctx.dst->CallStmt(ctx.dst->Call("foo")); });
+
+ ctx.Clone();
+ Program cloned(std::move(cloned_b));
+
+ auto* expect = R"(
+fn foo() {
+}
+
+fn f() {
+ var a = 1i;
+ loop {
+ if (!(true)) {
+ break;
+ }
+ {
+ }
+
+ continuing {
+ foo();
+ }
+ }
+}
+)";
+
+ EXPECT_EQ(expect, str(cloned));
+}
+
} // namespace
} // namespace tint::transform
diff --git a/src/tint/transform/var_for_dynamic_index_test.cc b/src/tint/transform/var_for_dynamic_index_test.cc
index 80a79d5..2130ae1 100644
--- a/src/tint/transform/var_for_dynamic_index_test.cc
+++ b/src/tint/transform/var_for_dynamic_index_test.cc
@@ -126,9 +126,14 @@
fn f() {
var i : i32;
let p = array<array<i32, 2>, 2>(array<i32, 2>(1, 2), array<i32, 2>(3, 4));
- var var_for_index : array<array<i32, 2u>, 2u> = p;
- for(let x = var_for_index[i]; ; ) {
- break;
+ {
+ var var_for_index : array<array<i32, 2u>, 2u> = p;
+ let x = var_for_index[i];
+ loop {
+ {
+ break;
+ }
+ }
}
}
)";
@@ -154,9 +159,14 @@
fn f() {
var i : i32;
let p = mat2x2(1.0, 2.0, 3.0, 4.0);
- var var_for_index : mat2x2<f32> = p;
- for(let x = var_for_index[i]; ; ) {
- break;
+ {
+ var var_for_index : mat2x2<f32> = p;
+ let x = var_for_index[i];
+ loop {
+ {
+ break;
+ }
+ }
}
}
)";
diff --git a/src/tint/transform/vertex_pulling.cc b/src/tint/transform/vertex_pulling.cc
index 09a68bb..e07dcfe 100644
--- a/src/tint/transform/vertex_pulling.cc
+++ b/src/tint/transform/vertex_pulling.cc
@@ -56,8 +56,8 @@
kFloat, // unsigned normalized, signed normalized, and float
};
-/// Writes the VertexFormat to the std::ostream.
-/// @param out the std::ostream to write to
+/// Writes the VertexFormat to the stream.
+/// @param out the stream to write to
/// @param format the VertexFormat to write
/// @returns out so calls can be chained
utils::StringStream& operator<<(utils::StringStream& out, VertexFormat format) {
diff --git a/src/tint/type/sampler_kind.cc b/src/tint/type/sampler_kind.cc
index 4e20700..0076287 100644
--- a/src/tint/type/sampler_kind.cc
+++ b/src/tint/type/sampler_kind.cc
@@ -16,7 +16,7 @@
namespace tint::type {
-std::ostream& operator<<(std::ostream& out, SamplerKind kind) {
+utils::StringStream& operator<<(utils::StringStream& out, SamplerKind kind) {
switch (kind) {
case SamplerKind::kSampler:
out << "sampler";
diff --git a/src/tint/type/sampler_kind.h b/src/tint/type/sampler_kind.h
index 3522fda..b5b01b9 100644
--- a/src/tint/type/sampler_kind.h
+++ b/src/tint/type/sampler_kind.h
@@ -15,7 +15,7 @@
#ifndef SRC_TINT_TYPE_SAMPLER_KIND_H_
#define SRC_TINT_TYPE_SAMPLER_KIND_H_
-#include <ostream>
+#include "src/tint/utils/string_stream.h"
namespace tint::type {
@@ -27,10 +27,10 @@
kComparisonSampler
};
-/// @param out the std::ostream to write to
+/// @param out the stream to write to
/// @param kind the SamplerKind
-/// @return the std::ostream so calls can be chained
-std::ostream& operator<<(std::ostream& out, SamplerKind kind);
+/// @return the stream so calls can be chained
+utils::StringStream& operator<<(utils::StringStream& out, SamplerKind kind);
} // namespace tint::type
diff --git a/src/tint/type/texture_dimension.cc b/src/tint/type/texture_dimension.cc
index 4b4fea9..c450516 100644
--- a/src/tint/type/texture_dimension.cc
+++ b/src/tint/type/texture_dimension.cc
@@ -16,7 +16,7 @@
namespace tint::type {
-std::ostream& operator<<(std::ostream& out, type::TextureDimension dim) {
+utils::StringStream& operator<<(utils::StringStream& out, type::TextureDimension dim) {
switch (dim) {
case type::TextureDimension::kNone:
out << "None";
diff --git a/src/tint/type/texture_dimension.h b/src/tint/type/texture_dimension.h
index 0da2b05..a315b7e 100644
--- a/src/tint/type/texture_dimension.h
+++ b/src/tint/type/texture_dimension.h
@@ -15,7 +15,7 @@
#ifndef SRC_TINT_TYPE_TEXTURE_DIMENSION_H_
#define SRC_TINT_TYPE_TEXTURE_DIMENSION_H_
-#include <ostream>
+#include "src/tint/utils/string_stream.h"
namespace tint::type {
@@ -37,10 +37,10 @@
kCubeArray,
};
-/// @param out the std::ostream to write to
+/// @param out the stream to write to
/// @param dim the type::TextureDimension
-/// @return the std::ostream so calls can be chained
-std::ostream& operator<<(std::ostream& out, type::TextureDimension dim);
+/// @return the stream so calls can be chained
+utils::StringStream& operator<<(utils::StringStream& out, type::TextureDimension dim);
} // namespace tint::type
diff --git a/src/tint/utils/enum_set.h b/src/tint/utils/enum_set.h
index 9b75ba0..575868b 100644
--- a/src/tint/utils/enum_set.h
+++ b/src/tint/utils/enum_set.h
@@ -17,10 +17,11 @@
#include <cstdint>
#include <functional>
-#include <ostream>
#include <type_traits>
#include <utility>
+#include "src/tint/utils/string_stream.h"
+
namespace tint::utils {
/// EnumSet is a set of enum values.
@@ -216,12 +217,12 @@
uint64_t set = 0;
};
-/// Writes the EnumSet to the std::ostream.
-/// @param out the std::ostream to write to
+/// Writes the EnumSet to the stream.
+/// @param out the stream to write to
/// @param set the EnumSet to write
/// @returns out so calls can be chained
template <typename ENUM>
-inline std::ostream& operator<<(std::ostream& out, EnumSet<ENUM> set) {
+inline utils::StringStream& operator<<(utils::StringStream& out, EnumSet<ENUM> set) {
out << "{";
bool first = true;
for (auto e : set) {
diff --git a/src/tint/utils/enum_set_test.cc b/src/tint/utils/enum_set_test.cc
index a6bb169..6e9b59c 100644
--- a/src/tint/utils/enum_set_test.cc
+++ b/src/tint/utils/enum_set_test.cc
@@ -14,7 +14,6 @@
#include "src/tint/utils/enum_set.h"
-#include <sstream>
#include <vector>
#include "gmock/gmock.h"
@@ -27,7 +26,7 @@
enum class E { A = 0, B = 3, C = 7 };
-std::ostream& operator<<(std::ostream& out, E e) {
+utils::StringStream& operator<<(utils::StringStream& out, E e) {
switch (e) {
case E::A:
return out << "A";
diff --git a/src/tint/utils/hashmap_base.h b/src/tint/utils/hashmap_base.h
index 959bebe..12c1ed2 100644
--- a/src/tint/utils/hashmap_base.h
+++ b/src/tint/utils/hashmap_base.h
@@ -91,12 +91,12 @@
operator KeyValue<KEY, VALUE>() const { return {key, value}; }
};
-/// Writes the KeyValue to the std::ostream.
-/// @param out the std::ostream to write to
+/// Writes the KeyValue to the stream.
+/// @param out the stream to write to
/// @param key_value the KeyValue to write
/// @returns out so calls can be chained
template <typename KEY, typename VALUE>
-std::ostream& operator<<(std::ostream& out, const KeyValue<KEY, VALUE>& key_value) {
+utils::StringStream& operator<<(utils::StringStream& out, const KeyValue<KEY, VALUE>& key_value) {
return out << "[" << key_value.key << ": " << key_value.value << "]";
}
diff --git a/src/tint/utils/io/command_windows.cc b/src/tint/utils/io/command_windows.cc
index 31d0308..fc5df2c 100644
--- a/src/tint/utils/io/command_windows.cc
+++ b/src/tint/utils/io/command_windows.cc
@@ -17,7 +17,6 @@
#define WIN32_LEAN_AND_MEAN 1
#include <Windows.h>
#include <dbghelp.h>
-#include <sstream>
#include <string>
#include "src/tint/utils/defer.h"
diff --git a/src/tint/utils/io/tmpfile.h b/src/tint/utils/io/tmpfile.h
index 7949a37..016ac08 100644
--- a/src/tint/utils/io/tmpfile.h
+++ b/src/tint/utils/io/tmpfile.h
@@ -15,7 +15,6 @@
#ifndef SRC_TINT_UTILS_IO_TMPFILE_H_
#define SRC_TINT_UTILS_IO_TMPFILE_H_
-#include <sstream>
#include <string>
#include "src/tint/utils/string_stream.h"
diff --git a/src/tint/utils/math.h b/src/tint/utils/math.h
index d882b34..c10a2c9 100644
--- a/src/tint/utils/math.h
+++ b/src/tint/utils/math.h
@@ -15,7 +15,6 @@
#ifndef SRC_TINT_UTILS_MATH_H_
#define SRC_TINT_UTILS_MATH_H_
-#include <sstream>
#include <string>
#include <type_traits>
diff --git a/src/tint/utils/result.h b/src/tint/utils/result.h
index 41fda19..2b433fb 100644
--- a/src/tint/utils/result.h
+++ b/src/tint/utils/result.h
@@ -15,11 +15,11 @@
#ifndef SRC_TINT_UTILS_RESULT_H_
#define SRC_TINT_UTILS_RESULT_H_
-#include <ostream>
#include <utility>
#include <variant>
#include "src/tint/debug.h"
+#include "src/tint/utils/string_stream.h"
namespace tint::utils {
@@ -145,12 +145,12 @@
std::variant<std::monostate, SUCCESS_TYPE, FAILURE_TYPE> value;
};
-/// Writes the result to the ostream.
-/// @param out the std::ostream to write to
+/// Writes the result to the stream.
+/// @param out the stream to write to
/// @param res the result
-/// @return the std::ostream so calls can be chained
+/// @return the stream so calls can be chained
template <typename SUCCESS, typename FAILURE>
-inline std::ostream& operator<<(std::ostream& out, Result<SUCCESS, FAILURE> res) {
+inline utils::StringStream& operator<<(utils::StringStream& out, Result<SUCCESS, FAILURE> res) {
return res ? (out << "success: " << res.Get()) : (out << "failure: " << res.Failure());
}
diff --git a/src/tint/utils/string.h b/src/tint/utils/string.h
index e77e637..5c7255d 100644
--- a/src/tint/utils/string.h
+++ b/src/tint/utils/string.h
@@ -15,7 +15,6 @@
#ifndef SRC_TINT_UTILS_STRING_H_
#define SRC_TINT_UTILS_STRING_H_
-#include <sstream>
#include <string>
#include <variant>
@@ -40,7 +39,7 @@
}
/// @param value the value to be printed as a string
-/// @returns value printed as a string via the std::ostream `<<` operator
+/// @returns value printed as a string via the stream `<<` operator
template <typename T>
std::string ToString(const T& value) {
utils::StringStream s;
@@ -49,7 +48,7 @@
}
/// @param value the variant to be printed as a string
-/// @returns value printed as a string via the std::ostream `<<` operator
+/// @returns value printed as a string via the stream `<<` operator
template <typename... TYs>
std::string ToString(const std::variant<TYs...>& value) {
utils::StringStream s;
diff --git a/src/tint/utils/string_stream.cc b/src/tint/utils/string_stream.cc
index 2d1ed44..f0dbe0c 100644
--- a/src/tint/utils/string_stream.cc
+++ b/src/tint/utils/string_stream.cc
@@ -25,3 +25,31 @@
StringStream::~StringStream() = default;
} // namespace tint::utils
+
+namespace tint::text {
+
+utils::StringStream& operator<<(utils::StringStream& out, CodePoint code_point) {
+ if (code_point < 0x7f) {
+ // See https://en.cppreference.com/w/cpp/language/escape
+ switch (code_point) {
+ case '\a':
+ return out << R"('\a')";
+ case '\b':
+ return out << R"('\b')";
+ case '\f':
+ return out << R"('\f')";
+ case '\n':
+ return out << R"('\n')";
+ case '\r':
+ return out << R"('\r')";
+ case '\t':
+ return out << R"('\t')";
+ case '\v':
+ return out << R"('\v')";
+ }
+ return out << "'" << static_cast<char>(code_point) << "'";
+ }
+ return out << "'U+" << std::hex << code_point.value << "'";
+}
+
+} // namespace tint::text
diff --git a/src/tint/utils/string_stream.h b/src/tint/utils/string_stream.h
index 893d2b9..4703095 100644
--- a/src/tint/utils/string_stream.h
+++ b/src/tint/utils/string_stream.h
@@ -16,12 +16,15 @@
#define SRC_TINT_UTILS_STRING_STREAM_H_
#include <functional>
+#include <iomanip>
#include <iterator>
#include <limits>
#include <sstream>
#include <string>
#include <utility>
+#include "src/tint/text/unicode.h"
+
namespace tint::utils {
/// Stringstream wrapper which automatically resets the locale and sets floating point emission
@@ -44,23 +47,57 @@
/// @param value the value to emit
/// @returns a reference to this
template <typename T,
- typename std::enable_if<!std::is_floating_point<T>::value>::type* = nullptr>
- StringStream& operator<<(const T& value) {
- sstream_ << value;
+ typename std::enable_if_t<std::is_integral_v<std::decay_t<T>>, bool> = true>
+ StringStream& operator<<(T&& value) {
+ return EmitValue(std::forward<T>(value));
+ }
+
+ /// Emit `value` to the stream
+ /// @param value the value to emit
+ /// @returns a reference to this
+ StringStream& operator<<(const char* value) { return EmitValue(value); }
+ /// Emit `value` to the stream
+ /// @param value the value to emit
+ /// @returns a reference to this
+ StringStream& operator<<(const std::string& value) { return EmitValue(value); }
+ /// Emit `value` to the stream
+ /// @param value the value to emit
+ /// @returns a reference to this
+ StringStream& operator<<(std::string_view value) { return EmitValue(value); }
+
+ /// Emit `value` to the stream
+ /// @param value the value to emit
+ /// @returns a reference to this
+ StringStream& operator<<(const void* value) { return EmitValue(value); }
+
+ /// Emit `value` to the stream
+ /// @param value the value to emit
+ /// @returns a reference to this
+ template <typename T,
+ typename std::enable_if_t<std::is_floating_point_v<std::decay_t<T>>, bool> = true>
+ StringStream& operator<<(T&& value) {
+ return EmitFloat(std::forward<T>(value));
+ }
+
+ /// Emit `value` to the stream
+ /// @param value the value to emit
+ /// @returns a reference to this
+ template <typename T>
+ StringStream& EmitValue(T&& value) {
+ sstream_ << std::forward<T>(value);
return *this;
}
/// Emit `value` to the stream
/// @param value the value to emit
/// @returns a reference to this
- template <typename T,
- typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
- StringStream& operator<<(const T& value) {
+ template <typename T>
+ StringStream& EmitFloat(const T& value) {
// Try printing the float in fixed point, with a smallish limit on the precision
std::stringstream fixed;
fixed.flags(fixed.flags() | std::ios_base::showpoint | std::ios_base::fixed);
fixed.imbue(std::locale::classic());
- fixed.precision(9);
+ fixed.precision(20);
fixed << value;
std::string str = fixed.str();
@@ -71,6 +108,7 @@
double roundtripped;
fixed >> roundtripped;
+ // Strip trailing zeros from the number.
auto float_equal_no_warning = std::equal_to<T>();
if (float_equal_no_warning(value, static_cast<T>(roundtripped))) {
while (str.length() >= 2 && str[str.size() - 1] == '0' && str[str.size() - 2] != '.') {
@@ -111,6 +149,57 @@
return *this;
}
+ /// The callback to emit a `std::hex` to the stream
+ using StdHex = std::ios_base& (*)(std::ios_base&);
+
+ /// @param manipulator the callback to emit too
+ /// @returns a reference to this
+ StringStream& operator<<(StdHex manipulator) {
+ // call the function, and return it's value
+ manipulator(sstream_);
+ return *this;
+ }
+
+ /// @param value the value to emit
+ /// @returns a reference to this
+ template <typename T,
+ typename std::enable_if<std::is_same<decltype(std::setw(std::declval<int>())),
+ typename std::decay<T>::type>::value,
+ int>::type = 0>
+ StringStream& operator<<(T&& value) {
+ // call the function, and return it's value
+ sstream_ << std::forward<T>(value);
+ return *this;
+ }
+
+ // On MSVC the type of `std::setw` and `std::setprecision` are the same. Can't check for
+ // _MSC_VER because this is also set by clang-cl on windows.
+#if defined(__GNUC__) || defined(__clang__)
+ /// @param value the value to emit
+ /// @returns a reference to this
+ template <typename T,
+ typename std::enable_if<std::is_same<decltype(std::setprecision(std::declval<int>())),
+ typename std::decay<T>::type>::value,
+ int>::type = 0>
+ StringStream& operator<<(T&& value) {
+ // call the function, and return it's value
+ sstream_ << std::forward<T>(value);
+ return *this;
+ }
+#endif // defined(_MSC_VER)
+
+ /// @param value the value to emit
+ /// @returns a reference to this
+ template <typename T,
+ typename std::enable_if<std::is_same<decltype(std::setfill(std::declval<char>())),
+ typename std::decay<T>::type>::value,
+ char>::type = 0>
+ StringStream& operator<<(T&& value) {
+ // call the function, and return it's value
+ sstream_ << std::forward<T>(value);
+ return *this;
+ }
+
/// @returns the string contents of the stream
std::string str() const { return sstream_.str(); }
@@ -120,4 +209,14 @@
} // namespace tint::utils
+namespace tint::text {
+
+/// Writes the CodePoint to the stream.
+/// @param out the stream to write to
+/// @param codepoint the CodePoint to write
+/// @returns out so calls can be chained
+utils::StringStream& operator<<(utils::StringStream& out, CodePoint codepoint);
+
+} // namespace tint::text
+
#endif // SRC_TINT_UTILS_STRING_STREAM_H_
diff --git a/src/tint/utils/string_stream_test.cc b/src/tint/utils/string_stream_test.cc
index eebefd6..5f99026 100644
--- a/src/tint/utils/string_stream_test.cc
+++ b/src/tint/utils/string_stream_test.cc
@@ -88,22 +88,22 @@
{
StringStream s;
s << 1e-8f;
- EXPECT_EQ(s.str(), "0.00000001");
+ EXPECT_EQ(s.str(), "0.00000000999999993923");
}
{
StringStream s;
s << 1e-9f;
- EXPECT_EQ(s.str(), "0.000000001");
+ EXPECT_EQ(s.str(), "0.00000000099999997172");
}
{
StringStream s;
s << 1e-10f;
- EXPECT_EQ(s.str(), "1.00000001e-10");
+ EXPECT_EQ(s.str(), "0.00000000010000000134");
}
{
StringStream s;
s << 1e-20f;
- EXPECT_EQ(s.str(), "9.99999968e-21");
+ EXPECT_EQ(s.str(), "0.00000000000000000001");
}
}
diff --git a/src/tint/utils/vector.h b/src/tint/utils/vector.h
index e39854a..ed4fcf1 100644
--- a/src/tint/utils/vector.h
+++ b/src/tint/utils/vector.h
@@ -20,7 +20,6 @@
#include <algorithm>
#include <iterator>
#include <new>
-#include <ostream>
#include <utility>
#include <vector>
@@ -28,6 +27,7 @@
#include "src/tint/utils/compiler_macros.h"
#include "src/tint/utils/slice.h"
#include "src/tint/utils/string.h"
+#include "src/tint/utils/string_stream.h"
namespace tint::utils {
@@ -740,11 +740,11 @@
}
/// Prints the vector @p vec to @p o
-/// @param o the std::ostream to write to
+/// @param o the stream to write to
/// @param vec the vector
-/// @return the std::ostream so calls can be chained
+/// @return the stream so calls can be chained
template <typename T, size_t N>
-inline std::ostream& operator<<(std::ostream& o, const utils::Vector<T, N>& vec) {
+inline utils::StringStream& operator<<(utils::StringStream& o, const utils::Vector<T, N>& vec) {
o << "[";
bool first = true;
for (auto& el : vec) {
@@ -759,11 +759,11 @@
}
/// Prints the vector @p vec to @p o
-/// @param o the std::ostream to write to
+/// @param o the stream to write to
/// @param vec the vector reference
-/// @return the std::ostream so calls can be chained
+/// @return the stream so calls can be chained
template <typename T>
-inline std::ostream& operator<<(std::ostream& o, utils::VectorRef<T> vec) {
+inline utils::StringStream& operator<<(utils::StringStream& o, utils::VectorRef<T> vec) {
o << "[";
bool first = true;
for (auto& el : vec) {
diff --git a/src/tint/writer/float_to_string.cc b/src/tint/writer/float_to_string.cc
index 0ce4954..fdf4675 100644
--- a/src/tint/writer/float_to_string.cc
+++ b/src/tint/writer/float_to_string.cc
@@ -19,7 +19,6 @@
#include <functional>
#include <iomanip>
#include <limits>
-#include <sstream>
#include "src/tint/debug.h"
#include "src/tint/utils/string_stream.h"
diff --git a/src/tint/writer/float_to_string_test.cc b/src/tint/writer/float_to_string_test.cc
index 901334e..eb70369 100644
--- a/src/tint/writer/float_to_string_test.cc
+++ b/src/tint/writer/float_to_string_test.cc
@@ -73,10 +73,10 @@
}
TEST(FloatToStringTest, Precision) {
- EXPECT_EQ(FloatToString(1e-8f), "0.00000001");
- EXPECT_EQ(FloatToString(1e-9f), "0.000000001");
- EXPECT_EQ(FloatToString(1e-10f), "1.00000001e-10");
- EXPECT_EQ(FloatToString(1e-20f), "9.99999968e-21");
+ EXPECT_EQ(FloatToString(1e-8f), "0.00000000999999993923");
+ EXPECT_EQ(FloatToString(1e-9f), "0.00000000099999997172");
+ EXPECT_EQ(FloatToString(1e-10f), "0.00000000010000000134");
+ EXPECT_EQ(FloatToString(1e-20f), "0.00000000000000000001");
}
////////////////////////////////////////////////////////////////////////////////
@@ -179,15 +179,15 @@
////////////////////////////////////////////////////////////////////////////////
TEST(DoubleToStringTest, Zero) {
- EXPECT_EQ(DoubleToString(0.0), "0.0");
+ EXPECT_EQ(DoubleToString(0.000000000), "0.0");
}
TEST(DoubleToStringTest, One) {
- EXPECT_EQ(DoubleToString(1.0), "1.0");
+ EXPECT_EQ(DoubleToString(1.000000000), "1.0");
}
TEST(DoubleToStringTest, MinusOne) {
- EXPECT_EQ(DoubleToString(-1.0), "-1.0");
+ EXPECT_EQ(DoubleToString(-1.000000000), "-1.0");
}
TEST(DoubleToStringTest, Billion) {
@@ -231,8 +231,8 @@
TEST(DoubleToStringTest, Precision) {
EXPECT_EQ(DoubleToString(1e-8), "0.00000001");
EXPECT_EQ(DoubleToString(1e-9), "0.000000001");
- EXPECT_EQ(DoubleToString(1e-10), "1e-10");
- EXPECT_EQ(DoubleToString(1e-15), "1.0000000000000001e-15");
+ EXPECT_EQ(DoubleToString(1e-10), "0.0000000001");
+ EXPECT_EQ(DoubleToString(1e-15), "0.000000000000001");
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/src/tint/writer/glsl/generator.h b/src/tint/writer/glsl/generator.h
index 4d31bdf..2bb4b03 100644
--- a/src/tint/writer/glsl/generator.h
+++ b/src/tint/writer/glsl/generator.h
@@ -63,6 +63,9 @@
/// transform
std::unordered_map<sem::BindingPoint, builtin::Access> access_controls;
+ /// Set to `true` to disable software robustness that prevents out-of-bounds accesses.
+ bool disable_robustness = false;
+
/// If true, then validation will be disabled for binding point collisions
/// generated by the BindingRemapper transform
bool allow_collisions = false;
@@ -75,6 +78,13 @@
/// The GLSL version to emit
Version version;
+
+ /// Reflect the fields of this class so that it can be used by tint::ForeachField()
+ TINT_REFLECT(disable_robustness,
+ allow_collisions,
+ disable_workgroup_init,
+ generate_external_texture_bindings,
+ version);
};
/// The result produced when generating GLSL.
diff --git a/src/tint/writer/glsl/generator_impl.cc b/src/tint/writer/glsl/generator_impl.cc
index 46428b0..24c6386 100644
--- a/src/tint/writer/glsl/generator_impl.cc
+++ b/src/tint/writer/glsl/generator_impl.cc
@@ -57,6 +57,7 @@
#include "src/tint/transform/promote_side_effects_to_decl.h"
#include "src/tint/transform/remove_phonies.h"
#include "src/tint/transform/renamer.h"
+#include "src/tint/transform/robustness.h"
#include "src/tint/transform/simplify_pointers.h"
#include "src/tint/transform/single_entry_point.h"
#include "src/tint/transform/std140.h"
@@ -149,6 +150,33 @@
// ExpandCompoundAssignment must come before BuiltinPolyfill
manager.Add<transform::ExpandCompoundAssignment>();
+ if (!entry_point.empty()) {
+ manager.Add<transform::SingleEntryPoint>();
+ data.Add<transform::SingleEntryPoint::Config>(entry_point);
+ }
+ manager.Add<transform::Renamer>();
+ data.Add<transform::Renamer::Config>(transform::Renamer::Target::kGlslKeywords,
+ /* preserve_unicode */ false);
+
+ manager.Add<transform::PreservePadding>(); // Must come before DirectVariableAccess
+
+ manager.Add<transform::Unshadow>(); // Must come before DirectVariableAccess
+ manager.Add<transform::DirectVariableAccess>();
+
+ manager.Add<transform::PromoteSideEffectsToDecl>();
+
+ if (!options.disable_robustness) {
+ // Robustness must come before BuiltinPolyfill
+ manager.Add<transform::Robustness>();
+ }
+
+ if (options.generate_external_texture_bindings) {
+ // Note: it is more efficient for MultiplanarExternalTexture to come after Robustness
+ auto new_bindings_map = writer::GenerateExternalTextureBindings(in);
+ data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(new_bindings_map);
+ manager.Add<transform::MultiplanarExternalTexture>();
+ }
+
{ // Builtin polyfills
transform::BuiltinPolyfill::Builtins polyfills;
polyfills.acosh = transform::BuiltinPolyfill::Level::kRangeCheck;
@@ -169,26 +197,16 @@
manager.Add<transform::BuiltinPolyfill>();
}
- if (!entry_point.empty()) {
- manager.Add<transform::SingleEntryPoint>();
- data.Add<transform::SingleEntryPoint::Config>(entry_point);
- }
- manager.Add<transform::Renamer>();
- data.Add<transform::Renamer::Config>(transform::Renamer::Target::kGlslKeywords,
- /* preserve_unicode */ false);
-
- manager.Add<transform::PreservePadding>(); // Must come before DirectVariableAccess
-
- manager.Add<transform::Unshadow>(); // Must come before DirectVariableAccess
- manager.Add<transform::DirectVariableAccess>();
-
if (!options.disable_workgroup_init) {
// ZeroInitWorkgroupMemory must come before CanonicalizeEntryPointIO as
// ZeroInitWorkgroupMemory may inject new builtin parameters.
manager.Add<transform::ZeroInitWorkgroupMemory>();
}
+
+ // CanonicalizeEntryPointIO must come after Robustness
manager.Add<transform::CanonicalizeEntryPointIO>();
- manager.Add<transform::PromoteSideEffectsToDecl>();
+
+ // PadStructs must come after CanonicalizeEntryPointIO
manager.Add<transform::PadStructs>();
// DemoteToHelper must come after PromoteSideEffectsToDecl and ExpandCompoundAssignment.
@@ -196,12 +214,6 @@
manager.Add<transform::RemovePhonies>();
- if (options.generate_external_texture_bindings) {
- auto new_bindings_map = writer::GenerateExternalTextureBindings(in);
- data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(new_bindings_map);
- }
- manager.Add<transform::MultiplanarExternalTexture>();
-
data.Add<transform::CombineSamplers::BindingInfo>(options.binding_map,
options.placeholder_binding_point);
manager.Add<transform::CombineSamplers>();
diff --git a/src/tint/writer/glsl/generator_impl_binary_test.cc b/src/tint/writer/glsl/generator_impl_binary_test.cc
index 475ae46..1c03530 100644
--- a/src/tint/writer/glsl/generator_impl_binary_test.cc
+++ b/src/tint/writer/glsl/generator_impl_binary_test.cc
@@ -29,7 +29,9 @@
ast::BinaryOp op;
};
inline std::ostream& operator<<(std::ostream& out, BinaryData data) {
- out << data.op;
+ utils::StringStream str;
+ str << data.op;
+ out << str.str();
return out;
}
diff --git a/src/tint/writer/glsl/generator_impl_builtin_test.cc b/src/tint/writer/glsl/generator_impl_builtin_test.cc
index 3d14a68..d281cdb 100644
--- a/src/tint/writer/glsl/generator_impl_builtin_test.cc
+++ b/src/tint/writer/glsl/generator_impl_builtin_test.cc
@@ -932,7 +932,7 @@
EXPECT_EQ(gen.result(), R"(#version 310 es
float tint_degrees(float param_0) {
- return param_0 * 57.295779513082323f;
+ return param_0 * 57.29577951308232286465f;
}
@@ -960,7 +960,7 @@
EXPECT_EQ(gen.result(), R"(#version 310 es
vec3 tint_degrees(vec3 param_0) {
- return param_0 * 57.295779513082323f;
+ return param_0 * 57.29577951308232286465f;
}
@@ -991,7 +991,7 @@
#extension GL_AMD_gpu_shader_half_float : require
float16_t tint_degrees(float16_t param_0) {
- return param_0 * 57.295779513082323hf;
+ return param_0 * 57.29577951308232286465hf;
}
@@ -1022,7 +1022,7 @@
#extension GL_AMD_gpu_shader_half_float : require
f16vec3 tint_degrees(f16vec3 param_0) {
- return param_0 * 57.295779513082323hf;
+ return param_0 * 57.29577951308232286465hf;
}
@@ -1050,7 +1050,7 @@
EXPECT_EQ(gen.result(), R"(#version 310 es
float tint_radians(float param_0) {
- return param_0 * 0.017453292519943295f;
+ return param_0 * 0.01745329251994329547f;
}
@@ -1078,7 +1078,7 @@
EXPECT_EQ(gen.result(), R"(#version 310 es
vec3 tint_radians(vec3 param_0) {
- return param_0 * 0.017453292519943295f;
+ return param_0 * 0.01745329251994329547f;
}
@@ -1109,7 +1109,7 @@
#extension GL_AMD_gpu_shader_half_float : require
float16_t tint_radians(float16_t param_0) {
- return param_0 * 0.017453292519943295hf;
+ return param_0 * 0.01745329251994329547hf;
}
@@ -1140,7 +1140,7 @@
#extension GL_AMD_gpu_shader_half_float : require
f16vec3 tint_radians(f16vec3 param_0) {
- return param_0 * 0.017453292519943295hf;
+ return param_0 * 0.01745329251994329547hf;
}
diff --git a/src/tint/writer/glsl/generator_impl_constructor_test.cc b/src/tint/writer/glsl/generator_impl_constructor_test.cc
index 2f4b3d0..02d148c 100644
--- a/src/tint/writer/glsl/generator_impl_constructor_test.cc
+++ b/src/tint/writer/glsl/generator_impl_constructor_test.cc
@@ -79,7 +79,7 @@
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.Generate()) << gen.error();
- EXPECT_THAT(gen.result(), HasSubstr("-0.000012f"));
+ EXPECT_THAT(gen.result(), HasSubstr("-0.00001200000042445026f"));
}
TEST_F(GlslGeneratorImplTest_Constructor, Type_F16) {
@@ -90,7 +90,7 @@
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.Generate()) << gen.error();
- EXPECT_THAT(gen.result(), HasSubstr("-0.00119972229hf"));
+ EXPECT_THAT(gen.result(), HasSubstr("-0.0011997222900390625hf"));
}
TEST_F(GlslGeneratorImplTest_Constructor, Type_Bool) {
diff --git a/src/tint/writer/glsl/generator_impl_import_test.cc b/src/tint/writer/glsl/generator_impl_import_test.cc
index 3201712..bf546ac 100644
--- a/src/tint/writer/glsl/generator_impl_import_test.cc
+++ b/src/tint/writer/glsl/generator_impl_import_test.cc
@@ -98,8 +98,10 @@
utils::StringStream out;
ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error();
- EXPECT_EQ(out.str(),
- std::string(param.glsl_name) + "(vec3(0.100000001f, 0.200000003f, 0.300000012f))");
+ EXPECT_EQ(
+ out.str(),
+ std::string(param.glsl_name) +
+ "(vec3(0.10000000149011611938f, 0.20000000298023223877f, 0.30000001192092895508f))");
}
INSTANTIATE_TEST_SUITE_P(GlslGeneratorImplTest_Import,
GlslImportData_SingleVectorParamTest,
diff --git a/src/tint/writer/glsl/generator_impl_loop_test.cc b/src/tint/writer/glsl/generator_impl_loop_test.cc
index 0979f53..2ee83b8 100644
--- a/src/tint/writer/glsl/generator_impl_loop_test.cc
+++ b/src/tint/writer/glsl/generator_impl_loop_test.cc
@@ -134,7 +134,7 @@
TEST_F(GlslGeneratorImplTest_Loop, Emit_LoopWithVarUsedInContinuing) {
// loop {
- // var lhs : f32 = 2.4;
+ // var lhs : f32 = 2.5;
// var other : f32;
// break;
// continuing {
@@ -144,7 +144,7 @@
GlobalVar("rhs", ty.f32(), builtin::AddressSpace::kPrivate);
- auto* body = Block(Decl(Var("lhs", ty.f32(), Expr(2.4_f))), //
+ auto* body = Block(Decl(Var("lhs", ty.f32(), Expr(2.5_f))), //
Decl(Var("other", ty.f32())), //
Break());
auto* continuing = Block(Assign("lhs", "rhs"));
@@ -157,7 +157,7 @@
ASSERT_TRUE(gen.EmitStatement(outer)) << gen.error();
EXPECT_EQ(gen.result(), R"( while (true) {
- float lhs = 2.400000095f;
+ float lhs = 2.5f;
float other = 0.0f;
break;
{
diff --git a/src/tint/writer/glsl/generator_impl_type_test.cc b/src/tint/writer/glsl/generator_impl_type_test.cc
index 2cc13f6..2535efd 100644
--- a/src/tint/writer/glsl/generator_impl_type_test.cc
+++ b/src/tint/writer/glsl/generator_impl_type_test.cc
@@ -318,7 +318,9 @@
std::string result;
};
inline std::ostream& operator<<(std::ostream& out, GlslDepthTextureData data) {
- out << data.dim;
+ utils::StringStream s;
+ s << data.dim;
+ out << s.str();
return out;
}
using GlslDepthTexturesTest = TestParamHelper<GlslDepthTextureData>;
@@ -378,7 +380,9 @@
std::string result;
};
inline std::ostream& operator<<(std::ostream& out, GlslSampledTextureData data) {
- out << data.dim;
+ utils::StringStream str;
+ str << data.dim;
+ out << str.str();
return out;
}
using GlslSampledTexturesTest = TestParamHelper<GlslSampledTextureData>;
@@ -527,7 +531,9 @@
std::string result;
};
inline std::ostream& operator<<(std::ostream& out, GlslStorageTextureData data) {
- return out << data.dim;
+ utils::StringStream str;
+ str << data.dim;
+ return out << str.str();
}
using GlslStorageTexturesTest = TestParamHelper<GlslStorageTextureData>;
TEST_P(GlslStorageTexturesTest, Emit) {
diff --git a/src/tint/writer/glsl/test_helper.h b/src/tint/writer/glsl/test_helper.h
index 2f806ce..98c7d8d 100644
--- a/src/tint/writer/glsl/test_helper.h
+++ b/src/tint/writer/glsl/test_helper.h
@@ -32,6 +32,14 @@
TestHelperBase() = default;
~TestHelperBase() override = default;
+ /// @returns the default generator options for SanitizeAndBuild(), if no explicit options are
+ /// provided.
+ static Options DefaultOptions() {
+ Options opts;
+ opts.disable_robustness = true;
+ return opts;
+ }
+
/// Builds the program and returns a GeneratorImpl from the program.
/// @note The generator is only built once. Multiple calls to Build() will
/// return the same GeneratorImpl without rebuilding.
@@ -60,7 +68,8 @@
/// @param version the GLSL version
/// @param options the GLSL backend options
/// @return the built generator
- GeneratorImpl& SanitizeAndBuild(Version version = Version(), const Options& options = {}) {
+ GeneratorImpl& SanitizeAndBuild(Version version = Version(),
+ const Options& options = DefaultOptions()) {
if (gen_) {
return *gen_;
}
diff --git a/src/tint/writer/hlsl/generator.h b/src/tint/writer/hlsl/generator.h
index 80dd518..74d79ba 100644
--- a/src/tint/writer/hlsl/generator.h
+++ b/src/tint/writer/hlsl/generator.h
@@ -49,23 +49,32 @@
/// @returns this Options
Options& operator=(const Options&);
+ /// Set to `true` to disable software robustness that prevents out-of-bounds accesses.
+ bool disable_robustness = false;
+
/// The binding point to use for information passed via root constants.
std::optional<sem::BindingPoint> root_constant_binding_point;
+
/// Set to `true` to disable workgroup memory zero initialization
bool disable_workgroup_init = false;
+
/// Set to 'true' to generates binding mappings for external textures
bool generate_external_texture_bindings = false;
+
/// Options used to specify a mapping of binding points to indices into a UBO
/// from which to load buffer sizes.
ArrayLengthFromUniformOptions array_length_from_uniform = {};
+
/// Interstage locations actually used as inputs in the next stage of the pipeline.
/// This is potentially used for truncating unused interstage outputs at current shader stage.
std::bitset<16> interstage_locations;
+
/// Set to `true` to generate polyfill for `reflect` builtin for vec2<f32>
bool polyfill_reflect_vec2_f32 = false;
/// Reflect the fields of this class so that it can be used by tint::ForeachField()
- TINT_REFLECT(root_constant_binding_point,
+ TINT_REFLECT(disable_robustness,
+ root_constant_binding_point,
disable_workgroup_init,
generate_external_texture_bindings,
array_length_from_uniform);
diff --git a/src/tint/writer/hlsl/generator_impl.cc b/src/tint/writer/hlsl/generator_impl.cc
index 2bb4a9f..823e6bd 100644
--- a/src/tint/writer/hlsl/generator_impl.cc
+++ b/src/tint/writer/hlsl/generator_impl.cc
@@ -57,6 +57,7 @@
#include "src/tint/transform/promote_side_effects_to_decl.h"
#include "src/tint/transform/remove_continue_in_switch.h"
#include "src/tint/transform/remove_phonies.h"
+#include "src/tint/transform/robustness.h"
#include "src/tint/transform/simplify_pointers.h"
#include "src/tint/transform/truncate_interstage_variables.h"
#include "src/tint/transform/unshadow.h"
@@ -165,6 +166,33 @@
// ExpandCompoundAssignment must come before BuiltinPolyfill
manager.Add<transform::ExpandCompoundAssignment>();
+ manager.Add<transform::Unshadow>(); // Must come before DirectVariableAccess
+
+ manager.Add<transform::DirectVariableAccess>();
+
+ // LocalizeStructArrayAssignment must come after:
+ // * SimplifyPointers, because it assumes assignment to arrays in structs are
+ // done directly, not indirectly.
+ // TODO(crbug.com/tint/1340): See if we can get rid of the duplicate
+ // SimplifyPointers transform. Can't do it right now because
+ // LocalizeStructArrayAssignment introduces pointers.
+ manager.Add<transform::SimplifyPointers>();
+ manager.Add<transform::LocalizeStructArrayAssignment>();
+
+ manager.Add<transform::PromoteSideEffectsToDecl>();
+
+ if (!options.disable_robustness) {
+ // Robustness must come before BuiltinPolyfill
+ manager.Add<transform::Robustness>();
+ }
+
+ if (options.generate_external_texture_bindings) {
+ // Note: it is more efficient for MultiplanarExternalTexture to come after Robustness
+ auto new_bindings_map = GenerateExternalTextureBindings(in);
+ data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(new_bindings_map);
+ manager.Add<transform::MultiplanarExternalTexture>();
+ }
+
{ // Builtin polyfills
transform::BuiltinPolyfill::Builtins polyfills;
polyfills.acosh = transform::BuiltinPolyfill::Level::kFull;
@@ -189,37 +217,13 @@
manager.Add<transform::BuiltinPolyfill>();
}
- // Build the config for the internal ArrayLengthFromUniform transform.
- auto& array_length_from_uniform = options.array_length_from_uniform;
- transform::ArrayLengthFromUniform::Config array_length_from_uniform_cfg(
- array_length_from_uniform.ubo_binding);
- array_length_from_uniform_cfg.bindpoint_to_size_index =
- array_length_from_uniform.bindpoint_to_size_index;
-
- if (options.generate_external_texture_bindings) {
- auto new_bindings_map = GenerateExternalTextureBindings(in);
- data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(new_bindings_map);
- }
- manager.Add<transform::MultiplanarExternalTexture>();
-
- manager.Add<transform::Unshadow>(); // Must come before DirectVariableAccess
-
- manager.Add<transform::DirectVariableAccess>();
-
- // LocalizeStructArrayAssignment must come after:
- // * SimplifyPointers, because it assumes assignment to arrays in structs are
- // done directly, not indirectly.
- // TODO(crbug.com/tint/1340): See if we can get rid of the duplicate
- // SimplifyPointers transform. Can't do it right now because
- // LocalizeStructArrayAssignment introduces pointers.
- manager.Add<transform::SimplifyPointers>();
- manager.Add<transform::LocalizeStructArrayAssignment>();
-
if (!options.disable_workgroup_init) {
// ZeroInitWorkgroupMemory must come before CanonicalizeEntryPointIO as
// ZeroInitWorkgroupMemory may inject new builtin parameters.
manager.Add<transform::ZeroInitWorkgroupMemory>();
}
+
+ // CanonicalizeEntryPointIO must come after Robustness
manager.Add<transform::CanonicalizeEntryPointIO>();
if (options.interstage_locations.any()) {
@@ -246,11 +250,17 @@
// assumes that num_workgroups builtins only appear as struct members and are
// only accessed directly via member accessors.
manager.Add<transform::NumWorkgroupsFromUniform>();
- manager.Add<transform::PromoteSideEffectsToDecl>();
manager.Add<transform::VectorizeScalarMatrixInitializers>();
manager.Add<transform::SimplifyPointers>();
manager.Add<transform::RemovePhonies>();
+ // Build the config for the internal ArrayLengthFromUniform transform.
+ auto& array_length_from_uniform = options.array_length_from_uniform;
+ transform::ArrayLengthFromUniform::Config array_length_from_uniform_cfg(
+ array_length_from_uniform.ubo_binding);
+ array_length_from_uniform_cfg.bindpoint_to_size_index =
+ array_length_from_uniform.bindpoint_to_size_index;
+
// DemoteToHelper must come after CanonicalizeEntryPointIO, PromoteSideEffectsToDecl, and
// ExpandCompoundAssignment.
// TODO(crbug.com/tint/1752): This is only necessary when FXC is being used.
diff --git a/src/tint/writer/hlsl/generator_impl_binary_test.cc b/src/tint/writer/hlsl/generator_impl_binary_test.cc
index 630fc09..7221e1a 100644
--- a/src/tint/writer/hlsl/generator_impl_binary_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_binary_test.cc
@@ -32,7 +32,9 @@
Types valid_for = Types::All;
};
inline std::ostream& operator<<(std::ostream& out, BinaryData data) {
- out << data.op;
+ utils::StringStream str;
+ str << data.op;
+ out << str.str();
return out;
}
diff --git a/src/tint/writer/hlsl/generator_impl_builtin_test.cc b/src/tint/writer/hlsl/generator_impl_builtin_test.cc
index 229213b..5054327 100644
--- a/src/tint/writer/hlsl/generator_impl_builtin_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_builtin_test.cc
@@ -812,7 +812,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(float tint_degrees(float param_0) {
- return param_0 * 57.295779513082323;
+ return param_0 * 57.29577951308232286465;
}
[numthreads(1, 1, 1)]
@@ -833,7 +833,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(float3 tint_degrees(float3 param_0) {
- return param_0 * 57.295779513082323;
+ return param_0 * 57.29577951308232286465;
}
[numthreads(1, 1, 1)]
@@ -856,7 +856,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(float16_t tint_degrees(float16_t param_0) {
- return param_0 * 57.295779513082323;
+ return param_0 * 57.29577951308232286465;
}
[numthreads(1, 1, 1)]
@@ -879,7 +879,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(vector<float16_t, 3> tint_degrees(vector<float16_t, 3> param_0) {
- return param_0 * 57.295779513082323;
+ return param_0 * 57.29577951308232286465;
}
[numthreads(1, 1, 1)]
@@ -900,7 +900,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(float tint_radians(float param_0) {
- return param_0 * 0.017453292519943295;
+ return param_0 * 0.01745329251994329547;
}
[numthreads(1, 1, 1)]
@@ -921,7 +921,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(float3 tint_radians(float3 param_0) {
- return param_0 * 0.017453292519943295;
+ return param_0 * 0.01745329251994329547;
}
[numthreads(1, 1, 1)]
@@ -944,7 +944,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(float16_t tint_radians(float16_t param_0) {
- return param_0 * 0.017453292519943295;
+ return param_0 * 0.01745329251994329547;
}
[numthreads(1, 1, 1)]
@@ -967,7 +967,7 @@
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(vector<float16_t, 3> tint_radians(vector<float16_t, 3> param_0) {
- return param_0 * 0.017453292519943295;
+ return param_0 * 0.01745329251994329547;
}
[numthreads(1, 1, 1)]
diff --git a/src/tint/writer/hlsl/generator_impl_constructor_test.cc b/src/tint/writer/hlsl/generator_impl_constructor_test.cc
index 6cd264e..d285cd6 100644
--- a/src/tint/writer/hlsl/generator_impl_constructor_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_constructor_test.cc
@@ -79,7 +79,7 @@
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.Generate()) << gen.error();
- EXPECT_THAT(gen.result(), HasSubstr("-0.000012f"));
+ EXPECT_THAT(gen.result(), HasSubstr("-0.00001200000042445026f"));
}
TEST_F(HlslGeneratorImplTest_Constructor, Type_F16) {
@@ -90,7 +90,7 @@
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.Generate()) << gen.error();
- EXPECT_THAT(gen.result(), HasSubstr("float16_t(-0.00119972229h)"));
+ EXPECT_THAT(gen.result(), HasSubstr("float16_t(-0.0011997222900390625h)"));
}
TEST_F(HlslGeneratorImplTest_Constructor, Type_Bool) {
@@ -402,8 +402,10 @@
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.Generate()) << gen.error();
- EXPECT_THAT(gen.result(), HasSubstr("{float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f),"
- " float3(7.0f, 8.0f, 9.0f)}"));
+ EXPECT_THAT(
+ gen.result(),
+ HasSubstr(
+ "{float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f), float3(7.0f, 8.0f, 9.0f)}"));
}
TEST_F(HlslGeneratorImplTest_Constructor, Type_Array_Empty) {
diff --git a/src/tint/writer/hlsl/generator_impl_import_test.cc b/src/tint/writer/hlsl/generator_impl_import_test.cc
index 28b72dc..133774a 100644
--- a/src/tint/writer/hlsl/generator_impl_import_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_import_test.cc
@@ -97,8 +97,10 @@
utils::StringStream out;
ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error();
- EXPECT_EQ(out.str(),
- std::string(param.hlsl_name) + "(float3(0.100000001f, 0.200000003f, 0.300000012f))");
+ EXPECT_EQ(
+ out.str(),
+ std::string(param.hlsl_name) +
+ "(float3(0.10000000149011611938f, 0.20000000298023223877f, 0.30000001192092895508f))");
}
INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest_Import,
HlslImportData_SingleVectorParamTest,
diff --git a/src/tint/writer/hlsl/generator_impl_loop_test.cc b/src/tint/writer/hlsl/generator_impl_loop_test.cc
index 45bf04a..98b7f79 100644
--- a/src/tint/writer/hlsl/generator_impl_loop_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_loop_test.cc
@@ -134,7 +134,7 @@
TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopWithVarUsedInContinuing) {
// loop {
- // var lhs : f32 = 2.4;
+ // var lhs : f32 = 2.5;
// var other : f32;
// break;
// continuing {
@@ -144,7 +144,7 @@
GlobalVar("rhs", ty.f32(), builtin::AddressSpace::kPrivate);
- auto* body = Block(Decl(Var("lhs", ty.f32(), Expr(2.4_f))), //
+ auto* body = Block(Decl(Var("lhs", ty.f32(), Expr(2.5_f))), //
Decl(Var("other", ty.f32())), //
Break());
@@ -158,7 +158,7 @@
ASSERT_TRUE(gen.EmitStatement(outer)) << gen.error();
EXPECT_EQ(gen.result(), R"( while (true) {
- float lhs = 2.400000095f;
+ float lhs = 2.5f;
float other = 0.0f;
break;
{
diff --git a/src/tint/writer/hlsl/generator_impl_test.cc b/src/tint/writer/hlsl/generator_impl_test.cc
index eeb9acb..0c39a31 100644
--- a/src/tint/writer/hlsl/generator_impl_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_test.cc
@@ -53,7 +53,9 @@
const char* attribute_name;
};
inline std::ostream& operator<<(std::ostream& out, HlslBuiltinData data) {
- out << data.builtin;
+ utils::StringStream str;
+ str << data.builtin;
+ out << str.str();
return out;
}
using HlslBuiltinConversionTest = TestParamHelper<HlslBuiltinData>;
diff --git a/src/tint/writer/hlsl/generator_impl_type_test.cc b/src/tint/writer/hlsl/generator_impl_type_test.cc
index 4ee8a22..cb8d349 100644
--- a/src/tint/writer/hlsl/generator_impl_type_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_type_test.cc
@@ -313,7 +313,9 @@
std::string result;
};
inline std::ostream& operator<<(std::ostream& out, HlslDepthTextureData data) {
- out << data.dim;
+ utils::StringStream str;
+ str << data.dim;
+ out << str.str();
return out;
}
using HlslDepthTexturesTest = TestParamHelper<HlslDepthTextureData>;
@@ -376,7 +378,9 @@
std::string result;
};
inline std::ostream& operator<<(std::ostream& out, HlslSampledTextureData data) {
- out << data.dim;
+ utils::StringStream str;
+ str << data.dim;
+ out << str.str();
return out;
}
using HlslSampledTexturesTest = TestParamHelper<HlslSampledTextureData>;
@@ -525,7 +529,9 @@
std::string result;
};
inline std::ostream& operator<<(std::ostream& out, HlslStorageTextureData data) {
- out << data.dim;
+ utils::StringStream str;
+ str << data.dim;
+ out << str.str();
return out;
}
using HlslStorageTexturesTest = TestParamHelper<HlslStorageTextureData>;
diff --git a/src/tint/writer/hlsl/test_helper.h b/src/tint/writer/hlsl/test_helper.h
index 8fd6bae..24eb56a 100644
--- a/src/tint/writer/hlsl/test_helper.h
+++ b/src/tint/writer/hlsl/test_helper.h
@@ -34,6 +34,14 @@
TestHelperBase() = default;
~TestHelperBase() override = default;
+ /// @returns the default generator options for SanitizeAndBuild(), if no explicit options are
+ /// provided.
+ static Options DefaultOptions() {
+ Options opts;
+ opts.disable_robustness = true;
+ return opts;
+ }
+
/// Builds the program and returns a GeneratorImpl from the program.
/// @note The generator is only built once. Multiple calls to Build() will
/// return the same GeneratorImpl without rebuilding.
@@ -60,7 +68,7 @@
/// @note The generator is only built once. Multiple calls to Build() will
/// return the same GeneratorImpl without rebuilding.
/// @return the built generator
- GeneratorImpl& SanitizeAndBuild(const Options& options = {}) {
+ GeneratorImpl& SanitizeAndBuild(const Options& options = DefaultOptions()) {
if (gen_) {
return *gen_;
}
diff --git a/src/tint/writer/msl/generator.h b/src/tint/writer/msl/generator.h
index bdc2be5..1add259 100644
--- a/src/tint/writer/msl/generator.h
+++ b/src/tint/writer/msl/generator.h
@@ -44,6 +44,9 @@
/// @returns this Options
Options& operator=(const Options&);
+ /// Set to `true` to disable software robustness that prevents out-of-bounds accesses.
+ bool disable_robustness = false;
+
/// The index to use when generating a UBO to receive storage buffer sizes.
/// Defaults to 30, which is the last valid buffer slot.
uint32_t buffer_size_ubo_index = 30;
@@ -67,7 +70,8 @@
ArrayLengthFromUniformOptions array_length_from_uniform = {};
/// Reflect the fields of this class so that it can be used by tint::ForeachField()
- TINT_REFLECT(buffer_size_ubo_index,
+ TINT_REFLECT(disable_robustness,
+ buffer_size_ubo_index,
fixed_sample_mask,
emit_vertex_point_size,
disable_workgroup_init,
diff --git a/src/tint/writer/msl/generator_impl.cc b/src/tint/writer/msl/generator_impl.cc
index 81b32c0..b2c9ffa 100644
--- a/src/tint/writer/msl/generator_impl.cc
+++ b/src/tint/writer/msl/generator_impl.cc
@@ -53,6 +53,7 @@
#include "src/tint/transform/promote_initializers_to_let.h"
#include "src/tint/transform/promote_side_effects_to_decl.h"
#include "src/tint/transform/remove_phonies.h"
+#include "src/tint/transform/robustness.h"
#include "src/tint/transform/simplify_pointers.h"
#include "src/tint/transform/unshadow.h"
#include "src/tint/transform/vectorize_scalar_matrix_initializers.h"
@@ -171,24 +172,6 @@
// ExpandCompoundAssignment must come before BuiltinPolyfill
manager.Add<transform::ExpandCompoundAssignment>();
- { // Builtin polyfills
- transform::BuiltinPolyfill::Builtins polyfills;
- polyfills.acosh = transform::BuiltinPolyfill::Level::kRangeCheck;
- polyfills.atanh = transform::BuiltinPolyfill::Level::kRangeCheck;
- polyfills.bitshift_modulo = true; // crbug.com/tint/1543
- polyfills.clamp_int = true;
- polyfills.extract_bits = transform::BuiltinPolyfill::Level::kClampParameters;
- polyfills.first_leading_bit = true;
- polyfills.first_trailing_bit = true;
- polyfills.insert_bits = transform::BuiltinPolyfill::Level::kClampParameters;
- polyfills.int_div_mod = true;
- polyfills.sign_int = true;
- polyfills.texture_sample_base_clamp_to_edge_2d_f32 = true;
- polyfills.workgroup_uniform_load = true;
- data.Add<transform::BuiltinPolyfill::Config>(polyfills);
- manager.Add<transform::BuiltinPolyfill>();
- }
-
// Build the config for the internal ArrayLengthFromUniform transform.
auto& array_length_from_uniform = options.array_length_from_uniform;
transform::ArrayLengthFromUniform::Config array_length_from_uniform_cfg(
@@ -217,23 +200,51 @@
transform::CanonicalizeEntryPointIO::ShaderStyle::kMsl, options.fixed_sample_mask,
options.emit_vertex_point_size);
- if (options.generate_external_texture_bindings) {
- auto new_bindings_map = GenerateExternalTextureBindings(in);
- data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(new_bindings_map);
- }
- manager.Add<transform::MultiplanarExternalTexture>();
-
manager.Add<transform::PreservePadding>();
manager.Add<transform::Unshadow>();
+ manager.Add<transform::PromoteSideEffectsToDecl>();
+
+ if (!options.disable_robustness) {
+ // Robustness must come before BuiltinPolyfill
+ manager.Add<transform::Robustness>();
+ }
+
+ { // Builtin polyfills
+ transform::BuiltinPolyfill::Builtins polyfills;
+ polyfills.acosh = transform::BuiltinPolyfill::Level::kRangeCheck;
+ polyfills.atanh = transform::BuiltinPolyfill::Level::kRangeCheck;
+ polyfills.bitshift_modulo = true; // crbug.com/tint/1543
+ polyfills.clamp_int = true;
+ polyfills.extract_bits = transform::BuiltinPolyfill::Level::kClampParameters;
+ polyfills.first_leading_bit = true;
+ polyfills.first_trailing_bit = true;
+ polyfills.insert_bits = transform::BuiltinPolyfill::Level::kClampParameters;
+ polyfills.int_div_mod = true;
+ polyfills.sign_int = true;
+ polyfills.texture_sample_base_clamp_to_edge_2d_f32 = true;
+ polyfills.workgroup_uniform_load = true;
+ data.Add<transform::BuiltinPolyfill::Config>(polyfills);
+ manager.Add<transform::BuiltinPolyfill>();
+ }
+
+ if (options.generate_external_texture_bindings) {
+ // Note: it is more efficient for MultiplanarExternalTexture to come after Robustness
+ auto new_bindings_map = GenerateExternalTextureBindings(in);
+ data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(new_bindings_map);
+ manager.Add<transform::MultiplanarExternalTexture>();
+ }
+
if (!options.disable_workgroup_init) {
// ZeroInitWorkgroupMemory must come before CanonicalizeEntryPointIO as
// ZeroInitWorkgroupMemory may inject new builtin parameters.
manager.Add<transform::ZeroInitWorkgroupMemory>();
}
+
+ // CanonicalizeEntryPointIO must come after Robustness
manager.Add<transform::CanonicalizeEntryPointIO>();
- manager.Add<transform::PromoteSideEffectsToDecl>();
+
manager.Add<transform::PromoteInitializersToLet>();
// DemoteToHelper must come after PromoteSideEffectsToDecl and ExpandCompoundAssignment.
diff --git a/src/tint/writer/msl/generator_impl_binary_test.cc b/src/tint/writer/msl/generator_impl_binary_test.cc
index 8b7e4b5..0297d8a 100644
--- a/src/tint/writer/msl/generator_impl_binary_test.cc
+++ b/src/tint/writer/msl/generator_impl_binary_test.cc
@@ -23,7 +23,9 @@
ast::BinaryOp op;
};
inline std::ostream& operator<<(std::ostream& out, BinaryData data) {
- out << data.op;
+ utils::StringStream str;
+ str << data.op;
+ out << str.str();
return out;
}
using MslBinaryTest = TestParamHelper<BinaryData>;
diff --git a/src/tint/writer/msl/generator_impl_builtin_test.cc b/src/tint/writer/msl/generator_impl_builtin_test.cc
index 0c6ba28..08a2d25 100644
--- a/src/tint/writer/msl/generator_impl_builtin_test.cc
+++ b/src/tint/writer/msl/generator_impl_builtin_test.cc
@@ -851,7 +851,7 @@
using namespace metal;
float tint_degrees(float param_0) {
- return param_0 * 57.295779513082323;
+ return param_0 * 57.29577951308232286465;
}
kernel void test_function() {
@@ -876,7 +876,7 @@
using namespace metal;
float3 tint_degrees(float3 param_0) {
- return param_0 * 57.295779513082323;
+ return param_0 * 57.29577951308232286465;
}
kernel void test_function() {
@@ -903,7 +903,7 @@
using namespace metal;
half tint_degrees(half param_0) {
- return param_0 * 57.295779513082323;
+ return param_0 * 57.29577951308232286465;
}
kernel void test_function() {
@@ -930,7 +930,7 @@
using namespace metal;
half3 tint_degrees(half3 param_0) {
- return param_0 * 57.295779513082323;
+ return param_0 * 57.29577951308232286465;
}
kernel void test_function() {
@@ -955,7 +955,7 @@
using namespace metal;
float tint_radians(float param_0) {
- return param_0 * 0.017453292519943295;
+ return param_0 * 0.01745329251994329547;
}
kernel void test_function() {
@@ -980,7 +980,7 @@
using namespace metal;
float3 tint_radians(float3 param_0) {
- return param_0 * 0.017453292519943295;
+ return param_0 * 0.01745329251994329547;
}
kernel void test_function() {
@@ -1007,7 +1007,7 @@
using namespace metal;
half tint_radians(half param_0) {
- return param_0 * 0.017453292519943295;
+ return param_0 * 0.01745329251994329547;
}
kernel void test_function() {
@@ -1034,7 +1034,7 @@
using namespace metal;
half3 tint_radians(half3 param_0) {
- return param_0 * 0.017453292519943295;
+ return param_0 * 0.01745329251994329547;
}
kernel void test_function() {
diff --git a/src/tint/writer/msl/generator_impl_constructor_test.cc b/src/tint/writer/msl/generator_impl_constructor_test.cc
index ba567ab..ec5646c 100644
--- a/src/tint/writer/msl/generator_impl_constructor_test.cc
+++ b/src/tint/writer/msl/generator_impl_constructor_test.cc
@@ -79,7 +79,7 @@
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.Generate()) << gen.error();
- EXPECT_THAT(gen.result(), HasSubstr("-0.000012f"));
+ EXPECT_THAT(gen.result(), HasSubstr("-0.00001200000042445026f"));
}
TEST_F(MslGeneratorImplTest_Constructor, Type_F16) {
@@ -90,7 +90,7 @@
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.Generate()) << gen.error();
- EXPECT_THAT(gen.result(), HasSubstr("-0.00119972229h"));
+ EXPECT_THAT(gen.result(), HasSubstr("-0.0011997222900390625h"));
}
TEST_F(MslGeneratorImplTest_Constructor, Type_Bool) {
diff --git a/src/tint/writer/msl/generator_impl_loop_test.cc b/src/tint/writer/msl/generator_impl_loop_test.cc
index 6d2959c..a0c56f7 100644
--- a/src/tint/writer/msl/generator_impl_loop_test.cc
+++ b/src/tint/writer/msl/generator_impl_loop_test.cc
@@ -131,7 +131,7 @@
TEST_F(MslGeneratorImplTest, Emit_LoopWithVarUsedInContinuing) {
// loop {
- // var lhs : f32 = 2.4;
+ // var lhs : f32 = 2.5;
// var other : f32;
// continuing {
// lhs = rhs
@@ -141,7 +141,7 @@
GlobalVar("rhs", ty.f32(), builtin::AddressSpace::kPrivate);
- auto* body = Block(Decl(Var("lhs", ty.f32(), Expr(2.4_f))), //
+ auto* body = Block(Decl(Var("lhs", ty.f32(), Expr(2.5_f))), //
Decl(Var("other", ty.f32())), //
Break());
@@ -155,7 +155,7 @@
ASSERT_TRUE(gen.EmitStatement(outer)) << gen.error();
EXPECT_EQ(gen.result(), R"( while (true) {
- float lhs = 2.400000095f;
+ float lhs = 2.5f;
float other = 0.0f;
break;
{
diff --git a/src/tint/writer/msl/generator_impl_test.cc b/src/tint/writer/msl/generator_impl_test.cc
index 52ae381..43eb558 100644
--- a/src/tint/writer/msl/generator_impl_test.cc
+++ b/src/tint/writer/msl/generator_impl_test.cc
@@ -65,7 +65,9 @@
const char* attribute_name;
};
inline std::ostream& operator<<(std::ostream& out, MslBuiltinData data) {
- out << data.builtin;
+ utils::StringStream str;
+ str << data.builtin;
+ out << str.str();
return out;
}
using MslBuiltinConversionTest = TestParamHelper<MslBuiltinData>;
diff --git a/src/tint/writer/msl/generator_impl_type_test.cc b/src/tint/writer/msl/generator_impl_type_test.cc
index e1e18a3..ce1c215 100644
--- a/src/tint/writer/msl/generator_impl_type_test.cc
+++ b/src/tint/writer/msl/generator_impl_type_test.cc
@@ -763,7 +763,9 @@
std::string result;
};
inline std::ostream& operator<<(std::ostream& out, MslDepthTextureData data) {
- out << data.dim;
+ utils::StringStream str;
+ str << data.dim;
+ out << str.str();
return out;
}
using MslDepthTexturesTest = TestParamHelper<MslDepthTextureData>;
@@ -805,7 +807,9 @@
std::string result;
};
inline std::ostream& operator<<(std::ostream& out, MslTextureData data) {
- out << data.dim;
+ utils::StringStream str;
+ str << data.dim;
+ out << str.str();
return out;
}
using MslSampledtexturesTest = TestParamHelper<MslTextureData>;
@@ -849,7 +853,9 @@
std::string result;
};
inline std::ostream& operator<<(std::ostream& out, MslStorageTextureData data) {
- return out << data.dim;
+ utils::StringStream str;
+ str << data.dim;
+ return out << str.str();
}
using MslStorageTexturesTest = TestParamHelper<MslStorageTextureData>;
TEST_P(MslStorageTexturesTest, Emit) {
diff --git a/src/tint/writer/msl/test_helper.h b/src/tint/writer/msl/test_helper.h
index f1b530d..17802d7 100644
--- a/src/tint/writer/msl/test_helper.h
+++ b/src/tint/writer/msl/test_helper.h
@@ -33,6 +33,14 @@
TestHelperBase() = default;
~TestHelperBase() override = default;
+ /// @returns the default generator options for SanitizeAndBuild(), if no explicit options are
+ /// provided.
+ static Options DefaultOptions() {
+ Options opts;
+ opts.disable_robustness = true;
+ return opts;
+ }
+
/// Builds and returns a GeneratorImpl from the program.
/// @note The generator is only built once. Multiple calls to Build() will
/// return the same GeneratorImpl without rebuilding.
@@ -59,7 +67,7 @@
/// @note The generator is only built once. Multiple calls to Build() will
/// return the same GeneratorImpl without rebuilding.
/// @return the built generator
- GeneratorImpl& SanitizeAndBuild(const Options& options = {}) {
+ GeneratorImpl& SanitizeAndBuild(const Options& options = DefaultOptions()) {
if (gen_) {
return *gen_;
}
diff --git a/src/tint/writer/spirv/builder_binary_expression_test.cc b/src/tint/writer/spirv/builder_binary_expression_test.cc
index 7251929..705bf77 100644
--- a/src/tint/writer/spirv/builder_binary_expression_test.cc
+++ b/src/tint/writer/spirv/builder_binary_expression_test.cc
@@ -27,7 +27,9 @@
std::string name;
};
inline std::ostream& operator<<(std::ostream& out, BinaryData data) {
- out << data.op;
+ utils::StringStream str;
+ str << data.op;
+ out << str.str();
return out;
}
diff --git a/src/tint/writer/spirv/builder_builtin_test.cc b/src/tint/writer/spirv/builder_builtin_test.cc
index 1645ee6..5db867a 100644
--- a/src/tint/writer/spirv/builder_builtin_test.cc
+++ b/src/tint/writer/spirv/builder_builtin_test.cc
@@ -2107,7 +2107,7 @@
OpExecutionMode %24 OriginUpperLeft
OpName %5 "v"
OpName %8 "tint_quantizeToF16"
-OpName %9 "v_1"
+OpName %9 "v"
OpName %24 "a_func"
%2 = OpTypeFloat 32
%1 = OpTypeVector %2 3
diff --git a/src/tint/writer/spirv/builder_format_conversion_test.cc b/src/tint/writer/spirv/builder_format_conversion_test.cc
index 63f2183..1efdcca 100644
--- a/src/tint/writer/spirv/builder_format_conversion_test.cc
+++ b/src/tint/writer/spirv/builder_format_conversion_test.cc
@@ -24,7 +24,9 @@
bool extended_format = false;
};
inline std::ostream& operator<<(std::ostream& out, TestData data) {
- out << data.ast_format;
+ utils::StringStream str;
+ str << data.ast_format;
+ out << str.str();
return out;
}
using ImageFormatConversionTest = TestParamHelper<TestData>;
diff --git a/src/tint/writer/spirv/builder_function_attribute_test.cc b/src/tint/writer/spirv/builder_function_attribute_test.cc
index 555c9ea..1b23982 100644
--- a/src/tint/writer/spirv/builder_function_attribute_test.cc
+++ b/src/tint/writer/spirv/builder_function_attribute_test.cc
@@ -43,7 +43,9 @@
SpvExecutionModel model;
};
inline std::ostream& operator<<(std::ostream& out, FunctionStageData data) {
- out << data.stage;
+ utils::StringStream str;
+ str << data.stage;
+ out << str.str();
return out;
}
using Attribute_StageTest = TestParamHelper<FunctionStageData>;
diff --git a/src/tint/writer/spirv/builder_global_variable_test.cc b/src/tint/writer/spirv/builder_global_variable_test.cc
index 2f551ff..569d5e9 100644
--- a/src/tint/writer/spirv/builder_global_variable_test.cc
+++ b/src/tint/writer/spirv/builder_global_variable_test.cc
@@ -256,7 +256,9 @@
SpvBuiltIn result;
};
inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
- out << data.builtin;
+ utils::StringStream str;
+ str << data.builtin;
+ out << str.str();
return out;
}
using BuiltinDataTest = TestParamHelper<BuiltinData>;
diff --git a/src/tint/writer/spirv/builder_type_test.cc b/src/tint/writer/spirv/builder_type_test.cc
index 55b92c6..89ba34e 100644
--- a/src/tint/writer/spirv/builder_type_test.cc
+++ b/src/tint/writer/spirv/builder_type_test.cc
@@ -611,7 +611,9 @@
SpvStorageClass result;
};
inline std::ostream& operator<<(std::ostream& out, PtrData data) {
- out << data.ast_class;
+ utils::StringStream str;
+ str << data.ast_class;
+ out << str.str();
return out;
}
using PtrDataTest = TestParamHelper<PtrData>;
diff --git a/src/tint/writer/spirv/generator.h b/src/tint/writer/spirv/generator.h
index e406f6e..8b34032 100644
--- a/src/tint/writer/spirv/generator.h
+++ b/src/tint/writer/spirv/generator.h
@@ -35,6 +35,9 @@
/// Configuration options used for generating SPIR-V.
struct Options {
+ /// Set to `true` to disable software robustness that prevents out-of-bounds accesses.
+ bool disable_robustness = false;
+
/// Set to `true` to generate a PointSize builtin and have it set to 1.0
/// from all vertex shaders in the module.
bool emit_vertex_point_size = true;
@@ -50,7 +53,8 @@
bool use_zero_initialize_workgroup_memory_extension = false;
/// Reflect the fields of this class so that it can be used by tint::ForeachField()
- TINT_REFLECT(emit_vertex_point_size,
+ TINT_REFLECT(disable_robustness,
+ emit_vertex_point_size,
disable_workgroup_init,
generate_external_texture_bindings,
use_zero_initialize_workgroup_memory_extension);
diff --git a/src/tint/writer/spirv/generator_impl.cc b/src/tint/writer/spirv/generator_impl.cc
index ef6aa2d..c46bf9a 100644
--- a/src/tint/writer/spirv/generator_impl.cc
+++ b/src/tint/writer/spirv/generator_impl.cc
@@ -32,6 +32,7 @@
#include "src/tint/transform/promote_side_effects_to_decl.h"
#include "src/tint/transform/remove_phonies.h"
#include "src/tint/transform/remove_unreachable_statements.h"
+#include "src/tint/transform/robustness.h"
#include "src/tint/transform/simplify_pointers.h"
#include "src/tint/transform/std140.h"
#include "src/tint/transform/unshadow.h"
@@ -53,7 +54,34 @@
// ExpandCompoundAssignment must come before BuiltinPolyfill
manager.Add<transform::ExpandCompoundAssignment>();
+ manager.Add<transform::PreservePadding>(); // Must come before DirectVariableAccess
+
+ manager.Add<transform::Unshadow>(); // Must come before DirectVariableAccess
+
+ manager.Add<transform::RemoveUnreachableStatements>();
+ manager.Add<transform::PromoteSideEffectsToDecl>();
+ manager.Add<transform::SimplifyPointers>(); // Required for arrayLength()
+ manager.Add<transform::RemovePhonies>();
+ manager.Add<transform::VectorizeScalarMatrixInitializers>();
+ manager.Add<transform::VectorizeMatrixConversions>();
+ manager.Add<transform::WhileToLoop>(); // ZeroInitWorkgroupMemory
+ manager.Add<transform::MergeReturn>();
+
+ if (!options.disable_robustness) {
+ // Robustness must come before BuiltinPolyfill
+ manager.Add<transform::Robustness>();
+ }
+
+ if (options.generate_external_texture_bindings) {
+ // Note: it is more efficient for MultiplanarExternalTexture to come after Robustness
+ auto new_bindings_map = GenerateExternalTextureBindings(in);
+ data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(new_bindings_map);
+ manager.Add<transform::MultiplanarExternalTexture>();
+ }
+
{ // Builtin polyfills
+ // BuiltinPolyfill must come before DirectVariableAccess, due to the use of pointer
+ // parameter for workgroupUniformLoad()
transform::BuiltinPolyfill::Builtins polyfills;
polyfills.acosh = transform::BuiltinPolyfill::Level::kRangeCheck;
polyfills.atanh = transform::BuiltinPolyfill::Level::kRangeCheck;
@@ -75,18 +103,11 @@
manager.Add<transform::BuiltinPolyfill>();
}
- if (options.generate_external_texture_bindings) {
- auto new_bindings_map = GenerateExternalTextureBindings(in);
- data.Add<transform::MultiplanarExternalTexture::NewBindingPoints>(new_bindings_map);
- }
- manager.Add<transform::MultiplanarExternalTexture>();
-
- manager.Add<transform::PreservePadding>(); // Must come before DirectVariableAccess
-
- manager.Add<transform::Unshadow>(); // Must come before DirectVariableAccess
bool disable_workgroup_init_in_sanitizer =
options.disable_workgroup_init || options.use_zero_initialize_workgroup_memory_extension;
if (!disable_workgroup_init_in_sanitizer) {
+ // ZeroInitWorkgroupMemory must come before CanonicalizeEntryPointIO as
+ // ZeroInitWorkgroupMemory may inject new builtin parameters.
manager.Add<transform::ZeroInitWorkgroupMemory>();
}
@@ -98,16 +119,11 @@
manager.Add<transform::DirectVariableAccess>();
}
- manager.Add<transform::RemoveUnreachableStatements>();
- manager.Add<transform::PromoteSideEffectsToDecl>();
- manager.Add<transform::SimplifyPointers>(); // Required for arrayLength()
- manager.Add<transform::RemovePhonies>();
- manager.Add<transform::VectorizeScalarMatrixInitializers>();
- manager.Add<transform::VectorizeMatrixConversions>();
- manager.Add<transform::WhileToLoop>(); // ZeroInitWorkgroupMemory
- manager.Add<transform::MergeReturn>();
+ // CanonicalizeEntryPointIO must come after Robustness
manager.Add<transform::CanonicalizeEntryPointIO>();
manager.Add<transform::AddEmptyEntryPoint>();
+
+ // AddBlockAttribute must come after MultiplanarExternalTexture
manager.Add<transform::AddBlockAttribute>();
// DemoteToHelper must come after CanonicalizeEntryPointIO, PromoteSideEffectsToDecl, and
diff --git a/src/tint/writer/spirv/test_helper.h b/src/tint/writer/spirv/test_helper.h
index 2e58760..028d363 100644
--- a/src/tint/writer/spirv/test_helper.h
+++ b/src/tint/writer/spirv/test_helper.h
@@ -33,6 +33,14 @@
TestHelperBase() = default;
~TestHelperBase() override = default;
+ /// @returns the default generator options for SanitizeAndBuild(), if no explicit options are
+ /// provided.
+ static Options DefaultOptions() {
+ Options opts;
+ opts.disable_robustness = true;
+ return opts;
+ }
+
/// Builds and returns a spirv::Builder from the program.
/// @note The spirv::Builder is only built once. Multiple calls to Build()
/// will return the same spirv::Builder without rebuilding.
@@ -59,7 +67,7 @@
/// @note The spirv::Builder is only built once. Multiple calls to Build()
/// will return the same spirv::Builder without rebuilding.
/// @return the built spirv::Builder
- spirv::Builder& SanitizeAndBuild(const Options& options = {}) {
+ spirv::Builder& SanitizeAndBuild(const Options& options = DefaultOptions()) {
if (spirv_builder) {
return *spirv_builder;
}
diff --git a/src/tint/writer/text_generator.h b/src/tint/writer/text_generator.h
index 74e3ecb..2bd725f 100644
--- a/src/tint/writer/text_generator.h
+++ b/src/tint/writer/text_generator.h
@@ -15,7 +15,6 @@
#ifndef SRC_TINT_WRITER_TEXT_GENERATOR_H_
#define SRC_TINT_WRITER_TEXT_GENERATOR_H_
-#include <sstream>
#include <string>
#include <unordered_map>
#include <utility>
diff --git a/src/tint/writer/wgsl/generator_impl_binary_test.cc b/src/tint/writer/wgsl/generator_impl_binary_test.cc
index 88bf9f5..fbb6c32 100644
--- a/src/tint/writer/wgsl/generator_impl_binary_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_binary_test.cc
@@ -23,7 +23,9 @@
ast::BinaryOp op;
};
inline std::ostream& operator<<(std::ostream& out, BinaryData data) {
- out << data.op;
+ utils::StringStream str;
+ str << data.op;
+ out << str.str();
return out;
}
using WgslBinaryTest = TestParamHelper<BinaryData>;
diff --git a/src/tint/writer/wgsl/generator_impl_constructor_test.cc b/src/tint/writer/wgsl/generator_impl_constructor_test.cc
index c815f42..7278736 100644
--- a/src/tint/writer/wgsl/generator_impl_constructor_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_constructor_test.cc
@@ -79,7 +79,7 @@
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.Generate()) << gen.error();
- EXPECT_THAT(gen.result(), HasSubstr("f32(-0.000012f)"));
+ EXPECT_THAT(gen.result(), HasSubstr("f32(-0.00001200000042445026f)"));
}
TEST_F(WgslGeneratorImplTest_Constructor, Type_F16) {
@@ -90,7 +90,7 @@
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.Generate()) << gen.error();
- EXPECT_THAT(gen.result(), HasSubstr("f16(-1.19805336e-05h)"));
+ EXPECT_THAT(gen.result(), HasSubstr("f16(-0.00001198053359985352h)"));
}
TEST_F(WgslGeneratorImplTest_Constructor, Type_Bool) {
diff --git a/src/tint/writer/wgsl/generator_impl_literal_test.cc b/src/tint/writer/wgsl/generator_impl_literal_test.cc
index e947778..b70f535 100644
--- a/src/tint/writer/wgsl/generator_impl_literal_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_literal_test.cc
@@ -183,16 +183,16 @@
INSTANTIATE_TEST_SUITE_P(Subnormal,
WgslGenerator_F16LiteralTest,
::testing::ValuesIn(std::vector<F16Data>{
- {MakeF16(0, 0, 1), "5.96046448e-08h"}, // Smallest
- {MakeF16(1, 0, 1), "-5.96046448e-08h"},
- {MakeF16(0, 0, 2), "1.1920929e-07h"},
- {MakeF16(1, 0, 2), "-1.1920929e-07h"},
- {MakeF16(0, 0, 0x3ffu), "6.09755516e-05h"}, // Largest
- {MakeF16(1, 0, 0x3ffu), "-6.09755516e-05h"}, // Largest
- {MakeF16(0, 0, 0x3afu), "5.620718e-05h"}, // Scattered bits
- {MakeF16(1, 0, 0x3afu), "-5.620718e-05h"}, // Scattered bits
- {MakeF16(0, 0, 0x2c7u), "4.23789024e-05h"}, // Scattered bits
- {MakeF16(1, 0, 0x2c7u), "-4.23789024e-05h"}, // Scattered bits
+ {MakeF16(0, 0, 1), "0.00000005960464477539h"}, // Smallest
+ {MakeF16(1, 0, 1), "-0.00000005960464477539h"},
+ {MakeF16(0, 0, 2), "0.00000011920928955078h"},
+ {MakeF16(1, 0, 2), "-0.00000011920928955078h"},
+ {MakeF16(0, 0, 0x3ffu), "0.00006097555160522461h"}, // Largest
+ {MakeF16(1, 0, 0x3ffu), "-0.00006097555160522461h"}, // Largest
+ {MakeF16(0, 0, 0x3afu), "0.00005620718002319336h"}, // Scattered bits
+ {MakeF16(1, 0, 0x3afu), "-0.00005620718002319336h"}, // Scattered bits
+ {MakeF16(0, 0, 0x2c7u), "0.00004237890243530273h"}, // Scattered bits
+ {MakeF16(1, 0, 0x2c7u), "-0.00004237890243530273h"}, // Scattered bits
}));
} // namespace