Generic template and forward in stringstream.

This CL updates the templates in the StringStream to match more types.
All of the internal `operator<<` methods have been converted over to
StringStream. The precision was increased in order to better match the
precision needed to read back as a double.

Bug: tint:1686
Change-Id: Iaa15cf247f174967dd1014647ba5a74804997c22
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/122080
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
dan sinclair 2023-03-02 21:28:45 +00:00 committed by Dawn LUCI CQ
parent 03de0e83ae
commit 6cc183c85a
1345 changed files with 2569 additions and 2353 deletions

View File

@ -297,10 +297,10 @@ constexpr const char* Operator(BinaryOp op) {
return "<invalid>"; return "<invalid>";
} }
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param op the BinaryOp /// @param op the BinaryOp
/// @return the std::ostream so calls can be chained /// @return the stream so calls can be chained
inline std::ostream& operator<<(std::ostream& out, BinaryOp op) { inline utils::StringStream& operator<<(utils::StringStream& out, BinaryOp op) {
out << FriendlyName(op); out << FriendlyName(op);
return out; return out;
} }

View File

@ -23,6 +23,45 @@
using namespace tint::number_suffixes; // NOLINT using namespace tint::number_suffixes; // NOLINT
namespace tint::ast::builtin::test { 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, TextureOverloadCase::TextureOverloadCase(ValidTextureOverload o,
const char* desc, const char* desc,
@ -80,57 +119,24 @@ TextureOverloadCase::TextureOverloadCase(ValidTextureOverload o,
TextureOverloadCase::TextureOverloadCase(const TextureOverloadCase&) = default; TextureOverloadCase::TextureOverloadCase(const TextureOverloadCase&) = default;
TextureOverloadCase::~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) { std::ostream& operator<<(std::ostream& out, const TextureOverloadCase& data) {
out << "TextureOverloadCase " << static_cast<int>(data.overload) << "\n"; utils::StringStream str;
out << data.description << "\n"; str << "TextureOverloadCase " << static_cast<int>(data.overload) << "\n";
out << "texture_kind: " << data.texture_kind << "\n"; str << data.description << "\n";
out << "sampler_kind: "; str << "texture_kind: " << data.texture_kind << "\n";
str << "sampler_kind: ";
if (data.texture_kind != TextureKind::kStorage) { if (data.texture_kind != TextureKind::kStorage) {
out << data.sampler_kind; str << data.sampler_kind;
} else { } else {
out << "<unused>"; str << "<unused>";
} }
out << "\n"; str << "\n";
out << "access: " << data.access << "\n"; str << "access: " << data.access << "\n";
out << "texel_format: " << data.texel_format << "\n"; str << "texel_format: " << data.texel_format << "\n";
out << "texture_dimension: " << data.texture_dimension << "\n"; str << "texture_dimension: " << data.texture_dimension << "\n";
out << "texture_data_type: " << data.texture_data_type << "\n"; str << "texture_data_type: " << data.texture_data_type << "\n";
out << str.str();
return out; return out;
} }

View File

@ -15,7 +15,6 @@
#ifndef SRC_TINT_AST_DIAGNOSTIC_CONTROL_H_ #ifndef SRC_TINT_AST_DIAGNOSTIC_CONTROL_H_
#define SRC_TINT_AST_DIAGNOSTIC_CONTROL_H_ #define SRC_TINT_AST_DIAGNOSTIC_CONTROL_H_
#include <ostream>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>

View File

@ -37,7 +37,7 @@ const FloatLiteralExpression* FloatLiteralExpression::Clone(CloneContext* ctx) c
return ctx->dst->create<FloatLiteralExpression>(src, value, suffix); 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) { switch (suffix) {
default: default:
return out; return out;

View File

@ -56,11 +56,11 @@ class FloatLiteralExpression final : public Castable<FloatLiteralExpression, Lit
const Suffix suffix; const Suffix suffix;
}; };
/// Writes the float literal suffix to the std::ostream. /// Writes the float literal suffix to the stream.
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param suffix the suffix to write /// @param suffix the suffix to write
/// @returns out so calls can be chained /// @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 } // namespace tint::ast

View File

@ -35,7 +35,7 @@ const IntLiteralExpression* IntLiteralExpression::Clone(CloneContext* ctx) const
return ctx->dst->create<IntLiteralExpression>(src, value, suffix); 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) { switch (suffix) {
default: default:
return out; return out;

View File

@ -55,11 +55,11 @@ class IntLiteralExpression final : public Castable<IntLiteralExpression, Literal
const Suffix suffix; const Suffix suffix;
}; };
/// Writes the integer literal suffix to the std::ostream. /// Writes the integer literal suffix to the stream.
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param suffix the suffix to write /// @param suffix the suffix to write
/// @returns out so calls can be chained /// @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 } // namespace tint::ast

View File

@ -15,7 +15,6 @@
#ifndef SRC_TINT_AST_INTERPOLATE_ATTRIBUTE_H_ #ifndef SRC_TINT_AST_INTERPOLATE_ATTRIBUTE_H_
#define SRC_TINT_AST_INTERPOLATE_ATTRIBUTE_H_ #define SRC_TINT_AST_INTERPOLATE_ATTRIBUTE_H_
#include <ostream>
#include <string> #include <string>
#include "src/tint/ast/attribute.h" #include "src/tint/ast/attribute.h"

View File

@ -16,7 +16,7 @@
namespace tint::ast { namespace tint::ast {
std::ostream& operator<<(std::ostream& out, PipelineStage stage) { utils::StringStream& operator<<(utils::StringStream& out, PipelineStage stage) {
switch (stage) { switch (stage) {
case PipelineStage::kNone: { case PipelineStage::kNone: {
out << "none"; out << "none";

View File

@ -15,17 +15,17 @@
#ifndef SRC_TINT_AST_PIPELINE_STAGE_H_ #ifndef SRC_TINT_AST_PIPELINE_STAGE_H_
#define 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 { namespace tint::ast {
/// The pipeline stage /// The pipeline stage
enum class PipelineStage { kNone = -1, kVertex, kFragment, kCompute }; 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 /// @param stage the PipelineStage
/// @return the std::ostream so calls can be chained /// @return the stream so calls can be chained
std::ostream& operator<<(std::ostream& out, PipelineStage stage); utils::StringStream& operator<<(utils::StringStream& out, PipelineStage stage);
} // namespace tint::ast } // namespace tint::ast

View File

@ -16,7 +16,7 @@
namespace tint::ast { namespace tint::ast {
std::ostream& operator<<(std::ostream& out, UnaryOp mod) { utils::StringStream& operator<<(utils::StringStream& out, UnaryOp mod) {
switch (mod) { switch (mod) {
case UnaryOp::kAddressOf: { case UnaryOp::kAddressOf: {
out << "address-of"; out << "address-of";

View File

@ -15,7 +15,7 @@
#ifndef SRC_TINT_AST_UNARY_OP_H_ #ifndef SRC_TINT_AST_UNARY_OP_H_
#define 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 { namespace tint::ast {
@ -28,10 +28,10 @@ enum class UnaryOp {
kNot, // !EXPR kNot, // !EXPR
}; };
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param mod the UnaryOp /// @param mod the UnaryOp
/// @return the std::ostream so calls can be chained /// @return the stream so calls can be chained
std::ostream& operator<<(std::ostream& out, UnaryOp mod); utils::StringStream& operator<<(utils::StringStream& out, UnaryOp mod);
} // namespace tint::ast } // namespace tint::ast

View File

@ -15,7 +15,7 @@
#include "src/tint/bench/benchmark.h" #include "src/tint/bench/benchmark.h"
#include <filesystem> #include <filesystem>
#include <sstream> #include <iostream>
#include <utility> #include <utility>
#include <vector> #include <vector>

View File

@ -40,7 +40,7 @@ Access ParseAccess(std::string_view str) {
return Access::kUndefined; return Access::kUndefined;
} }
std::ostream& operator<<(std::ostream& out, Access value) { utils::StringStream& operator<<(utils::StringStream& out, Access value) {
switch (value) { switch (value) {
case Access::kUndefined: case Access::kUndefined:
return out << "undefined"; return out << "undefined";

View File

@ -23,7 +23,7 @@
#ifndef SRC_TINT_BUILTIN_ACCESS_H_ #ifndef SRC_TINT_BUILTIN_ACCESS_H_
#define SRC_TINT_BUILTIN_ACCESS_H_ #define SRC_TINT_BUILTIN_ACCESS_H_
#include <ostream> #include "src/tint/utils/string_stream.h"
namespace tint::builtin { namespace tint::builtin {
@ -35,10 +35,10 @@ enum class Access {
kWrite, kWrite,
}; };
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param value the Access /// @param value the Access
/// @returns `out` so calls can be chained /// @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. /// ParseAccess parses a Access from a string.
/// @param str the string to parse /// @param str the string to parse

View File

@ -17,7 +17,7 @@ See:
#ifndef SRC_TINT_BUILTIN_ACCESS_H_ #ifndef SRC_TINT_BUILTIN_ACCESS_H_
#define SRC_TINT_BUILTIN_ACCESS_H_ #define SRC_TINT_BUILTIN_ACCESS_H_
#include <ostream> #include "src/tint/utils/string_stream.h"
namespace tint::builtin { namespace tint::builtin {

View File

@ -55,7 +55,7 @@ AddressSpace ParseAddressSpace(std::string_view str) {
return AddressSpace::kUndefined; return AddressSpace::kUndefined;
} }
std::ostream& operator<<(std::ostream& out, AddressSpace value) { utils::StringStream& operator<<(utils::StringStream& out, AddressSpace value) {
switch (value) { switch (value) {
case AddressSpace::kUndefined: case AddressSpace::kUndefined:
return out << "undefined"; return out << "undefined";

View File

@ -23,7 +23,7 @@
#ifndef SRC_TINT_BUILTIN_ADDRESS_SPACE_H_ #ifndef SRC_TINT_BUILTIN_ADDRESS_SPACE_H_
#define 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 { namespace tint::builtin {
@ -41,10 +41,10 @@ enum class AddressSpace {
kWorkgroup, kWorkgroup,
}; };
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param value the AddressSpace /// @param value the AddressSpace
/// @returns `out` so calls can be chained /// @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. /// ParseAddressSpace parses a AddressSpace from a string.
/// @param str the string to parse /// @param str the string to parse

View File

@ -17,7 +17,7 @@ See:
#ifndef SRC_TINT_BUILTIN_ADDRESS_SPACE_H_ #ifndef SRC_TINT_BUILTIN_ADDRESS_SPACE_H_
#define 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 { namespace tint::builtin {

View File

@ -76,7 +76,7 @@ Attribute ParseAttribute(std::string_view str) {
return Attribute::kUndefined; return Attribute::kUndefined;
} }
std::ostream& operator<<(std::ostream& out, Attribute value) { utils::StringStream& operator<<(utils::StringStream& out, Attribute value) {
switch (value) { switch (value) {
case Attribute::kUndefined: case Attribute::kUndefined:
return out << "undefined"; return out << "undefined";

View File

@ -23,7 +23,7 @@
#ifndef SRC_TINT_BUILTIN_ATTRIBUTE_H_ #ifndef SRC_TINT_BUILTIN_ATTRIBUTE_H_
#define SRC_TINT_BUILTIN_ATTRIBUTE_H_ #define SRC_TINT_BUILTIN_ATTRIBUTE_H_
#include <ostream> #include "src/tint/utils/string_stream.h"
/// \cond DO_NOT_DOCUMENT /// \cond DO_NOT_DOCUMENT
/// There is a bug in doxygen where this enum conflicts with the ast::Attribute /// There is a bug in doxygen where this enum conflicts with the ast::Attribute
@ -50,10 +50,10 @@ enum class Attribute {
kWorkgroupSize, kWorkgroupSize,
}; };
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param value the Attribute /// @param value the Attribute
/// @returns `out` so calls can be chained /// @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. /// ParseAttribute parses a Attribute from a string.
/// @param str the string to parse /// @param str the string to parse

View File

@ -17,7 +17,7 @@ See:
#ifndef SRC_TINT_BUILTIN_ATTRIBUTE_H_ #ifndef SRC_TINT_BUILTIN_ATTRIBUTE_H_
#define SRC_TINT_BUILTIN_ATTRIBUTE_H_ #define SRC_TINT_BUILTIN_ATTRIBUTE_H_
#include <ostream> #include "src/tint/utils/string_stream.h"
/// \cond DO_NOT_DOCUMENT /// \cond DO_NOT_DOCUMENT
/// There is a bug in doxygen where this enum conflicts with the ast::Attribute /// There is a bug in doxygen where this enum conflicts with the ast::Attribute

View File

@ -241,7 +241,7 @@ Builtin ParseBuiltin(std::string_view str) {
return Builtin::kUndefined; return Builtin::kUndefined;
} }
std::ostream& operator<<(std::ostream& out, Builtin value) { utils::StringStream& operator<<(utils::StringStream& out, Builtin value) {
switch (value) { switch (value) {
case Builtin::kUndefined: case Builtin::kUndefined:
return out << "undefined"; return out << "undefined";

View File

@ -23,7 +23,7 @@
#ifndef SRC_TINT_BUILTIN_BUILTIN_H_ #ifndef SRC_TINT_BUILTIN_BUILTIN_H_
#define SRC_TINT_BUILTIN_BUILTIN_H_ #define SRC_TINT_BUILTIN_BUILTIN_H_
#include <ostream> #include "src/tint/utils/string_stream.h"
namespace tint::builtin { namespace tint::builtin {
@ -102,10 +102,10 @@ enum class Builtin {
kVec4U, kVec4U,
}; };
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param value the Builtin /// @param value the Builtin
/// @returns `out` so calls can be chained /// @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. /// ParseBuiltin parses a Builtin from a string.
/// @param str the string to parse /// @param str the string to parse

View File

@ -18,7 +18,7 @@ See:
#ifndef SRC_TINT_BUILTIN_BUILTIN_H_ #ifndef SRC_TINT_BUILTIN_BUILTIN_H_
#define SRC_TINT_BUILTIN_BUILTIN_H_ #define SRC_TINT_BUILTIN_BUILTIN_H_
#include <ostream> #include "src/tint/utils/string_stream.h"
namespace tint::builtin { namespace tint::builtin {

View File

@ -70,7 +70,7 @@ BuiltinValue ParseBuiltinValue(std::string_view str) {
return BuiltinValue::kUndefined; return BuiltinValue::kUndefined;
} }
std::ostream& operator<<(std::ostream& out, BuiltinValue value) { utils::StringStream& operator<<(utils::StringStream& out, BuiltinValue value) {
switch (value) { switch (value) {
case BuiltinValue::kUndefined: case BuiltinValue::kUndefined:
return out << "undefined"; return out << "undefined";

View File

@ -23,7 +23,7 @@
#ifndef SRC_TINT_BUILTIN_BUILTIN_VALUE_H_ #ifndef SRC_TINT_BUILTIN_BUILTIN_VALUE_H_
#define 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 { namespace tint::builtin {
@ -45,10 +45,10 @@ enum class BuiltinValue {
kWorkgroupId, kWorkgroupId,
}; };
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param value the BuiltinValue /// @param value the BuiltinValue
/// @returns `out` so calls can be chained /// @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. /// ParseBuiltinValue parses a BuiltinValue from a string.
/// @param str the string to parse /// @param str the string to parse

View File

@ -14,7 +14,7 @@ See:
#ifndef SRC_TINT_BUILTIN_BUILTIN_VALUE_H_ #ifndef SRC_TINT_BUILTIN_BUILTIN_VALUE_H_
#define 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 { namespace tint::builtin {

View File

@ -22,9 +22,10 @@
#include "src/tint/builtin/diagnostic_rule.h" #include "src/tint/builtin/diagnostic_rule.h"
#include <ostream>
#include <string> #include <string>
#include "src/tint/utils/string_stream.h"
namespace tint::builtin { namespace tint::builtin {
/// ParseDiagnosticRule parses a DiagnosticRule from a string. /// ParseDiagnosticRule parses a DiagnosticRule from a string.
@ -40,7 +41,7 @@ DiagnosticRule ParseDiagnosticRule(std::string_view str) {
return DiagnosticRule::kUndefined; return DiagnosticRule::kUndefined;
} }
std::ostream& operator<<(std::ostream& out, DiagnosticRule value) { utils::StringStream& operator<<(utils::StringStream& out, DiagnosticRule value) {
switch (value) { switch (value) {
case DiagnosticRule::kUndefined: case DiagnosticRule::kUndefined:
return out << "undefined"; return out << "undefined";

View File

@ -12,9 +12,10 @@ See:
#include "src/tint/builtin/diagnostic_rule.h" #include "src/tint/builtin/diagnostic_rule.h"
#include <ostream>
#include <string> #include <string>
#include "src/tint/utils/string_stream.h"
namespace tint::builtin { namespace tint::builtin {
{{ Eval "ParseEnum" (Sem.Enum "diagnostic_rule")}} {{ Eval "ParseEnum" (Sem.Enum "diagnostic_rule")}}

View File

@ -25,6 +25,8 @@
#include <string> #include <string>
#include "src/tint/utils/string_stream.h"
namespace tint::builtin { namespace tint::builtin {
/// The diagnostic rule. /// The diagnostic rule.
@ -34,10 +36,10 @@ enum class DiagnosticRule {
kDerivativeUniformity, kDerivativeUniformity,
}; };
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param value the DiagnosticRule /// @param value the DiagnosticRule
/// @returns `out` so calls can be chained /// @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. /// ParseDiagnosticRule parses a DiagnosticRule from a string.
/// @param str the string to parse /// @param str the string to parse

View File

@ -15,6 +15,8 @@ See:
#include <string> #include <string>
#include "src/tint/utils/string_stream.h"
namespace tint::builtin { namespace tint::builtin {
/// The diagnostic rule. /// The diagnostic rule.

View File

@ -58,7 +58,7 @@ DiagnosticSeverity ParseDiagnosticSeverity(std::string_view str) {
return DiagnosticSeverity::kUndefined; return DiagnosticSeverity::kUndefined;
} }
std::ostream& operator<<(std::ostream& out, DiagnosticSeverity value) { utils::StringStream& operator<<(utils::StringStream& out, DiagnosticSeverity value) {
switch (value) { switch (value) {
case DiagnosticSeverity::kUndefined: case DiagnosticSeverity::kUndefined:
return out << "undefined"; return out << "undefined";

View File

@ -23,12 +23,12 @@
#ifndef SRC_TINT_BUILTIN_DIAGNOSTIC_SEVERITY_H_ #ifndef SRC_TINT_BUILTIN_DIAGNOSTIC_SEVERITY_H_
#define SRC_TINT_BUILTIN_DIAGNOSTIC_SEVERITY_H_ #define SRC_TINT_BUILTIN_DIAGNOSTIC_SEVERITY_H_
#include <ostream>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include "src/tint/builtin/diagnostic_rule.h" #include "src/tint/builtin/diagnostic_rule.h"
#include "src/tint/diagnostic/diagnostic.h" #include "src/tint/diagnostic/diagnostic.h"
#include "src/tint/utils/string_stream.h"
namespace tint::builtin { namespace tint::builtin {
@ -41,10 +41,10 @@ enum class DiagnosticSeverity {
kWarning, kWarning,
}; };
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param value the DiagnosticSeverity /// @param value the DiagnosticSeverity
/// @returns `out` so calls can be chained /// @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. /// ParseDiagnosticSeverity parses a DiagnosticSeverity from a string.
/// @param str the string to parse /// @param str the string to parse

View File

@ -13,10 +13,10 @@ See:
#ifndef SRC_TINT_BUILTIN_DIAGNOSTIC_SEVERITY_H_ #ifndef SRC_TINT_BUILTIN_DIAGNOSTIC_SEVERITY_H_
#define SRC_TINT_BUILTIN_DIAGNOSTIC_SEVERITY_H_ #define SRC_TINT_BUILTIN_DIAGNOSTIC_SEVERITY_H_
#include <ostream>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include "src/tint/utils/string_stream.h"
#include "src/tint/builtin/diagnostic_rule.h" #include "src/tint/builtin/diagnostic_rule.h"
#include "src/tint/diagnostic/diagnostic.h" #include "src/tint/diagnostic/diagnostic.h"

View File

@ -49,7 +49,7 @@ Extension ParseExtension(std::string_view str) {
return Extension::kUndefined; return Extension::kUndefined;
} }
std::ostream& operator<<(std::ostream& out, Extension value) { utils::StringStream& operator<<(utils::StringStream& out, Extension value) {
switch (value) { switch (value) {
case Extension::kUndefined: case Extension::kUndefined:
return out << "undefined"; return out << "undefined";

View File

@ -23,8 +23,7 @@
#ifndef SRC_TINT_BUILTIN_EXTENSION_H_ #ifndef SRC_TINT_BUILTIN_EXTENSION_H_
#define 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" #include "src/tint/utils/unique_vector.h"
namespace tint::builtin { namespace tint::builtin {
@ -41,10 +40,10 @@ enum class Extension {
kF16, kF16,
}; };
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param value the Extension /// @param value the Extension
/// @returns `out` so calls can be chained /// @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. /// ParseExtension parses a Extension from a string.
/// @param str the string to parse /// @param str the string to parse

View File

@ -14,8 +14,7 @@ See:
#ifndef SRC_TINT_BUILTIN_EXTENSION_H_ #ifndef SRC_TINT_BUILTIN_EXTENSION_H_
#define 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" #include "src/tint/utils/unique_vector.h"
namespace tint::builtin { namespace tint::builtin {

View File

@ -43,7 +43,7 @@ InterpolationSampling ParseInterpolationSampling(std::string_view str) {
return InterpolationSampling::kUndefined; return InterpolationSampling::kUndefined;
} }
std::ostream& operator<<(std::ostream& out, InterpolationSampling value) { utils::StringStream& operator<<(utils::StringStream& out, InterpolationSampling value) {
switch (value) { switch (value) {
case InterpolationSampling::kUndefined: case InterpolationSampling::kUndefined:
return out << "undefined"; return out << "undefined";

View File

@ -23,9 +23,10 @@
#ifndef SRC_TINT_BUILTIN_INTERPOLATION_SAMPLING_H_ #ifndef SRC_TINT_BUILTIN_INTERPOLATION_SAMPLING_H_
#define SRC_TINT_BUILTIN_INTERPOLATION_SAMPLING_H_ #define SRC_TINT_BUILTIN_INTERPOLATION_SAMPLING_H_
#include <ostream>
#include <string> #include <string>
#include "src/tint/utils/string_stream.h"
namespace tint::builtin { namespace tint::builtin {
/// The interpolation sampling. /// The interpolation sampling.
@ -36,10 +37,10 @@ enum class InterpolationSampling {
kSample, kSample,
}; };
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param value the InterpolationSampling /// @param value the InterpolationSampling
/// @returns `out` so calls can be chained /// @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. /// ParseInterpolationSampling parses a InterpolationSampling from a string.
/// @param str the string to parse /// @param str the string to parse

View File

@ -13,9 +13,10 @@ See:
#ifndef SRC_TINT_BUILTIN_INTERPOLATION_SAMPLING_H_ #ifndef SRC_TINT_BUILTIN_INTERPOLATION_SAMPLING_H_
#define SRC_TINT_BUILTIN_INTERPOLATION_SAMPLING_H_ #define SRC_TINT_BUILTIN_INTERPOLATION_SAMPLING_H_
#include <ostream>
#include <string> #include <string>
#include "src/tint/utils/string_stream.h"
namespace tint::builtin { namespace tint::builtin {
/// The interpolation sampling. /// The interpolation sampling.

View File

@ -42,7 +42,7 @@ InterpolationType ParseInterpolationType(std::string_view str) {
return InterpolationType::kUndefined; return InterpolationType::kUndefined;
} }
std::ostream& operator<<(std::ostream& out, InterpolationType value) { utils::StringStream& operator<<(utils::StringStream& out, InterpolationType value) {
switch (value) { switch (value) {
case InterpolationType::kUndefined: case InterpolationType::kUndefined:
return out << "undefined"; return out << "undefined";

View File

@ -23,9 +23,10 @@
#ifndef SRC_TINT_BUILTIN_INTERPOLATION_TYPE_H_ #ifndef SRC_TINT_BUILTIN_INTERPOLATION_TYPE_H_
#define SRC_TINT_BUILTIN_INTERPOLATION_TYPE_H_ #define SRC_TINT_BUILTIN_INTERPOLATION_TYPE_H_
#include <ostream>
#include <string> #include <string>
#include "src/tint/utils/string_stream.h"
namespace tint::builtin { namespace tint::builtin {
/// The interpolation type. /// The interpolation type.
@ -36,10 +37,10 @@ enum class InterpolationType {
kPerspective, kPerspective,
}; };
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param value the InterpolationType /// @param value the InterpolationType
/// @returns `out` so calls can be chained /// @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. /// ParseInterpolationType parses a InterpolationType from a string.
/// @param str the string to parse /// @param str the string to parse

View File

@ -13,9 +13,10 @@ See:
#ifndef SRC_TINT_BUILTIN_INTERPOLATION_TYPE_H_ #ifndef SRC_TINT_BUILTIN_INTERPOLATION_TYPE_H_
#define SRC_TINT_BUILTIN_INTERPOLATION_TYPE_H_ #define SRC_TINT_BUILTIN_INTERPOLATION_TYPE_H_
#include <ostream>
#include <string> #include <string>
#include "src/tint/utils/string_stream.h"
namespace tint::builtin { namespace tint::builtin {
/// The interpolation type. /// The interpolation type.

View File

@ -82,7 +82,7 @@ TexelFormat ParseTexelFormat(std::string_view str) {
return TexelFormat::kUndefined; return TexelFormat::kUndefined;
} }
std::ostream& operator<<(std::ostream& out, TexelFormat value) { utils::StringStream& operator<<(utils::StringStream& out, TexelFormat value) {
switch (value) { switch (value) {
case TexelFormat::kUndefined: case TexelFormat::kUndefined:
return out << "undefined"; return out << "undefined";

View File

@ -23,7 +23,7 @@
#ifndef SRC_TINT_BUILTIN_TEXEL_FORMAT_H_ #ifndef SRC_TINT_BUILTIN_TEXEL_FORMAT_H_
#define 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 { namespace tint::builtin {
@ -49,10 +49,10 @@ enum class TexelFormat {
kRgba8Unorm, kRgba8Unorm,
}; };
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param value the TexelFormat /// @param value the TexelFormat
/// @returns `out` so calls can be chained /// @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. /// ParseTexelFormat parses a TexelFormat from a string.
/// @param str the string to parse /// @param str the string to parse

View File

@ -14,7 +14,7 @@ See:
#ifndef SRC_TINT_BUILTIN_TEXEL_FORMAT_H_ #ifndef SRC_TINT_BUILTIN_TEXEL_FORMAT_H_
#define 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 { namespace tint::builtin {

View File

@ -14,6 +14,7 @@
#include "src/tint/cmd/helper.h" #include "src/tint/cmd/helper.h"
#include <iostream>
#include <utility> #include <utility>
#include <vector> #include <vector>

View File

@ -13,6 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include <iostream>
#if TINT_BUILD_SPV_READER #if TINT_BUILD_SPV_READER
#include "spirv-tools/libspirv.hpp" #include "spirv-tools/libspirv.hpp"
#endif // TINT_BUILD_SPV_READER #endif // TINT_BUILD_SPV_READER

View File

@ -16,6 +16,7 @@
#include <algorithm> #include <algorithm>
#include <iterator> #include <iterator>
#include <utility>
#include <vector> #include <vector>
#include "src/tint/diagnostic/diagnostic.h" #include "src/tint/diagnostic/diagnostic.h"
@ -85,8 +86,8 @@ struct Formatter::State {
/// @param msg the value or string to write to the printer /// @param msg the value or string to write to the printer
/// @returns this State so that calls can be chained /// @returns this State so that calls can be chained
template <typename T> template <typename T>
State& operator<<(const T& msg) { State& operator<<(T&& msg) {
stream << msg; stream << std::forward<T>(msg);
return *this; return *this;
} }

View File

@ -16,7 +16,6 @@
#define SRC_TINT_DIAGNOSTIC_PRINTER_H_ #define SRC_TINT_DIAGNOSTIC_PRINTER_H_
#include <memory> #include <memory>
#include <sstream>
#include <string> #include <string>
#include "src/tint/utils/string_stream.h" #include "src/tint/utils/string_stream.h"

View File

@ -17,6 +17,7 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include <fstream> #include <fstream>
#include <iostream>
#include <memory> #include <memory>
#include <sstream> #include <sstream>
#include <string> #include <string>

View File

@ -273,7 +273,11 @@ ast::Type InspectorBuilder::GetCoordsType(type::TextureDimension dim, ast::Type
case type::TextureDimension::kCubeArray: case type::TextureDimension::kCubeArray:
return ty.vec3(scalar); return ty.vec3(scalar);
default: default:
[=]() { FAIL() << "Unsupported texture dimension: " << dim; }(); [=]() {
utils::StringStream str;
str << dim;
FAIL() << "Unsupported texture dimension: " << str.str();
}();
} }
return ast::Type{}; return ast::Type{};
} }

View File

@ -544,8 +544,8 @@ match workgroup
@must_use @const fn abs<N: num, T: fia_fiu32_f16>(vec<N, T>) -> vec<N, T> @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<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 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<T: fa_f32_f16>(@test_value(1.5430806348) 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<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(bool) -> bool
@must_use @const fn all<N: num>(vec<N, bool>) -> bool @must_use @const fn all<N: num>(vec<N, bool>) -> bool
@must_use @const fn any(bool) -> bool @must_use @const fn any(bool) -> bool
@ -658,8 +658,8 @@ match workgroup
@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 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<T: iu32>(T) -> T
@must_use @const fn reverseBits<N: num, T: iu32>(vec<N, T>) -> vec<N, 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<T: fa_f32_f16>(@test_value(3.5) 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<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>(@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 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 @must_use @const("select_bool") fn select<T: scalar>(T, T, bool) -> T

View File

@ -15,8 +15,6 @@
#ifndef SRC_TINT_IR_BINARY_H_ #ifndef SRC_TINT_IR_BINARY_H_
#define SRC_TINT_IR_BINARY_H_ #define SRC_TINT_IR_BINARY_H_
#include <ostream>
#include "src/tint/castable.h" #include "src/tint/castable.h"
#include "src/tint/ir/instruction.h" #include "src/tint/ir/instruction.h"
#include "src/tint/symbol_table.h" #include "src/tint/symbol_table.h"

View File

@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include <sstream>
#include "src/tint/ir/instruction.h" #include "src/tint/ir/instruction.h"
#include "src/tint/ir/test_helper.h" #include "src/tint/ir/test_helper.h"
#include "src/tint/utils/string_stream.h" #include "src/tint/utils/string_stream.h"

View File

@ -15,8 +15,6 @@
#ifndef SRC_TINT_IR_BITCAST_H_ #ifndef SRC_TINT_IR_BITCAST_H_
#define SRC_TINT_IR_BITCAST_H_ #define SRC_TINT_IR_BITCAST_H_
#include <ostream>
#include "src/tint/castable.h" #include "src/tint/castable.h"
#include "src/tint/ir/instruction.h" #include "src/tint/ir/instruction.h"
#include "src/tint/symbol_table.h" #include "src/tint/symbol_table.h"

View File

@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include <sstream>
#include "src/tint/ir/instruction.h" #include "src/tint/ir/instruction.h"
#include "src/tint/ir/test_helper.h" #include "src/tint/ir/test_helper.h"
#include "src/tint/utils/string_stream.h" #include "src/tint/utils/string_stream.h"

View File

@ -1836,8 +1836,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Compound) {
EXPECT_EQ(d.AsString(), R"(%1 (u32) = 3 >> 4 EXPECT_EQ(d.AsString(), R"(%1 (u32) = 3 >> 4
%2 (u32) = %1 (u32) + 9 %2 (u32) = %1 (u32) + 9
%3 (bool) = 1 < %2 (u32) %3 (bool) = 1 < %2 (u32)
%4 (f32) = 2.299999952 * 5.5 %4 (f32) = 2.29999995231628417969 * 5.5
%5 (f32) = 6.699999809 / %4 (f32) %5 (f32) = 6.69999980926513671875 / %4 (f32)
%6 (bool) = 2.5 > %5 (f32) %6 (bool) = 2.5 > %5 (f32)
%7 (bool) = %3 (bool) && %6 (bool) %7 (bool) = %3 (bool) && %6 (bool)
)"); )");

View File

@ -15,8 +15,6 @@
#ifndef SRC_TINT_IR_CONSTANT_H_ #ifndef SRC_TINT_IR_CONSTANT_H_
#define SRC_TINT_IR_CONSTANT_H_ #define SRC_TINT_IR_CONSTANT_H_
#include <ostream>
#include "src/tint/constant/value.h" #include "src/tint/constant/value.h"
#include "src/tint/ir/value.h" #include "src/tint/ir/value.h"
#include "src/tint/symbol_table.h" #include "src/tint/symbol_table.h"

View File

@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include <sstream>
#include "src/tint/ir/test_helper.h" #include "src/tint/ir/test_helper.h"
#include "src/tint/ir/value.h" #include "src/tint/ir/value.h"
#include "src/tint/utils/string_stream.h" #include "src/tint/utils/string_stream.h"
@ -34,7 +32,7 @@ TEST_F(IR_ConstantTest, f32) {
EXPECT_EQ(1.2_f, c->value->As<constant::Scalar<f32>>()->ValueAs<f32>()); EXPECT_EQ(1.2_f, c->value->As<constant::Scalar<f32>>()->ValueAs<f32>());
c->ToString(str, b.builder.ir.symbols); 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_TRUE(c->value->Is<constant::Scalar<f32>>());
EXPECT_FALSE(c->value->Is<constant::Scalar<f16>>()); EXPECT_FALSE(c->value->Is<constant::Scalar<f16>>());

View File

@ -14,7 +14,6 @@
#include "src/tint/ir/debug.h" #include "src/tint/ir/debug.h"
#include <sstream>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>

View File

@ -15,7 +15,6 @@
#ifndef SRC_TINT_IR_DISASSEMBLER_H_ #ifndef SRC_TINT_IR_DISASSEMBLER_H_
#define SRC_TINT_IR_DISASSEMBLER_H_ #define SRC_TINT_IR_DISASSEMBLER_H_
#include <sstream>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>

View File

@ -15,8 +15,6 @@
#ifndef SRC_TINT_IR_INSTRUCTION_H_ #ifndef SRC_TINT_IR_INSTRUCTION_H_
#define SRC_TINT_IR_INSTRUCTION_H_ #define SRC_TINT_IR_INSTRUCTION_H_
#include <ostream>
#include "src/tint/castable.h" #include "src/tint/castable.h"
#include "src/tint/ir/value.h" #include "src/tint/ir/value.h"
#include "src/tint/symbol_table.h" #include "src/tint/symbol_table.h"

View File

@ -15,8 +15,6 @@
#ifndef SRC_TINT_IR_TEMP_H_ #ifndef SRC_TINT_IR_TEMP_H_
#define SRC_TINT_IR_TEMP_H_ #define SRC_TINT_IR_TEMP_H_
#include <ostream>
#include "src/tint/ir/value.h" #include "src/tint/ir/value.h"
#include "src/tint/symbol_table.h" #include "src/tint/symbol_table.h"
#include "src/tint/utils/string_stream.h" #include "src/tint/utils/string_stream.h"

View File

@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include <sstream>
#include "src/tint/ir/temp.h" #include "src/tint/ir/temp.h"
#include "src/tint/ir/test_helper.h" #include "src/tint/ir/test_helper.h"
#include "src/tint/utils/string_stream.h" #include "src/tint/utils/string_stream.h"

View File

@ -15,8 +15,6 @@
#ifndef SRC_TINT_IR_VALUE_H_ #ifndef SRC_TINT_IR_VALUE_H_
#define SRC_TINT_IR_VALUE_H_ #define SRC_TINT_IR_VALUE_H_
#include <ostream>
#include "src/tint/castable.h" #include "src/tint/castable.h"
#include "src/tint/symbol_table.h" #include "src/tint/symbol_table.h"
#include "src/tint/type/type.h" #include "src/tint/type/type.h"

View File

@ -17,10 +17,10 @@
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <cstring> #include <cstring>
#include <ostream>
#include "src/tint/debug.h" #include "src/tint/debug.h"
#include "src/tint/utils/bitcast.h" #include "src/tint/utils/bitcast.h"
#include "src/tint/utils/string_stream.h"
namespace tint { namespace tint {
namespace { namespace {
@ -50,7 +50,7 @@ constexpr uint32_t kMinF32BiasedExpForF16SubnormalNumber = 103;
} // namespace } // namespace
std::ostream& operator<<(std::ostream& out, ConversionFailure failure) { utils::StringStream& operator<<(utils::StringStream& out, ConversionFailure failure) {
switch (failure) { switch (failure) {
case ConversionFailure::kExceedsPositiveLimit: case ConversionFailure::kExceedsPositiveLimit:
return out << "value exceeds positive limit for type"; return out << "value exceeds positive limit for type";

View File

@ -20,11 +20,11 @@
#include <functional> #include <functional>
#include <limits> #include <limits>
#include <optional> #include <optional>
#include <ostream>
#include "src/tint/traits.h" #include "src/tint/traits.h"
#include "src/tint/utils/compiler_macros.h" #include "src/tint/utils/compiler_macros.h"
#include "src/tint/utils/result.h" #include "src/tint/utils/result.h"
#include "src/tint/utils/string_stream.h"
// Forward declaration // Forward declaration
namespace tint { namespace tint {
@ -175,11 +175,11 @@ struct Number : NumberBase<Number<T>> {
}; };
/// Writes the number to the ostream. /// 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 /// @param num the Number
/// @return the std::ostream so calls can be chained /// @return the stream so calls can be chained
template <typename T> 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; return out << num.value;
} }
@ -314,10 +314,10 @@ enum class ConversionFailure {
}; };
/// Writes the conversion failure message to the ostream. /// 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 /// @param failure the ConversionFailure
/// @return the std::ostream so calls can be chained /// @return the stream so calls can be chained
std::ostream& operator<<(std::ostream& out, ConversionFailure failure); 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. /// 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. /// @returns the resulting value of the conversion, or a failure reason.

View File

@ -16,10 +16,10 @@
#define SRC_TINT_PROGRAM_ID_H_ #define SRC_TINT_PROGRAM_ID_H_
#include <stdint.h> #include <stdint.h>
#include <iostream>
#include <utility> #include <utility>
#include "src/tint/debug.h" #include "src/tint/debug.h"
#include "src/tint/utils/string_stream.h"
namespace tint { namespace tint {
@ -71,11 +71,11 @@ inline ProgramID ProgramIDOf(ProgramID id) {
return id; return id;
} }
/// Writes the ProgramID to the std::ostream. /// Writes the ProgramID to the stream.
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param id the program identifier to write /// @param id the program identifier to write
/// @returns out so calls can be chained /// @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() << ">"; out << "Program<" << id.Value() << ">";
return out; return out;
} }

View File

@ -16,7 +16,6 @@
#define SRC_TINT_READER_SPIRV_CONSTRUCT_H_ #define SRC_TINT_READER_SPIRV_CONSTRUCT_H_
#include <memory> #include <memory>
#include <sstream>
#include <string> #include <string>
#include "src/tint/utils/string_stream.h" #include "src/tint/utils/string_stream.h"

View File

@ -19,7 +19,7 @@
namespace tint::reader::spirv { 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 /// and can be used to record failure by writing the false value
/// to given a pointer-to-bool. /// to given a pointer-to-bool.
class FailStream { class FailStream {

View File

@ -28,6 +28,7 @@
#include "src/tint/reader/spirv/attributes.h" #include "src/tint/reader/spirv/attributes.h"
#include "src/tint/reader/spirv/construct.h" #include "src/tint/reader/spirv/construct.h"
#include "src/tint/reader/spirv/parser_impl.h" #include "src/tint/reader/spirv/parser_impl.h"
#include "src/tint/utils/string_stream.h"
namespace tint::reader::spirv { namespace tint::reader::spirv {
@ -178,11 +179,11 @@ struct BlockInfo {
utils::Vector<uint32_t, 4> phis_needing_state_vars; utils::Vector<uint32_t, 4> phis_needing_state_vars;
}; };
/// Writes the BlockInfo to the ostream /// Writes the BlockInfo to the stream
/// @param o the ostream /// @param o the stream
/// @param bi the BlockInfo /// @param bi the BlockInfo
/// @returns the ostream so calls can be chained /// @returns the stream so calls can be chained
inline std::ostream& operator<<(std::ostream& o, const BlockInfo& bi) { inline utils::StringStream& operator<<(utils::StringStream& o, const BlockInfo& bi) {
o << "BlockInfo{" o << "BlockInfo{"
<< " id: " << bi.id << " pos: " << bi.pos << " merge_for_header: " << bi.merge_for_header << " id: " << bi.id << " pos: " << bi.pos << " merge_for_header: " << bi.merge_for_header
<< " continue_for_header: " << bi.continue_for_header << " continue_for_header: " << bi.continue_for_header
@ -353,11 +354,11 @@ struct DefInfo {
SkipReason skip = SkipReason::kDontSkip; SkipReason skip = SkipReason::kDontSkip;
}; };
/// Writes the DefInfo to the ostream /// Writes the DefInfo to the stream
/// @param o the ostream /// @param o the stream
/// @param di the DefInfo /// @param di the DefInfo
/// @returns the ostream so calls can be chained /// @returns the stream so calls can be chained
inline std::ostream& operator<<(std::ostream& o, const DefInfo& di) { inline utils::StringStream& operator<<(utils::StringStream& o, const DefInfo& di) {
o << "DefInfo{" o << "DefInfo{"
<< " inst.result_id: " << di.inst.result_id(); << " inst.result_id: " << di.inst.result_id();
if (di.local.has_value()) { if (di.local.has_value()) {

View File

@ -2598,10 +2598,11 @@ TEST_F(SpvParserCFGTest, VerifyHeaderContinueMergeOrder_HeaderDoesNotStrictlyDom
fe.ComputeBlockOrderAndPositions(); fe.ComputeBlockOrderAndPositions();
fe.RegisterMerges(); fe.RegisterMerges();
EXPECT_FALSE(fe.VerifyHeaderContinueMergeOrder()); 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")) EXPECT_THAT(p->error(), Eq("Header 50 does not strictly dominate its merge block 20"))
<< *fe.GetBlockInfo(50) << std::endl << result.str() << Dump(fe.block_order());
<< *fe.GetBlockInfo(20) << std::endl
<< Dump(fe.block_order());
} }
TEST_F(SpvParserCFGTest, TEST_F(SpvParserCFGTest,
@ -2634,10 +2635,10 @@ TEST_F(SpvParserCFGTest,
fe.ComputeBlockOrderAndPositions(); fe.ComputeBlockOrderAndPositions();
fe.RegisterMerges(); fe.RegisterMerges();
EXPECT_FALSE(fe.VerifyHeaderContinueMergeOrder()); 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")) EXPECT_THAT(p->error(), Eq("Loop header 50 does not dominate its continue target 20"))
<< *fe.GetBlockInfo(50) << std::endl << str.str() << Dump(fe.block_order());
<< *fe.GetBlockInfo(20) << std::endl
<< Dump(fe.block_order());
} }
TEST_F(SpvParserCFGTest, VerifyHeaderContinueMergeOrder_MergeInsideContinueTarget) { TEST_F(SpvParserCFGTest, VerifyHeaderContinueMergeOrder_MergeInsideContinueTarget) {
@ -2752,10 +2753,15 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_FunctionIsOnlyIfSelectionAnd
EXPECT_TRUE(fe.LabelControlFlowConstructs()); EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs(); const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 2u); EXPECT_EQ(constructs.Length(), 2u);
utils::StringStream str;
str << constructs;
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{ EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,4) begin_id:10 end_id:0 depth:0 parent:null } 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{ IfSelection [0,3) begin_id:10 end_id:99 depth:1 parent:Function@10 }
})")) << constructs; })")) << str.str();
// The block records the nearest enclosing construct. // The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get()); EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[1].get()); EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[1].get());
@ -2798,10 +2804,15 @@ TEST_F(SpvParserCFGTest,
EXPECT_TRUE(fe.LabelControlFlowConstructs()); EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs(); const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 2u); EXPECT_EQ(constructs.Length(), 2u);
utils::StringStream str;
str << constructs;
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{ EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,6) begin_id:5 end_id:0 depth:0 parent:null } 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 } 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. // The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(5)->construct, constructs[0].get()); EXPECT_EQ(fe.GetBlockInfo(5)->construct, constructs[0].get());
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get()); EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get());
@ -2842,10 +2853,15 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_SwitchSelection) {
EXPECT_TRUE(fe.LabelControlFlowConstructs()); EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs(); const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 2u); EXPECT_EQ(constructs.Length(), 2u);
utils::StringStream str;
str << constructs;
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{ EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,5) begin_id:10 end_id:0 depth:0 parent:null } 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 } 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. // The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get()); EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[1].get()); EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[1].get());
@ -2879,12 +2895,17 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_SingleBlockLoop) {
EXPECT_TRUE(fe.LabelControlFlowConstructs()); EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs(); const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 2u); EXPECT_EQ(constructs.Length(), 2u);
utils::StringStream str;
str << constructs;
// A single-block loop consists *only* of a continue target with one block in // A single-block loop consists *only* of a continue target with one block in
// it. // it.
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{ EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,3) begin_id:10 end_id:0 depth:0 parent:null } 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 } 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. // The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get()); EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[1].get()); EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[1].get());
@ -2925,11 +2946,16 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_MultiBlockLoop_HeaderIsNotCo
fe.RegisterMerges(); fe.RegisterMerges();
EXPECT_TRUE(fe.LabelControlFlowConstructs()); EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs(); const auto& constructs = fe.constructs();
utils::StringStream str;
str << constructs;
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{ EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,6) begin_id:10 end_id:0 depth:0 parent:null } 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{ 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 } 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. // The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get()); EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[2].get()); EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[2].get());
@ -2973,10 +2999,14 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_MultiBlockLoop_HeaderIsConti
fe.RegisterMerges(); fe.RegisterMerges();
EXPECT_TRUE(fe.LabelControlFlowConstructs()); EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs(); const auto& constructs = fe.constructs();
utils::StringStream str;
str << constructs;
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{ EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,6) begin_id:10 end_id:0 depth:0 parent:null } 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 } 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. // The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get()); EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[1].get()); EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[1].get());
@ -3020,13 +3050,18 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_MergeBlockIsAlsoSingleBlockL
EXPECT_TRUE(fe.LabelControlFlowConstructs()); EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs(); const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 3u); EXPECT_EQ(constructs.Length(), 3u);
utils::StringStream str;
str << constructs;
// A single-block loop consists *only* of a continue target with one block in // A single-block loop consists *only* of a continue target with one block in
// it. // it.
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{ EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,4) begin_id:10 end_id:0 depth:0 parent:null } 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{ 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 } 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. // The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get()); EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[1].get()); EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[1].get());
@ -3068,12 +3103,17 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_MergeBlockIsAlsoMultiBlockLo
EXPECT_TRUE(fe.LabelControlFlowConstructs()); EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs(); const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 4u); EXPECT_EQ(constructs.Length(), 4u);
utils::StringStream str;
str << constructs;
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{ EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,5) begin_id:10 end_id:0 depth:0 parent:null } 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{ 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{ 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 } 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. // The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get()); EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[1].get()); EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[1].get());
@ -3127,12 +3167,17 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_Nest_If_If) {
EXPECT_TRUE(fe.LabelControlFlowConstructs()); EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs(); const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 4u); EXPECT_EQ(constructs.Length(), 4u);
utils::StringStream str;
str << constructs;
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{ EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,9) begin_id:10 end_id:0 depth:0 parent:null } 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 [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 [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 } 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. // The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get()); EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[2].get()); EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[2].get());
@ -3187,13 +3232,18 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_Nest_Switch_If) {
EXPECT_TRUE(fe.LabelControlFlowConstructs()); EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs(); const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 4u); EXPECT_EQ(constructs.Length(), 4u);
utils::StringStream str;
str << constructs;
// The ordering among siblings depends on the computed block order. // The ordering among siblings depends on the computed block order.
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{ EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,8) begin_id:10 end_id:0 depth:0 parent:null } 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{ 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 [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 } 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. // The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get()); EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[3].get()); EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[3].get());
@ -3237,11 +3287,16 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_Nest_If_Switch) {
EXPECT_TRUE(fe.LabelControlFlowConstructs()); EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs(); const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 3u); EXPECT_EQ(constructs.Length(), 3u);
utils::StringStream str;
str << constructs;
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{ EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,5) begin_id:10 end_id:0 depth:0 parent:null } 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{ 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 } 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. // The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get()); EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[2].get()); EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[2].get());
@ -3291,12 +3346,17 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_Nest_Loop_Loop) {
EXPECT_TRUE(fe.LabelControlFlowConstructs()); EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs(); const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 4u); EXPECT_EQ(constructs.Length(), 4u);
utils::StringStream str;
str << constructs;
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{ EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,8) begin_id:10 end_id:0 depth:0 parent:null } 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{ 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{ 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 } 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. // The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get()); EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[2].get()); EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[2].get());
@ -3346,12 +3406,17 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_Nest_Loop_If) {
EXPECT_TRUE(fe.LabelControlFlowConstructs()); EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs(); const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 4u); EXPECT_EQ(constructs.Length(), 4u);
utils::StringStream str;
str << constructs;
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{ EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,7) begin_id:10 end_id:0 depth:0 parent:null } 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{ 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{ 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 } 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. // The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get()); EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[2].get()); EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[2].get());
@ -3397,12 +3462,16 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_Nest_LoopContinue_If) {
EXPECT_TRUE(fe.LabelControlFlowConstructs()); EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs(); const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 4u); EXPECT_EQ(constructs.Length(), 4u);
utils::StringStream str;
str << constructs;
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{ EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,6) begin_id:10 end_id:0 depth:0 parent:null } 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{ 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{ 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 } 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. // The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get()); EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[2].get()); EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[2].get());
@ -3441,11 +3510,15 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_Nest_If_SingleBlockLoop) {
EXPECT_TRUE(fe.LabelControlFlowConstructs()); EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs(); const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 3u); EXPECT_EQ(constructs.Length(), 3u);
utils::StringStream str;
str << constructs;
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{ EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,4) begin_id:10 end_id:0 depth:0 parent:null } 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{ 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 } 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. // The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get()); EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[2].get()); EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[2].get());
@ -3490,12 +3563,17 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_Nest_If_MultiBlockLoop) {
EXPECT_TRUE(fe.LabelControlFlowConstructs()); EXPECT_TRUE(fe.LabelControlFlowConstructs());
const auto& constructs = fe.constructs(); const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 4u); EXPECT_EQ(constructs.Length(), 4u);
utils::StringStream str;
str << constructs;
EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{ EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,7) begin_id:10 end_id:0 depth:0 parent:null } 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{ 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{ 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 } 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. // The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get()); EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[3].get()); EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[3].get());
@ -3540,12 +3618,17 @@ TEST_F(SpvParserCFGTest, LabelControlFlowConstructs_LoopInterallyDiverge) {
ASSERT_TRUE(FlowLabelControlFlowConstructs(&fe)) << p->error(); ASSERT_TRUE(FlowLabelControlFlowConstructs(&fe)) << p->error();
const auto& constructs = fe.constructs(); const auto& constructs = fe.constructs();
EXPECT_EQ(constructs.Length(), 4u); EXPECT_EQ(constructs.Length(), 4u);
utils::StringStream str;
str << constructs;
ASSERT_THAT(ToString(constructs), Eq(R"(ConstructList{ ASSERT_THAT(ToString(constructs), Eq(R"(ConstructList{
Construct{ Function [0,6) begin_id:10 end_id:0 depth:0 parent:null } 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{ 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{ 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 } 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. // The block records the nearest enclosing construct.
EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get()); EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get());
EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[3].get()); EXPECT_EQ(fe.GetBlockInfo(20)->construct, constructs[3].get());

View File

@ -532,9 +532,10 @@ TEST_F(SpvFUnordTest, FUnordEqual_Vector) {
auto fe = p->function_emitter(100); auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error(); EXPECT_TRUE(fe.EmitBody()) << p->error();
auto ast_body = fe.ast_body(); auto ast_body = fe.ast_body();
EXPECT_THAT(test::ToString(p->program(), ast_body), EXPECT_THAT(
HasSubstr("let x_1 : vec2<bool> = " test::ToString(p->program(), ast_body),
"!((vec2<f32>(50.0f, 60.0f) != vec2<f32>(60.0f, 50.0f)));")); HasSubstr(
"let x_1 : vec2<bool> = !((vec2<f32>(50.0f, 60.0f) != vec2<f32>(60.0f, 50.0f)));"));
} }
TEST_F(SpvFUnordTest, FUnordNotEqual_Scalar) { TEST_F(SpvFUnordTest, FUnordNotEqual_Scalar) {
@ -567,9 +568,10 @@ TEST_F(SpvFUnordTest, FUnordNotEqual_Vector) {
auto fe = p->function_emitter(100); auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error(); EXPECT_TRUE(fe.EmitBody()) << p->error();
auto ast_body = fe.ast_body(); auto ast_body = fe.ast_body();
EXPECT_THAT(test::ToString(p->program(), ast_body), EXPECT_THAT(
HasSubstr("let x_1 : vec2<bool> = " test::ToString(p->program(), ast_body),
"!((vec2<f32>(50.0f, 60.0f) == vec2<f32>(60.0f, 50.0f)));")); HasSubstr(
"let x_1 : vec2<bool> = !((vec2<f32>(50.0f, 60.0f) == vec2<f32>(60.0f, 50.0f)));"));
} }
TEST_F(SpvFUnordTest, FUnordLessThan_Scalar) { TEST_F(SpvFUnordTest, FUnordLessThan_Scalar) {
@ -602,9 +604,10 @@ TEST_F(SpvFUnordTest, FUnordLessThan_Vector) {
auto fe = p->function_emitter(100); auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error(); EXPECT_TRUE(fe.EmitBody()) << p->error();
auto ast_body = fe.ast_body(); auto ast_body = fe.ast_body();
EXPECT_THAT(test::ToString(p->program(), ast_body), EXPECT_THAT(
HasSubstr("let x_1 : vec2<bool> = " test::ToString(p->program(), ast_body),
"!((vec2<f32>(50.0f, 60.0f) >= vec2<f32>(60.0f, 50.0f)));")); HasSubstr(
"let x_1 : vec2<bool> = !((vec2<f32>(50.0f, 60.0f) >= vec2<f32>(60.0f, 50.0f)));"));
} }
TEST_F(SpvFUnordTest, FUnordLessThanEqual_Scalar) { TEST_F(SpvFUnordTest, FUnordLessThanEqual_Scalar) {
@ -637,9 +640,10 @@ TEST_F(SpvFUnordTest, FUnordLessThanEqual_Vector) {
auto fe = p->function_emitter(100); auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error(); EXPECT_TRUE(fe.EmitBody()) << p->error();
auto ast_body = fe.ast_body(); auto ast_body = fe.ast_body();
EXPECT_THAT(test::ToString(p->program(), ast_body), EXPECT_THAT(
HasSubstr("let x_1 : vec2<bool> = " test::ToString(p->program(), ast_body),
"!((vec2<f32>(50.0f, 60.0f) > vec2<f32>(60.0f, 50.0f)));")); HasSubstr(
"let x_1 : vec2<bool> = !((vec2<f32>(50.0f, 60.0f) > vec2<f32>(60.0f, 50.0f)));"));
} }
TEST_F(SpvFUnordTest, FUnordGreaterThan_Scalar) { TEST_F(SpvFUnordTest, FUnordGreaterThan_Scalar) {
@ -672,9 +676,10 @@ TEST_F(SpvFUnordTest, FUnordGreaterThan_Vector) {
auto fe = p->function_emitter(100); auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error(); EXPECT_TRUE(fe.EmitBody()) << p->error();
auto ast_body = fe.ast_body(); auto ast_body = fe.ast_body();
EXPECT_THAT(test::ToString(p->program(), ast_body), EXPECT_THAT(
HasSubstr("let x_1 : vec2<bool> = " test::ToString(p->program(), ast_body),
"!((vec2<f32>(50.0f, 60.0f) <= vec2<f32>(60.0f, 50.0f)));")); HasSubstr(
"let x_1 : vec2<bool> = !((vec2<f32>(50.0f, 60.0f) <= vec2<f32>(60.0f, 50.0f)));"));
} }
TEST_F(SpvFUnordTest, FUnordGreaterThanEqual_Scalar) { TEST_F(SpvFUnordTest, FUnordGreaterThanEqual_Scalar) {
@ -707,10 +712,10 @@ TEST_F(SpvFUnordTest, FUnordGreaterThanEqual_Vector) {
auto fe = p->function_emitter(100); auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error(); EXPECT_TRUE(fe.EmitBody()) << p->error();
auto ast_body = fe.ast_body(); auto ast_body = fe.ast_body();
EXPECT_THAT(test::ToString(p->program(), ast_body), EXPECT_THAT(
HasSubstr("let x_1 : vec2<bool> = !((" test::ToString(p->program(), ast_body),
"vec2<f32>(50.0f, 60.0f) < vec2<f32>(60.0f, 50.0f)" HasSubstr(
"));")); "let x_1 : vec2<bool> = !((vec2<f32>(50.0f, 60.0f) < vec2<f32>(60.0f, 50.0f)));"));
} }
using SpvLogicalTest = SpvParserTestBase<::testing::Test>; using SpvLogicalTest = SpvParserTestBase<::testing::Test>;

View File

@ -15,7 +15,6 @@
#include "src/tint/reader/spirv/namer.h" #include "src/tint/reader/spirv/namer.h"
#include <algorithm> #include <algorithm>
#include <sstream>
#include <unordered_set> #include <unordered_set>
#include "src/tint/debug.h" #include "src/tint/debug.h"

View File

@ -1645,7 +1645,7 @@ INSTANTIATE_TEST_SUITE_P(
R"(@group(0) @binding(0) var x_10 : sampler_comparison; R"(@group(0) @binding(0) var x_10 : sampler_comparison;
@group(2) @binding(1) var x_20 : texture_depth_2d;)", @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 // OpImageDrefGather 2DDepth ConstOffset signed
ImageAccessCase{"%float 2D 1 0 0 1 Unknown", ImageAccessCase{"%float 2D 1 0 0 1 Unknown",
"%result = OpImageDrefGather " "%result = OpImageDrefGather "
@ -1653,7 +1653,7 @@ INSTANTIATE_TEST_SUITE_P(
R"(@group(0) @binding(0) var x_10 : sampler_comparison; R"(@group(0) @binding(0) var x_10 : sampler_comparison;
@group(2) @binding(1) var x_20 : texture_depth_2d;)", @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))"}, "vec2<i32>(3i, 4i))"},
// OpImageDrefGather 2DDepth ConstOffset unsigned // OpImageDrefGather 2DDepth ConstOffset unsigned
ImageAccessCase{"%float 2D 1 0 0 1 Unknown", ImageAccessCase{"%float 2D 1 0 0 1 Unknown",
@ -1663,7 +1663,7 @@ INSTANTIATE_TEST_SUITE_P(
R"(@group(0) @binding(0) var x_10 : sampler_comparison; R"(@group(0) @binding(0) var x_10 : sampler_comparison;
@group(2) @binding(1) var x_20 : texture_depth_2d;)", @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)))"}, "vec2<i32>(vec2<u32>(3u, 4u)))"},
// OpImageDrefGather 2DDepth Array // OpImageDrefGather 2DDepth Array
ImageAccessCase{"%float 2D 1 1 0 1 Unknown", ImageAccessCase{"%float 2D 1 1 0 1 Unknown",
@ -1673,7 +1673,7 @@ INSTANTIATE_TEST_SUITE_P(
@group(2) @binding(1) var x_20 : texture_depth_2d_array;)", @group(2) @binding(1) var x_20 : texture_depth_2d_array;)",
"textureGatherCompare(x_20, x_10, coords123.xy, " "textureGatherCompare(x_20, x_10, coords123.xy, "
"i32(round(coords123.z)), 0.200000003f)"}, "i32(round(coords123.z)), 0.20000000298023223877f)"},
// OpImageDrefGather 2DDepth Array ConstOffset signed // OpImageDrefGather 2DDepth Array ConstOffset signed
ImageAccessCase{"%float 2D 1 1 0 1 Unknown", ImageAccessCase{"%float 2D 1 1 0 1 Unknown",
"%result = OpImageDrefGather " "%result = OpImageDrefGather "
@ -1682,7 +1682,7 @@ INSTANTIATE_TEST_SUITE_P(
@group(2) @binding(1) var x_20 : texture_depth_2d_array;)", @group(2) @binding(1) var x_20 : texture_depth_2d_array;)",
"textureGatherCompare(x_20, x_10, coords123.xy, " "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 // OpImageDrefGather 2DDepth Array ConstOffset unsigned
ImageAccessCase{"%float 2D 1 1 0 1 Unknown", ImageAccessCase{"%float 2D 1 1 0 1 Unknown",
"%result = OpImageDrefGather " "%result = OpImageDrefGather "
@ -1692,7 +1692,7 @@ INSTANTIATE_TEST_SUITE_P(
@group(2) @binding(1) var x_20 : texture_depth_2d_array;)", @group(2) @binding(1) var x_20 : texture_depth_2d_array;)",
"textureGatherCompare(x_20, x_10, coords123.xy, " "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)))"}, "vec2<i32>(vec2<u32>(3u, 4u)))"},
// OpImageDrefGather DepthCube // OpImageDrefGather DepthCube
ImageAccessCase{"%float Cube 1 0 0 1 Unknown", ImageAccessCase{"%float Cube 1 0 0 1 Unknown",
@ -1701,7 +1701,7 @@ INSTANTIATE_TEST_SUITE_P(
R"(@group(0) @binding(0) var x_10 : sampler_comparison; R"(@group(0) @binding(0) var x_10 : sampler_comparison;
@group(2) @binding(1) var x_20 : texture_depth_cube;)", @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 // OpImageDrefGather DepthCube Array
ImageAccessCase{"%float Cube 1 1 0 1 Unknown", ImageAccessCase{"%float Cube 1 1 0 1 Unknown",
"%result = OpImageDrefGather " "%result = OpImageDrefGather "
@ -1710,7 +1710,7 @@ INSTANTIATE_TEST_SUITE_P(
@group(2) @binding(1) var x_20 : texture_depth_cube_array;)", @group(2) @binding(1) var x_20 : texture_depth_cube_array;)",
"textureGatherCompare(x_20, x_10, coords1234.xyz, " "textureGatherCompare(x_20, x_10, coords1234.xyz, "
"i32(round(coords1234.w)), 0.200000003f)"}})); "i32(round(coords1234.w)), 0.20000000298023223877f)"}}));
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
ImageSampleImplicitLod, ImageSampleImplicitLod,
@ -1829,7 +1829,7 @@ INSTANTIATE_TEST_SUITE_P(
)", )",
R"( R"(
let x_200 : vec4<f32> = vec4<f32>(textureSample(x_20, x_10, coords12), 0.0f, 0.0f, 0.0f); 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( INSTANTIATE_TEST_SUITE_P(
@ -1844,7 +1844,7 @@ INSTANTIATE_TEST_SUITE_P(
@group(2) @binding(1) var x_20 : texture_depth_2d; @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 // ImageSampleDrefImplicitLod - arrayed
ImageAccessCase{ ImageAccessCase{
"%float 2D 0 1 0 1 Unknown", "%float 2D 0 1 0 1 Unknown",
@ -1853,7 +1853,7 @@ INSTANTIATE_TEST_SUITE_P(
R"(@group(0) @binding(0) var x_10 : sampler_comparison; R"(@group(0) @binding(0) var x_10 : sampler_comparison;
@group(2) @binding(1) var x_20 : texture_depth_2d_array;)", @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 // ImageSampleDrefImplicitLod with ConstOffset
ImageAccessCase{ ImageAccessCase{
"%float 2D 0 0 0 1 Unknown", "%float 2D 0 0 0 1 Unknown",
@ -1863,7 +1863,7 @@ INSTANTIATE_TEST_SUITE_P(
@group(2) @binding(1) var x_20 : texture_depth_2d; @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 // ImageSampleDrefImplicitLod arrayed with ConstOffset
ImageAccessCase{ ImageAccessCase{
"%float 2D 0 1 0 1 Unknown", "%float 2D 0 1 0 1 Unknown",
@ -1872,7 +1872,7 @@ INSTANTIATE_TEST_SUITE_P(
R"(@group(0) @binding(0) var x_10 : sampler_comparison; R"(@group(0) @binding(0) var x_10 : sampler_comparison;
@group(2) @binding(1) var x_20 : texture_depth_2d_array;)", @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( INSTANTIATE_TEST_SUITE_P(
ImageSampleDrefExplicitLod, ImageSampleDrefExplicitLod,
@ -1881,14 +1881,15 @@ INSTANTIATE_TEST_SUITE_P(
// Another test checks cases where the Lod is not float constant 0. // Another test checks cases where the Lod is not float constant 0.
::testing::Values( ::testing::Values(
// 2D // 2D
ImageAccessCase{"%float 2D 1 0 0 1 Unknown", ImageAccessCase{
"%result = OpImageSampleDrefExplicitLod " "%float 2D 1 0 0 1 Unknown",
"%float %sampled_image %coords12 %depth Lod %float_0", "%result = OpImageSampleDrefExplicitLod "
R"(@group(0) @binding(0) var x_10 : sampler_comparison; "%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; @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 // 2D array
ImageAccessCase{ ImageAccessCase{
"%float 2D 1 1 0 1 Unknown", "%float 2D 1 1 0 1 Unknown",
@ -1897,7 +1898,7 @@ INSTANTIATE_TEST_SUITE_P(
R"(@group(0) @binding(0) var x_10 : sampler_comparison; R"(@group(0) @binding(0) var x_10 : sampler_comparison;
@group(2) @binding(1) var x_20 : texture_depth_2d_array;)", @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 // 2D, ConstOffset
ImageAccessCase{ ImageAccessCase{
"%float 2D 1 0 0 1 Unknown", "%float 2D 1 0 0 1 Unknown",
@ -1908,7 +1909,7 @@ INSTANTIATE_TEST_SUITE_P(
@group(2) @binding(1) var x_20 : texture_depth_2d; @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 // 2D array, ConstOffset
ImageAccessCase{ ImageAccessCase{
"%float 2D 1 1 0 1 Unknown", "%float 2D 1 1 0 1 Unknown",
@ -1918,15 +1919,16 @@ INSTANTIATE_TEST_SUITE_P(
R"(@group(0) @binding(0) var x_10 : sampler_comparison; R"(@group(0) @binding(0) var x_10 : sampler_comparison;
@group(2) @binding(1) var x_20 : texture_depth_2d_array;)", @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 // Cube
ImageAccessCase{"%float Cube 1 0 0 1 Unknown", ImageAccessCase{
"%result = OpImageSampleDrefExplicitLod " "%float Cube 1 0 0 1 Unknown",
"%float %sampled_image %coords123 %depth Lod %float_0", "%result = OpImageSampleDrefExplicitLod "
R"(@group(0) @binding(0) var x_10 : sampler_comparison; "%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;)", @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 // Cube array
ImageAccessCase{ ImageAccessCase{
"%float Cube 1 1 0 1 Unknown", "%float Cube 1 1 0 1 Unknown",
@ -1935,7 +1937,7 @@ INSTANTIATE_TEST_SUITE_P(
R"(@group(0) @binding(0) var x_10 : sampler_comparison; R"(@group(0) @binding(0) var x_10 : sampler_comparison;
@group(2) @binding(1) var x_20 : texture_depth_cube_array;)", @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( INSTANTIATE_TEST_SUITE_P(
ImageSampleExplicitLod_UsingLod, ImageSampleExplicitLod_UsingLod,
@ -2308,7 +2310,7 @@ INSTANTIATE_TEST_SUITE_P(
@group(2) @binding(1) var x_20 : texture_depth_2d; @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 // OpImageSampleProjDrefImplicitLod 2D depth-texture, Lod ConstOffset
ImageAccessCase{ ImageAccessCase{
@ -2320,7 +2322,7 @@ INSTANTIATE_TEST_SUITE_P(
@group(2) @binding(1) var x_20 : texture_depth_2d; @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 // End projection sampling

View File

@ -14,8 +14,6 @@
#include "src/tint/reader/spirv/usage.h" #include "src/tint/reader/spirv/usage.h"
#include <sstream>
#include "src/tint/utils/string_stream.h" #include "src/tint/utils/string_stream.h"
namespace tint::reader::spirv { namespace tint::reader::spirv {
@ -24,7 +22,7 @@ Usage::Usage() {}
Usage::Usage(const Usage& other) = default; Usage::Usage(const Usage& other) = default;
Usage::~Usage() = default; Usage::~Usage() = default;
std::ostream& Usage::operator<<(std::ostream& out) const { utils::StringStream& Usage::operator<<(utils::StringStream& out) const {
out << "Usage("; out << "Usage(";
if (IsSampler()) { if (IsSampler()) {
out << "Sampler("; out << "Sampler(";

View File

@ -17,6 +17,8 @@
#include <string> #include <string>
#include "src/tint/utils/string_stream.h"
namespace tint::reader::spirv { namespace tint::reader::spirv {
/// Records the properties of a sampler or texture based on how it's used /// Records the properties of a sampler or texture based on how it's used
@ -73,7 +75,7 @@ class Usage {
/// Emits this usage to the given stream /// Emits this usage to the given stream
/// @param out the output stream. /// @param out the output stream.
/// @returns the modified stream. /// @returns the modified stream.
std::ostream& operator<<(std::ostream& out) const; utils::StringStream& operator<<(utils::StringStream& out) const;
/// Equality operator /// Equality operator
/// @param other the RHS of the equality test. /// @param other the RHS of the equality test.
@ -122,11 +124,11 @@ class Usage {
bool is_storage_write_ = false; bool is_storage_write_ = false;
}; };
/// Writes the Usage to the ostream /// Writes the Usage to the stream
/// @param out the ostream /// @param out the stream
/// @param u the Usage /// @param u the Usage
/// @returns the ostream so calls can be chained /// @returns the stream so calls can be chained
inline std::ostream& operator<<(std::ostream& out, const Usage& u) { inline utils::StringStream& operator<<(utils::StringStream& out, const Usage& u) {
return u.operator<<(out); return u.operator<<(out);
} }

View File

@ -468,7 +468,7 @@ struct Case {
static bool ParsedAsTemplateArgumentList(BinaryOperatorInfo lhs_op, BinaryOperatorInfo rhs_op) { static bool ParsedAsTemplateArgumentList(BinaryOperatorInfo lhs_op, BinaryOperatorInfo rhs_op) {
return lhs_op.bit == kOpLt && rhs_op.bit & (kOpGt | kOpGe | kOpShr); 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 "; return o << "a " << c.lhs_op.symbol << " b " << c.rhs_op.symbol << " c ";
} }

View File

@ -353,7 +353,7 @@ class Token {
std::variant<int64_t, double, std::string, std::string_view> value_; 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); out << Token::TypeToName(type);
return out; return out;
} }

View File

@ -2070,7 +2070,7 @@ INSTANTIATE_TEST_SUITE_P(ResolverTest,
namespace texture_builtin_tests { namespace texture_builtin_tests {
enum class Texture { kF32, kI32, kU32 }; 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) { if (data == Texture::kF32) {
out << "f32"; out << "f32";
} else if (data == Texture::kI32) { } else if (data == Texture::kI32) {
@ -2087,7 +2087,9 @@ struct TextureTestParams {
builtin::TexelFormat format = builtin::TexelFormat::kR32Float; builtin::TexelFormat format = builtin::TexelFormat::kR32Float;
}; };
inline std::ostream& operator<<(std::ostream& out, TextureTestParams data) { 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; return out;
} }
@ -2110,7 +2112,11 @@ class ResolverBuiltinTest_TextureOperation : public ResolverTestWithParam<Textur
case type::TextureDimension::kCubeArray: case type::TextureDimension::kCubeArray:
return ty.vec3(scalar); return ty.vec3(scalar);
default: default:
[=]() { FAIL() << "Unsupported texture dimension: " << dim; }(); [=]() {
utils::StringStream str;
str << dim;
FAIL() << "Unsupported texture dimension: " << str.str();
}();
} }
return ast::Type{}; return ast::Type{};
} }
@ -2448,8 +2454,11 @@ TEST_P(ResolverBuiltinTest_Texture, Call) {
if (std::string(param.function) == "textureDimensions") { if (std::string(param.function) == "textureDimensions") {
switch (param.texture_dimension) { switch (param.texture_dimension) {
default: default: {
FAIL() << "invalid texture dimensions: " << param.texture_dimension; utils::StringStream str;
str << param.texture_dimension;
FAIL() << "invalid texture dimensions: " << str.str();
}
case type::TextureDimension::k1d: case type::TextureDimension::k1d:
EXPECT_TRUE(TypeOf(call)->Is<type::U32>()); EXPECT_TRUE(TypeOf(call)->Is<type::U32>());
break; break;

View File

@ -1607,7 +1607,7 @@ TEST_F(ResolverConstEvalTest, NonShortCircuit_And_Invalid_Materialize) {
"179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558" "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558"
"632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245" "632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245"
"490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168" "490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168"
"738177180919299881250404026184124858368.000000000 cannot be represented as 'f32'"); "738177180919299881250404026184124858368.0 cannot be represented as 'f32'");
} }
TEST_F(ResolverConstEvalTest, ShortCircuit_And_Error_Materialize) { TEST_F(ResolverConstEvalTest, ShortCircuit_And_Error_Materialize) {
@ -1658,7 +1658,7 @@ TEST_F(ResolverConstEvalTest, NonShortCircuit_Or_Invalid_Materialize) {
"179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558" "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558"
"632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245" "632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245"
"490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168" "490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168"
"738177180919299881250404026184124858368.000000000 cannot be represented as 'f32'"); "738177180919299881250404026184124858368.0 cannot be represented as 'f32'");
} }
TEST_F(ResolverConstEvalTest, ShortCircuit_Or_Error_Materialize) { TEST_F(ResolverConstEvalTest, ShortCircuit_Or_Error_Materialize) {

View File

@ -2025,10 +2025,10 @@ std::vector<Case> Pack2x16floatCases() {
C({Vec(f32(10), f32(-10.5))}, Val(u32(0xc940'4900))), C({Vec(f32(10), f32(-10.5))}, Val(u32(0xc940'4900))),
E({Vec(f32(0), f32::Highest())}, E({Vec(f32(0), f32::Highest())},
"12:34 error: value 340282346638528859811704183484516925440.000000000 cannot be " "12:34 error: value 340282346638528859811704183484516925440.0 cannot be "
"represented as 'f16'"), "represented as 'f16'"),
E({Vec(f32::Lowest(), f32(0))}, 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'"), "represented as 'f16'"),
}; };
} }
@ -2850,16 +2850,15 @@ std::vector<Case> QuantizeToF16Cases() {
Vec(0x0.034p-14_f, -0x0.034p-14_f, 0x0.068p-14_f, -0x0.068p-14_f)), Vec(0x0.034p-14_f, -0x0.034p-14_f, 0x0.068p-14_f, -0x0.068p-14_f)),
// Value out of f16 range // Value out of f16 range
E({65504.003_f}, "12:34 error: value 65504.003906250 cannot be represented as 'f16'"), E({65504.003_f}, "12:34 error: value 65504.00390625 cannot be represented as 'f16'"),
E({-65504.003_f}, "12:34 error: value -65504.003906250 cannot be represented as 'f16'"), E({-65504.003_f}, "12:34 error: value -65504.00390625 cannot be represented as 'f16'"),
E({0x1.234p56_f}, E({0x1.234p56_f}, "12:34 error: value 81979586966978560.0 cannot be represented as 'f16'"),
"12:34 error: value 81979586966978560.000000000 cannot be represented as 'f16'"),
E({0x4.321p65_f}, 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)}, 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)}, 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( // INSTANTIATE_TEST_SUITE_P( //

View File

@ -431,8 +431,7 @@ TEST_F(ResolverConstEvalTest, Vec3_Convert_Large_f32_to_f16) {
WrapInFunction(expr); WrapInFunction(expr);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(), "12:34 error: value 10000000000.0 cannot be represented as 'f16'");
"12:34 error: value 10000000000.000000000 cannot be represented as 'f16'");
} }
TEST_F(ResolverConstEvalTest, Vec3_Convert_Small_f32_to_f16) { TEST_F(ResolverConstEvalTest, Vec3_Convert_Small_f32_to_f16) {

View File

@ -363,7 +363,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Exp_F32_Overflow) {
auto result = const_eval.exp(a->Type(), utils::Vector{a}, {}); auto result = const_eval.exp(a->Type(), utils::Vector{a}, {});
ASSERT_TRUE(result); ASSERT_TRUE(result);
EXPECT_EQ(result.Get()->ValueAs<f32>(), 0.f); EXPECT_EQ(result.Get()->ValueAs<f32>(), 0.f);
EXPECT_EQ(error(), R"(warning: e^1000.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) { TEST_F(ResolverConstEvalRuntimeSemanticsTest, Exp2_F32_Overflow) {
@ -371,7 +371,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Exp2_F32_Overflow) {
auto result = const_eval.exp2(a->Type(), utils::Vector{a}, {}); auto result = const_eval.exp2(a->Type(), utils::Vector{a}, {});
ASSERT_TRUE(result); ASSERT_TRUE(result);
EXPECT_EQ(result.Get()->ValueAs<f32>(), 0.f); EXPECT_EQ(result.Get()->ValueAs<f32>(), 0.f);
EXPECT_EQ(error(), R"(warning: 2^1000.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) { TEST_F(ResolverConstEvalRuntimeSemanticsTest, ExtractBits_I32_TooManyBits) {
@ -476,7 +476,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Pack2x16Float_OutOfRange) {
auto result = const_eval.pack2x16float(create<type::U32>(), utils::Vector{vec}, {}); auto result = const_eval.pack2x16float(create<type::U32>(), utils::Vector{vec}, {});
ASSERT_TRUE(result); ASSERT_TRUE(result);
EXPECT_EQ(result.Get()->ValueAs<u32>(), 0x51430000); EXPECT_EQ(result.Get()->ValueAs<u32>(), 0x51430000);
EXPECT_EQ(error(), R"(warning: value 75250.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) { TEST_F(ResolverConstEvalRuntimeSemanticsTest, Pow_F32_Overflow) {
@ -502,7 +502,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, QuantizeToF16_OutOfRange) {
auto result = const_eval.quantizeToF16(create<type::U32>(), utils::Vector{a}, {}); auto result = const_eval.quantizeToF16(create<type::U32>(), utils::Vector{a}, {});
ASSERT_TRUE(result); ASSERT_TRUE(result);
EXPECT_EQ(result.Get()->ValueAs<u32>(), 0); EXPECT_EQ(result.Get()->ValueAs<u32>(), 0);
EXPECT_EQ(error(), R"(warning: value 75250.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) { TEST_F(ResolverConstEvalRuntimeSemanticsTest, Sqrt_F32_OutOfRange) {
@ -536,7 +536,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Convert_F32_TooHigh) {
EXPECT_EQ(result.Get()->ValueAs<f32>(), f32::kHighestValue); EXPECT_EQ(result.Get()->ValueAs<f32>(), f32::kHighestValue);
EXPECT_EQ( EXPECT_EQ(
error(), 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) { TEST_F(ResolverConstEvalRuntimeSemanticsTest, Convert_F32_TooLow) {
@ -546,7 +546,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Convert_F32_TooLow) {
EXPECT_EQ(result.Get()->ValueAs<f32>(), f32::kLowestValue); EXPECT_EQ(result.Get()->ValueAs<f32>(), f32::kLowestValue);
EXPECT_EQ( EXPECT_EQ(
error(), 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) { TEST_F(ResolverConstEvalRuntimeSemanticsTest, Convert_F16_TooHigh) {
@ -554,7 +554,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Convert_F16_TooHigh) {
auto result = const_eval.Convert(create<type::F16>(), a, {}); auto result = const_eval.Convert(create<type::F16>(), a, {});
ASSERT_TRUE(result); ASSERT_TRUE(result);
EXPECT_EQ(result.Get()->ValueAs<f32>(), f16::kHighestValue); EXPECT_EQ(result.Get()->ValueAs<f32>(), f16::kHighestValue);
EXPECT_EQ(error(), R"(warning: value 1000000.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) { TEST_F(ResolverConstEvalRuntimeSemanticsTest, Convert_F16_TooLow) {
@ -562,7 +562,7 @@ TEST_F(ResolverConstEvalRuntimeSemanticsTest, Convert_F16_TooLow) {
auto result = const_eval.Convert(create<type::F16>(), a, {}); auto result = const_eval.Convert(create<type::F16>(), a, {});
ASSERT_TRUE(result); ASSERT_TRUE(result);
EXPECT_EQ(result.Get()->ValueAs<f32>(), f16::kLowestValue); EXPECT_EQ(result.Get()->ValueAs<f32>(), f16::kLowestValue);
EXPECT_EQ(error(), R"(warning: value -1000000.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) { TEST_F(ResolverConstEvalRuntimeSemanticsTest, Vec_Overflow_SingleComponent) {

View File

@ -14092,8 +14092,8 @@ constexpr IntrinsicInfo kBuiltins[] = {
}, },
{ {
/* [2] */ /* [2] */
/* fn acosh<T : fa_f32_f16>(@test_value(2) T) -> T */ /* fn acosh<T : fa_f32_f16>(@test_value(1.5430806348) T) -> T */
/* fn acosh<N : num, T : fa_f32_f16>(@test_value(2) vec<N, T>) -> vec<N, T> */ /* fn acosh<N : num, T : fa_f32_f16>(@test_value(1.5430806348) vec<N, T>) -> vec<N, T> */
/* num overloads */ 2, /* num overloads */ 2,
/* overloads */ &kOverloads[287], /* overloads */ &kOverloads[287],
}, },
@ -14526,8 +14526,8 @@ constexpr IntrinsicInfo kBuiltins[] = {
}, },
{ {
/* [66] */ /* [66] */
/* fn round<T : fa_f32_f16>(@test_value(3.4) T) -> T */ /* fn round<T : fa_f32_f16>(@test_value(3.5) T) -> T */
/* fn round<N : num, T : fa_f32_f16>(@test_value(3.4) vec<N, T>) -> vec<N, T> */ /* fn round<N : num, T : fa_f32_f16>(@test_value(3.5) vec<N, T>) -> vec<N, T> */
/* num overloads */ 2, /* num overloads */ 2,
/* overloads */ &kOverloads[383], /* overloads */ &kOverloads[383],
}, },

View File

@ -15,7 +15,6 @@
#include "src/tint/resolver/uniformity.h" #include "src/tint/resolver/uniformity.h"
#include <limits> #include <limits>
#include <sstream>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>

View File

@ -13,7 +13,6 @@
// limitations under the License. // limitations under the License.
#include <memory> #include <memory>
#include <sstream>
#include <string> #include <string>
#include <tuple> #include <tuple>
#include <utility> #include <utility>

View File

@ -16,7 +16,7 @@
namespace tint::sem { namespace tint::sem {
std::ostream& operator<<(std::ostream& out, Behavior behavior) { utils::StringStream& operator<<(utils::StringStream& out, Behavior behavior) {
switch (behavior) { switch (behavior) {
case Behavior::kReturn: case Behavior::kReturn:
return out << "Return"; return out << "Return";

View File

@ -31,11 +31,11 @@ enum class Behavior {
/// Behaviors is a set of Behavior /// Behaviors is a set of Behavior
using Behaviors = utils::EnumSet<Behavior>; using Behaviors = utils::EnumSet<Behavior>;
/// Writes the Behavior to the std::ostream. /// Writes the Behavior to the stream.
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param behavior the Behavior to write /// @param behavior the Behavior to write
/// @returns out so calls can be chained /// @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 } // namespace tint::sem

View File

@ -18,10 +18,10 @@
#include <stdint.h> #include <stdint.h>
#include <functional> #include <functional>
#include <ostream>
#include "src/tint/reflection.h" #include "src/tint/reflection.h"
#include "src/tint/utils/hash.h" #include "src/tint/utils/hash.h"
#include "src/tint/utils/string_stream.h"
namespace tint::sem { namespace tint::sem {
@ -49,10 +49,10 @@ struct BindingPoint {
}; };
/// Prints the BindingPoint @p bp to @p o /// 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 /// @param bp the BindingPoint
/// @return the std::ostream so calls can be chained /// @return the stream so calls can be chained
inline std::ostream& operator<<(std::ostream& o, const BindingPoint& bp) { inline utils::StringStream& operator<<(utils::StringStream& o, const BindingPoint& bp) {
return o << "[group: " << bp.group << ", binding: " << bp.binding << "]"; return o << "[group: " << bp.group << ", binding: " << bp.binding << "]";
} }

View File

@ -22,8 +22,6 @@
#include "src/tint/sem/builtin_type.h" #include "src/tint/sem/builtin_type.h"
#include <sstream>
namespace tint::sem { namespace tint::sem {
BuiltinType ParseBuiltinType(const std::string& name) { BuiltinType ParseBuiltinType(const std::string& name) {
@ -608,7 +606,7 @@ const char* str(BuiltinType i) {
return "<unknown>"; return "<unknown>";
} }
std::ostream& operator<<(std::ostream& out, BuiltinType i) { utils::StringStream& operator<<(utils::StringStream& out, BuiltinType i) {
out << str(i); out << str(i);
return out; return out;
} }

View File

@ -13,8 +13,6 @@ See:
#include "src/tint/sem/builtin_type.h" #include "src/tint/sem/builtin_type.h"
#include <sstream>
namespace tint::sem { namespace tint::sem {
BuiltinType ParseBuiltinType(const std::string& name) { BuiltinType ParseBuiltinType(const std::string& name) {
@ -38,7 +36,7 @@ const char* str(BuiltinType i) {
return "<unknown>"; return "<unknown>";
} }
std::ostream& operator<<(std::ostream& out, BuiltinType i) { utils::StringStream& operator<<(utils::StringStream& out, BuiltinType i) {
out << str(i); out << str(i);
return out; return out;
} }

View File

@ -23,9 +23,10 @@
#ifndef SRC_TINT_SEM_BUILTIN_TYPE_H_ #ifndef SRC_TINT_SEM_BUILTIN_TYPE_H_
#define SRC_TINT_SEM_BUILTIN_TYPE_H_ #define SRC_TINT_SEM_BUILTIN_TYPE_H_
#include <sstream>
#include <string> #include <string>
#include "src/tint/utils/string_stream.h"
namespace tint::sem { namespace tint::sem {
/// Enumerator of all builtin functions /// Enumerator of all builtin functions
@ -159,7 +160,7 @@ const char* str(BuiltinType i);
/// Emits the name of the builtin function type. The spelling, including case, /// Emits the name of the builtin function type. The spelling, including case,
/// matches the name in the WGSL spec. /// 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 /// All builtin function
constexpr BuiltinType kBuiltinTypes[] = { constexpr BuiltinType kBuiltinTypes[] = {

View File

@ -14,9 +14,10 @@ See:
#ifndef SRC_TINT_SEM_BUILTIN_TYPE_H_ #ifndef SRC_TINT_SEM_BUILTIN_TYPE_H_
#define SRC_TINT_SEM_BUILTIN_TYPE_H_ #define SRC_TINT_SEM_BUILTIN_TYPE_H_
#include <sstream>
#include <string> #include <string>
#include "src/tint/utils/string_stream.h"
namespace tint::sem { namespace tint::sem {
/// Enumerator of all builtin functions /// Enumerator of all builtin functions
@ -39,7 +40,7 @@ const char* str(BuiltinType i);
/// Emits the name of the builtin function type. The spelling, including case, /// Emits the name of the builtin function type. The spelling, including case,
/// matches the name in the WGSL spec. /// 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 /// All builtin function
constexpr BuiltinType kBuiltinTypes[] = { constexpr BuiltinType kBuiltinTypes[] = {

View File

@ -17,9 +17,9 @@
#include <cstdint> #include <cstdint>
#include <functional> #include <functional>
#include <ostream>
#include "src/tint/sem/binding_point.h" #include "src/tint/sem/binding_point.h"
#include "src/tint/utils/string_stream.h"
namespace tint::sem { namespace tint::sem {
@ -45,10 +45,10 @@ struct SamplerTexturePair {
}; };
/// Prints the SamplerTexturePair @p stp to @p o /// 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 /// @param stp the SamplerTexturePair
/// @return the std::ostream so calls can be chained /// @return the stream so calls can be chained
inline std::ostream& operator<<(std::ostream& o, const SamplerTexturePair& stp) { inline utils::StringStream& operator<<(utils::StringStream& o, const SamplerTexturePair& stp) {
return o << "[sampler: " << stp.sampler_binding_point return o << "[sampler: " << stp.sampler_binding_point
<< ", texture: " << stp.sampler_binding_point << "]"; << ", texture: " << stp.sampler_binding_point << "]";
} }

View File

@ -15,7 +15,6 @@
#include "src/tint/source.h" #include "src/tint/source.h"
#include <algorithm> #include <algorithm>
#include <sstream>
#include <string_view> #include <string_view>
#include <utility> #include <utility>
@ -122,7 +121,7 @@ Source::FileContent::~FileContent() = default;
Source::File::~File() = default; 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; auto rng = source.range;
if (source.file) { if (source.file) {

View File

@ -16,12 +16,13 @@
#ifndef SRC_TINT_SOURCE_H_ #ifndef SRC_TINT_SOURCE_H_
#define SRC_TINT_SOURCE_H_ #define SRC_TINT_SOURCE_H_
#include <iostream>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <tuple> #include <tuple>
#include <vector> #include <vector>
#include "src/tint/utils/string_stream.h"
namespace tint { namespace tint {
/// Source describes a range of characters within a source file. /// Source describes a range of characters within a source file.
@ -191,35 +192,36 @@ class Source {
const File* file = nullptr; const File* file = nullptr;
}; };
/// Writes the Source::Location to the std::ostream. /// Writes the Source::Location to the stream.
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param loc the location to write /// @param loc the location to write
/// @returns out so calls can be chained /// @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; out << loc.line << ":" << loc.column;
return out; return out;
} }
/// Writes the Source::Range to the std::ostream. /// Writes the Source::Range to the stream.
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param range the range to write /// @param range the range to write
/// @returns out so calls can be chained /// @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 << "]"; out << "[" << range.begin << ", " << range.end << "]";
return out; return out;
} }
/// Writes the Source to the std::ostream. /// Writes the Source to the stream.
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param source the source to write /// @param source the source to write
/// @returns out so calls can be chained /// @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. /// Writes the Source::FileContent to the stream.
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param content the file content to write /// @param content the file content to write
/// @returns out so calls can be chained /// @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; out << content.data;
return out; return out;
} }

View File

@ -47,10 +47,10 @@ enum class {{$enum}} {
{{- end }} {{- end }}
}; };
/// @param out the std::ostream to write to /// @param out the stream to write to
/// @param value the {{$enum}} /// @param value the {{$enum}}
/// @returns `out` so calls can be chained /// @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. /// Parse{{$enum}} parses a {{$enum}} from a string.
/// @param str the string to parse /// @param str the string to parse
@ -90,11 +90,11 @@ constexpr const char* k{{$enum}}Strings[] = {
{{- /* ------------------------------------------------------------------ */ -}} {{- /* ------------------------------------------------------------------ */ -}}
{{- define "EnumOStream" -}} {{- define "EnumOStream" -}}
{{- /* Implements the std::ostream 'operator<<()' function to print the */ -}} {{- /* Implements the stream 'operator<<()' function to print the */ -}}
{{- /* provided sem.Enum. */ -}} {{- /* provided sem.Enum. */ -}}
{{- /* ------------------------------------------------------------------ */ -}} {{- /* ------------------------------------------------------------------ */ -}}
{{- $enum := Eval "EnumName" $ -}} {{- $enum := Eval "EnumName" $ -}}
std::ostream& operator<<(std::ostream& out, {{$enum}} value) { utils::StringStream& operator<<(utils::StringStream& out, {{$enum}} value) {
switch (value) { switch (value) {
case {{$enum}}::kUndefined: case {{$enum}}::kUndefined:
return out << "undefined"; return out << "undefined";

Some files were not shown because too many files have changed in this diff Show More