Convert MSL generator over to utils::StringStream.

This CL converts the MSL generator to use utils::StringStream
internally.

Bug: tint:1686
Change-Id: I4225ebb87fd5281a3527bf2a9067651b60b114a8
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/121920
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
dan sinclair 2023-02-28 14:54:51 +00:00 committed by Dawn LUCI CQ
parent 2b9d5b338a
commit 52fa68b1a7
15 changed files with 178 additions and 149 deletions

View File

@ -31,6 +31,13 @@ class StringStream {
/// Destructor /// Destructor
~StringStream(); ~StringStream();
/// @returns the format flags for the stream
std::ios_base::fmtflags flags() const { return sstream_.flags(); }
/// @param flags the flags to set
/// @returns the original format flags
std::ios_base::fmtflags flags(std::ios_base::fmtflags flags) { return sstream_.flags(flags); }
/// Emit `value` to the stream /// Emit `value` to the stream
/// @param value the value to emit /// @param value the value to emit
/// @returns a reference to this /// @returns a reference to this

View File

@ -78,6 +78,7 @@
#include "src/tint/utils/defer.h" #include "src/tint/utils/defer.h"
#include "src/tint/utils/map.h" #include "src/tint/utils/map.h"
#include "src/tint/utils/scoped_assignment.h" #include "src/tint/utils/scoped_assignment.h"
#include "src/tint/utils/string_stream.h"
#include "src/tint/writer/check_supported_extensions.h" #include "src/tint/writer/check_supported_extensions.h"
#include "src/tint/writer/float_to_string.h" #include "src/tint/writer/float_to_string.h"
#include "src/tint/writer/generate_external_texture_bindings.h" #include "src/tint/writer/generate_external_texture_bindings.h"
@ -89,7 +90,7 @@ bool last_is_break(const ast::BlockStatement* stmts) {
return IsAnyOf<ast::BreakStatement>(stmts->Last()); return IsAnyOf<ast::BreakStatement>(stmts->Last());
} }
void PrintF32(std::ostream& out, float value) { void PrintF32(utils::StringStream& out, float value) {
// Note: Currently inf and nan should not be constructable, but this is implemented for the day // Note: Currently inf and nan should not be constructable, but this is implemented for the day
// we support them. // we support them.
if (std::isinf(value)) { if (std::isinf(value)) {
@ -101,7 +102,7 @@ void PrintF32(std::ostream& out, float value) {
} }
} }
void PrintF16(std::ostream& out, float value) { void PrintF16(utils::StringStream& out, float value) {
// Note: Currently inf and nan should not be constructable, but this is implemented for the day // Note: Currently inf and nan should not be constructable, but this is implemented for the day
// we support them. // we support them.
if (std::isinf(value)) { if (std::isinf(value)) {
@ -115,7 +116,7 @@ void PrintF16(std::ostream& out, float value) {
} }
} }
void PrintI32(std::ostream& out, int32_t value) { void PrintI32(utils::StringStream& out, int32_t value) {
// MSL (and C++) parse `-2147483648` as a `long` because it parses unary minus and `2147483648` // MSL (and C++) parse `-2147483648` as a `long` because it parses unary minus and `2147483648`
// as separate tokens, and the latter doesn't fit into an (32-bit) `int`. // as separate tokens, and the latter doesn't fit into an (32-bit) `int`.
// WGSL, on the other hand, parses this as an `i32`. // WGSL, on the other hand, parses this as an `i32`.
@ -131,7 +132,7 @@ void PrintI32(std::ostream& out, int32_t value) {
class ScopedBitCast { class ScopedBitCast {
public: public:
ScopedBitCast(GeneratorImpl* generator, ScopedBitCast(GeneratorImpl* generator,
std::ostream& stream, utils::StringStream& stream,
const type::Type* curr_type, const type::Type* curr_type,
const type::Type* target_type) const type::Type* target_type)
: s(stream) { : s(stream) {
@ -152,7 +153,7 @@ class ScopedBitCast {
~ScopedBitCast() { s << ")"; } ~ScopedBitCast() { s << ")"; }
private: private:
std::ostream& s; utils::StringStream& s;
}; };
} // namespace } // namespace
@ -369,7 +370,8 @@ bool GeneratorImpl::EmitTypeDecl(const type::Type* ty) {
return true; return true;
} }
bool GeneratorImpl::EmitIndexAccessor(std::ostream& out, const ast::IndexAccessorExpression* expr) { bool GeneratorImpl::EmitIndexAccessor(utils::StringStream& out,
const ast::IndexAccessorExpression* expr) {
bool paren_lhs = bool paren_lhs =
!expr->object !expr->object
->IsAnyOf<ast::AccessorExpression, ast::CallExpression, ast::IdentifierExpression>(); ->IsAnyOf<ast::AccessorExpression, ast::CallExpression, ast::IdentifierExpression>();
@ -394,7 +396,7 @@ bool GeneratorImpl::EmitIndexAccessor(std::ostream& out, const ast::IndexAccesso
return true; return true;
} }
bool GeneratorImpl::EmitBitcast(std::ostream& out, const ast::BitcastExpression* expr) { bool GeneratorImpl::EmitBitcast(utils::StringStream& out, const ast::BitcastExpression* expr) {
out << "as_type<"; out << "as_type<";
if (!EmitType(out, TypeOf(expr)->UnwrapRef(), "")) { if (!EmitType(out, TypeOf(expr)->UnwrapRef(), "")) {
return false; return false;
@ -427,7 +429,7 @@ bool GeneratorImpl::EmitAssign(const ast::AssignmentStatement* stmt) {
return true; return true;
} }
bool GeneratorImpl::EmitBinary(std::ostream& out, const ast::BinaryExpression* expr) { bool GeneratorImpl::EmitBinary(utils::StringStream& out, const ast::BinaryExpression* expr) {
auto emit_op = [&] { auto emit_op = [&] {
out << " "; out << " ";
@ -523,7 +525,7 @@ bool GeneratorImpl::EmitBinary(std::ostream& out, const ast::BinaryExpression* e
// Handle fmod // Handle fmod
if (expr->op == ast::BinaryOp::kModulo && lhs_type->is_float_scalar_or_vector()) { if (expr->op == ast::BinaryOp::kModulo && lhs_type->is_float_scalar_or_vector()) {
out << "fmod"; out << "fmod";
ScopedParen sp(out); ScopedParen sp(out.stream());
if (!EmitExpression(out, expr->lhs)) { if (!EmitExpression(out, expr->lhs)) {
return false; return false;
} }
@ -547,7 +549,7 @@ bool GeneratorImpl::EmitBinary(std::ostream& out, const ast::BinaryExpression* e
// WGSL defines behaviour for signed overflow, MSL does not. For these // WGSL defines behaviour for signed overflow, MSL does not. For these
// cases, bitcast operands to unsigned, then cast result to signed. // cases, bitcast operands to unsigned, then cast result to signed.
ScopedBitCast outer_int_cast(this, out, target_type, signed_type_of(target_type)); ScopedBitCast outer_int_cast(this, out, target_type, signed_type_of(target_type));
ScopedParen sp(out); ScopedParen sp(out.stream());
{ {
ScopedBitCast lhs_uint_cast(this, out, lhs_type, unsigned_type_of(target_type)); ScopedBitCast lhs_uint_cast(this, out, lhs_type, unsigned_type_of(target_type));
if (!EmitExpression(out, expr->lhs)) { if (!EmitExpression(out, expr->lhs)) {
@ -574,7 +576,7 @@ bool GeneratorImpl::EmitBinary(std::ostream& out, const ast::BinaryExpression* e
// Shift left: discards top bits, so convert first operand to unsigned // Shift left: discards top bits, so convert first operand to unsigned
// first, then convert result back to signed // first, then convert result back to signed
ScopedBitCast outer_int_cast(this, out, lhs_type, signed_type_of(lhs_type)); ScopedBitCast outer_int_cast(this, out, lhs_type, signed_type_of(lhs_type));
ScopedParen sp(out); ScopedParen sp(out.stream());
{ {
ScopedBitCast lhs_uint_cast(this, out, lhs_type, unsigned_type_of(lhs_type)); ScopedBitCast lhs_uint_cast(this, out, lhs_type, unsigned_type_of(lhs_type));
if (!EmitExpression(out, expr->lhs)) { if (!EmitExpression(out, expr->lhs)) {
@ -593,7 +595,7 @@ bool GeneratorImpl::EmitBinary(std::ostream& out, const ast::BinaryExpression* e
// Handle '&' and '|' of booleans. // Handle '&' and '|' of booleans.
if ((expr->IsAnd() || expr->IsOr()) && lhs_type->Is<type::Bool>()) { if ((expr->IsAnd() || expr->IsOr()) && lhs_type->Is<type::Bool>()) {
out << "bool"; out << "bool";
ScopedParen sp(out); ScopedParen sp(out.stream());
if (!EmitExpression(out, expr->lhs)) { if (!EmitExpression(out, expr->lhs)) {
return false; return false;
} }
@ -607,7 +609,7 @@ bool GeneratorImpl::EmitBinary(std::ostream& out, const ast::BinaryExpression* e
} }
// Emit as usual // Emit as usual
ScopedParen sp(out); ScopedParen sp(out.stream());
if (!EmitExpression(out, expr->lhs)) { if (!EmitExpression(out, expr->lhs)) {
return false; return false;
} }
@ -636,7 +638,7 @@ bool GeneratorImpl::EmitBreakIf(const ast::BreakIfStatement* b) {
return true; return true;
} }
bool GeneratorImpl::EmitCall(std::ostream& out, const ast::CallExpression* expr) { bool GeneratorImpl::EmitCall(utils::StringStream& out, const ast::CallExpression* expr) {
auto* call = program_->Sem().Get<sem::Call>(expr); auto* call = program_->Sem().Get<sem::Call>(expr);
auto* target = call->Target(); auto* target = call->Target();
return Switch( return Switch(
@ -650,7 +652,7 @@ bool GeneratorImpl::EmitCall(std::ostream& out, const ast::CallExpression* expr)
}); });
} }
bool GeneratorImpl::EmitFunctionCall(std::ostream& out, bool GeneratorImpl::EmitFunctionCall(utils::StringStream& out,
const sem::Call* call, const sem::Call* call,
const sem::Function* fn) { const sem::Function* fn) {
out << program_->Symbols().NameFor(fn->Declaration()->name->symbol) << "("; out << program_->Symbols().NameFor(fn->Declaration()->name->symbol) << "(";
@ -671,7 +673,7 @@ bool GeneratorImpl::EmitFunctionCall(std::ostream& out,
return true; return true;
} }
bool GeneratorImpl::EmitBuiltinCall(std::ostream& out, bool GeneratorImpl::EmitBuiltinCall(utils::StringStream& out,
const sem::Call* call, const sem::Call* call,
const sem::Builtin* builtin) { const sem::Builtin* builtin) {
auto* expr = call->Declaration(); auto* expr = call->Declaration();
@ -746,7 +748,7 @@ bool GeneratorImpl::EmitBuiltinCall(std::ostream& out,
if (sem->Type()->UnwrapRef()->is_scalar()) { if (sem->Type()->UnwrapRef()->is_scalar()) {
// Emulate scalar overload using fabs(x - y); // Emulate scalar overload using fabs(x - y);
out << "fabs"; out << "fabs";
ScopedParen sp(out); ScopedParen sp(out.stream());
if (!EmitExpression(out, expr->args[0])) { if (!EmitExpression(out, expr->args[0])) {
return false; return false;
} }
@ -785,7 +787,7 @@ bool GeneratorImpl::EmitBuiltinCall(std::ostream& out,
return true; return true;
} }
bool GeneratorImpl::EmitTypeConversion(std::ostream& out, bool GeneratorImpl::EmitTypeConversion(utils::StringStream& out,
const sem::Call* call, const sem::Call* call,
const sem::ValueConversion* conv) { const sem::ValueConversion* conv) {
if (!EmitType(out, conv->Target(), "")) { if (!EmitType(out, conv->Target(), "")) {
@ -801,7 +803,7 @@ bool GeneratorImpl::EmitTypeConversion(std::ostream& out,
return true; return true;
} }
bool GeneratorImpl::EmitTypeInitializer(std::ostream& out, bool GeneratorImpl::EmitTypeInitializer(utils::StringStream& out,
const sem::Call* call, const sem::Call* call,
const sem::ValueConstructor* ctor) { const sem::ValueConstructor* ctor) {
auto* type = ctor->ReturnType(); auto* type = ctor->ReturnType();
@ -858,13 +860,13 @@ bool GeneratorImpl::EmitTypeInitializer(std::ostream& out,
return true; return true;
} }
bool GeneratorImpl::EmitAtomicCall(std::ostream& out, bool GeneratorImpl::EmitAtomicCall(utils::StringStream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Builtin* builtin) { const sem::Builtin* builtin) {
auto call = [&](const std::string& name, bool append_memory_order_relaxed) { auto call = [&](const std::string& name, bool append_memory_order_relaxed) {
out << name; out << name;
{ {
ScopedParen sp(out); ScopedParen sp(out.stream());
for (size_t i = 0; i < expr->args.Length(); i++) { for (size_t i = 0; i < expr->args.Length(); i++) {
auto* arg = expr->args[i]; auto* arg = expr->args[i];
if (i > 0) { if (i > 0) {
@ -982,7 +984,7 @@ bool GeneratorImpl::EmitAtomicCall(std::ostream& out,
return false; return false;
} }
bool GeneratorImpl::EmitTextureCall(std::ostream& out, bool GeneratorImpl::EmitTextureCall(utils::StringStream& out,
const sem::Call* call, const sem::Call* call,
const sem::Builtin* builtin) { const sem::Builtin* builtin) {
using Usage = sem::ParameterUsage; using Usage = sem::ParameterUsage;
@ -1231,7 +1233,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
out << "gradientcube("; out << "gradientcube(";
break; break;
default: { default: {
std::stringstream err; utils::StringStream err;
err << "MSL does not support gradients for " << dim << " textures"; err << "MSL does not support gradients for " << dim << " textures";
diagnostics_.add_error(diag::System::Writer, err.str()); diagnostics_.add_error(diag::System::Writer, err.str());
return false; return false;
@ -1294,7 +1296,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& out,
return true; return true;
} }
bool GeneratorImpl::EmitDotCall(std::ostream& out, bool GeneratorImpl::EmitDotCall(utils::StringStream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Builtin* builtin) { const sem::Builtin* builtin) {
auto* vec_ty = builtin->Parameters()[0]->Type()->As<type::Vector>(); auto* vec_ty = builtin->Parameters()[0]->Type()->As<type::Vector>();
@ -1339,7 +1341,7 @@ bool GeneratorImpl::EmitDotCall(std::ostream& out,
return true; return true;
} }
bool GeneratorImpl::EmitModfCall(std::ostream& out, bool GeneratorImpl::EmitModfCall(utils::StringStream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Builtin* builtin) { const sem::Builtin* builtin) {
return CallBuiltinHelper( return CallBuiltinHelper(
@ -1365,7 +1367,7 @@ bool GeneratorImpl::EmitModfCall(std::ostream& out,
}); });
} }
bool GeneratorImpl::EmitFrexpCall(std::ostream& out, bool GeneratorImpl::EmitFrexpCall(utils::StringStream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Builtin* builtin) { const sem::Builtin* builtin) {
return CallBuiltinHelper( return CallBuiltinHelper(
@ -1391,7 +1393,7 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
}); });
} }
bool GeneratorImpl::EmitDegreesCall(std::ostream& out, bool GeneratorImpl::EmitDegreesCall(utils::StringStream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Builtin* builtin) { const sem::Builtin* builtin) {
return CallBuiltinHelper(out, expr, builtin, return CallBuiltinHelper(out, expr, builtin,
@ -1402,7 +1404,7 @@ bool GeneratorImpl::EmitDegreesCall(std::ostream& out,
}); });
} }
bool GeneratorImpl::EmitRadiansCall(std::ostream& out, bool GeneratorImpl::EmitRadiansCall(utils::StringStream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Builtin* builtin) { const sem::Builtin* builtin) {
return CallBuiltinHelper(out, expr, builtin, return CallBuiltinHelper(out, expr, builtin,
@ -1614,7 +1616,7 @@ bool GeneratorImpl::EmitContinue(const ast::ContinueStatement*) {
return true; return true;
} }
bool GeneratorImpl::EmitZeroValue(std::ostream& out, const type::Type* type) { bool GeneratorImpl::EmitZeroValue(utils::StringStream& out, const type::Type* type) {
return Switch( return Switch(
type, type,
[&](const type::Bool*) { [&](const type::Bool*) {
@ -1644,7 +1646,7 @@ bool GeneratorImpl::EmitZeroValue(std::ostream& out, const type::Type* type) {
if (!EmitType(out, mat, "")) { if (!EmitType(out, mat, "")) {
return false; return false;
} }
ScopedParen sp(out); ScopedParen sp(out.stream());
return EmitZeroValue(out, mat->type()); return EmitZeroValue(out, mat->type());
}, },
[&](const type::Array*) { [&](const type::Array*) {
@ -1663,7 +1665,7 @@ bool GeneratorImpl::EmitZeroValue(std::ostream& out, const type::Type* type) {
}); });
} }
bool GeneratorImpl::EmitConstant(std::ostream& out, const constant::Value* constant) { bool GeneratorImpl::EmitConstant(utils::StringStream& out, const constant::Value* constant) {
return Switch( return Switch(
constant->Type(), // constant->Type(), //
[&](const type::Bool*) { [&](const type::Bool*) {
@ -1691,7 +1693,7 @@ bool GeneratorImpl::EmitConstant(std::ostream& out, const constant::Value* const
return false; return false;
} }
ScopedParen sp(out); ScopedParen sp(out.stream());
if (constant->AllEqual()) { if (constant->AllEqual()) {
if (!EmitConstant(out, constant->Index(0))) { if (!EmitConstant(out, constant->Index(0))) {
@ -1715,7 +1717,7 @@ bool GeneratorImpl::EmitConstant(std::ostream& out, const constant::Value* const
return false; return false;
} }
ScopedParen sp(out); ScopedParen sp(out.stream());
for (size_t i = 0; i < m->columns(); i++) { for (size_t i = 0; i < m->columns(); i++) {
if (i > 0) { if (i > 0) {
@ -1790,7 +1792,7 @@ bool GeneratorImpl::EmitConstant(std::ostream& out, const constant::Value* const
}); });
} }
bool GeneratorImpl::EmitLiteral(std::ostream& out, const ast::LiteralExpression* lit) { bool GeneratorImpl::EmitLiteral(utils::StringStream& out, const ast::LiteralExpression* lit) {
return Switch( return Switch(
lit, lit,
[&](const ast::BoolLiteralExpression* l) { [&](const ast::BoolLiteralExpression* l) {
@ -1826,7 +1828,7 @@ bool GeneratorImpl::EmitLiteral(std::ostream& out, const ast::LiteralExpression*
}); });
} }
bool GeneratorImpl::EmitExpression(std::ostream& out, const ast::Expression* expr) { bool GeneratorImpl::EmitExpression(utils::StringStream& out, const ast::Expression* expr) {
if (auto* sem = builder_.Sem().GetVal(expr)) { if (auto* sem = builder_.Sem().GetVal(expr)) {
if (auto* constant = sem->ConstantValue()) { if (auto* constant = sem->ConstantValue()) {
return EmitConstant(out, constant); return EmitConstant(out, constant);
@ -1849,7 +1851,7 @@ bool GeneratorImpl::EmitExpression(std::ostream& out, const ast::Expression* exp
}); });
} }
void GeneratorImpl::EmitStage(std::ostream& out, ast::PipelineStage stage) { void GeneratorImpl::EmitStage(utils::StringStream& out, ast::PipelineStage stage) {
switch (stage) { switch (stage) {
case ast::PipelineStage::kFragment: case ast::PipelineStage::kFragment:
out << "fragment"; out << "fragment";
@ -2126,7 +2128,8 @@ bool GeneratorImpl::EmitEntryPointFunction(const ast::Function* func) {
return true; return true;
} }
bool GeneratorImpl::EmitIdentifier(std::ostream& out, const ast::IdentifierExpression* expr) { bool GeneratorImpl::EmitIdentifier(utils::StringStream& out,
const ast::IdentifierExpression* expr) {
out << program_->Symbols().NameFor(expr->identifier->symbol); out << program_->Symbols().NameFor(expr->identifier->symbol);
return true; return true;
} }
@ -2167,7 +2170,7 @@ bool GeneratorImpl::EmitForLoop(const ast::ForLoopStatement* stmt) {
} }
TextBuffer cond_pre; TextBuffer cond_pre;
std::stringstream cond_buf; utils::StringStream cond_buf;
if (auto* cond = stmt->condition) { if (auto* cond = stmt->condition) {
TINT_SCOPED_ASSIGNMENT(current_buffer_, &cond_pre); TINT_SCOPED_ASSIGNMENT(current_buffer_, &cond_pre);
if (!EmitExpression(cond_buf, cond)) { if (!EmitExpression(cond_buf, cond)) {
@ -2268,7 +2271,7 @@ bool GeneratorImpl::EmitForLoop(const ast::ForLoopStatement* stmt) {
bool GeneratorImpl::EmitWhile(const ast::WhileStatement* stmt) { bool GeneratorImpl::EmitWhile(const ast::WhileStatement* stmt) {
TextBuffer cond_pre; TextBuffer cond_pre;
std::stringstream cond_buf; utils::StringStream cond_buf;
{ {
auto* cond = stmt->condition; auto* cond = stmt->condition;
@ -2354,7 +2357,7 @@ bool GeneratorImpl::EmitIf(const ast::IfStatement* stmt) {
return true; return true;
} }
bool GeneratorImpl::EmitMemberAccessor(std::ostream& out, bool GeneratorImpl::EmitMemberAccessor(utils::StringStream& out,
const ast::MemberAccessorExpression* expr) { const ast::MemberAccessorExpression* expr) {
auto write_lhs = [&] { auto write_lhs = [&] {
bool paren_lhs = !expr->object->IsAnyOf<ast::AccessorExpression, ast::CallExpression, bool paren_lhs = !expr->object->IsAnyOf<ast::AccessorExpression, ast::CallExpression,
@ -2541,7 +2544,7 @@ bool GeneratorImpl::EmitSwitch(const ast::SwitchStatement* stmt) {
return true; return true;
} }
bool GeneratorImpl::EmitType(std::ostream& out, bool GeneratorImpl::EmitType(utils::StringStream& out,
const type::Type* type, const type::Type* type,
const std::string& name, const std::string& name,
bool* name_printed /* = nullptr */) { bool* name_printed /* = nullptr */) {
@ -2749,7 +2752,7 @@ bool GeneratorImpl::EmitType(std::ostream& out,
}); });
} }
bool GeneratorImpl::EmitTypeAndName(std::ostream& out, bool GeneratorImpl::EmitTypeAndName(utils::StringStream& out,
const type::Type* type, const type::Type* type,
const std::string& name) { const std::string& name) {
bool name_printed = false; bool name_printed = false;
@ -2762,7 +2765,7 @@ bool GeneratorImpl::EmitTypeAndName(std::ostream& out,
return true; return true;
} }
bool GeneratorImpl::EmitAddressSpace(std::ostream& out, builtin::AddressSpace sc) { bool GeneratorImpl::EmitAddressSpace(utils::StringStream& out, builtin::AddressSpace sc) {
switch (sc) { switch (sc) {
case builtin::AddressSpace::kFunction: case builtin::AddressSpace::kFunction:
case builtin::AddressSpace::kPrivate: case builtin::AddressSpace::kPrivate:
@ -2796,7 +2799,7 @@ bool GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) {
bool is_host_shareable = str->IsHostShareable(); bool is_host_shareable = str->IsHostShareable();
// Emits a `/* 0xnnnn */` byte offset comment for a struct member. // Emits a `/* 0xnnnn */` byte offset comment for a struct member.
auto add_byte_offset_comment = [&](std::ostream& out, uint32_t offset) { auto add_byte_offset_comment = [&](utils::StringStream& out, uint32_t offset) {
std::ios_base::fmtflags saved_flag_state(out.flags()); std::ios_base::fmtflags saved_flag_state(out.flags());
out << "/* 0x" << std::hex << std::setfill('0') << std::setw(4) << offset << " */ "; out << "/* 0x" << std::hex << std::setfill('0') << std::setw(4) << offset << " */ ";
out.flags(saved_flag_state); out.flags(saved_flag_state);
@ -2955,7 +2958,7 @@ bool GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) {
return true; return true;
} }
bool GeneratorImpl::EmitUnaryOp(std::ostream& out, const ast::UnaryOpExpression* expr) { bool GeneratorImpl::EmitUnaryOp(utils::StringStream& out, const ast::UnaryOpExpression* expr) {
// Handle `-e` when `e` is signed, so that we ensure that if `e` is the // Handle `-e` when `e` is signed, so that we ensure that if `e` is the
// largest negative value, it returns `e`. // largest negative value, it returns `e`.
auto* expr_type = TypeOf(expr->expr)->UnwrapRef(); auto* expr_type = TypeOf(expr->expr)->UnwrapRef();
@ -3234,7 +3237,7 @@ GeneratorImpl::SizeAndAlign GeneratorImpl::MslPackedTypeSizeAndAlign(const type:
} }
template <typename F> template <typename F>
bool GeneratorImpl::CallBuiltinHelper(std::ostream& out, bool GeneratorImpl::CallBuiltinHelper(utils::StringStream& out,
const ast::CallExpression* call, const ast::CallExpression* call,
const sem::Builtin* builtin, const sem::Builtin* builtin,
F&& build) { F&& build) {
@ -3283,7 +3286,7 @@ bool GeneratorImpl::CallBuiltinHelper(std::ostream& out,
// Call the helper // Call the helper
out << fn; out << fn;
{ {
ScopedParen sp(out); ScopedParen sp(out.stream());
bool first = true; bool first = true;
for (auto* arg : call->args) { for (auto* arg : call->args) {
if (!first) { if (!first) {

View File

@ -40,6 +40,7 @@
#include "src/tint/program.h" #include "src/tint/program.h"
#include "src/tint/scope_stack.h" #include "src/tint/scope_stack.h"
#include "src/tint/sem/struct.h" #include "src/tint/sem/struct.h"
#include "src/tint/utils/string_stream.h"
#include "src/tint/writer/array_length_from_uniform_options.h" #include "src/tint/writer/array_length_from_uniform_options.h"
#include "src/tint/writer/msl/generator.h" #include "src/tint/writer/msl/generator.h"
#include "src/tint/writer/text_generator.h" #include "src/tint/writer/text_generator.h"
@ -106,7 +107,7 @@ class GeneratorImpl : public TextGenerator {
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the expression to emit /// @param expr the expression to emit
/// @returns true if the index accessor was emitted /// @returns true if the index accessor was emitted
bool EmitIndexAccessor(std::ostream& out, const ast::IndexAccessorExpression* expr); bool EmitIndexAccessor(utils::StringStream& out, const ast::IndexAccessorExpression* expr);
/// Handles an assignment statement /// Handles an assignment statement
/// @param stmt the statement to emit /// @param stmt the statement to emit
/// @returns true if the statement was emitted successfully /// @returns true if the statement was emitted successfully
@ -115,12 +116,12 @@ class GeneratorImpl : public TextGenerator {
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the binary expression /// @param expr the binary expression
/// @returns true if the expression was emitted, false otherwise /// @returns true if the expression was emitted, false otherwise
bool EmitBinary(std::ostream& out, const ast::BinaryExpression* expr); bool EmitBinary(utils::StringStream& out, const ast::BinaryExpression* expr);
/// Handles generating a bitcast expression /// Handles generating a bitcast expression
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the bitcast expression /// @param expr the bitcast expression
/// @returns true if the bitcast was emitted /// @returns true if the bitcast was emitted
bool EmitBitcast(std::ostream& out, const ast::BitcastExpression* expr); bool EmitBitcast(utils::StringStream& out, const ast::BitcastExpression* expr);
/// Handles a block statement /// Handles a block statement
/// @param stmt the statement to emit /// @param stmt the statement to emit
/// @returns true if the statement was emitted successfully /// @returns true if the statement was emitted successfully
@ -137,19 +138,21 @@ class GeneratorImpl : public TextGenerator {
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitCall(std::ostream& out, const ast::CallExpression* expr); bool EmitCall(utils::StringStream& out, const ast::CallExpression* expr);
/// Handles generating a builtin call expression /// Handles generating a builtin call expression
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param call the call expression /// @param call the call expression
/// @param builtin the builtin being called /// @param builtin the builtin being called
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitBuiltinCall(std::ostream& out, const sem::Call* call, const sem::Builtin* builtin); bool EmitBuiltinCall(utils::StringStream& out,
const sem::Call* call,
const sem::Builtin* builtin);
/// Handles generating a value conversion expression /// Handles generating a value conversion expression
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param call the call expression /// @param call the call expression
/// @param conv the value conversion /// @param conv the value conversion
/// @returns true if the expression is emitted /// @returns true if the expression is emitted
bool EmitTypeConversion(std::ostream& out, bool EmitTypeConversion(utils::StringStream& out,
const sem::Call* call, const sem::Call* call,
const sem::ValueConversion* conv); const sem::ValueConversion* conv);
/// Handles generating a value constructor /// Handles generating a value constructor
@ -157,7 +160,7 @@ class GeneratorImpl : public TextGenerator {
/// @param call the call expression /// @param call the call expression
/// @param ctor the value constructor /// @param ctor the value constructor
/// @returns true if the initializer is emitted /// @returns true if the initializer is emitted
bool EmitTypeInitializer(std::ostream& out, bool EmitTypeInitializer(utils::StringStream& out,
const sem::Call* call, const sem::Call* call,
const sem::ValueConstructor* ctor); const sem::ValueConstructor* ctor);
/// Handles generating a function call /// Handles generating a function call
@ -165,14 +168,16 @@ class GeneratorImpl : public TextGenerator {
/// @param call the call expression /// @param call the call expression
/// @param func the target function /// @param func the target function
/// @returns true if the call is emitted /// @returns true if the call is emitted
bool EmitFunctionCall(std::ostream& out, const sem::Call* call, const sem::Function* func); bool EmitFunctionCall(utils::StringStream& out,
const sem::Call* call,
const sem::Function* func);
/// Handles generating a call to an atomic function (`atomicAdd`, /// Handles generating a call to an atomic function (`atomicAdd`,
/// `atomicMax`, etc) /// `atomicMax`, etc)
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param builtin the semantic information for the atomic builtin /// @param builtin the semantic information for the atomic builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitAtomicCall(std::ostream& out, bool EmitAtomicCall(utils::StringStream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Builtin* builtin); const sem::Builtin* builtin);
/// Handles generating a call to a texture function (`textureSample`, /// Handles generating a call to a texture function (`textureSample`,
@ -181,13 +186,15 @@ class GeneratorImpl : public TextGenerator {
/// @param call the call expression /// @param call the call expression
/// @param builtin the semantic information for the texture builtin /// @param builtin the semantic information for the texture builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitTextureCall(std::ostream& out, const sem::Call* call, const sem::Builtin* builtin); bool EmitTextureCall(utils::StringStream& out,
const sem::Call* call,
const sem::Builtin* builtin);
/// Handles generating a call to the `dot()` builtin /// Handles generating a call to the `dot()` builtin
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the call expression /// @param expr the call expression
/// @param builtin the semantic information for the builtin /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitDotCall(std::ostream& out, bool EmitDotCall(utils::StringStream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Builtin* builtin); const sem::Builtin* builtin);
/// Handles generating a call to the `modf()` builtin /// Handles generating a call to the `modf()` builtin
@ -195,7 +202,7 @@ class GeneratorImpl : public TextGenerator {
/// @param expr the call expression /// @param expr the call expression
/// @param builtin the semantic information for the builtin /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitModfCall(std::ostream& out, bool EmitModfCall(utils::StringStream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Builtin* builtin); const sem::Builtin* builtin);
/// Handles generating a call to the `frexp()` builtin /// Handles generating a call to the `frexp()` builtin
@ -203,7 +210,7 @@ class GeneratorImpl : public TextGenerator {
/// @param expr the call expression /// @param expr the call expression
/// @param builtin the semantic information for the builtin /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitFrexpCall(std::ostream& out, bool EmitFrexpCall(utils::StringStream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Builtin* builtin); const sem::Builtin* builtin);
/// Handles generating a call to the `degrees()` builtin /// Handles generating a call to the `degrees()` builtin
@ -211,7 +218,7 @@ class GeneratorImpl : public TextGenerator {
/// @param expr the call expression /// @param expr the call expression
/// @param builtin the semantic information for the builtin /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitDegreesCall(std::ostream& out, bool EmitDegreesCall(utils::StringStream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Builtin* builtin); const sem::Builtin* builtin);
/// Handles generating a call to the `radians()` builtin /// Handles generating a call to the `radians()` builtin
@ -219,7 +226,7 @@ class GeneratorImpl : public TextGenerator {
/// @param expr the call expression /// @param expr the call expression
/// @param builtin the semantic information for the builtin /// @param builtin the semantic information for the builtin
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
bool EmitRadiansCall(std::ostream& out, bool EmitRadiansCall(utils::StringStream& out,
const ast::CallExpression* expr, const ast::CallExpression* expr,
const sem::Builtin* builtin); const sem::Builtin* builtin);
/// Handles a case statement /// Handles a case statement
@ -242,7 +249,7 @@ class GeneratorImpl : public TextGenerator {
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the expression /// @param expr the expression
/// @returns true if the expression was emitted /// @returns true if the expression was emitted
bool EmitExpression(std::ostream& out, const ast::Expression* expr); bool EmitExpression(utils::StringStream& out, const ast::Expression* expr);
/// Handles generating a function /// Handles generating a function
/// @param func the function to generate /// @param func the function to generate
/// @returns true if the function was emitted /// @returns true if the function was emitted
@ -251,7 +258,7 @@ class GeneratorImpl : public TextGenerator {
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the identifier expression /// @param expr the identifier expression
/// @returns true if the identifier was emitted /// @returns true if the identifier was emitted
bool EmitIdentifier(std::ostream& out, const ast::IdentifierExpression* expr); bool EmitIdentifier(utils::StringStream& out, const ast::IdentifierExpression* expr);
/// Handles an if statement /// Handles an if statement
/// @param stmt the statement to emit /// @param stmt the statement to emit
/// @returns true if the statement was successfully emitted /// @returns true if the statement was successfully emitted
@ -260,12 +267,12 @@ class GeneratorImpl : public TextGenerator {
/// @param out the output stream /// @param out the output stream
/// @param constant the constant value to emit /// @param constant the constant value to emit
/// @returns true if the constant value was successfully emitted /// @returns true if the constant value was successfully emitted
bool EmitConstant(std::ostream& out, const constant::Value* constant); bool EmitConstant(utils::StringStream& out, const constant::Value* constant);
/// Handles a literal /// Handles a literal
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param lit the literal to emit /// @param lit the literal to emit
/// @returns true if the literal was successfully emitted /// @returns true if the literal was successfully emitted
bool EmitLiteral(std::ostream& out, const ast::LiteralExpression* lit); bool EmitLiteral(utils::StringStream& out, const ast::LiteralExpression* lit);
/// Handles a loop statement /// Handles a loop statement
/// @param stmt the statement to emit /// @param stmt the statement to emit
/// @returns true if the statement was emitted /// @returns true if the statement was emitted
@ -282,7 +289,7 @@ class GeneratorImpl : public TextGenerator {
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the member accessor expression /// @param expr the member accessor expression
/// @returns true if the member accessor was emitted /// @returns true if the member accessor was emitted
bool EmitMemberAccessor(std::ostream& out, const ast::MemberAccessorExpression* expr); bool EmitMemberAccessor(utils::StringStream& out, const ast::MemberAccessorExpression* expr);
/// Handles return statements /// Handles return statements
/// @param stmt the statement to emit /// @param stmt the statement to emit
/// @returns true if the statement was successfully emitted /// @returns true if the statement was successfully emitted
@ -290,7 +297,7 @@ class GeneratorImpl : public TextGenerator {
/// Handles emitting a pipeline stage name /// Handles emitting a pipeline stage name
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param stage the stage to emit /// @param stage the stage to emit
void EmitStage(std::ostream& out, ast::PipelineStage stage); void EmitStage(utils::StringStream& out, ast::PipelineStage stage);
/// Handles statement /// Handles statement
/// @param stmt the statement to emit /// @param stmt the statement to emit
/// @returns true if the statement was emitted /// @returns true if the statement was emitted
@ -313,7 +320,7 @@ class GeneratorImpl : public TextGenerator {
/// @param name the name of the variable, only used for array emission /// @param name the name of the variable, only used for array emission
/// @param name_printed (optional) if not nullptr and an array was printed /// @param name_printed (optional) if not nullptr and an array was printed
/// @returns true if the type is emitted /// @returns true if the type is emitted
bool EmitType(std::ostream& out, bool EmitType(utils::StringStream& out,
const type::Type* type, const type::Type* type,
const std::string& name, const std::string& name,
bool* name_printed = nullptr); bool* name_printed = nullptr);
@ -322,12 +329,12 @@ class GeneratorImpl : public TextGenerator {
/// @param type the type to generate /// @param type the type to generate
/// @param name the name to emit /// @param name the name to emit
/// @returns true if the type is emitted /// @returns true if the type is emitted
bool EmitTypeAndName(std::ostream& out, const type::Type* type, const std::string& name); bool EmitTypeAndName(utils::StringStream& out, const type::Type* type, const std::string& name);
/// Handles generating a address space /// Handles generating a address space
/// @param out the output of the type stream /// @param out the output of the type stream
/// @param sc the address space to generate /// @param sc the address space to generate
/// @returns true if the address space is emitted /// @returns true if the address space is emitted
bool EmitAddressSpace(std::ostream& out, builtin::AddressSpace sc); bool EmitAddressSpace(utils::StringStream& out, builtin::AddressSpace sc);
/// Handles generating a struct declaration. If the structure has already been emitted, then /// Handles generating a struct declaration. If the structure has already been emitted, then
/// this function will simply return `true` without emitting anything. /// this function will simply return `true` without emitting anything.
/// @param buffer the text buffer that the type declaration will be written to /// @param buffer the text buffer that the type declaration will be written to
@ -338,7 +345,7 @@ class GeneratorImpl : public TextGenerator {
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the expression to emit /// @param expr the expression to emit
/// @returns true if the expression was emitted /// @returns true if the expression was emitted
bool EmitUnaryOp(std::ostream& out, const ast::UnaryOpExpression* expr); bool EmitUnaryOp(utils::StringStream& out, const ast::UnaryOpExpression* expr);
/// Handles generating a 'var' declaration /// Handles generating a 'var' declaration
/// @param var the variable to generate /// @param var the variable to generate
/// @returns true if the variable was emitted /// @returns true if the variable was emitted
@ -351,7 +358,7 @@ class GeneratorImpl : public TextGenerator {
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param type the type to emit the value for /// @param type the type to emit the value for
/// @returns true if the zero value was successfully emitted. /// @returns true if the zero value was successfully emitted.
bool EmitZeroValue(std::ostream& out, const type::Type* type); bool EmitZeroValue(utils::StringStream& out, const type::Type* type);
/// Handles generating a builtin name /// Handles generating a builtin name
/// @param builtin the semantic info for the builtin /// @param builtin the semantic info for the builtin
@ -391,7 +398,7 @@ class GeneratorImpl : public TextGenerator {
/// `params` is the name of all the generated function parameters /// `params` is the name of all the generated function parameters
/// @returns true if the call expression is emitted /// @returns true if the call expression is emitted
template <typename F> template <typename F>
bool CallBuiltinHelper(std::ostream& out, bool CallBuiltinHelper(utils::StringStream& out,
const ast::CallExpression* call, const ast::CallExpression* call,
const sem::Builtin* builtin, const sem::Builtin* builtin,
F&& build); F&& build);

View File

@ -12,6 +12,7 @@
// 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 "src/tint/utils/string_stream.h"
#include "src/tint/writer/msl/test_helper.h" #include "src/tint/writer/msl/test_helper.h"
using namespace tint::number_suffixes; // NOLINT using namespace tint::number_suffixes; // NOLINT
@ -28,7 +29,7 @@ TEST_F(MslGeneratorImplTest, IndexAccessor) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), "ary[5]"); EXPECT_EQ(out.str(), "ary[5]");
} }
@ -42,7 +43,7 @@ TEST_F(MslGeneratorImplTest, IndexAccessor_OfDref) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), "(*(p))[5]"); EXPECT_EQ(out.str(), "(*(p))[5]");
} }

View File

@ -12,6 +12,7 @@
// 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 "src/tint/utils/string_stream.h"
#include "src/tint/writer/msl/test_helper.h" #include "src/tint/writer/msl/test_helper.h"
namespace tint::writer::msl { namespace tint::writer::msl {
@ -44,7 +45,7 @@ TEST_P(MslBinaryTest, Emit) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), params.result); EXPECT_EQ(out.str(), params.result);
} }
@ -88,7 +89,7 @@ TEST_P(MslBinaryTest_SignedOverflowDefinedBehaviour, Emit) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), params.result); EXPECT_EQ(out.str(), params.result);
} }
@ -122,7 +123,7 @@ TEST_P(MslBinaryTest_SignedOverflowDefinedBehaviour_Chained, Emit) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, expr2)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, expr2)) << gen.error();
EXPECT_EQ(out.str(), params.result); EXPECT_EQ(out.str(), params.result);
} }
@ -149,7 +150,7 @@ TEST_F(MslBinaryTest, ModF32) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), "fmod(left, right)"); EXPECT_EQ(out.str(), "fmod(left, right)");
} }
@ -164,7 +165,7 @@ TEST_F(MslBinaryTest, ModF16) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), "fmod(left, right)"); EXPECT_EQ(out.str(), "fmod(left, right)");
} }
@ -177,7 +178,7 @@ TEST_F(MslBinaryTest, ModVec3F32) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), "fmod(left, right)"); EXPECT_EQ(out.str(), "fmod(left, right)");
} }
@ -192,7 +193,7 @@ TEST_F(MslBinaryTest, ModVec3F16) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), "fmod(left, right)"); EXPECT_EQ(out.str(), "fmod(left, right)");
} }
@ -205,7 +206,7 @@ TEST_F(MslBinaryTest, BoolAnd) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), "bool(left & right)"); EXPECT_EQ(out.str(), "bool(left & right)");
} }
@ -218,7 +219,7 @@ TEST_F(MslBinaryTest, BoolOr) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), "bool(left | right)"); EXPECT_EQ(out.str(), "bool(left | right)");
} }

View File

@ -12,6 +12,7 @@
// 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 "src/tint/utils/string_stream.h"
#include "src/tint/writer/msl/test_helper.h" #include "src/tint/writer/msl/test_helper.h"
using namespace tint::number_suffixes; // NOLINT using namespace tint::number_suffixes; // NOLINT
@ -28,7 +29,7 @@ TEST_F(MslGeneratorImplTest, EmitExpression_Bitcast) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, bitcast)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, bitcast)) << gen.error();
EXPECT_EQ(out.str(), "as_type<float>(a)"); EXPECT_EQ(out.str(), "as_type<float>(a)");
} }

View File

@ -14,6 +14,7 @@
#include "src/tint/ast/call_statement.h" #include "src/tint/ast/call_statement.h"
#include "src/tint/sem/call.h" #include "src/tint/sem/call.h"
#include "src/tint/utils/string_stream.h"
#include "src/tint/writer/msl/test_helper.h" #include "src/tint/writer/msl/test_helper.h"
using namespace tint::number_suffixes; // NOLINT using namespace tint::number_suffixes; // NOLINT
@ -61,8 +62,8 @@ const ast::CallExpression* GenerateCall(BuiltinType builtin,
CallParamType type, CallParamType type,
ProgramBuilder* builder) { ProgramBuilder* builder) {
std::string name; std::string name;
std::ostringstream str(name); utils::StringStream str;
str << builtin; str << name << builtin;
switch (builtin) { switch (builtin) {
case BuiltinType::kAcos: case BuiltinType::kAcos:
case BuiltinType::kAsin: case BuiltinType::kAsin:
@ -378,7 +379,7 @@ TEST_F(MslGeneratorImplTest, Builtin_Call) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
EXPECT_EQ(out.str(), "dot(param1, param2)"); EXPECT_EQ(out.str(), "dot(param1, param2)");
} }
@ -389,7 +390,7 @@ TEST_F(MslGeneratorImplTest, StorageBarrier) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
EXPECT_EQ(out.str(), "threadgroup_barrier(mem_flags::mem_device)"); EXPECT_EQ(out.str(), "threadgroup_barrier(mem_flags::mem_device)");
} }
@ -400,7 +401,7 @@ TEST_F(MslGeneratorImplTest, WorkgroupBarrier) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
EXPECT_EQ(out.str(), "threadgroup_barrier(mem_flags::mem_threadgroup)"); EXPECT_EQ(out.str(), "threadgroup_barrier(mem_flags::mem_threadgroup)");
} }
@ -1052,7 +1053,7 @@ TEST_F(MslGeneratorImplTest, Pack2x16Float) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
EXPECT_EQ(out.str(), "as_type<uint>(half2(p1))"); EXPECT_EQ(out.str(), "as_type<uint>(half2(p1))");
} }
@ -1064,7 +1065,7 @@ TEST_F(MslGeneratorImplTest, Unpack2x16Float) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
EXPECT_EQ(out.str(), "float2(as_type<half2>(p1))"); EXPECT_EQ(out.str(), "float2(as_type<half2>(p1))");
} }

View File

@ -14,6 +14,7 @@
#include "src/tint/ast/builtin_texture_helper_test.h" #include "src/tint/ast/builtin_texture_helper_test.h"
#include "src/tint/ast/call_statement.h" #include "src/tint/ast/call_statement.h"
#include "src/tint/utils/string_stream.h"
#include "src/tint/writer/msl/test_helper.h" #include "src/tint/writer/msl/test_helper.h"
namespace tint::writer::msl { namespace tint::writer::msl {
@ -285,7 +286,7 @@ TEST_P(MslGeneratorBuiltinTextureTest, Call) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
auto expected = expected_texture_overload(param.overload); auto expected = expected_texture_overload(param.overload);

View File

@ -13,6 +13,7 @@
// limitations under the License. // limitations under the License.
#include "src/tint/ast/call_statement.h" #include "src/tint/ast/call_statement.h"
#include "src/tint/utils/string_stream.h"
#include "src/tint/writer/msl/test_helper.h" #include "src/tint/writer/msl/test_helper.h"
using namespace tint::number_suffixes; // NOLINT using namespace tint::number_suffixes; // NOLINT
@ -30,7 +31,7 @@ TEST_F(MslGeneratorImplTest, EmitExpression_Call_WithoutParams) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
EXPECT_EQ(out.str(), "my_func()"); EXPECT_EQ(out.str(), "my_func()");
} }
@ -53,7 +54,7 @@ TEST_F(MslGeneratorImplTest, EmitExpression_Call_WithParams) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error();
EXPECT_EQ(out.str(), "my_func(param1, param2)"); EXPECT_EQ(out.str(), "my_func(param1, param2)");
} }

View File

@ -12,6 +12,7 @@
// 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 "src/tint/utils/string_stream.h"
#include "src/tint/writer/msl/test_helper.h" #include "src/tint/writer/msl/test_helper.h"
using namespace tint::number_suffixes; // NOLINT using namespace tint::number_suffixes; // NOLINT
@ -27,7 +28,7 @@ TEST_F(MslGeneratorImplTest, EmitExpression_Cast_Scalar) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, cast)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, cast)) << gen.error();
EXPECT_EQ(out.str(), "1.0f"); EXPECT_EQ(out.str(), "1.0f");
} }
@ -38,7 +39,7 @@ TEST_F(MslGeneratorImplTest, EmitExpression_Cast_Vector) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, cast)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, cast)) << gen.error();
EXPECT_EQ(out.str(), "float3(1.0f, 2.0f, 3.0f)"); EXPECT_EQ(out.str(), "float3(1.0f, 2.0f, 3.0f)");
} }
@ -49,7 +50,7 @@ TEST_F(MslGeneratorImplTest, EmitExpression_Cast_IntMin) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, cast)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, cast)) << gen.error();
EXPECT_EQ(out.str(), "2147483648u"); EXPECT_EQ(out.str(), "2147483648u");
} }

View File

@ -12,6 +12,7 @@
// 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 "src/tint/utils/string_stream.h"
#include "src/tint/writer/msl/test_helper.h" #include "src/tint/writer/msl/test_helper.h"
namespace tint::writer::msl { namespace tint::writer::msl {
@ -27,7 +28,7 @@ TEST_F(MslGeneratorImplTest, EmitIdentifierExpression) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, i)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, i)) << gen.error();
EXPECT_EQ(out.str(), "foo"); EXPECT_EQ(out.str(), "foo");
} }

View File

@ -13,6 +13,7 @@
// limitations under the License. // limitations under the License.
#include "src/tint/sem/call.h" #include "src/tint/sem/call.h"
#include "src/tint/utils/string_stream.h"
#include "src/tint/writer/msl/test_helper.h" #include "src/tint/writer/msl/test_helper.h"
using namespace tint::number_suffixes; // NOLINT using namespace tint::number_suffixes; // NOLINT
@ -81,7 +82,7 @@ TEST_F(MslGeneratorImplTest, MslImportData_SingleParamTest_IntScalar) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error();
EXPECT_EQ(out.str(), R"(abs(1))"); EXPECT_EQ(out.str(), R"(abs(1))");
} }
@ -92,7 +93,7 @@ TEST_F(MslGeneratorImplTest, MslImportData_SingleParamTest_ScalarLength) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error();
EXPECT_EQ(out.str(), R"(fabs(2.0f))"); EXPECT_EQ(out.str(), R"(fabs(2.0f))");
} }
@ -106,7 +107,7 @@ TEST_P(MslImportData_DualParam_ScalarTest, Float) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error();
EXPECT_EQ(out.str(), std::string(param.msl_name) + "(1.0f, 2.0f)"); EXPECT_EQ(out.str(), std::string(param.msl_name) + "(1.0f, 2.0f)");
} }
@ -124,7 +125,7 @@ TEST_F(MslGeneratorImplTest, MslImportData_DualParam_ScalarDistance) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error();
EXPECT_EQ(out.str(), R"(fabs(2.0f - 3.0f))"); EXPECT_EQ(out.str(), R"(fabs(2.0f - 3.0f))");
} }
@ -138,7 +139,7 @@ TEST_P(MslImportData_DualParam_VectorTest, Float) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error();
EXPECT_EQ(out.str(), std::string(param.msl_name) + EXPECT_EQ(out.str(), std::string(param.msl_name) +
R"((float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f)))"); R"((float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f)))");
@ -163,7 +164,7 @@ TEST_P(MslImportData_DualParam_Int_Test, IntScalar) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error();
EXPECT_EQ(out.str(), std::string(param.msl_name) + "(1, 2)"); EXPECT_EQ(out.str(), std::string(param.msl_name) + "(1, 2)");
} }
@ -180,7 +181,7 @@ TEST_P(MslImportData_TripleParam_ScalarTest, Float) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error();
EXPECT_EQ(out.str(), std::string(param.msl_name) + "(1.0f, 2.0f, 3.0f)"); EXPECT_EQ(out.str(), std::string(param.msl_name) + "(1.0f, 2.0f, 3.0f)");
} }
@ -201,7 +202,7 @@ TEST_P(MslImportData_TripleParam_VectorTest, Float) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error();
EXPECT_EQ( EXPECT_EQ(
out.str(), out.str(),
@ -224,7 +225,7 @@ TEST_P(MslImportData_TripleParam_Int_Test, IntScalar) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error();
EXPECT_EQ(out.str(), std::string(param.msl_name) + "(1, 2, 3)"); EXPECT_EQ(out.str(), std::string(param.msl_name) + "(1, 2, 3)");
} }
@ -242,7 +243,7 @@ TEST_F(MslGeneratorImplTest, MslImportData_Determinant) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error();
EXPECT_EQ(out.str(), std::string("determinant(var)")); EXPECT_EQ(out.str(), std::string("determinant(var)"));
} }
@ -255,7 +256,7 @@ TEST_F(MslGeneratorImplTest, MslImportData_QuantizeToF16_Scalar) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error();
EXPECT_EQ(out.str(), "float(half(v))"); EXPECT_EQ(out.str(), "float(half(v))");
} }
@ -268,7 +269,7 @@ TEST_F(MslGeneratorImplTest, MslImportData_QuantizeToF16_Vector) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error();
EXPECT_EQ(out.str(), "float3(half3(v))"); EXPECT_EQ(out.str(), "float3(half3(v))");
} }

View File

@ -12,6 +12,7 @@
// 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 "src/tint/utils/string_stream.h"
#include "src/tint/writer/msl/test_helper.h" #include "src/tint/writer/msl/test_helper.h"
namespace tint::writer::msl { namespace tint::writer::msl {
@ -27,7 +28,7 @@ TEST_F(MslGeneratorImplTest, EmitExpression_MemberAccessor) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), "str.mem"); EXPECT_EQ(out.str(), "str.mem");
} }
@ -39,7 +40,7 @@ TEST_F(MslGeneratorImplTest, EmitExpression_MemberAccessor_Swizzle_xyz) {
WrapInFunction(expr); WrapInFunction(expr);
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), "my_vec.xyz"); EXPECT_EQ(out.str(), "my_vec.xyz");
} }
@ -51,7 +52,7 @@ TEST_F(MslGeneratorImplTest, EmitExpression_MemberAccessor_Swizzle_gbr) {
WrapInFunction(expr); WrapInFunction(expr);
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), "my_vec.gbr"); EXPECT_EQ(out.str(), "my_vec.gbr");
} }

View File

@ -23,6 +23,7 @@
#include "src/tint/type/sampler.h" #include "src/tint/type/sampler.h"
#include "src/tint/type/storage_texture.h" #include "src/tint/type/storage_texture.h"
#include "src/tint/type/texture_dimension.h" #include "src/tint/type/texture_dimension.h"
#include "src/tint/utils/string_stream.h"
#include "src/tint/writer/msl/test_helper.h" #include "src/tint/writer/msl/test_helper.h"
using ::testing::HasSubstr; using ::testing::HasSubstr;
@ -32,7 +33,7 @@ using namespace tint::number_suffixes; // NOLINT
namespace tint::writer::msl { namespace tint::writer::msl {
namespace { namespace {
void FormatMSLField(std::stringstream& out, void FormatMSLField(utils::StringStream& out,
const char* addr, const char* addr,
const char* type, const char* type,
size_t array_count, size_t array_count,
@ -94,7 +95,7 @@ TEST_F(MslGeneratorImplTest, EmitType_Array) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type), "ary")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type), "ary")) << gen.error();
EXPECT_EQ(out.str(), "tint_array<bool, 4>"); EXPECT_EQ(out.str(), "tint_array<bool, 4>");
} }
@ -106,7 +107,7 @@ TEST_F(MslGeneratorImplTest, EmitType_ArrayOfArray) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type), "ary")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type), "ary")) << gen.error();
EXPECT_EQ(out.str(), "tint_array<tint_array<bool, 4>, 5>"); EXPECT_EQ(out.str(), "tint_array<tint_array<bool, 4>, 5>");
} }
@ -119,7 +120,7 @@ TEST_F(MslGeneratorImplTest, EmitType_ArrayOfArrayOfArray) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type), "ary")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type), "ary")) << gen.error();
EXPECT_EQ(out.str(), "tint_array<tint_array<tint_array<bool, 4>, 5>, 6>"); EXPECT_EQ(out.str(), "tint_array<tint_array<tint_array<bool, 4>, 5>, 6>");
} }
@ -130,7 +131,7 @@ TEST_F(MslGeneratorImplTest, EmitType_Array_WithoutName) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type), "")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type), "")) << gen.error();
EXPECT_EQ(out.str(), "tint_array<bool, 4>"); EXPECT_EQ(out.str(), "tint_array<bool, 4>");
} }
@ -141,7 +142,7 @@ TEST_F(MslGeneratorImplTest, EmitType_RuntimeArray) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type), "ary")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type), "ary")) << gen.error();
EXPECT_EQ(out.str(), "tint_array<bool, 1>"); EXPECT_EQ(out.str(), "tint_array<bool, 1>");
} }
@ -151,7 +152,7 @@ TEST_F(MslGeneratorImplTest, EmitType_Bool) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, bool_, "")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, bool_, "")) << gen.error();
EXPECT_EQ(out.str(), "bool"); EXPECT_EQ(out.str(), "bool");
} }
@ -161,7 +162,7 @@ TEST_F(MslGeneratorImplTest, EmitType_F32) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, f32, "")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, f32, "")) << gen.error();
EXPECT_EQ(out.str(), "float"); EXPECT_EQ(out.str(), "float");
} }
@ -171,7 +172,7 @@ TEST_F(MslGeneratorImplTest, EmitType_F16) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, f16, "")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, f16, "")) << gen.error();
EXPECT_EQ(out.str(), "half"); EXPECT_EQ(out.str(), "half");
} }
@ -181,7 +182,7 @@ TEST_F(MslGeneratorImplTest, EmitType_I32) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, i32, "")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, i32, "")) << gen.error();
EXPECT_EQ(out.str(), "int"); EXPECT_EQ(out.str(), "int");
} }
@ -193,7 +194,7 @@ TEST_F(MslGeneratorImplTest, EmitType_Matrix_F32) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, mat2x3, "")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, mat2x3, "")) << gen.error();
EXPECT_EQ(out.str(), "float2x3"); EXPECT_EQ(out.str(), "float2x3");
} }
@ -205,7 +206,7 @@ TEST_F(MslGeneratorImplTest, EmitType_Matrix_F16) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, mat2x3, "")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, mat2x3, "")) << gen.error();
EXPECT_EQ(out.str(), "half2x3"); EXPECT_EQ(out.str(), "half2x3");
} }
@ -217,7 +218,7 @@ TEST_F(MslGeneratorImplTest, EmitType_Pointer) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, p, "")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, p, "")) << gen.error();
EXPECT_EQ(out.str(), "threadgroup float* "); EXPECT_EQ(out.str(), "threadgroup float* ");
} }
@ -230,7 +231,7 @@ TEST_F(MslGeneratorImplTest, EmitType_Struct) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, program->TypeOf(s), "")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, program->TypeOf(s), "")) << gen.error();
EXPECT_EQ(out.str(), "S"); EXPECT_EQ(out.str(), "S");
} }
@ -338,7 +339,7 @@ TEST_F(MslGeneratorImplTest, EmitType_Struct_Layout_NonComposites) {
FIELD(0x0304, int8_t, 124, tint_pad_12) FIELD(0x0304, int8_t, 124, tint_pad_12)
// Check that the generated string is as expected. // Check that the generated string is as expected.
std::stringstream expect; utils::StringStream expect;
expect << "struct S {\n"; expect << "struct S {\n";
#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \ #define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \
FormatMSLField(expect, #ADDR, #TYPE, ARRAY_COUNT, #NAME); FormatMSLField(expect, #ADDR, #TYPE, ARRAY_COUNT, #NAME);
@ -415,7 +416,7 @@ TEST_F(MslGeneratorImplTest, EmitType_Struct_Layout_Structures) {
FIELD(0x080c, int8_t, 500, tint_pad_1) FIELD(0x080c, int8_t, 500, tint_pad_1)
// Check that the generated string is as expected. // Check that the generated string is as expected.
std::stringstream expect; utils::StringStream expect;
expect << "struct S {\n"; expect << "struct S {\n";
#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \ #define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \
FormatMSLField(expect, #ADDR, #TYPE, ARRAY_COUNT, #NAME); FormatMSLField(expect, #ADDR, #TYPE, ARRAY_COUNT, #NAME);
@ -508,7 +509,7 @@ TEST_F(MslGeneratorImplTest, EmitType_Struct_Layout_ArrayDefaultStride) {
FIELD(0x1208, int8_t, 504, tint_pad_1) FIELD(0x1208, int8_t, 504, tint_pad_1)
// Check that the generated string is as expected. // Check that the generated string is as expected.
std::stringstream expect; utils::StringStream expect;
expect << "struct S {\n"; expect << "struct S {\n";
#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \ #define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \
FormatMSLField(expect, #ADDR, #TYPE, ARRAY_COUNT, #NAME); FormatMSLField(expect, #ADDR, #TYPE, ARRAY_COUNT, #NAME);
@ -589,7 +590,7 @@ TEST_F(MslGeneratorImplTest, EmitType_Struct_Layout_ArrayVec3DefaultStride) {
FIELD(0x0054, int8_t, 12, tint_pad_1) FIELD(0x0054, int8_t, 12, tint_pad_1)
// Check that the generated string is as expected. // Check that the generated string is as expected.
std::stringstream expect; utils::StringStream expect;
expect << "struct S {\n"; expect << "struct S {\n";
#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \ #define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \
FormatMSLField(expect, #ADDR, #TYPE, ARRAY_COUNT, #NAME); FormatMSLField(expect, #ADDR, #TYPE, ARRAY_COUNT, #NAME);
@ -711,7 +712,7 @@ TEST_F(MslGeneratorImplTest, EmitType_U32) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, u32, "")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, u32, "")) << gen.error();
EXPECT_EQ(out.str(), "uint"); EXPECT_EQ(out.str(), "uint");
} }
@ -722,7 +723,7 @@ TEST_F(MslGeneratorImplTest, EmitType_Vector) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, vec3, "")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, vec3, "")) << gen.error();
EXPECT_EQ(out.str(), "float3"); EXPECT_EQ(out.str(), "float3");
} }
@ -732,7 +733,7 @@ TEST_F(MslGeneratorImplTest, EmitType_Void) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, void_, "")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, void_, "")) << gen.error();
EXPECT_EQ(out.str(), "void"); EXPECT_EQ(out.str(), "void");
} }
@ -742,7 +743,7 @@ TEST_F(MslGeneratorImplTest, EmitType_Sampler) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, sampler, "")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, sampler, "")) << gen.error();
EXPECT_EQ(out.str(), "sampler"); EXPECT_EQ(out.str(), "sampler");
} }
@ -752,7 +753,7 @@ TEST_F(MslGeneratorImplTest, EmitType_SamplerComparison) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, sampler, "")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, sampler, "")) << gen.error();
EXPECT_EQ(out.str(), "sampler"); EXPECT_EQ(out.str(), "sampler");
} }
@ -773,7 +774,7 @@ TEST_P(MslDepthTexturesTest, Emit) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, &s, "")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, &s, "")) << gen.error();
EXPECT_EQ(out.str(), params.result); EXPECT_EQ(out.str(), params.result);
} }
@ -794,7 +795,7 @@ TEST_F(MslDepthMultisampledTexturesTest, Emit) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, &s, "")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, &s, "")) << gen.error();
EXPECT_EQ(out.str(), "depth2d_ms<float, access::read>"); EXPECT_EQ(out.str(), "depth2d_ms<float, access::read>");
} }
@ -816,7 +817,7 @@ TEST_P(MslSampledtexturesTest, Emit) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, s, "")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, s, "")) << gen.error();
EXPECT_EQ(out.str(), params.result); EXPECT_EQ(out.str(), params.result);
} }
@ -838,7 +839,7 @@ TEST_F(MslGeneratorImplTest, Emit_TypeMultisampledTexture) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, ms, "")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, ms, "")) << gen.error();
EXPECT_EQ(out.str(), "texture2d_ms<uint, access::read>"); EXPECT_EQ(out.str(), "texture2d_ms<uint, access::read>");
} }
@ -860,7 +861,7 @@ TEST_P(MslStorageTexturesTest, Emit) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type), "")) << gen.error(); ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type), "")) << gen.error();
EXPECT_EQ(out.str(), params.result); EXPECT_EQ(out.str(), params.result);
} }

View File

@ -12,6 +12,7 @@
// 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 "src/tint/utils/string_stream.h"
#include "src/tint/writer/msl/test_helper.h" #include "src/tint/writer/msl/test_helper.h"
namespace tint::writer::msl { namespace tint::writer::msl {
@ -26,7 +27,7 @@ TEST_F(MslUnaryOpTest, AddressOf) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error();
EXPECT_EQ(out.str(), "&(expr)"); EXPECT_EQ(out.str(), "&(expr)");
} }
@ -38,7 +39,7 @@ TEST_F(MslUnaryOpTest, Complement) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error();
EXPECT_EQ(out.str(), "~(expr)"); EXPECT_EQ(out.str(), "~(expr)");
} }
@ -51,7 +52,7 @@ TEST_F(MslUnaryOpTest, Indirection) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error();
EXPECT_EQ(out.str(), "*(expr)"); EXPECT_EQ(out.str(), "*(expr)");
} }
@ -63,7 +64,7 @@ TEST_F(MslUnaryOpTest, Not) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error();
EXPECT_EQ(out.str(), "!(expr)"); EXPECT_EQ(out.str(), "!(expr)");
} }
@ -75,7 +76,7 @@ TEST_F(MslUnaryOpTest, Negation) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error();
EXPECT_EQ(out.str(), "tint_unary_minus(expr)"); EXPECT_EQ(out.str(), "tint_unary_minus(expr)");
} }
@ -86,7 +87,7 @@ TEST_F(MslUnaryOpTest, IntMin) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
std::stringstream out; utils::StringStream out;
ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error(); ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error();
EXPECT_EQ(out.str(), "(-2147483647 - 1)"); EXPECT_EQ(out.str(), "(-2147483647 - 1)");
} }