diff --git a/src/writer/hlsl/generator.cc b/src/writer/hlsl/generator.cc index d55e70c814..297788e0fb 100644 --- a/src/writer/hlsl/generator.cc +++ b/src/writer/hlsl/generator.cc @@ -26,7 +26,7 @@ Generator::Generator(const Program* program) Generator::~Generator() = default; bool Generator::Generate() { - auto ret = impl_->Generate(out_); + auto ret = impl_->Generate(); if (!ret) { error_ = impl_->error(); } @@ -34,7 +34,7 @@ bool Generator::Generate() { } std::string Generator::result() const { - return out_.str(); + return impl_->result(); } std::string Generator::error() const { diff --git a/src/writer/hlsl/generator.h b/src/writer/hlsl/generator.h index 3623dd59d9..a3bef0059a 100644 --- a/src/writer/hlsl/generator.h +++ b/src/writer/hlsl/generator.h @@ -48,7 +48,6 @@ class Generator : public Text { std::string error() const; private: - std::ostringstream out_; std::unique_ptr impl_; }; diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc index f7677e4a55..496be2d6fa 100644 --- a/src/writer/hlsl/generator_impl.cc +++ b/src/writer/hlsl/generator_impl.cc @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -100,13 +101,6 @@ std::ostream& operator<<(std::ostream& s, const RegisterAndSpace& rs) { return s; } -// Helper for writting a '(' on construction and a ')' destruction. -struct ScopedParen { - std::ostream& s_; - explicit ScopedParen(std::ostream& s) : s_(s) { s << "("; } - ~ScopedParen() { s_ << ")"; } -}; - } // namespace GeneratorImpl::GeneratorImpl(const Program* program) @@ -114,7 +108,7 @@ GeneratorImpl::GeneratorImpl(const Program* program) GeneratorImpl::~GeneratorImpl() = default; -bool GeneratorImpl::Generate(std::ostream& out) { +bool GeneratorImpl::Generate() { if (!builder_.HasTransformApplied()) { diagnostics_.add_error( diag::System::Writer, @@ -123,8 +117,8 @@ bool GeneratorImpl::Generate(std::ostream& out) { return false; } - std::stringstream pending; const TypeInfo* last_kind = nullptr; + std::streampos last_padding_pos; for (auto* decl : builder_.AST().GlobalDeclarations()) { if (decl->Is()) { @@ -134,29 +128,29 @@ bool GeneratorImpl::Generate(std::ostream& out) { // Emit a new line between declarations if the type of declaration has // changed, or we're about to emit a function auto* kind = &decl->TypeInfo(); - if (pending.str().length() && - (last_kind != kind || decl->Is())) { - out << pending.str() << std::endl; - pending.str(std::string()); - make_indent(out); + if (out_.tellp() != last_padding_pos) { + if (last_kind && (last_kind != kind || decl->Is())) { + out_ << std::endl; + last_padding_pos = out_.tellp(); + } } last_kind = kind; if (auto* global = decl->As()) { - if (!EmitGlobalVariable(pending, global)) { + if (!EmitGlobalVariable(global)) { return false; } } else if (auto* str = decl->As()) { - if (!EmitStructType(pending, builder_.Sem().Get(str))) { + if (!EmitStructType(builder_.Sem().Get(str))) { return false; } } else if (auto* func = decl->As()) { if (func->IsEntryPoint()) { - if (!EmitEntryPointFunction(pending, func)) { + if (!EmitEntryPointFunction(func)) { return false; } } else { - if (!EmitFunction(pending, func)) { + if (!EmitFunction(func)) { return false; } } @@ -167,8 +161,6 @@ bool GeneratorImpl::Generate(std::ostream& out) { } } - out << pending.str(); - return true; } @@ -176,15 +168,14 @@ std::string GeneratorImpl::generate_name(const std::string& prefix) { return builder_.Symbols().NameFor(builder_.Symbols().New(prefix)); } -bool GeneratorImpl::EmitArrayAccessor(std::ostream& pre, - std::ostream& out, +bool GeneratorImpl::EmitArrayAccessor(std::ostream& out, ast::ArrayAccessorExpression* expr) { - if (!EmitExpression(pre, out, expr->array())) { + if (!EmitExpression(out, expr->array())) { return false; } out << "["; - if (!EmitExpression(pre, out, expr->idx_expr())) { + if (!EmitExpression(out, expr->idx_expr())) { return false; } out << "]"; @@ -192,8 +183,7 @@ bool GeneratorImpl::EmitArrayAccessor(std::ostream& pre, return true; } -bool GeneratorImpl::EmitBitcast(std::ostream& pre, - std::ostream& out, +bool GeneratorImpl::EmitBitcast(std::ostream& out, ast::BitcastExpression* expr) { auto* type = TypeOf(expr); if (!type->is_integer_scalar() && !type->is_float_scalar()) { @@ -208,67 +198,57 @@ bool GeneratorImpl::EmitBitcast(std::ostream& pre, return false; } out << "("; - if (!EmitExpression(pre, out, expr->expr())) { + if (!EmitExpression(out, expr->expr())) { return false; } out << ")"; return true; } -bool GeneratorImpl::EmitAssign(std::ostream& out, - ast::AssignmentStatement* stmt) { - make_indent(out); - - std::ostringstream pre; - - std::ostringstream lhs_out; - if (!EmitExpression(pre, lhs_out, stmt->lhs())) { +bool GeneratorImpl::EmitAssign(ast::AssignmentStatement* stmt) { + auto out = line(); + if (!EmitExpression(out, stmt->lhs())) { return false; } - std::ostringstream rhs_out; - if (!EmitExpression(pre, rhs_out, stmt->rhs())) { + out << " = "; + if (!EmitExpression(out, stmt->rhs())) { return false; } - - out << pre.str(); - out << lhs_out.str() << " = " << rhs_out.str() << ";" << std::endl; - + out << ";"; return true; } -bool GeneratorImpl::EmitBinary(std::ostream& pre, - std::ostream& out, - ast::BinaryExpression* expr) { +bool GeneratorImpl::EmitBinary(std::ostream& out, ast::BinaryExpression* expr) { if (expr->op() == ast::BinaryOp::kLogicalAnd || expr->op() == ast::BinaryOp::kLogicalOr) { - std::ostringstream lhs_out; - if (!EmitExpression(pre, lhs_out, expr->lhs())) { - return false; - } - auto name = generate_name(kTempNamePrefix); - make_indent(pre); - pre << "bool " << name << " = " << lhs_out.str() << ";" << std::endl; - make_indent(pre); - pre << "if ("; + { + auto pre = line(); + pre << "bool " << name << " = "; + if (!EmitExpression(pre, expr->lhs())) { + return false; + } + pre << ";"; + } + if (expr->op() == ast::BinaryOp::kLogicalOr) { - pre << "!"; - } - pre << name << ") {" << std::endl; - increment_indent(); - - std::ostringstream rhs_out; - if (!EmitExpression(pre, rhs_out, expr->rhs())) { - return false; + line() << "if (!" << name << ") {"; + } else { + line() << "if (" << name << ") {"; } - make_indent(pre); - pre << name << " = " << rhs_out.str() << ";" << std::endl; + { + ScopedIndent si(this); + auto pre = line(); + pre << name << " = "; + if (!EmitExpression(pre, expr->rhs())) { + return false; + } + pre << ";"; + } - decrement_indent(); - make_indent(pre); - pre << "}" << std::endl; + line() << "}"; out << "(" << name << ")"; return true; @@ -284,11 +264,11 @@ bool GeneratorImpl::EmitBinary(std::ostream& pre, (lhs_type->Is() && rhs_type->Is()))) { // Matrices are transposed, so swap LHS and RHS. out << "mul("; - if (!EmitExpression(pre, out, expr->rhs())) { + if (!EmitExpression(out, expr->rhs())) { return false; } out << ", "; - if (!EmitExpression(pre, out, expr->lhs())) { + if (!EmitExpression(out, expr->lhs())) { return false; } out << ")"; @@ -297,7 +277,7 @@ bool GeneratorImpl::EmitBinary(std::ostream& pre, } out << "("; - if (!EmitExpression(pre, out, expr->lhs())) { + if (!EmitExpression(out, expr->lhs())) { return false; } out << " "; @@ -369,7 +349,7 @@ bool GeneratorImpl::EmitBinary(std::ostream& pre, } out << " "; - if (!EmitExpression(pre, out, expr->rhs())) { + if (!EmitExpression(out, expr->rhs())) { return false; } @@ -377,46 +357,35 @@ bool GeneratorImpl::EmitBinary(std::ostream& pre, return true; } -bool GeneratorImpl::EmitBlock(std::ostream& out, - const ast::BlockStatement* stmt) { - return EmitBlockBraces(out, [&] { - for (auto* s : *stmt) { - if (!EmitStatement(out, s)) { - return false; - } +bool GeneratorImpl::EmitStatements(const ast::StatementList& stmts) { + for (auto* s : stmts) { + if (!EmitStatement(s)) { + return false; } - return true; - }); -} - -bool GeneratorImpl::EmitBlockAndNewline(std::ostream& out, - const ast::BlockStatement* stmt) { - const bool result = EmitBlock(out, stmt); - if (result) { - out << std::endl; } - return result; -} - -bool GeneratorImpl::EmitIndentedBlockAndNewline(std::ostream& out, - ast::BlockStatement* stmt) { - make_indent(out); - const bool result = EmitBlock(out, stmt); - if (result) { - out << std::endl; - } - return result; -} - -bool GeneratorImpl::EmitBreak(std::ostream& out, ast::BreakStatement*) { - make_indent(out); - out << "break;" << std::endl; return true; } -bool GeneratorImpl::EmitCall(std::ostream& pre, - std::ostream& out, - ast::CallExpression* expr) { +bool GeneratorImpl::EmitStatementsWithIndent(const ast::StatementList& stmts) { + ScopedIndent si(this); + return EmitStatements(stmts); +} + +bool GeneratorImpl::EmitBlock(const ast::BlockStatement* stmt) { + line() << "{"; + if (!EmitStatementsWithIndent(stmt->statements())) { + return false; + } + line() << "}"; + return true; +} + +bool GeneratorImpl::EmitBreak(ast::BreakStatement*) { + line() << "break;"; + return true; +} + +bool GeneratorImpl::EmitCall(std::ostream& out, ast::CallExpression* expr) { const auto& params = expr->params(); auto* ident = expr->func(); auto* call = builder_.Sem().Get(expr); @@ -428,11 +397,11 @@ bool GeneratorImpl::EmitCall(std::ostream& pre, func->Declaration()->decorations())) { // Special function generated by the CalculateArrayLength transform for // calling X.GetDimensions(Y) - if (!EmitExpression(pre, out, params[0])) { + if (!EmitExpression(out, params[0])) { return false; } out << ".GetDimensions("; - if (!EmitExpression(pre, out, params[1])) { + if (!EmitExpression(out, params[1])) { return false; } out << ")"; @@ -444,9 +413,9 @@ bool GeneratorImpl::EmitCall(std::ostream& pre, func->Declaration()->decorations())) { switch (intrinsic->storage_class) { case ast::StorageClass::kUniform: - return EmitUniformBufferAccess(pre, out, expr, intrinsic); + return EmitUniformBufferAccess(out, expr, intrinsic); case ast::StorageClass::kStorage: - return EmitStorageBufferAccess(pre, out, expr, intrinsic); + return EmitStorageBufferAccess(out, expr, intrinsic); default: TINT_UNREACHABLE(Writer, diagnostics_) << "unsupported DecomposeMemoryAccess::Intrinsic storage class:" @@ -458,23 +427,23 @@ bool GeneratorImpl::EmitCall(std::ostream& pre, if (auto* intrinsic = call->Target()->As()) { if (intrinsic->IsTexture()) { - return EmitTextureCall(pre, out, expr, intrinsic); + return EmitTextureCall(out, expr, intrinsic); } else if (intrinsic->Type() == sem::IntrinsicType::kSelect) { - return EmitSelectCall(pre, out, expr); + return EmitSelectCall(out, expr); } else if (intrinsic->Type() == sem::IntrinsicType::kFrexp) { - return EmitFrexpCall(pre, out, expr, intrinsic); + return EmitFrexpCall(out, expr, intrinsic); } else if (intrinsic->Type() == sem::IntrinsicType::kIsNormal) { - return EmitIsNormalCall(pre, out, expr, intrinsic); + return EmitIsNormalCall(out, expr, intrinsic); } else if (intrinsic->Type() == sem::IntrinsicType::kIgnore) { - return EmitExpression(pre, out, expr->params()[0]); + return EmitExpression(out, expr->params()[0]); } else if (intrinsic->IsDataPacking()) { - return EmitDataPackingCall(pre, out, expr, intrinsic); + return EmitDataPackingCall(out, expr, intrinsic); } else if (intrinsic->IsDataUnpacking()) { - return EmitDataUnpackingCall(pre, out, expr, intrinsic); + return EmitDataUnpackingCall(out, expr, intrinsic); } else if (intrinsic->IsBarrier()) { - return EmitBarrierCall(pre, out, intrinsic); + return EmitBarrierCall(out, intrinsic); } else if (intrinsic->IsAtomic()) { - return EmitWorkgroupAtomicCall(pre, out, expr, intrinsic); + return EmitWorkgroupAtomicCall(out, expr, intrinsic); } auto name = generate_builtin_name(intrinsic); if (name.empty()) { @@ -490,7 +459,7 @@ bool GeneratorImpl::EmitCall(std::ostream& pre, } first = false; - if (!EmitExpression(pre, out, param)) { + if (!EmitExpression(out, param)) { return false; } } @@ -519,7 +488,7 @@ bool GeneratorImpl::EmitCall(std::ostream& pre, } first = false; - if (!EmitExpression(pre, out, param)) { + if (!EmitExpression(out, param)) { return false; } } @@ -530,7 +499,6 @@ bool GeneratorImpl::EmitCall(std::ostream& pre, } bool GeneratorImpl::EmitUniformBufferAccess( - std::ostream& pre, std::ostream& out, ast::CallExpression* expr, const transform::DecomposeMemoryAccess::Intrinsic* intrinsic) { @@ -538,13 +506,12 @@ bool GeneratorImpl::EmitUniformBufferAccess( std::string scalar_offset = generate_name("scalar_offset"); { - std::stringstream ss; - ss << "const int " << scalar_offset << " = ("; - if (!EmitExpression(pre, ss, params[1])) { // offset + auto pre = line(); + pre << "const int " << scalar_offset << " = ("; + if (!EmitExpression(pre, params[1])) { // offset return false; } - make_indent(ss << ") / 4;" << std::endl); - pre << ss.str(); + pre << ") / 4;"; } using Op = transform::DecomposeMemoryAccess::Intrinsic::Op; @@ -558,7 +525,7 @@ bool GeneratorImpl::EmitUniformBufferAccess( return result; }; auto load_scalar = [&]() { - if (!EmitExpression(pre, out, params[0])) { // buffer + if (!EmitExpression(out, params[0])) { // buffer return false; } out << "[" << scalar_offset << " / 4][" << scalar_offset << " % 4]"; @@ -567,14 +534,15 @@ bool GeneratorImpl::EmitUniformBufferAccess( // Has a minimum alignment of 8 bytes, so is either .xy or .zw auto load_vec2 = [&] { std::string ubo_load = generate_name("ubo_load"); - std::stringstream ss; - ss << "uint4 " << ubo_load << " = "; - if (!EmitExpression(pre, ss, params[0])) { // buffer - return false; + + { + auto pre = line(); + pre << "uint4 " << ubo_load << " = "; + if (!EmitExpression(pre, params[0])) { // buffer + return false; + } + pre << "[" << scalar_offset << " / 4];"; } - ss << "[" << scalar_offset << " / 4]"; - make_indent(ss << ";" << std::endl); - pre << ss.str(); out << "((" << scalar_offset << " & 2) ? " << ubo_load << ".zw : " << ubo_load << ".xy)"; @@ -582,7 +550,7 @@ bool GeneratorImpl::EmitUniformBufferAccess( }; // vec3 has a minimum alignment of 16 bytes, so is just a .xyz swizzle auto load_vec3 = [&] { - if (!EmitExpression(pre, out, params[0])) { // buffer + if (!EmitExpression(out, params[0])) { // buffer return false; } out << "[" << scalar_offset << " / 4].xyz"; @@ -590,7 +558,7 @@ bool GeneratorImpl::EmitUniformBufferAccess( }; // vec4 has a minimum alignment of 16 bytes, easiest case auto load_vec4 = [&] { - if (!EmitExpression(pre, out, params[0])) { // buffer + if (!EmitExpression(out, params[0])) { // buffer return false; } out << "[" << scalar_offset << " / 4]"; @@ -637,7 +605,6 @@ bool GeneratorImpl::EmitUniformBufferAccess( } bool GeneratorImpl::EmitStorageBufferAccess( - std::ostream& pre, std::ostream& out, ast::CallExpression* expr, const transform::DecomposeMemoryAccess::Intrinsic* intrinsic) { @@ -651,7 +618,7 @@ bool GeneratorImpl::EmitStorageBufferAccess( if (cast) { out << cast << "("; } - if (!EmitExpression(pre, out, params[0])) { // buffer + if (!EmitExpression(out, params[0])) { // buffer return false; } out << ".Load"; @@ -659,7 +626,7 @@ bool GeneratorImpl::EmitStorageBufferAccess( out << n; } ScopedParen sp(out); - if (!EmitExpression(pre, out, params[1])) { // offset + if (!EmitExpression(out, params[1])) { // offset return false; } if (cast) { @@ -701,7 +668,7 @@ bool GeneratorImpl::EmitStorageBufferAccess( case Op::kStore: { auto store = [&](int n) { - if (!EmitExpression(pre, out, params[0])) { // buffer + if (!EmitExpression(out, params[0])) { // buffer return false; } out << ".Store"; @@ -709,12 +676,12 @@ bool GeneratorImpl::EmitStorageBufferAccess( out << n; } ScopedParen sp1(out); - if (!EmitExpression(pre, out, params[1])) { // offset + if (!EmitExpression(out, params[1])) { // offset return false; } out << ", asuint"; ScopedParen sp2(out); - if (!EmitExpression(pre, out, params[2])) { // value + if (!EmitExpression(out, params[2])) { // value return false; } return true; @@ -761,7 +728,7 @@ bool GeneratorImpl::EmitStorageBufferAccess( case Op::kAtomicXor: case Op::kAtomicExchange: case Op::kAtomicCompareExchangeWeak: - return EmitStorageAtomicCall(pre, out, expr, intrinsic->op); + return EmitStorageAtomicCall(out, expr, intrinsic->op); } TINT_UNREACHABLE(Writer, diagnostics_) @@ -771,55 +738,83 @@ bool GeneratorImpl::EmitStorageBufferAccess( } bool GeneratorImpl::EmitStorageAtomicCall( - std::ostream& pre, std::ostream& out, ast::CallExpression* expr, transform::DecomposeMemoryAccess::Intrinsic::Op op) { using Op = transform::DecomposeMemoryAccess::Intrinsic::Op; - std::stringstream ss; std::string result = generate_name("atomic_result"); auto* result_ty = TypeOf(expr); if (!result_ty->Is()) { - if (!EmitTypeAndName(ss, TypeOf(expr), ast::StorageClass::kNone, + auto pre = line(); + if (!EmitTypeAndName(pre, TypeOf(expr), ast::StorageClass::kNone, ast::Access::kUndefined, result)) { return false; } - ss << " = "; - if (!EmitZeroValue(ss, result_ty)) { + pre << " = "; + if (!EmitZeroValue(pre, result_ty)) { return false; } - make_indent(ss << ";" << std::endl); + pre << ";"; } auto* buffer = expr->params()[0]; auto* offset = expr->params()[1]; + auto call_buffer_method = [&](const char* name) { + auto pre = line(); + if (!EmitExpression(pre, buffer)) { + return false; + } + pre << "." << name; + { + ScopedParen sp(pre); + if (!EmitExpression(pre, offset)) { + return false; + } + + for (size_t i = 1; i < expr->params().size() - 1; i++) { + auto* arg = expr->params()[i]; + pre << ", "; + if (!EmitExpression(pre, arg)) { + return false; + } + } + + pre << ", " << result; + } + pre << ";"; + + out << result; + return true; + }; + switch (op) { case Op::kAtomicLoad: { // HLSL does not have an InterlockedLoad, so we emulate it with // InterlockedOr using 0 as the OR value - if (!EmitExpression(pre, ss, buffer)) { + auto pre = line(); + if (!EmitExpression(pre, buffer)) { return false; } - ss << ".InterlockedOr"; + pre << ".InterlockedOr"; { - ScopedParen sp(ss); - if (!EmitExpression(pre, ss, offset)) { + ScopedParen sp(pre); + if (!EmitExpression(pre, offset)) { return false; } - ss << ", 0, " << result; + pre << ", 0, " << result; } - make_indent(ss << ";" << std::endl); - pre << ss.str(); + pre << ";"; out << result; return true; } case Op::kAtomicStore: { // HLSL does not have an InterlockedStore, so we emulate it with // InterlockedExchange and discard the returned value + auto pre = line(); auto* value = expr->params()[2]; auto* value_ty = TypeOf(value); if (!EmitTypeAndName(pre, value_ty, ast::StorageClass::kNone, @@ -830,19 +825,19 @@ bool GeneratorImpl::EmitStorageAtomicCall( if (!EmitZeroValue(pre, value_ty)) { return false; } - make_indent(pre << ";" << std::endl); + pre << ";"; - if (!EmitExpression(pre, out, buffer)) { + if (!EmitExpression(out, buffer)) { return false; } out << ".InterlockedExchange"; { ScopedParen sp(out); - if (!EmitExpression(pre, out, offset)) { + if (!EmitExpression(out, offset)) { return false; } out << ", "; - if (!EmitExpression(pre, out, value)) { + if (!EmitExpression(out, value)) { return false; } out << ", " << result; @@ -854,174 +849,163 @@ bool GeneratorImpl::EmitStorageAtomicCall( auto* value = expr->params()[3]; std::string compare = generate_name("atomic_compare_value"); - if (!EmitTypeAndName(ss, TypeOf(compare_value), ast::StorageClass::kNone, - ast::Access::kUndefined, compare)) { - return false; - } - ss << " = "; - if (!EmitExpression(pre, ss, compare_value)) { - return false; - } - make_indent(ss << ";" << std::endl); - - if (!EmitExpression(pre, ss, buffer)) { - return false; - } - ss << ".InterlockedCompareExchange"; - { - ScopedParen sp(ss); - if (!EmitExpression(pre, ss, offset)) { + { // T atomic_compare_value = compare_value; + auto pre = line(); + if (!EmitTypeAndName(pre, TypeOf(compare_value), + ast::StorageClass::kNone, ast::Access::kUndefined, + compare)) { return false; } - ss << ", " << compare << ", "; - if (!EmitExpression(pre, ss, value)) { + pre << " = "; + if (!EmitExpression(pre, compare_value)) { return false; } - ss << ", " << result << ".x"; + pre << ";"; + } + { // buffer.InterlockedCompareExchange(offset, compare, value, result.x); + auto pre = line(); + if (!EmitExpression(pre, buffer)) { + return false; + } + pre << ".InterlockedCompareExchange"; + { + ScopedParen sp(pre); + if (!EmitExpression(pre, offset)) { + return false; + } + pre << ", " << compare << ", "; + if (!EmitExpression(pre, value)) { + return false; + } + pre << ", " << result << ".x"; + } + pre << ";"; + } + { // result.y = result.x == compare; + line() << result << ".y = " << result << ".x == " << compare << ";"; } - make_indent(ss << ";" << std::endl); - ss << result << ".y = " << result << ".x == " << compare; - make_indent(ss << ";" << std::endl); - - pre << ss.str(); out << result; return true; } case Op::kAtomicAdd: - if (!EmitExpression(pre, ss, buffer)) { - return false; - } - ss << ".InterlockedAdd"; - break; + return call_buffer_method("InterlockedAdd"); + case Op::kAtomicMax: - if (!EmitExpression(pre, ss, buffer)) { - return false; - } - ss << ".InterlockedMax"; - break; + return call_buffer_method("InterlockedMax"); + case Op::kAtomicMin: - if (!EmitExpression(pre, ss, buffer)) { - return false; - } - ss << ".InterlockedMin"; - break; + return call_buffer_method("InterlockedMin"); + case Op::kAtomicAnd: - if (!EmitExpression(pre, ss, buffer)) { - return false; - } - ss << ".InterlockedAnd"; - break; + return call_buffer_method("InterlockedAnd"); + case Op::kAtomicOr: - if (!EmitExpression(pre, ss, buffer)) { - return false; - } - ss << ".InterlockedOr"; - break; + return call_buffer_method("InterlockedOr"); + case Op::kAtomicXor: - if (!EmitExpression(pre, ss, buffer)) { - return false; - } - ss << ".InterlockedXor"; - break; + return call_buffer_method("InterlockedXor"); + case Op::kAtomicExchange: - if (!EmitExpression(pre, ss, buffer)) { - return false; - } - ss << ".InterlockedExchange"; - break; + return call_buffer_method("InterlockedExchange"); default: - TINT_UNREACHABLE(Writer, diagnostics_) - << "unsupported atomic DecomposeMemoryAccess::Intrinsic::Op: " - << static_cast(op); - return false; + break; } - { - ScopedParen sp(ss); - if (!EmitExpression(pre, ss, offset)) { - return false; - } - - for (size_t i = 1; i < expr->params().size() - 1; i++) { - auto* arg = expr->params()[i]; - ss << ", "; - if (!EmitExpression(pre, ss, arg)) { - return false; - } - } - - ss << ", " << result; - } - - make_indent(ss << ";" << std::endl); - pre << ss.str(); - out << result; - - return true; + TINT_UNREACHABLE(Writer, diagnostics_) + << "unsupported atomic DecomposeMemoryAccess::Intrinsic::Op: " + << static_cast(op); + return false; } -bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& pre, - std::ostream& out, +bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& out, ast::CallExpression* expr, const sem::Intrinsic* intrinsic) { - std::stringstream ss; std::string result = generate_name("atomic_result"); if (!intrinsic->ReturnType()->Is()) { - if (!EmitTypeAndName(ss, intrinsic->ReturnType(), ast::StorageClass::kNone, + auto pre = line(); + if (!EmitTypeAndName(pre, intrinsic->ReturnType(), ast::StorageClass::kNone, ast::Access::kUndefined, result)) { return false; } - ss << " = "; - if (!EmitZeroValue(ss, intrinsic->ReturnType())) { + pre << " = "; + if (!EmitZeroValue(pre, intrinsic->ReturnType())) { return false; } - make_indent(ss << ";" << std::endl); + pre << ";"; } + auto call = [&](const char* name) { + auto pre = line(); + pre << name; + + { + ScopedParen sp(pre); + for (size_t i = 0; i < expr->params().size(); i++) { + auto* arg = expr->params()[i]; + if (i > 0) { + pre << ", "; + } + if (!EmitExpression(pre, arg)) { + return false; + } + } + + pre << ", " << result; + } + + pre << ";"; + + out << result; + return true; + }; + switch (intrinsic->Type()) { case sem::IntrinsicType::kAtomicLoad: { // HLSL does not have an InterlockedLoad, so we emulate it with // InterlockedOr using 0 as the OR value - ss << "InterlockedOr"; + auto pre = line(); + pre << "InterlockedOr"; { - ScopedParen sp(ss); - if (!EmitExpression(pre, ss, expr->params()[0])) { + ScopedParen sp(pre); + if (!EmitExpression(pre, expr->params()[0])) { return false; } - ss << ", 0, " << result; + pre << ", 0, " << result; } - make_indent(ss << ";" << std::endl); + pre << ";"; - pre << ss.str(); out << result; return true; } case sem::IntrinsicType::kAtomicStore: { // HLSL does not have an InterlockedStore, so we emulate it with // InterlockedExchange and discard the returned value - auto* value_ty = intrinsic->Parameters()[1].type; - if (!EmitTypeAndName(pre, value_ty, ast::StorageClass::kNone, - ast::Access::kUndefined, result)) { - return false; + { // T result = 0; + auto pre = line(); + auto* value_ty = intrinsic->Parameters()[1].type; + if (!EmitTypeAndName(pre, value_ty, ast::StorageClass::kNone, + ast::Access::kUndefined, result)) { + return false; + } + pre << " = "; + if (!EmitZeroValue(pre, value_ty)) { + return false; + } + pre << ";"; } - pre << " = "; - if (!EmitZeroValue(pre, value_ty)) { - return false; - } - make_indent(pre << ";" << std::endl); out << "InterlockedExchange"; { ScopedParen sp(out); - if (!EmitExpression(pre, out, expr->params()[0])) { + if (!EmitExpression(out, expr->params()[0])) { return false; } out << ", "; - if (!EmitExpression(pre, out, expr->params()[1])) { + if (!EmitExpression(out, expr->params()[1])) { return false; } out << ", " << result; @@ -1034,116 +1018,102 @@ bool GeneratorImpl::EmitWorkgroupAtomicCall(std::ostream& pre, auto* value = expr->params()[2]; std::string compare = generate_name("atomic_compare_value"); - if (!EmitTypeAndName(ss, TypeOf(compare_value), ast::StorageClass::kNone, - ast::Access::kUndefined, compare)) { - return false; - } - ss << " = "; - if (!EmitExpression(pre, ss, compare_value)) { - return false; - } - make_indent(ss << ";" << std::endl); - ss << "InterlockedCompareExchange"; - { - ScopedParen sp(ss); - if (!EmitExpression(pre, ss, dest)) { + { // T compare_value = ; + auto pre = line(); + if (!EmitTypeAndName(pre, TypeOf(compare_value), + ast::StorageClass::kNone, ast::Access::kUndefined, + compare)) { return false; } - ss << ", " << compare << ", "; - if (!EmitExpression(pre, ss, value)) { + pre << " = "; + if (!EmitExpression(pre, compare_value)) { return false; } - ss << ", " << result << ".x"; + pre << ";"; } - make_indent(ss << ";" << std::endl); - ss << result << ".y = " << result << ".x == " << compare; - make_indent(ss << ";" << std::endl); + { // InterlockedCompareExchange(dst, compare, value, result.x); + auto pre = line(); + pre << "InterlockedCompareExchange"; + { + ScopedParen sp(pre); + if (!EmitExpression(pre, dest)) { + return false; + } + pre << ", " << compare << ", "; + if (!EmitExpression(pre, value)) { + return false; + } + pre << ", " << result << ".x"; + } + pre << ";"; + } + + { // result.y = result.x == compare; + line() << result << ".y = " << result << ".x == " << compare << ";"; + } - pre << ss.str(); out << result; return true; } case sem::IntrinsicType::kAtomicAdd: - ss << "InterlockedAdd"; - break; + return call("InterlockedAdd"); + case sem::IntrinsicType::kAtomicMax: - ss << "InterlockedMax"; - break; + return call("InterlockedMax"); + case sem::IntrinsicType::kAtomicMin: - ss << "InterlockedMin"; - break; + return call("InterlockedMin"); + case sem::IntrinsicType::kAtomicAnd: - ss << "InterlockedAnd"; - break; + return call("InterlockedAnd"); + case sem::IntrinsicType::kAtomicOr: - ss << "InterlockedOr"; - break; + return call("InterlockedOr"); + case sem::IntrinsicType::kAtomicXor: - ss << "InterlockedXor"; - break; + return call("InterlockedXor"); + case sem::IntrinsicType::kAtomicExchange: - ss << "InterlockedExchange"; - break; + return call("InterlockedExchange"); default: - TINT_UNREACHABLE(Writer, diagnostics_) - << "unsupported atomic intrinsic: " << intrinsic->Type(); - return false; + break; } - { - ScopedParen sp(ss); - for (size_t i = 0; i < expr->params().size(); i++) { - auto* arg = expr->params()[i]; - if (i > 0) { - ss << ", "; - } - if (!EmitExpression(pre, ss, arg)) { - return false; - } - } - - ss << ", " << result; - } - make_indent(ss << ";" << std::endl); - - pre << ss.str(); - out << result; - - return true; + TINT_UNREACHABLE(Writer, diagnostics_) + << "unsupported atomic intrinsic: " << intrinsic->Type(); + return false; } -bool GeneratorImpl::EmitSelectCall(std::ostream& pre, - std::ostream& out, +bool GeneratorImpl::EmitSelectCall(std::ostream& out, ast::CallExpression* expr) { auto* expr_true = expr->params()[0]; auto* expr_false = expr->params()[1]; auto* expr_cond = expr->params()[2]; ScopedParen paren(out); - if (!EmitExpression(pre, out, expr_cond)) { + if (!EmitExpression(out, expr_cond)) { return false; } out << " ? "; - if (!EmitExpression(pre, out, expr_true)) { + if (!EmitExpression(out, expr_true)) { return false; } out << " : "; - if (!EmitExpression(pre, out, expr_false)) { + if (!EmitExpression(out, expr_false)) { return false; } return true; } -bool GeneratorImpl::EmitFrexpCall(std::ostream& pre, - std::ostream& out, +bool GeneratorImpl::EmitFrexpCall(std::ostream& out, ast::CallExpression* expr, const sem::Intrinsic* intrinsic) { // Exponent is an integer in WGSL, but HLSL wants a float. @@ -1159,37 +1129,35 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& pre, // Exponent is an integer, which HLSL does not have an overload for. // We need to cast from a float. - std::stringstream ss; auto float_exp = generate_name(kTempNamePrefix); - ss << "float" << width << " " << float_exp << ";"; - - make_indent(ss << std::endl); auto significand = generate_name(kTempNamePrefix); - ss << "float" << width << " " << significand << " = frexp("; - if (!EmitExpression(pre, ss, expr->params()[0])) { - return false; + line() << "float" << width << " " << float_exp << ";"; + { + auto pre = line(); + pre << "float" << width << " " << significand << " = frexp("; + if (!EmitExpression(pre, expr->params()[0])) { + return false; + } + pre << ", " << float_exp << ");"; + } + { + auto pre = line(); + if (!EmitExpression(pre, expr->params()[1])) { + return false; + } + pre << " = "; + if (!EmitType(pre, exponent.type->UnwrapPtr(), ast::StorageClass::kNone, + ast::Access::kUndefined, "")) { + return false; + } + pre << "(" << float_exp << ");"; } - ss << ", " << float_exp << ");"; - make_indent(ss << std::endl); - if (!EmitExpression(pre, ss, expr->params()[1])) { - return false; - } - ss << " = "; - if (!EmitType(ss, exponent.type->UnwrapPtr(), ast::StorageClass::kNone, - ast::Access::kUndefined, "")) { - return false; - } - ss << "(" << float_exp << ");"; - - make_indent(ss << std::endl); - pre << ss.str(); out << significand; return true; } -bool GeneratorImpl::EmitIsNormalCall(std::ostream& pre, - std::ostream& out, +bool GeneratorImpl::EmitIsNormalCall(std::ostream& out, ast::CallExpression* expr, const sem::Intrinsic* intrinsic) { // HLSL doesn't have a isNormal intrinsic, we need to emulate @@ -1207,33 +1175,29 @@ bool GeneratorImpl::EmitIsNormalCall(std::ostream& pre, auto exponent = generate_name("tint_isnormal_exponent"); auto clamped = generate_name("tint_isnormal_clamped"); - std::stringstream ss; - ss << "uint" << width << " " << exponent << " = asuint("; - if (!EmitExpression(pre, ss, expr->params()[0])) { - return false; + { + auto pre = line(); + pre << "uint" << width << " " << exponent << " = asuint("; + if (!EmitExpression(pre, expr->params()[0])) { + return false; + } + pre << ") & " << kExponentMask << ";"; } - ss << ") & " << kExponentMask << ";"; - - make_indent(ss << std::endl); - ss << "uint" << width << " " << clamped << " = " - << "clamp(" << exponent << ", " << kMinNormalExponent << ", " - << kMaxNormalExponent << ");"; - - make_indent(ss << std::endl); - pre << ss.str(); + line() << "uint" << width << " " << clamped << " = " + << "clamp(" << exponent << ", " << kMinNormalExponent << ", " + << kMaxNormalExponent << ");"; out << "(" << clamped << " == " << exponent << ")"; return true; } -bool GeneratorImpl::EmitDataPackingCall(std::ostream& pre, - std::ostream& out, +bool GeneratorImpl::EmitDataPackingCall(std::ostream& out, ast::CallExpression* expr, const sem::Intrinsic* intrinsic) { auto* param = expr->params()[0]; auto tmp_name = generate_name(kTempNamePrefix); std::ostringstream expr_out; - if (!EmitExpression(pre, expr_out, param)) { + if (!EmitExpression(expr_out, param)) { return false; } uint32_t dims = 2; @@ -1253,15 +1217,18 @@ bool GeneratorImpl::EmitDataPackingCall(std::ostream& pre, case sem::IntrinsicType::kPack4x8snorm: case sem::IntrinsicType::kPack4x8unorm: case sem::IntrinsicType::kPack2x16snorm: - case sem::IntrinsicType::kPack2x16unorm: - pre << (is_signed ? "" : "u") << "int" << dims << " " << tmp_name << " = " - << (is_signed ? "" : "u") << "int" << dims << "(round(clamp(" - << expr_out.str() << ", " << (is_signed ? "-1.0" : "0.0") - << ", 1.0) * " << scale << ".0))"; - if (is_signed) { - pre << " & " << (dims == 4 ? "0xff" : "0xffff"); + case sem::IntrinsicType::kPack2x16unorm: { + { + auto pre = line(); + pre << (is_signed ? "" : "u") << "int" << dims << " " << tmp_name + << " = " << (is_signed ? "" : "u") << "int" << dims + << "(round(clamp(" << expr_out.str() << ", " + << (is_signed ? "-1.0" : "0.0") << ", 1.0) * " << scale << ".0))"; + if (is_signed) { + pre << " & " << (dims == 4 ? "0xff" : "0xffff"); + } + pre << ";"; } - pre << ";\n"; if (is_signed) { out << "asuint"; } @@ -1272,10 +1239,13 @@ bool GeneratorImpl::EmitDataPackingCall(std::ostream& pre, } out << ")"; break; - case sem::IntrinsicType::kPack2x16float: - pre << "uint2 " << tmp_name << " = f32tof16(" << expr_out.str() << ");\n"; + } + case sem::IntrinsicType::kPack2x16float: { + line() << "uint2 " << tmp_name << " = f32tof16(" << expr_out.str() + << ");"; out << "(" << tmp_name << ".x | " << tmp_name << ".y << 16)"; break; + } default: diagnostics_.add_error( diag::System::Writer, @@ -1286,14 +1256,13 @@ bool GeneratorImpl::EmitDataPackingCall(std::ostream& pre, return true; } -bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& pre, - std::ostream& out, +bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& out, ast::CallExpression* expr, const sem::Intrinsic* intrinsic) { auto* param = expr->params()[0]; auto tmp_name = generate_name(kTempNamePrefix); std::ostringstream expr_out; - if (!EmitExpression(pre, expr_out, param)) { + if (!EmitExpression(expr_out, param)) { return false; } uint32_t dims = 2; @@ -1313,16 +1282,19 @@ bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& pre, case sem::IntrinsicType::kUnpack4x8snorm: case sem::IntrinsicType::kUnpack2x16snorm: { auto tmp_name2 = generate_name(kTempNamePrefix); - pre << "int " << tmp_name2 << " = int(" << expr_out.str() << ");\n"; - // Perform sign extension on the converted values. - pre << "int" << dims << " " << tmp_name << " = int" << dims << "("; - if (dims == 2) { - pre << tmp_name2 << " << 16, " << tmp_name2 << ") >> 16"; - } else { - pre << tmp_name2 << " << 24, " << tmp_name2 << " << 16, " << tmp_name2 - << " << 8, " << tmp_name2 << ") >> 24"; + line() << "int " << tmp_name2 << " = int(" << expr_out.str() << ");"; + { // Perform sign extension on the converted values. + auto pre = line(); + pre << "int" << dims << " " << tmp_name << " = int" << dims << "("; + if (dims == 2) { + pre << tmp_name2 << " << 16, " << tmp_name2 << ") >> 16"; + } else { + pre << tmp_name2 << " << 24, " << tmp_name2 << " << 16, " << tmp_name2 + << " << 8, " << tmp_name2 << ") >> 24"; + } + pre << ";"; } - pre << ";\n"; + out << "clamp(float" << dims << "(" << tmp_name << ") / " << scale << ".0, " << (is_signed ? "-1.0" : "0.0") << ", 1.0)"; break; @@ -1330,21 +1302,24 @@ bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& pre, case sem::IntrinsicType::kUnpack4x8unorm: case sem::IntrinsicType::kUnpack2x16unorm: { auto tmp_name2 = generate_name(kTempNamePrefix); - pre << "uint " << tmp_name2 << " = " << expr_out.str() << ";\n"; - pre << "uint" << dims << " " << tmp_name << " = uint" << dims << "("; - pre << tmp_name2 << " & " << (dims == 2 ? "0xffff" : "0xff") << ", "; - if (dims == 4) { - pre << "(" << tmp_name2 << " >> " << (32 / dims) << ") & 0xff, (" - << tmp_name2 << " >> 16) & 0xff, " << tmp_name2 << " >> 24"; - } else { - pre << tmp_name2 << " >> " << (32 / dims); + line() << "uint " << tmp_name2 << " = " << expr_out.str() << ";"; + { + auto pre = line(); + pre << "uint" << dims << " " << tmp_name << " = uint" << dims << "("; + pre << tmp_name2 << " & " << (dims == 2 ? "0xffff" : "0xff") << ", "; + if (dims == 4) { + pre << "(" << tmp_name2 << " >> " << (32 / dims) << ") & 0xff, (" + << tmp_name2 << " >> 16) & 0xff, " << tmp_name2 << " >> 24"; + } else { + pre << tmp_name2 << " >> " << (32 / dims); + } + pre << ");"; } - pre << ");\n"; out << "float" << dims << "(" << tmp_name << ") / " << scale << ".0"; break; } case sem::IntrinsicType::kUnpack2x16float: - pre << "uint " << tmp_name << " = " << expr_out.str() << ";\n"; + line() << "uint " << tmp_name << " = " << expr_out.str() << ";"; out << "f16tof32(uint2(" << tmp_name << " & 0xffff, " << tmp_name << " >> 16))"; break; @@ -1358,8 +1333,7 @@ bool GeneratorImpl::EmitDataUnpackingCall(std::ostream& pre, return true; } -bool GeneratorImpl::EmitBarrierCall(std::ostream&, - std::ostream& out, +bool GeneratorImpl::EmitBarrierCall(std::ostream& out, const sem::Intrinsic* intrinsic) { // TODO(crbug.com/tint/661): Combine sequential barriers to a single // instruction. @@ -1375,8 +1349,7 @@ bool GeneratorImpl::EmitBarrierCall(std::ostream&, return true; } -bool GeneratorImpl::EmitTextureCall(std::ostream& pre, - std::ostream& out, +bool GeneratorImpl::EmitTextureCall(std::ostream& out, ast::CallExpression* expr, const sem::Intrinsic* intrinsic) { using Usage = sem::ParameterUsage; @@ -1519,49 +1492,47 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre, // Declare a variable to hold the queried texture info auto dims = generate_name(kTempNamePrefix); - if (num_dimensions == 1) { - pre << "int " << dims << ";"; + line() << "int " << dims << ";"; } else { - pre << "int" << num_dimensions << " " << dims << ";"; + line() << "int" << num_dimensions << " " << dims << ";"; } - pre << std::endl; - make_indent(pre); - - if (!EmitExpression(pre, pre, texture)) { - return false; - } - pre << ".GetDimensions("; - - if (level_arg) { - if (!EmitExpression(pre, pre, level_arg)) { + { // texture.GetDimensions(...) + auto pre = line(); + if (!EmitExpression(pre, texture)) { return false; } - pre << ", "; - } else if (intrinsic->Type() == sem::IntrinsicType::kTextureNumLevels) { - pre << "0, "; - } + pre << ".GetDimensions("; - if (num_dimensions == 1) { - pre << dims; - } else { - static constexpr char xyzw[] = {'x', 'y', 'z', 'w'}; - if (num_dimensions < 0 || num_dimensions > 4) { - TINT_ICE(Writer, diagnostics_) - << "vector dimensions are " << num_dimensions; - return false; - } - for (int i = 0; i < num_dimensions; i++) { - if (i > 0) { - pre << ", "; + if (level_arg) { + if (!EmitExpression(pre, level_arg)) { + return false; } - pre << dims << "." << xyzw[i]; + pre << ", "; + } else if (intrinsic->Type() == sem::IntrinsicType::kTextureNumLevels) { + pre << "0, "; } - } - pre << ");" << std::endl; - make_indent(pre); + if (num_dimensions == 1) { + pre << dims; + } else { + static constexpr char xyzw[] = {'x', 'y', 'z', 'w'}; + if (num_dimensions < 0 || num_dimensions > 4) { + TINT_ICE(Writer, diagnostics_) + << "vector dimensions are " << num_dimensions; + return false; + } + for (int i = 0; i < num_dimensions; i++) { + if (i > 0) { + pre << ", "; + } + pre << dims << "." << xyzw[i]; + } + } + + pre << ");"; + } // The out parameters of the GetDimensions() call is now in temporary // `dims` variable. This may be packed with other data, so the final @@ -1573,7 +1544,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre, break; } - if (!EmitExpression(pre, out, texture)) + if (!EmitExpression(out, texture)) return false; bool pack_mip_in_coords = false; @@ -1616,7 +1587,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre, } if (auto* sampler = arg(Usage::kSampler)) { - if (!EmitExpression(pre, out, sampler)) + if (!EmitExpression(out, sampler)) return false; out << ", "; } @@ -1633,7 +1604,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre, auto* stmt = builder_.Sem().Get(vector)->Stmt(); builder_.Sem().Add(zero, builder_.create(zero, i32, stmt)); auto* packed = AppendVector(&builder_, vector, zero); - return EmitExpression(pre, out, packed); + return EmitExpression(out, packed); }; if (auto* array_index = arg(Usage::kArrayIndex)) { @@ -1644,7 +1615,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre, return false; } } else { - if (!EmitExpression(pre, out, packed)) { + if (!EmitExpression(out, packed)) { return false; } } @@ -1654,7 +1625,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre, return false; } } else { - if (!EmitExpression(pre, out, param_coords)) { + if (!EmitExpression(out, param_coords)) { return false; } } @@ -1663,7 +1634,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre, Usage::kDdy, Usage::kSampleIndex, Usage::kOffset}) { if (auto* e = arg(usage)) { out << ", "; - if (!EmitExpression(pre, out, e)) { + if (!EmitExpression(out, e)) { return false; } } @@ -1671,7 +1642,7 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre, if (intrinsic->Type() == sem::IntrinsicType::kTextureStore) { out << "] = "; - if (!EmitExpression(pre, out, arg(Usage::kValue))) { + if (!EmitExpression(out, arg(Usage::kValue))) { return false; } } else { @@ -1792,69 +1763,53 @@ std::string GeneratorImpl::generate_builtin_name( return ""; } -bool GeneratorImpl::EmitCase(std::ostream& out, ast::CaseStatement* stmt) { - make_indent(out); - +bool GeneratorImpl::EmitCase(ast::CaseStatement* stmt) { if (stmt->IsDefault()) { - out << "default:"; + line() << "default: {"; } else { - bool first = true; for (auto* selector : stmt->selectors()) { - if (!first) { - out << std::endl; - make_indent(out); - } - first = false; - + auto out = line(); out << "case "; if (!EmitLiteral(out, selector)) { return false; } out << ":"; + if (selector == stmt->selectors().back()) { + out << " {"; + } } } - out << " {" << std::endl; - - increment_indent(); - - for (auto* s : *stmt->body()) { - if (!EmitStatement(out, s)) { + { + ScopedIndent si(this); + if (!EmitStatements(stmt->body()->statements())) { return false; } + if (!last_is_break_or_fallthrough(stmt->body())) { + line() << "break;"; + } } - if (!last_is_break_or_fallthrough(stmt->body())) { - make_indent(out); - out << "break;" << std::endl; - } - - decrement_indent(); - make_indent(out); - out << "}" << std::endl; + line() << "}"; return true; } -bool GeneratorImpl::EmitConstructor(std::ostream& pre, - std::ostream& out, +bool GeneratorImpl::EmitConstructor(std::ostream& out, ast::ConstructorExpression* expr) { if (auto* scalar = expr->As()) { - return EmitScalarConstructor(pre, out, scalar); + return EmitScalarConstructor(out, scalar); } - return EmitTypeConstructor(pre, out, - expr->As()); + return EmitTypeConstructor(out, expr->As()); } bool GeneratorImpl::EmitScalarConstructor( - std::ostream&, std::ostream& out, ast::ScalarConstructorExpression* expr) { return EmitLiteral(out, expr->literal()); } -bool GeneratorImpl::EmitTypeConstructor(std::ostream& pre, - std::ostream& out, +bool GeneratorImpl::EmitTypeConstructor(std::ostream& out, ast::TypeConstructorExpression* expr) { auto* type = TypeOf(expr)->UnwrapRef(); @@ -1897,7 +1852,7 @@ bool GeneratorImpl::EmitTypeConstructor(std::ostream& pre, } first = false; - if (!EmitExpression(pre, out, e)) { + if (!EmitExpression(out, e)) { return false; } } @@ -1910,49 +1865,45 @@ bool GeneratorImpl::EmitTypeConstructor(std::ostream& pre, return true; } -bool GeneratorImpl::EmitContinue(std::ostream& out, ast::ContinueStatement*) { - if (!emit_continuing_(out)) { +bool GeneratorImpl::EmitContinue(ast::ContinueStatement*) { + if (!emit_continuing_()) { return false; } - make_indent(out); - out << "continue;" << std::endl; + line() << "continue;"; return true; } -bool GeneratorImpl::EmitDiscard(std::ostream& out, ast::DiscardStatement*) { - make_indent(out); +bool GeneratorImpl::EmitDiscard(ast::DiscardStatement*) { // TODO(dsinclair): Verify this is correct when the discard semantics are // defined for WGSL (https://github.com/gpuweb/gpuweb/issues/361) - out << "discard;" << std::endl; + line() << "discard;"; return true; } -bool GeneratorImpl::EmitExpression(std::ostream& pre, - std::ostream& out, - ast::Expression* expr) { +bool GeneratorImpl::EmitExpression(std::ostream& out, ast::Expression* expr) { if (auto* a = expr->As()) { - return EmitArrayAccessor(pre, out, a); + return EmitArrayAccessor(out, a); } if (auto* b = expr->As()) { - return EmitBinary(pre, out, b); + return EmitBinary(out, b); } if (auto* b = expr->As()) { - return EmitBitcast(pre, out, b); + return EmitBitcast(out, b); } if (auto* c = expr->As()) { - return EmitCall(pre, out, c); + return EmitCall(out, c); } if (auto* c = expr->As()) { - return EmitConstructor(pre, out, c); + return EmitConstructor(out, c); } if (auto* i = expr->As()) { - return EmitIdentifier(pre, out, i); + return EmitIdentifier(out, i); } if (auto* m = expr->As()) { - return EmitMemberAccessor(pre, out, m); + return EmitMemberAccessor(out, m); } if (auto* u = expr->As()) { - return EmitUnaryOp(pre, out, u); + return EmitUnaryOp(out, u); } diagnostics_.add_error(diag::System::Writer, @@ -1960,71 +1911,60 @@ bool GeneratorImpl::EmitExpression(std::ostream& pre, return false; } -bool GeneratorImpl::EmitIdentifier(std::ostream&, - std::ostream& out, +bool GeneratorImpl::EmitIdentifier(std::ostream& out, ast::IdentifierExpression* expr) { out << builder_.Symbols().NameFor(expr->symbol()); return true; } -bool GeneratorImpl::EmitIf(std::ostream& out, ast::IfStatement* stmt) { - make_indent(out); - - std::ostringstream pre; - std::ostringstream cond; - if (!EmitExpression(pre, cond, stmt->condition())) { - return false; +bool GeneratorImpl::EmitIf(ast::IfStatement* stmt) { + { + auto out = line(); + out << "if ("; + if (!EmitExpression(out, stmt->condition())) { + return false; + } + out << ") {"; } - std::ostringstream if_out; - if_out << "if (" << cond.str() << ") "; - if (!EmitBlock(if_out, stmt->body())) { + if (!EmitStatementsWithIndent(stmt->body()->statements())) { return false; } for (auto* e : stmt->else_statements()) { if (e->HasCondition()) { - if_out << " else {" << std::endl; - + line() << "} else {"; increment_indent(); - std::ostringstream else_pre; - std::ostringstream else_cond_out; - if (!EmitExpression(else_pre, else_cond_out, e->condition())) { - return false; + { + auto out = line(); + out << "if ("; + if (!EmitExpression(out, e->condition())) { + return false; + } + out << ") {"; } - if_out << else_pre.str(); - - make_indent(if_out); - if_out << "if (" << else_cond_out.str() << ") "; } else { - if_out << " else "; + line() << "} else {"; } - if (!EmitBlock(if_out, e->body())) { + if (!EmitStatementsWithIndent(e->body()->statements())) { return false; } } - if_out << std::endl; + + line() << "}"; for (auto* e : stmt->else_statements()) { - if (!e->HasCondition()) { - continue; + if (e->HasCondition()) { + decrement_indent(); + line() << "}"; } - - decrement_indent(); - make_indent(if_out); - if_out << "}" << std::endl; } - - out << pre.str(); - out << if_out.str(); return true; } -bool GeneratorImpl::EmitFunction(std::ostream& out, ast::Function* func) { - make_indent(out); - +bool GeneratorImpl::EmitFunction(ast::Function* func) { auto* sem = builder_.Sem().Get(func); if (ast::HasDecoration(func->decorations())) { @@ -2032,74 +1972,75 @@ bool GeneratorImpl::EmitFunction(std::ostream& out, ast::Function* func) { return true; } - if (!EmitType(out, sem->ReturnType(), ast::StorageClass::kNone, - ast::Access::kReadWrite, "")) { - return false; - } - - out << " "; - - out << builder_.Symbols().NameFor(func->symbol()) << "("; - - bool first = true; - - for (auto* v : sem->Parameters()) { - if (!first) { - out << ", "; - } - first = false; - - auto const* type = v->Type(); - - if (auto* ptr = type->As()) { - // Transform pointer parameters in to `inout` parameters. - // The WGSL spec is highly restrictive in what can be passed in pointer - // parameters, which allows for this transformation. See: - // https://gpuweb.github.io/gpuweb/wgsl/#function-restriction - out << "inout "; - type = ptr->StoreType(); - } - - // Note: WGSL only allows for StorageClass::kNone on parameters, however the - // sanitizer transforms generates load / store functions for storage or - // uniform buffers. These functions have a buffer parameter with - // StorageClass::kStorage or StorageClass::kUniform. This is required to - // correctly translate the parameter to a [RW]ByteAddressBuffer for storage - // buffers and a uint4[N] for uniform buffers. - if (!EmitTypeAndName( - out, type, v->StorageClass(), v->Access(), - builder_.Symbols().NameFor(v->Declaration()->symbol()))) { + { + auto out = line(); + if (!EmitType(out, sem->ReturnType(), ast::StorageClass::kNone, + ast::Access::kReadWrite, "")) { return false; } + + out << " " << builder_.Symbols().NameFor(func->symbol()) << "("; + + bool first = true; + + for (auto* v : sem->Parameters()) { + if (!first) { + out << ", "; + } + first = false; + + auto const* type = v->Type(); + + if (auto* ptr = type->As()) { + // Transform pointer parameters in to `inout` parameters. + // The WGSL spec is highly restrictive in what can be passed in pointer + // parameters, which allows for this transformation. See: + // https://gpuweb.github.io/gpuweb/wgsl/#function-restriction + out << "inout "; + type = ptr->StoreType(); + } + + // Note: WGSL only allows for StorageClass::kNone on parameters, however + // the sanitizer transforms generates load / store functions for storage + // or uniform buffers. These functions have a buffer parameter with + // StorageClass::kStorage or StorageClass::kUniform. This is required to + // correctly translate the parameter to a [RW]ByteAddressBuffer for + // storage buffers and a uint4[N] for uniform buffers. + if (!EmitTypeAndName( + out, type, v->StorageClass(), v->Access(), + builder_.Symbols().NameFor(v->Declaration()->symbol()))) { + return false; + } + } + out << ") {"; } - out << ") "; - - if (!EmitBlockAndNewline(out, func->body())) { + if (!EmitStatementsWithIndent(func->body()->statements())) { return false; } + line() << "}"; + return true; } -bool GeneratorImpl::EmitGlobalVariable(std::ostream& out, - ast::Variable* global) { +bool GeneratorImpl::EmitGlobalVariable(ast::Variable* global) { if (global->is_const()) { - return EmitProgramConstVariable(out, global); + return EmitProgramConstVariable(global); } auto* sem = builder_.Sem().Get(global); switch (sem->StorageClass()) { case ast::StorageClass::kUniform: - return EmitUniformVariable(out, sem); + return EmitUniformVariable(sem); case ast::StorageClass::kStorage: - return EmitStorageVariable(out, sem); + return EmitStorageVariable(sem); case ast::StorageClass::kUniformConstant: - return EmitHandleVariable(out, sem); + return EmitHandleVariable(sem); case ast::StorageClass::kPrivate: - return EmitPrivateVariable(out, sem); + return EmitPrivateVariable(sem); case ast::StorageClass::kWorkgroup: - return EmitWorkgroupVariable(out, sem); + return EmitWorkgroupVariable(sem); default: break; } @@ -2109,10 +2050,7 @@ bool GeneratorImpl::EmitGlobalVariable(std::ostream& out, return false; } -bool GeneratorImpl::EmitUniformVariable(std::ostream& out, - const sem::Variable* var) { - make_indent(out); - +bool GeneratorImpl::EmitUniformVariable(const sem::Variable* var) { auto* decl = var->Declaration(); auto binding_point = decl->binding_point(); auto* type = var->Type()->UnwrapRef(); @@ -2125,29 +2063,28 @@ bool GeneratorImpl::EmitUniformVariable(std::ostream& out, } auto name = builder_.Symbols().NameFor(decl->symbol()); - out << "cbuffer cbuffer_" << name << RegisterAndSpace('b', binding_point) - << " {" << std::endl; + line() << "cbuffer cbuffer_" << name << RegisterAndSpace('b', binding_point) + << " {"; - increment_indent(); - make_indent(out); - - if (!EmitTypeAndName(out, type, ast::StorageClass::kUniform, var->Access(), - name)) { - return false; + { + ScopedIndent si(this); + auto out = line(); + if (!EmitTypeAndName(out, type, ast::StorageClass::kUniform, var->Access(), + name)) { + return false; + } + out << ";"; } - out << ";" << std::endl; - decrement_indent(); - out << "};" << std::endl; + + line() << "};"; return true; } -bool GeneratorImpl::EmitStorageVariable(std::ostream& out, - const sem::Variable* var) { - make_indent(out); - +bool GeneratorImpl::EmitStorageVariable(const sem::Variable* var) { auto* decl = var->Declaration(); auto* type = var->Type()->UnwrapRef(); + auto out = line(); if (!EmitTypeAndName(out, type, ast::StorageClass::kStorage, var->Access(), builder_.Symbols().NameFor(decl->symbol()))) { return false; @@ -2155,17 +2092,15 @@ bool GeneratorImpl::EmitStorageVariable(std::ostream& out, out << RegisterAndSpace(var->Access() == ast::Access::kRead ? 't' : 'u', decl->binding_point()) - << ";" << std::endl; + << ";"; return true; } -bool GeneratorImpl::EmitHandleVariable(std::ostream& out, - const sem::Variable* var) { - make_indent(out); - +bool GeneratorImpl::EmitHandleVariable(const sem::Variable* var) { auto* decl = var->Declaration(); auto* unwrapped_type = var->Type()->UnwrapRef(); + auto out = line(); auto name = builder_.Symbols().NameFor(decl->symbol()); auto* type = var->Type()->UnwrapRef(); @@ -2192,26 +2127,13 @@ bool GeneratorImpl::EmitHandleVariable(std::ostream& out, << bp.group->value() << ")"; } - out << ";" << std::endl; + out << ";"; return true; } -bool GeneratorImpl::EmitPrivateVariable(std::ostream& out, - const sem::Variable* var) { - make_indent(out); - +bool GeneratorImpl::EmitPrivateVariable(const sem::Variable* var) { auto* decl = var->Declaration(); - - std::ostringstream constructor_out; - if (auto* constructor = decl->constructor()) { - if (!EmitExpression(out, constructor_out, constructor)) { - return false; - } - } else { - if (!EmitZeroValue(constructor_out, var->Type()->UnwrapRef())) { - return false; - } - } + auto out = line(); out << "static "; @@ -2221,27 +2143,25 @@ bool GeneratorImpl::EmitPrivateVariable(std::ostream& out, return false; } - if (constructor_out.str().length()) { - out << " = " << constructor_out.str(); - } - - out << ";" << std::endl; - return true; -} - -bool GeneratorImpl::EmitWorkgroupVariable(std::ostream& out, - const sem::Variable* var) { - make_indent(out); - - auto* decl = var->Declaration(); - - std::ostringstream constructor_out; + out << " = "; if (auto* constructor = decl->constructor()) { - if (!EmitExpression(out, constructor_out, constructor)) { + if (!EmitExpression(out, constructor)) { + return false; + } + } else { + if (!EmitZeroValue(out, var->Type()->UnwrapRef())) { return false; } } + out << ";"; + return true; +} + +bool GeneratorImpl::EmitWorkgroupVariable(const sem::Variable* var) { + auto* decl = var->Declaration(); + auto out = line(); + out << "groupshared "; auto name = builder_.Symbols().NameFor(decl->symbol()); @@ -2250,11 +2170,14 @@ bool GeneratorImpl::EmitWorkgroupVariable(std::ostream& out, return false; } - if (constructor_out.str().length()) { - out << " = " << constructor_out.str(); + if (auto* constructor = decl->constructor()) { + out << " = "; + if (!EmitExpression(out, constructor)) { + return false; + } } - out << ";" << std::endl; + out << ";"; return true; } @@ -2288,85 +2211,81 @@ std::string GeneratorImpl::builtin_to_attribute(ast::Builtin builtin) const { return ""; } -bool GeneratorImpl::EmitEntryPointFunction(std::ostream& out, - ast::Function* func) { - make_indent(out); - +bool GeneratorImpl::EmitEntryPointFunction(ast::Function* func) { auto* func_sem = builder_.Sem().Get(func); - if (func->pipeline_stage() == ast::PipelineStage::kCompute) { - // Emit the workgroup_size attribute. - auto wgsize = func_sem->workgroup_size(); - out << "[numthreads("; - for (int i = 0; i < 3; i++) { - if (i > 0) { + { + auto out = line(); + if (func->pipeline_stage() == ast::PipelineStage::kCompute) { + // Emit the workgroup_size attribute. + auto wgsize = func_sem->workgroup_size(); + out << "[numthreads("; + for (int i = 0; i < 3; i++) { + if (i > 0) { + out << ", "; + } + + if (wgsize[i].overridable_const) { + auto* sem_const = builder_.Sem().Get(wgsize[i].overridable_const); + if (!sem_const->IsPipelineConstant()) { + TINT_ICE(Writer, builder_.Diagnostics()) + << "expected a pipeline-overridable constant"; + } + out << kSpecConstantPrefix << sem_const->ConstantId(); + } else { + out << std::to_string(wgsize[i].value); + } + } + out << ")]" << std::endl; + } + + out << func->return_type()->FriendlyName(builder_.Symbols()); + + out << " " << builder_.Symbols().NameFor(func->symbol()) << "("; + + bool first = true; + + // Emit entry point parameters. + for (auto* var : func->params()) { + auto* sem = builder_.Sem().Get(var); + auto* type = sem->Type(); + if (!type->Is()) { + // ICE likely indicates that the CanonicalizeEntryPointIO transform was + // not run, or a builtin parameter was added after it was run. + TINT_ICE(Writer, diagnostics_) + << "Unsupported non-struct entry point parameter"; + } + + if (!first) { out << ", "; } + first = false; - if (wgsize[i].overridable_const) { - auto* sem_const = builder_.Sem().Get(wgsize[i].overridable_const); - if (!sem_const->IsPipelineConstant()) { - TINT_ICE(Writer, builder_.Diagnostics()) - << "expected a pipeline-overridable constant"; - } - out << kSpecConstantPrefix << sem_const->ConstantId(); - } else { - out << std::to_string(wgsize[i].value); + if (!EmitTypeAndName(out, type, sem->StorageClass(), sem->Access(), + builder_.Symbols().NameFor(var->symbol()))) { + return false; } } - out << ")]" << std::endl; - make_indent(out); + + out << ") {"; } - out << func->return_type()->FriendlyName(builder_.Symbols()); + { + ScopedIndent si(this); - out << " " << builder_.Symbols().NameFor(func->symbol()) << "("; - - bool first = true; - - // Emit entry point parameters. - for (auto* var : func->params()) { - auto* sem = builder_.Sem().Get(var); - auto* type = sem->Type(); - if (!type->Is()) { - // ICE likely indicates that the CanonicalizeEntryPointIO transform was - // not run, or a builtin parameter was added after it was run. - TINT_ICE(Writer, diagnostics_) - << "Unsupported non-struct entry point parameter"; - } - - if (!first) { - out << ", "; - } - first = false; - - if (!EmitTypeAndName(out, type, sem->StorageClass(), sem->Access(), - builder_.Symbols().NameFor(var->symbol()))) { + if (!EmitStatements(func->body()->statements())) { return false; } - } - out << ") {" << std::endl; - - increment_indent(); - - for (auto* s : *func->body()) { - if (!EmitStatement(out, s)) { - return false; - } - } - auto* last_statement = func->get_last_statement(); - if (last_statement == nullptr || - !last_statement->Is()) { - ast::ReturnStatement ret(ProgramID(), Source{}); - if (!EmitStatement(out, &ret)) { - return false; + if (!Is(func->get_last_statement())) { + ast::ReturnStatement ret(ProgramID(), Source{}); + if (!EmitStatement(&ret)) { + return false; + } } } - decrement_indent(); - make_indent(out); - out << "}" << std::endl; + line() << "}"; return true; } @@ -2465,37 +2384,35 @@ bool GeneratorImpl::EmitZeroValue(std::ostream& out, const sem::Type* type) { return true; } -bool GeneratorImpl::EmitLoop(std::ostream& out, ast::LoopStatement* stmt) { - make_indent(out); - - auto emit_continuing = [this, stmt](std::ostream& o) { +bool GeneratorImpl::EmitLoop(ast::LoopStatement* stmt) { + auto emit_continuing = [this, stmt]() { if (stmt->has_continuing()) { - make_indent(o); - if (!EmitBlock(o, stmt->continuing())) { + if (!EmitBlock(stmt->continuing())) { return false; } - o << std::endl; } return true; }; TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing); - bool ok = EmitBlockBraces(out, "while (true)", [&] { - for (auto* s : stmt->body()->statements()) { - if (!EmitStatement(out, s)) { - return false; - } + line() << "while (true) {"; + { + ScopedIndent si(this); + if (!EmitStatements(stmt->body()->statements())) { + return false; } - return emit_continuing(out); - }); - out << std::endl; - return ok; + if (!emit_continuing()) { + return false; + } + } + line() << "}"; + + return true; } -bool GeneratorImpl::EmitMemberAccessor(std::ostream& pre, - std::ostream& out, +bool GeneratorImpl::EmitMemberAccessor(std::ostream& out, ast::MemberAccessorExpression* expr) { - if (!EmitExpression(pre, out, expr->structure())) { + if (!EmitExpression(out, expr->structure())) { return false; } out << "."; @@ -2503,80 +2420,72 @@ bool GeneratorImpl::EmitMemberAccessor(std::ostream& pre, // Swizzles output the name directly if (builder_.Sem().Get(expr)->Is()) { out << builder_.Symbols().NameFor(expr->member()->symbol()); - } else if (!EmitExpression(pre, out, expr->member())) { + } else if (!EmitExpression(out, expr->member())) { return false; } return true; } -bool GeneratorImpl::EmitReturn(std::ostream& out, ast::ReturnStatement* stmt) { - make_indent(out); - +bool GeneratorImpl::EmitReturn(ast::ReturnStatement* stmt) { if (stmt->has_value()) { - std::ostringstream pre; - std::ostringstream ret_out; - if (!EmitExpression(pre, ret_out, stmt->value())) { + auto out = line(); + out << "return "; + if (!EmitExpression(out, stmt->value())) { return false; } - out << pre.str(); - out << "return " << ret_out.str(); + out << ";"; } else { - out << "return"; + line() << "return;"; } - out << ";" << std::endl; return true; } -bool GeneratorImpl::EmitStatement(std::ostream& out, ast::Statement* stmt) { +bool GeneratorImpl::EmitStatement(ast::Statement* stmt) { if (auto* a = stmt->As()) { - return EmitAssign(out, a); + return EmitAssign(a); } if (auto* b = stmt->As()) { - return EmitIndentedBlockAndNewline(out, b); + return EmitBlock(b); } if (auto* b = stmt->As()) { - return EmitBreak(out, b); + return EmitBreak(b); } if (auto* c = stmt->As()) { - make_indent(out); - std::ostringstream pre; - std::ostringstream call_out; - if (!EmitCall(pre, call_out, c->expr())) { - return false; - } - out << pre.str(); + auto out = line(); if (!TypeOf(c->expr())->Is()) { out << "(void) "; } - out << call_out.str() << ";" << std::endl; + if (!EmitCall(out, c->expr())) { + return false; + } + out << ";"; return true; } if (auto* c = stmt->As()) { - return EmitContinue(out, c); + return EmitContinue(c); } if (auto* d = stmt->As()) { - return EmitDiscard(out, d); + return EmitDiscard(d); } if (stmt->As()) { - make_indent(out); - out << "/* fallthrough */" << std::endl; + line() << "/* fallthrough */"; return true; } if (auto* i = stmt->As()) { - return EmitIf(out, i); + return EmitIf(i); } if (auto* l = stmt->As()) { - return EmitLoop(out, l); + return EmitLoop(l); } if (auto* r = stmt->As()) { - return EmitReturn(out, r); + return EmitReturn(r); } if (auto* s = stmt->As()) { - return EmitSwitch(out, s); + return EmitSwitch(s); } if (auto* v = stmt->As()) { - return EmitVariable(out, v->variable()); + return EmitVariable(v->variable()); } diagnostics_.add_error(diag::System::Writer, @@ -2584,29 +2493,26 @@ bool GeneratorImpl::EmitStatement(std::ostream& out, ast::Statement* stmt) { return false; } -bool GeneratorImpl::EmitSwitch(std::ostream& out, ast::SwitchStatement* stmt) { - make_indent(out); - - std::ostringstream pre; - std::ostringstream cond; - if (!EmitExpression(pre, cond, stmt->condition())) { - return false; +bool GeneratorImpl::EmitSwitch(ast::SwitchStatement* stmt) { + { // switch(expr) { + auto out = line(); + out << "switch("; + if (!EmitExpression(out, stmt->condition())) { + return false; + } + out << ") {"; } - out << pre.str(); - out << "switch(" << cond.str() << ") {" << std::endl; - - increment_indent(); - - for (auto* s : stmt->body()) { - if (!EmitCase(out, s)) { - return false; + { + ScopedIndent si(this); + for (auto* s : stmt->body()) { + if (!EmitCase(s)) { + return false; + } } } - decrement_indent(); - make_indent(out); - out << "}" << std::endl; + line() << "}"; return true; } @@ -2806,7 +2712,7 @@ bool GeneratorImpl::EmitTypeAndName(std::ostream& out, return true; } -bool GeneratorImpl::EmitStructType(std::ostream& out, const sem::Struct* str) { +bool GeneratorImpl::EmitStructType(const sem::Struct* str) { auto storage_class_uses = str->StorageClassUsage(); if (storage_class_uses.size() == (storage_class_uses.count(ast::StorageClass::kStorage) + @@ -2821,72 +2727,69 @@ bool GeneratorImpl::EmitStructType(std::ostream& out, const sem::Struct* str) { } auto struct_name = builder_.Symbols().NameFor(str->Declaration()->name()); - out << "struct " << struct_name << " {" << std::endl; + line() << "struct " << struct_name << " {"; + { + ScopedIndent si(this); + for (auto* mem : str->Members()) { + auto name = builder_.Symbols().NameFor(mem->Declaration()->symbol()); - increment_indent(); - for (auto* mem : str->Members()) { - make_indent(out); + auto* ty = mem->Type(); - auto name = builder_.Symbols().NameFor(mem->Declaration()->symbol()); - - auto* ty = mem->Type(); - - if (!EmitTypeAndName(out, ty, ast::StorageClass::kNone, - ast::Access::kReadWrite, name)) { - return false; - } - - for (auto* deco : mem->Declaration()->decorations()) { - if (auto* location = deco->As()) { - auto& pipeline_stage_uses = str->PipelineStageUses(); - if (pipeline_stage_uses.size() != 1) { - TINT_ICE(Writer, diagnostics_) - << "invalid entry point IO struct uses"; - } - - if (pipeline_stage_uses.count(sem::PipelineStageUsage::kVertexInput)) { - out << " : TEXCOORD" + std::to_string(location->value()); - } else if (pipeline_stage_uses.count( - sem::PipelineStageUsage::kVertexOutput)) { - out << " : TEXCOORD" + std::to_string(location->value()); - } else if (pipeline_stage_uses.count( - sem::PipelineStageUsage::kFragmentInput)) { - out << " : TEXCOORD" + std::to_string(location->value()); - } else if (pipeline_stage_uses.count( - sem::PipelineStageUsage::kFragmentOutput)) { - out << " : SV_Target" + std::to_string(location->value()); - } else { - TINT_ICE(Writer, diagnostics_) - << "invalid use of location decoration"; - } - } else if (auto* builtin = deco->As()) { - auto attr = builtin_to_attribute(builtin->value()); - if (attr.empty()) { - diagnostics_.add_error(diag::System::Writer, "unsupported builtin"); - return false; - } - out << " : " << attr; + auto out = line(); + if (!EmitTypeAndName(out, ty, ast::StorageClass::kNone, + ast::Access::kReadWrite, name)) { + return false; } - } - out << ";" << std::endl; + for (auto* deco : mem->Declaration()->decorations()) { + if (auto* location = deco->As()) { + auto& pipeline_stage_uses = str->PipelineStageUses(); + if (pipeline_stage_uses.size() != 1) { + TINT_ICE(Writer, diagnostics_) + << "invalid entry point IO struct uses"; + } + + if (pipeline_stage_uses.count( + sem::PipelineStageUsage::kVertexInput)) { + out << " : TEXCOORD" + std::to_string(location->value()); + } else if (pipeline_stage_uses.count( + sem::PipelineStageUsage::kVertexOutput)) { + out << " : TEXCOORD" + std::to_string(location->value()); + } else if (pipeline_stage_uses.count( + sem::PipelineStageUsage::kFragmentInput)) { + out << " : TEXCOORD" + std::to_string(location->value()); + } else if (pipeline_stage_uses.count( + sem::PipelineStageUsage::kFragmentOutput)) { + out << " : SV_Target" + std::to_string(location->value()); + } else { + TINT_ICE(Writer, diagnostics_) + << "invalid use of location decoration"; + } + } else if (auto* builtin = deco->As()) { + auto attr = builtin_to_attribute(builtin->value()); + if (attr.empty()) { + diagnostics_.add_error(diag::System::Writer, "unsupported builtin"); + return false; + } + out << " : " << attr; + } + } + + out << ";"; + } } - decrement_indent(); - make_indent(out); - - out << "};" << std::endl; + line() << "};"; return true; } -bool GeneratorImpl::EmitUnaryOp(std::ostream& pre, - std::ostream& out, +bool GeneratorImpl::EmitUnaryOp(std::ostream& out, ast::UnaryOpExpression* expr) { switch (expr->op()) { case ast::UnaryOp::kIndirection: case ast::UnaryOp::kAddressOf: - return EmitExpression(pre, out, expr->expr()); + return EmitExpression(out, expr->expr()); case ast::UnaryOp::kComplement: out << "~"; break; @@ -2899,7 +2802,7 @@ bool GeneratorImpl::EmitUnaryOp(std::ostream& pre, } out << "("; - if (!EmitExpression(pre, out, expr->expr())) { + if (!EmitExpression(out, expr->expr())) { return false; } @@ -2908,9 +2811,7 @@ bool GeneratorImpl::EmitUnaryOp(std::ostream& pre, return true; } -bool GeneratorImpl::EmitVariable(std::ostream& out, ast::Variable* var) { - make_indent(out); - +bool GeneratorImpl::EmitVariable(ast::Variable* var) { auto* sem = builder_.Sem().Get(var); auto* type = sem->Type()->UnwrapRef(); @@ -2921,21 +2822,7 @@ bool GeneratorImpl::EmitVariable(std::ostream& out, ast::Variable* var) { return false; } - std::ostringstream constructor_out; - constructor_out << " = "; - - if (var->constructor()) { - std::ostringstream pre; - if (!EmitExpression(pre, constructor_out, var->constructor())) { - return false; - } - out << pre.str(); - } else { - if (!EmitZeroValue(constructor_out, type)) { - return false; - } - } - + auto out = line(); if (var->is_const()) { out << "const "; } @@ -2943,15 +2830,24 @@ bool GeneratorImpl::EmitVariable(std::ostream& out, ast::Variable* var) { builder_.Symbols().NameFor(var->symbol()))) { return false; } - out << constructor_out.str() << ";" << std::endl; + + out << " = "; + + if (var->constructor()) { + if (!EmitExpression(out, var->constructor())) { + return false; + } + } else { + if (!EmitZeroValue(out, type)) { + return false; + } + } + out << ";"; return true; } -bool GeneratorImpl::EmitProgramConstVariable(std::ostream& out, - const ast::Variable* var) { - make_indent(out); - +bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) { for (auto* d : var->decorations()) { if (!d->Is()) { diagnostics_.add_error(diag::System::Writer, @@ -2964,48 +2860,45 @@ bool GeneratorImpl::EmitProgramConstVariable(std::ostream& out, return false; } - std::ostringstream constructor_out; - if (var->constructor() != nullptr) { - std::ostringstream pre; - if (!EmitExpression(pre, constructor_out, var->constructor())) { - return false; - } - out << pre.str(); - } - auto* sem = builder_.Sem().Get(var); auto* type = sem->Type(); if (sem->IsPipelineConstant()) { auto const_id = sem->ConstantId(); - out << "#ifndef " << kSpecConstantPrefix << const_id << std::endl; + line() << "#ifndef " << kSpecConstantPrefix << const_id; if (var->constructor() != nullptr) { - out << "#define " << kSpecConstantPrefix << const_id << " " - << constructor_out.str() << std::endl; + auto out = line(); + out << "#define " << kSpecConstantPrefix << const_id << " "; + if (!EmitExpression(out, var->constructor())) { + return false; + } } else { - out << "#error spec constant required for constant id " << const_id - << std::endl; + line() << "#error spec constant required for constant id " << const_id; } - out << "#endif" << std::endl; - out << "static const "; - if (!EmitTypeAndName(out, type, sem->StorageClass(), sem->Access(), - builder_.Symbols().NameFor(var->symbol()))) { - return false; + line() << "#endif"; + { + auto out = line(); + out << "static const "; + if (!EmitTypeAndName(out, type, sem->StorageClass(), sem->Access(), + builder_.Symbols().NameFor(var->symbol()))) { + return false; + } + out << " = " << kSpecConstantPrefix << const_id << ";"; } - out << " = " << kSpecConstantPrefix << const_id << ";" << std::endl; } else { + auto out = line(); out << "static const "; if (!EmitTypeAndName(out, type, sem->StorageClass(), sem->Access(), builder_.Symbols().NameFor(var->symbol()))) { return false; } - - if (var->constructor() != nullptr) { - out << " = " << constructor_out.str(); + out << " = "; + if (!EmitExpression(out, var->constructor())) { + return false; } - out << ";" << std::endl; + out << ";"; } return true; @@ -3026,23 +2919,6 @@ std::string GeneratorImpl::get_buffer_name(ast::Expression* expr) { return ""; } -template -bool GeneratorImpl::EmitBlockBraces(std::ostream& out, - const std::string& prefix, - F&& cb) { - out << prefix << (prefix.empty() ? "{" : " {") << std::endl; - increment_indent(); - - if (!cb()) { - return false; - } - - decrement_indent(); - make_indent(out); - out << "}"; - return true; -} - } // namespace hlsl } // namespace writer } // namespace tint diff --git a/src/writer/hlsl/generator_impl.h b/src/writer/hlsl/generator_impl.h index e46a6bda02..fd3c6bdbec 100644 --- a/src/writer/hlsl/generator_impl.h +++ b/src/writer/hlsl/generator_impl.h @@ -54,320 +54,246 @@ class GeneratorImpl : public TextGenerator { explicit GeneratorImpl(const Program* program); ~GeneratorImpl(); - /// @param out the output stream /// @returns true on successful generation; false otherwise - bool Generate(std::ostream& out); + bool Generate(); /// Handles an array accessor expression - /// @param pre the preamble for the expression stream /// @param out the output of the expression stream /// @param expr the expression to emit /// @returns true if the array accessor was emitted - bool EmitArrayAccessor(std::ostream& pre, - std::ostream& out, - ast::ArrayAccessorExpression* expr); + bool EmitArrayAccessor(std::ostream& out, ast::ArrayAccessorExpression* expr); /// Handles an assignment statement - /// @param out the output stream /// @param stmt the statement to emit /// @returns true if the statement was emitted successfully - bool EmitAssign(std::ostream& out, ast::AssignmentStatement* stmt); + bool EmitAssign(ast::AssignmentStatement* stmt); /// Handles generating a binary expression - /// @param pre the preamble for the expression stream /// @param out the output of the expression stream /// @param expr the binary expression /// @returns true if the expression was emitted, false otherwise - bool EmitBinary(std::ostream& pre, - std::ostream& out, - ast::BinaryExpression* expr); + bool EmitBinary(std::ostream& out, ast::BinaryExpression* expr); /// Handles generating a bitcast expression - /// @param pre the preamble for the expression stream /// @param out the output of the expression stream /// @param expr the as expression /// @returns true if the bitcast was emitted - bool EmitBitcast(std::ostream& pre, - std::ostream& out, - ast::BitcastExpression* expr); + bool EmitBitcast(std::ostream& out, ast::BitcastExpression* expr); + /// Emits a list of statements + /// @param stmts the statement list + /// @returns true if the statements were emitted successfully + bool EmitStatements(const ast::StatementList& stmts); + /// Emits a list of statements with an indentation + /// @param stmts the statement list + /// @returns true if the statements were emitted successfully + bool EmitStatementsWithIndent(const ast::StatementList& stmts); /// Handles a block statement - /// @param out the output stream /// @param stmt the statement to emit /// @returns true if the statement was emitted successfully - bool EmitBlock(std::ostream& out, const ast::BlockStatement* stmt); - /// Handles a block statement with a newline at the end - /// @param out the output stream - /// @param stmt the statement to emit - /// @returns true if the statement was emitted successfully - bool EmitIndentedBlockAndNewline(std::ostream& out, - ast::BlockStatement* stmt); - /// Handles a block statement with a newline at the end - /// @param out the output stream - /// @param stmt the statement to emit - /// @returns true if the statement was emitted successfully - bool EmitBlockAndNewline(std::ostream& out, const ast::BlockStatement* stmt); + bool EmitBlock(const ast::BlockStatement* stmt); /// Handles a break statement - /// @param out the output stream /// @param stmt the statement to emit /// @returns true if the statement was emitted successfully - bool EmitBreak(std::ostream& out, ast::BreakStatement* stmt); + bool EmitBreak(ast::BreakStatement* stmt); /// Handles generating a call expression - /// @param pre the preamble for the expression stream /// @param out the output of the expression stream /// @param expr the call expression /// @returns true if the call expression is emitted - bool EmitCall(std::ostream& pre, - std::ostream& out, - ast::CallExpression* expr); + bool EmitCall(std::ostream& out, ast::CallExpression* expr); /// Handles generating a call expression to a /// transform::DecomposeMemoryAccess::Intrinsic for a uniform buffer - /// @param pre the preamble for the expression stream /// @param out the output of the expression stream /// @param expr the call expression /// @param intrinsic the transform::DecomposeMemoryAccess::Intrinsic /// @returns true if the call expression is emitted bool EmitUniformBufferAccess( - std::ostream& pre, std::ostream& out, ast::CallExpression* expr, const transform::DecomposeMemoryAccess::Intrinsic* intrinsic); /// Handles generating a call expression to a /// transform::DecomposeMemoryAccess::Intrinsic for a storage buffer - /// @param pre the preamble for the expression stream /// @param out the output of the expression stream /// @param expr the call expression /// @param intrinsic the transform::DecomposeMemoryAccess::Intrinsic /// @returns true if the call expression is emitted bool EmitStorageBufferAccess( - std::ostream& pre, std::ostream& out, ast::CallExpression* expr, const transform::DecomposeMemoryAccess::Intrinsic* intrinsic); /// Handles generating a barrier intrinsic call - /// @param pre the preamble for the expression stream /// @param out the output of the expression stream /// @param intrinsic the semantic information for the barrier intrinsic /// @returns true if the call expression is emitted - bool EmitBarrierCall(std::ostream& pre, - std::ostream& out, - const sem::Intrinsic* intrinsic); + bool EmitBarrierCall(std::ostream& out, const sem::Intrinsic* intrinsic); /// Handles generating an atomic intrinsic call for a storage buffer variable - /// @param pre the preamble for the expression stream /// @param out the output of the expression stream /// @param expr the call expression /// @param op the atomic op /// @returns true if the call expression is emitted bool EmitStorageAtomicCall( - std::ostream& pre, std::ostream& out, ast::CallExpression* expr, transform::DecomposeMemoryAccess::Intrinsic::Op op); /// Handles generating an atomic intrinsic call for a workgroup variable - /// @param pre the preamble for the expression stream /// @param out the output of the expression stream /// @param expr the call expression /// @param intrinsic the semantic information for the atomic intrinsic /// @returns true if the call expression is emitted - bool EmitWorkgroupAtomicCall(std::ostream& pre, - std::ostream& out, + bool EmitWorkgroupAtomicCall(std::ostream& out, ast::CallExpression* expr, const sem::Intrinsic* intrinsic); /// Handles generating a call to a texture function (`textureSample`, /// `textureSampleGrad`, etc) - /// @param pre the preamble for the expression stream /// @param out the output of the expression stream /// @param expr the call expression /// @param intrinsic the semantic information for the texture intrinsic /// @returns true if the call expression is emitted - bool EmitTextureCall(std::ostream& pre, - std::ostream& out, + bool EmitTextureCall(std::ostream& out, ast::CallExpression* expr, const sem::Intrinsic* intrinsic); /// Handles generating a call to the `select()` intrinsic - /// @param pre the preamble of the expression stream /// @param out the output of the expression stream /// @param expr the call expression /// @returns true if the call expression is emitted - bool EmitSelectCall(std::ostream& pre, - std::ostream& out, - ast::CallExpression* expr); + bool EmitSelectCall(std::ostream& out, ast::CallExpression* expr); /// Handles generating a call to the `frexp()` intrinsic - /// @param pre the preamble of the expression stream /// @param out the output of the expression stream /// @param expr the call expression /// @param intrinsic the semantic information for the intrinsic /// @returns true if the call expression is emitted - bool EmitFrexpCall(std::ostream& pre, - std::ostream& out, + bool EmitFrexpCall(std::ostream& out, ast::CallExpression* expr, const sem::Intrinsic* intrinsic); /// Handles generating a call to the `isNormal()` intrinsic - /// @param pre the preamble of the expression stream /// @param out the output of the expression stream /// @param expr the call expression /// @param intrinsic the semantic information for the intrinsic /// @returns true if the call expression is emitted - bool EmitIsNormalCall(std::ostream& pre, - std::ostream& out, + bool EmitIsNormalCall(std::ostream& out, ast::CallExpression* expr, const sem::Intrinsic* intrinsic); /// Handles generating a call to data packing intrinsic - /// @param pre the preamble of the expression stream /// @param out the output of the expression stream /// @param expr the call expression /// @param intrinsic the semantic information for the texture intrinsic /// @returns true if the call expression is emitted - bool EmitDataPackingCall(std::ostream& pre, - std::ostream& out, + bool EmitDataPackingCall(std::ostream& out, ast::CallExpression* expr, const sem::Intrinsic* intrinsic); /// Handles generating a call to data unpacking intrinsic - /// @param pre the preamble of the expression stream /// @param out the output of the expression stream /// @param expr the call expression /// @param intrinsic the semantic information for the texture intrinsic /// @returns true if the call expression is emitted - bool EmitDataUnpackingCall(std::ostream& pre, - std::ostream& out, + bool EmitDataUnpackingCall(std::ostream& out, ast::CallExpression* expr, const sem::Intrinsic* intrinsic); /// Handles a case statement - /// @param out the output stream /// @param stmt the statement - /// @returns true if the statment was emitted successfully - bool EmitCase(std::ostream& out, ast::CaseStatement* stmt); + /// @returns true if the statement was emitted successfully + bool EmitCase(ast::CaseStatement* stmt); /// Handles generating constructor expressions - /// @param pre the preamble for the expression stream /// @param out the output of the expression stream /// @param expr the constructor expression /// @returns true if the expression was emitted - bool EmitConstructor(std::ostream& pre, - std::ostream& out, - ast::ConstructorExpression* expr); + bool EmitConstructor(std::ostream& out, ast::ConstructorExpression* expr); /// Handles generating a discard statement - /// @param out the output stream /// @param stmt the discard statement /// @returns true if the statement was successfully emitted - bool EmitDiscard(std::ostream& out, ast::DiscardStatement* stmt); + bool EmitDiscard(ast::DiscardStatement* stmt); /// Handles generating a scalar constructor - /// @param pre the preamble for the expression stream /// @param out the output of the expression stream /// @param expr the scalar constructor expression /// @returns true if the scalar constructor is emitted - bool EmitScalarConstructor(std::ostream& pre, - std::ostream& out, + bool EmitScalarConstructor(std::ostream& out, ast::ScalarConstructorExpression* expr); /// Handles emitting a type constructor - /// @param pre the preamble for the expression stream /// @param out the output of the expression stream /// @param expr the type constructor expression /// @returns true if the constructor is emitted - bool EmitTypeConstructor(std::ostream& pre, - std::ostream& out, + bool EmitTypeConstructor(std::ostream& out, ast::TypeConstructorExpression* expr); /// Handles a continue statement - /// @param out the output stream /// @param stmt the statement to emit /// @returns true if the statement was emitted successfully - bool EmitContinue(std::ostream& out, ast::ContinueStatement* stmt); + bool EmitContinue(ast::ContinueStatement* stmt); /// Handles generate an Expression - /// @param pre the preamble for the expression stream /// @param out the output of the expression stream /// @param expr the expression /// @returns true if the expression was emitted - bool EmitExpression(std::ostream& pre, - std::ostream& out, - ast::Expression* expr); + bool EmitExpression(std::ostream& out, ast::Expression* expr); /// Handles generating a function - /// @param out the output stream /// @param func the function to generate /// @returns true if the function was emitted - bool EmitFunction(std::ostream& out, ast::Function* func); + bool EmitFunction(ast::Function* func); /// Handles emitting a global variable - /// @param out the output stream /// @param global the global variable /// @returns true on success - bool EmitGlobalVariable(std::ostream& out, ast::Variable* global); + bool EmitGlobalVariable(ast::Variable* global); /// Handles emitting a global variable with the uniform storage class - /// @param out the output stream /// @param var the global variable /// @returns true on success - bool EmitUniformVariable(std::ostream& out, const sem::Variable* var); + bool EmitUniformVariable(const sem::Variable* var); /// Handles emitting a global variable with the storage storage class - /// @param out the output stream /// @param var the global variable /// @returns true on success - bool EmitStorageVariable(std::ostream& out, const sem::Variable* var); + bool EmitStorageVariable(const sem::Variable* var); /// Handles emitting a global variable with the handle storage class - /// @param out the output stream /// @param var the global variable /// @returns true on success - bool EmitHandleVariable(std::ostream& out, const sem::Variable* var); + bool EmitHandleVariable(const sem::Variable* var); /// Handles emitting a global variable with the private storage class - /// @param out the output stream /// @param var the global variable /// @returns true on success - bool EmitPrivateVariable(std::ostream& out, const sem::Variable* var); + bool EmitPrivateVariable(const sem::Variable* var); /// Handles emitting a global variable with the workgroup storage class - /// @param out the output stream /// @param var the global variable /// @returns true on success - bool EmitWorkgroupVariable(std::ostream& out, const sem::Variable* var); + bool EmitWorkgroupVariable(const sem::Variable* var); /// Handles emitting the entry point function - /// @param out the output stream /// @param func the entry point /// @returns true if the entry point function was emitted - bool EmitEntryPointFunction(std::ostream& out, ast::Function* func); + bool EmitEntryPointFunction(ast::Function* func); /// Handles an if statement - /// @param out the output stream /// @param stmt the statement to emit /// @returns true if the statement was successfully emitted - bool EmitIf(std::ostream& out, ast::IfStatement* stmt); + bool EmitIf(ast::IfStatement* stmt); /// Handles a literal /// @param out the output stream /// @param lit the literal to emit /// @returns true if the literal was successfully emitted bool EmitLiteral(std::ostream& out, ast::Literal* lit); /// Handles a loop statement - /// @param out the output stream /// @param stmt the statement to emit /// @returns true if the statement was emitted - bool EmitLoop(std::ostream& out, ast::LoopStatement* stmt); + bool EmitLoop(ast::LoopStatement* stmt); /// Handles generating an identifier expression - /// @param pre the preamble for the expression stream /// @param out the output of the expression stream /// @param expr the identifier expression /// @returns true if the identifeir was emitted - bool EmitIdentifier(std::ostream& pre, - std::ostream& out, - ast::IdentifierExpression* expr); + bool EmitIdentifier(std::ostream& out, ast::IdentifierExpression* expr); /// Handles a member accessor expression - /// @param pre the preamble for the expression stream /// @param out the output of the expression stream /// @param expr the member accessor expression /// @returns true if the member accessor was emitted - bool EmitMemberAccessor(std::ostream& pre, - std::ostream& out, + bool EmitMemberAccessor(std::ostream& out, ast::MemberAccessorExpression* expr); /// Handles return statements - /// @param out the output stream /// @param stmt the statement to emit /// @returns true if the statement was successfully emitted - bool EmitReturn(std::ostream& out, ast::ReturnStatement* stmt); + bool EmitReturn(ast::ReturnStatement* stmt); /// Handles statement - /// @param out the output stream /// @param stmt the statement to emit /// @returns true if the statement was emitted - bool EmitStatement(std::ostream& out, ast::Statement* stmt); + bool EmitStatement(ast::Statement* stmt); /// Handles generating a switch statement - /// @param out the output stream /// @param stmt the statement to emit /// @returns true if the statement was emitted - bool EmitSwitch(std::ostream& out, ast::SwitchStatement* stmt); + bool EmitSwitch(ast::SwitchStatement* stmt); /// Handles generating type /// @param out the output stream /// @param type the type to generate @@ -396,33 +322,27 @@ class GeneratorImpl : public TextGenerator { ast::Access access, const std::string& name); /// Handles generating a structure declaration - /// @param out the output stream /// @param ty the struct to generate /// @returns true if the struct is emitted - bool EmitStructType(std::ostream& out, const sem::Struct* ty); + bool EmitStructType(const sem::Struct* ty); /// Handles a unary op expression - /// @param pre the preamble for the expression stream /// @param out the output of the expression stream /// @param expr the expression to emit /// @returns true if the expression was emitted - bool EmitUnaryOp(std::ostream& pre, - std::ostream& out, - ast::UnaryOpExpression* expr); + bool EmitUnaryOp(std::ostream& out, ast::UnaryOpExpression* expr); /// Emits the zero value for the given type /// @param out the output stream /// @param type the type to emit the value for /// @returns true if the zero value was successfully emitted. bool EmitZeroValue(std::ostream& out, const sem::Type* type); /// Handles generating a variable - /// @param out the output stream /// @param var the variable to generate /// @returns true if the variable was emitted - bool EmitVariable(std::ostream& out, ast::Variable* var); + bool EmitVariable(ast::Variable* var); /// Handles generating a program scope constant variable - /// @param out the output stream /// @param var the variable to emit /// @returns true if the variable was emitted - bool EmitProgramConstVariable(std::ostream& out, const ast::Variable* var); + bool EmitProgramConstVariable(const ast::Variable* var); /// Handles generating a builtin method name /// @param intrinsic the semantic info for the intrinsic @@ -466,29 +386,8 @@ class GeneratorImpl : public TextGenerator { return builder_.TypeOf(type_decl); } - /// Emits `prefix`, followed by an opening brace `{`, then calls `cb` to emit - /// the block body, then finally emits the closing brace `}`. - /// @param out the output stream - /// @param prefix the string to emit before the opening brace - /// @param cb a function or function-like object with the signature `bool()` - /// that emits the block body. - /// @returns the return value of `cb`. - template - bool EmitBlockBraces(std::ostream& out, const std::string& prefix, F&& cb); - - /// Emits an opening brace `{`, then calls `cb` to emit the block body, then - /// finally emits the closing brace `}`. - /// @param out the output stream - /// @param cb a function or function-like object with the signature `bool()` - /// that emits the block body. - /// @returns the return value of `cb`. - template - bool EmitBlockBraces(std::ostream& out, F&& cb) { - return EmitBlockBraces(out, "", std::forward(cb)); - } - ProgramBuilder builder_; - std::function emit_continuing_; + std::function emit_continuing_; std::unordered_map structure_builders_; }; diff --git a/src/writer/hlsl/generator_impl_array_accessor_test.cc b/src/writer/hlsl/generator_impl_array_accessor_test.cc index 53c42ad509..b2fb021117 100644 --- a/src/writer/hlsl/generator_impl_array_accessor_test.cc +++ b/src/writer/hlsl/generator_impl_array_accessor_test.cc @@ -28,8 +28,9 @@ TEST_F(HlslGeneratorImplTest_Expression, ArrayAccessor) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitExpression(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), "ary[5]"); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), "ary[5]"); } } // namespace diff --git a/src/writer/hlsl/generator_impl_assign_test.cc b/src/writer/hlsl/generator_impl_assign_test.cc index 54e957a517..f5a0711524 100644 --- a/src/writer/hlsl/generator_impl_assign_test.cc +++ b/src/writer/hlsl/generator_impl_assign_test.cc @@ -31,8 +31,8 @@ TEST_F(HlslGeneratorImplTest_Assign, Emit_Assign) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitStatement(out, assign)) << gen.error(); - EXPECT_EQ(result(), " lhs = rhs;\n"); + ASSERT_TRUE(gen.EmitStatement(assign)) << gen.error(); + EXPECT_EQ(gen.result(), " lhs = rhs;\n"); } } // namespace diff --git a/src/writer/hlsl/generator_impl_binary_test.cc b/src/writer/hlsl/generator_impl_binary_test.cc index 743bb2bf8b..435ce1dea8 100644 --- a/src/writer/hlsl/generator_impl_binary_test.cc +++ b/src/writer/hlsl/generator_impl_binary_test.cc @@ -56,8 +56,9 @@ TEST_P(HlslBinaryTest, Emit_f32) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitExpression(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), params.result); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), params.result); } TEST_P(HlslBinaryTest, Emit_u32) { auto params = GetParam(); @@ -74,8 +75,9 @@ TEST_P(HlslBinaryTest, Emit_u32) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitExpression(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), params.result); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), params.result); } TEST_P(HlslBinaryTest, Emit_i32) { auto params = GetParam(); @@ -98,8 +100,9 @@ TEST_P(HlslBinaryTest, Emit_i32) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitExpression(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), params.result); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), params.result); } INSTANTIATE_TEST_SUITE_P( HlslGeneratorImplTest, @@ -133,8 +136,9 @@ TEST_F(HlslGeneratorImplTest_Binary, Multiply_VectorScalar) { GeneratorImpl& gen = Build(); - EXPECT_TRUE(gen.EmitExpression(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), + std::stringstream out; + EXPECT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), "(float3(1.0f, 1.0f, 1.0f) * " "1.0f)"); } @@ -150,8 +154,9 @@ TEST_F(HlslGeneratorImplTest_Binary, Multiply_ScalarVector) { GeneratorImpl& gen = Build(); - EXPECT_TRUE(gen.EmitExpression(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), + std::stringstream out; + EXPECT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), "(1.0f * float3(1.0f, 1.0f, " "1.0f))"); } @@ -167,8 +172,9 @@ TEST_F(HlslGeneratorImplTest_Binary, Multiply_MatrixScalar) { GeneratorImpl& gen = Build(); - EXPECT_TRUE(gen.EmitExpression(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), "(mat * 1.0f)"); + std::stringstream out; + EXPECT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), "(mat * 1.0f)"); } TEST_F(HlslGeneratorImplTest_Binary, Multiply_ScalarMatrix) { @@ -182,8 +188,9 @@ TEST_F(HlslGeneratorImplTest_Binary, Multiply_ScalarMatrix) { GeneratorImpl& gen = Build(); - EXPECT_TRUE(gen.EmitExpression(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), "(1.0f * mat)"); + std::stringstream out; + EXPECT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), "(1.0f * mat)"); } TEST_F(HlslGeneratorImplTest_Binary, Multiply_MatrixVector) { @@ -197,8 +204,9 @@ TEST_F(HlslGeneratorImplTest_Binary, Multiply_MatrixVector) { GeneratorImpl& gen = Build(); - EXPECT_TRUE(gen.EmitExpression(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), "mul(float3(1.0f, 1.0f, 1.0f), mat)"); + std::stringstream out; + EXPECT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), "mul(float3(1.0f, 1.0f, 1.0f), mat)"); } TEST_F(HlslGeneratorImplTest_Binary, Multiply_VectorMatrix) { @@ -212,8 +220,9 @@ TEST_F(HlslGeneratorImplTest_Binary, Multiply_VectorMatrix) { GeneratorImpl& gen = Build(); - EXPECT_TRUE(gen.EmitExpression(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), "mul(mat, float3(1.0f, 1.0f, 1.0f))"); + std::stringstream out; + EXPECT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), "mul(mat, float3(1.0f, 1.0f, 1.0f))"); } TEST_F(HlslGeneratorImplTest_Binary, Multiply_MatrixMatrix) { @@ -226,8 +235,9 @@ TEST_F(HlslGeneratorImplTest_Binary, Multiply_MatrixMatrix) { GeneratorImpl& gen = Build(); - EXPECT_TRUE(gen.EmitExpression(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), "mul(rhs, lhs)"); + std::stringstream out; + EXPECT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), "mul(rhs, lhs)"); } TEST_F(HlslGeneratorImplTest_Binary, Logical_And) { @@ -240,9 +250,10 @@ TEST_F(HlslGeneratorImplTest_Binary, Logical_And) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitExpression(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), "(tint_tmp)"); - EXPECT_EQ(pre_result(), R"(bool tint_tmp = a; + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), "(tint_tmp)"); + EXPECT_EQ(gen.result(), R"(bool tint_tmp = a; if (tint_tmp) { tint_tmp = b; } @@ -266,19 +277,20 @@ TEST_F(HlslGeneratorImplTest_Binary, Logical_Multi) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitExpression(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), "(tint_tmp_1)"); - EXPECT_EQ(pre_result(), R"(bool tint_tmp = a; -if (tint_tmp) { - tint_tmp = b; + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), "(tint_tmp)"); + EXPECT_EQ(gen.result(), R"(bool tint_tmp_1 = a; +if (tint_tmp_1) { + tint_tmp_1 = b; } -bool tint_tmp_1 = (tint_tmp); -if (!tint_tmp_1) { +bool tint_tmp = (tint_tmp_1); +if (!tint_tmp) { bool tint_tmp_2 = c; if (!tint_tmp_2) { tint_tmp_2 = d; } - tint_tmp_1 = (tint_tmp_2); + tint_tmp = (tint_tmp_2); } )"); } @@ -293,9 +305,10 @@ TEST_F(HlslGeneratorImplTest_Binary, Logical_Or) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitExpression(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), "(tint_tmp)"); - EXPECT_EQ(pre_result(), R"(bool tint_tmp = a; + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), "(tint_tmp)"); + EXPECT_EQ(gen.result(), R"(bool tint_tmp = a; if (!tint_tmp) { tint_tmp = b; } @@ -338,8 +351,8 @@ TEST_F(HlslGeneratorImplTest_Binary, If_WithLogical) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitStatement(out, expr)) << gen.error(); - EXPECT_EQ(result(), R"(bool tint_tmp = a; + ASSERT_TRUE(gen.EmitStatement(expr)) << gen.error(); + EXPECT_EQ(gen.result(), R"(bool tint_tmp = a; if (tint_tmp) { tint_tmp = b; } @@ -375,16 +388,16 @@ TEST_F(HlslGeneratorImplTest_Binary, Return_WithLogical) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitStatement(out, expr)) << gen.error(); - EXPECT_EQ(result(), R"(bool tint_tmp = a; -if (tint_tmp) { - tint_tmp = b; + ASSERT_TRUE(gen.EmitStatement(expr)) << gen.error(); + EXPECT_EQ(gen.result(), R"(bool tint_tmp_1 = a; +if (tint_tmp_1) { + tint_tmp_1 = b; } -bool tint_tmp_1 = (tint_tmp); -if (!tint_tmp_1) { - tint_tmp_1 = c; +bool tint_tmp = (tint_tmp_1); +if (!tint_tmp) { + tint_tmp = c; } -return (tint_tmp_1); +return (tint_tmp); )"); } @@ -406,16 +419,16 @@ TEST_F(HlslGeneratorImplTest_Binary, Assign_WithLogical) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitStatement(out, expr)) << gen.error(); - EXPECT_EQ(result(), R"(bool tint_tmp = b; -if (!tint_tmp) { - tint_tmp = c; + ASSERT_TRUE(gen.EmitStatement(expr)) << gen.error(); + EXPECT_EQ(gen.result(), R"(bool tint_tmp_1 = b; +if (!tint_tmp_1) { + tint_tmp_1 = c; } -bool tint_tmp_1 = (tint_tmp); -if (tint_tmp_1) { - tint_tmp_1 = d; +bool tint_tmp = (tint_tmp_1); +if (tint_tmp) { + tint_tmp = d; } -a = (tint_tmp_1); +a = (tint_tmp); )"); } @@ -438,16 +451,16 @@ TEST_F(HlslGeneratorImplTest_Binary, Decl_WithLogical) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitStatement(out, decl)) << gen.error(); - EXPECT_EQ(result(), R"(bool tint_tmp = b; -if (tint_tmp) { - tint_tmp = c; + ASSERT_TRUE(gen.EmitStatement(decl)) << gen.error(); + EXPECT_EQ(gen.result(), R"(bool tint_tmp_1 = b; +if (tint_tmp_1) { + tint_tmp_1 = c; } -bool tint_tmp_1 = (tint_tmp); -if (!tint_tmp_1) { - tint_tmp_1 = d; +bool tint_tmp = (tint_tmp_1); +if (!tint_tmp) { + tint_tmp = d; } -bool a = (tint_tmp_1); +bool a = (tint_tmp); )"); } @@ -467,8 +480,9 @@ TEST_F(HlslGeneratorImplTest_Binary, Bitcast_WithLogical) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitExpression(pre, out, expr)) << gen.error(); - EXPECT_EQ(pre_result(), R"(bool tint_tmp = a; + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error(); + EXPECT_EQ(gen.result(), R"(bool tint_tmp = a; if (tint_tmp) { bool tint_tmp_1 = b; if (!tint_tmp_1) { @@ -477,7 +491,7 @@ if (tint_tmp) { tint_tmp = (tint_tmp_1); } )"); - EXPECT_EQ(result(), R"(asint((tint_tmp)))"); + EXPECT_EQ(out.str(), R"(asint((tint_tmp)))"); } TEST_F(HlslGeneratorImplTest_Binary, Call_WithLogical) { @@ -512,8 +526,8 @@ TEST_F(HlslGeneratorImplTest_Binary, Call_WithLogical) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitStatement(out, expr)) << gen.error(); - EXPECT_EQ(result(), R"(bool tint_tmp = a; + ASSERT_TRUE(gen.EmitStatement(expr)) << gen.error(); + EXPECT_EQ(gen.result(), R"(bool tint_tmp = a; if (tint_tmp) { tint_tmp = b; } @@ -521,19 +535,19 @@ bool tint_tmp_1 = c; if (!tint_tmp_1) { tint_tmp_1 = d; } -bool tint_tmp_2 = a; -if (!tint_tmp_2) { - tint_tmp_2 = c; +bool tint_tmp_3 = a; +if (!tint_tmp_3) { + tint_tmp_3 = c; } -bool tint_tmp_3 = (tint_tmp_2); -if (tint_tmp_3) { +bool tint_tmp_2 = (tint_tmp_3); +if (tint_tmp_2) { bool tint_tmp_4 = b; if (!tint_tmp_4) { tint_tmp_4 = d; } - tint_tmp_3 = (tint_tmp_4); + tint_tmp_2 = (tint_tmp_4); } -foo((tint_tmp), (tint_tmp_1), (tint_tmp_3)); +foo((tint_tmp), (tint_tmp_1), (tint_tmp_2)); )"); } diff --git a/src/writer/hlsl/generator_impl_bitcast_test.cc b/src/writer/hlsl/generator_impl_bitcast_test.cc index 45de152560..9cb97d8b45 100644 --- a/src/writer/hlsl/generator_impl_bitcast_test.cc +++ b/src/writer/hlsl/generator_impl_bitcast_test.cc @@ -27,8 +27,9 @@ TEST_F(HlslGeneratorImplTest_Bitcast, EmitExpression_Bitcast_Float) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitExpression(pre, out, bitcast)) << gen.error(); - EXPECT_EQ(result(), "asfloat(1)"); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, bitcast)) << gen.error(); + EXPECT_EQ(out.str(), "asfloat(1)"); } TEST_F(HlslGeneratorImplTest_Bitcast, EmitExpression_Bitcast_Int) { @@ -37,8 +38,9 @@ TEST_F(HlslGeneratorImplTest_Bitcast, EmitExpression_Bitcast_Int) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitExpression(pre, out, bitcast)) << gen.error(); - EXPECT_EQ(result(), "asint(1u)"); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, bitcast)) << gen.error(); + EXPECT_EQ(out.str(), "asint(1u)"); } TEST_F(HlslGeneratorImplTest_Bitcast, EmitExpression_Bitcast_Uint) { @@ -47,8 +49,9 @@ TEST_F(HlslGeneratorImplTest_Bitcast, EmitExpression_Bitcast_Uint) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitExpression(pre, out, bitcast)) << gen.error(); - EXPECT_EQ(result(), "asuint(1)"); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, bitcast)) << gen.error(); + EXPECT_EQ(out.str(), "asuint(1)"); } } // namespace diff --git a/src/writer/hlsl/generator_impl_block_test.cc b/src/writer/hlsl/generator_impl_block_test.cc index 535304bd77..4aec6a349b 100644 --- a/src/writer/hlsl/generator_impl_block_test.cc +++ b/src/writer/hlsl/generator_impl_block_test.cc @@ -29,27 +29,13 @@ TEST_F(HlslGeneratorImplTest_Block, Emit_Block) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitStatement(out, b)) << gen.error(); - EXPECT_EQ(result(), R"( { + ASSERT_TRUE(gen.EmitStatement(b)) << gen.error(); + EXPECT_EQ(gen.result(), R"( { discard; } )"); } -TEST_F(HlslGeneratorImplTest_Block, Emit_Block_WithoutNewline) { - auto* b = Block(create()); - WrapInFunction(b); - - GeneratorImpl& gen = Build(); - - gen.increment_indent(); - - ASSERT_TRUE(gen.EmitBlock(out, b)) << gen.error(); - EXPECT_EQ(result(), R"({ - discard; - })"); -} - } // namespace } // namespace hlsl } // namespace writer diff --git a/src/writer/hlsl/generator_impl_break_test.cc b/src/writer/hlsl/generator_impl_break_test.cc index dbf3241f4a..b2f532fc08 100644 --- a/src/writer/hlsl/generator_impl_break_test.cc +++ b/src/writer/hlsl/generator_impl_break_test.cc @@ -29,8 +29,8 @@ TEST_F(HlslGeneratorImplTest_Break, Emit_Break) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitStatement(out, b)) << gen.error(); - EXPECT_EQ(result(), " break;\n"); + ASSERT_TRUE(gen.EmitStatement(b)) << gen.error(); + EXPECT_EQ(gen.result(), " break;\n"); } } // namespace diff --git a/src/writer/hlsl/generator_impl_call_test.cc b/src/writer/hlsl/generator_impl_call_test.cc index eadfcd406e..a0391e557c 100644 --- a/src/writer/hlsl/generator_impl_call_test.cc +++ b/src/writer/hlsl/generator_impl_call_test.cc @@ -31,8 +31,9 @@ TEST_F(HlslGeneratorImplTest_Call, EmitExpression_Call_WithoutParams) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitExpression(pre, out, call)) << gen.error(); - EXPECT_EQ(result(), "my_func()"); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); + EXPECT_EQ(out.str(), "my_func()"); } TEST_F(HlslGeneratorImplTest_Call, EmitExpression_Call_WithParams) { @@ -50,8 +51,9 @@ TEST_F(HlslGeneratorImplTest_Call, EmitExpression_Call_WithParams) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitExpression(pre, out, call)) << gen.error(); - EXPECT_EQ(result(), "my_func(param1, param2)"); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); + EXPECT_EQ(out.str(), "my_func(param1, param2)"); } TEST_F(HlslGeneratorImplTest_Call, EmitStatement_Call) { @@ -70,8 +72,8 @@ TEST_F(HlslGeneratorImplTest_Call, EmitStatement_Call) { GeneratorImpl& gen = Build(); gen.increment_indent(); - ASSERT_TRUE(gen.EmitStatement(out, call)) << gen.error(); - EXPECT_EQ(result(), " my_func(param1, param2);\n"); + ASSERT_TRUE(gen.EmitStatement(call)) << gen.error(); + EXPECT_EQ(gen.result(), " my_func(param1, param2);\n"); } } // namespace diff --git a/src/writer/hlsl/generator_impl_case_test.cc b/src/writer/hlsl/generator_impl_case_test.cc index b892acbfa2..93e80a69e2 100644 --- a/src/writer/hlsl/generator_impl_case_test.cc +++ b/src/writer/hlsl/generator_impl_case_test.cc @@ -33,8 +33,8 @@ TEST_F(HlslGeneratorImplTest_Case, Emit_Case) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitCase(out, c)) << gen.error(); - EXPECT_EQ(result(), R"( case 5: { + ASSERT_TRUE(gen.EmitCase(c)) << gen.error(); + EXPECT_EQ(gen.result(), R"( case 5: { break; } )"); @@ -50,8 +50,8 @@ TEST_F(HlslGeneratorImplTest_Case, Emit_Case_BreaksByDefault) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitCase(out, c)) << gen.error(); - EXPECT_EQ(result(), R"( case 5: { + ASSERT_TRUE(gen.EmitCase(c)) << gen.error(); + EXPECT_EQ(gen.result(), R"( case 5: { break; } )"); @@ -68,8 +68,8 @@ TEST_F(HlslGeneratorImplTest_Case, Emit_Case_WithFallthrough) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitCase(out, c)) << gen.error(); - EXPECT_EQ(result(), R"( case 5: { + ASSERT_TRUE(gen.EmitCase(c)) << gen.error(); + EXPECT_EQ(gen.result(), R"( case 5: { /* fallthrough */ } )"); @@ -87,8 +87,8 @@ TEST_F(HlslGeneratorImplTest_Case, Emit_Case_MultipleSelectors) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitCase(out, c)) << gen.error(); - EXPECT_EQ(result(), R"( case 5: + ASSERT_TRUE(gen.EmitCase(c)) << gen.error(); + EXPECT_EQ(gen.result(), R"( case 5: case 6: { break; } @@ -104,8 +104,8 @@ TEST_F(HlslGeneratorImplTest_Case, Emit_Case_Default) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitCase(out, c)) << gen.error(); - EXPECT_EQ(result(), R"( default: { + ASSERT_TRUE(gen.EmitCase(c)) << gen.error(); + EXPECT_EQ(gen.result(), R"( default: { break; } )"); diff --git a/src/writer/hlsl/generator_impl_cast_test.cc b/src/writer/hlsl/generator_impl_cast_test.cc index f123536dbb..b281f4bc1f 100644 --- a/src/writer/hlsl/generator_impl_cast_test.cc +++ b/src/writer/hlsl/generator_impl_cast_test.cc @@ -27,8 +27,9 @@ TEST_F(HlslGeneratorImplTest_Cast, EmitExpression_Cast_Scalar) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitExpression(pre, out, cast)) << gen.error(); - EXPECT_EQ(result(), "float(1)"); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, cast)) << gen.error(); + EXPECT_EQ(out.str(), "float(1)"); } TEST_F(HlslGeneratorImplTest_Cast, EmitExpression_Cast_Vector) { @@ -37,8 +38,9 @@ TEST_F(HlslGeneratorImplTest_Cast, EmitExpression_Cast_Vector) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitExpression(pre, out, cast)) << gen.error(); - EXPECT_EQ(result(), "float3(int3(1, 2, 3))"); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, cast)) << gen.error(); + EXPECT_EQ(out.str(), "float3(int3(1, 2, 3))"); } } // namespace diff --git a/src/writer/hlsl/generator_impl_constructor_test.cc b/src/writer/hlsl/generator_impl_constructor_test.cc index 9d1822619b..429b86daec 100644 --- a/src/writer/hlsl/generator_impl_constructor_test.cc +++ b/src/writer/hlsl/generator_impl_constructor_test.cc @@ -29,8 +29,8 @@ TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Bool) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("false")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("false")); } TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Int) { @@ -38,8 +38,8 @@ TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Int) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("-12345")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("-12345")); } TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_UInt) { @@ -47,8 +47,8 @@ TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_UInt) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("56779u")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("56779u")); } TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Float) { @@ -57,8 +57,8 @@ TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Float) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("1073741824.0f")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("1073741824.0f")); } TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Float) { @@ -66,8 +66,8 @@ TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Float) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("float(-0.000012f)")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("float(-0.000012f)")); } TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Bool) { @@ -75,8 +75,8 @@ TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Bool) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("bool(true)")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("bool(true)")); } TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Int) { @@ -84,8 +84,8 @@ TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Int) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("int(-12345)")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("int(-12345)")); } TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Uint) { @@ -93,8 +93,8 @@ TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Uint) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("uint(12345u)")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("uint(12345u)")); } TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec) { @@ -102,8 +102,8 @@ TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("float3(1.0f, 2.0f, 3.0f)")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("float3(1.0f, 2.0f, 3.0f)")); } TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec_Empty) { @@ -111,8 +111,8 @@ TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec_Empty) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("float3(0.0f, 0.0f, 0.0f)")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("float3(0.0f, 0.0f, 0.0f)")); } TEST_F(HlslGeneratorImplTest_Constructor, @@ -121,8 +121,8 @@ TEST_F(HlslGeneratorImplTest_Constructor, GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("float3((2.0f).xxx)")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("float3((2.0f).xxx)")); } TEST_F(HlslGeneratorImplTest_Constructor, @@ -131,8 +131,8 @@ TEST_F(HlslGeneratorImplTest_Constructor, GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("bool3((true).xxx)")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("bool3((true).xxx)")); } TEST_F(HlslGeneratorImplTest_Constructor, @@ -141,8 +141,8 @@ TEST_F(HlslGeneratorImplTest_Constructor, GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("int3((2).xxx)")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("int3((2).xxx)")); } TEST_F(HlslGeneratorImplTest_Constructor, @@ -151,8 +151,8 @@ TEST_F(HlslGeneratorImplTest_Constructor, GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("uint3((2u).xxx)")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("uint3((2u).xxx)")); } TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Mat) { @@ -161,10 +161,10 @@ TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Mat) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); EXPECT_THAT( - result(), + gen.result(), HasSubstr( "float2x3(float3(1.0f, 2.0f, 3.0f), float3(3.0f, 4.0f, 5.0f))")); } @@ -174,9 +174,9 @@ TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Mat_Empty) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); - EXPECT_THAT(result(), + EXPECT_THAT(gen.result(), HasSubstr("float2x3(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)")); } @@ -187,8 +187,8 @@ TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Array) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("{float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f)," " float3(7.0f, 8.0f, 9.0f)}")); } @@ -200,8 +200,8 @@ TEST_F(HlslGeneratorImplTest_Constructor, GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("{float3(0.0f, 0.0f, 0.0f), float3(0.0f, 0.0f, 0.0f)," " float3(0.0f, 0.0f, 0.0f)}")); } @@ -217,8 +217,8 @@ TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Struct) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("{1, 2.0f, int3(3, 4, 5)}")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("{1, 2.0f, int3(3, 4, 5)}")); } TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Struct_Empty) { @@ -232,8 +232,8 @@ TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Struct_Empty) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("{0, 0.0f, int3(0, 0, 0)}")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("{0, 0.0f, int3(0, 0, 0)}")); } } // namespace diff --git a/src/writer/hlsl/generator_impl_continue_test.cc b/src/writer/hlsl/generator_impl_continue_test.cc index 6a2482b6ae..e312b826ed 100644 --- a/src/writer/hlsl/generator_impl_continue_test.cc +++ b/src/writer/hlsl/generator_impl_continue_test.cc @@ -29,8 +29,8 @@ TEST_F(HlslGeneratorImplTest_Continue, Emit_Continue) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitStatement(out, loop)) << gen.error(); - EXPECT_EQ(result(), R"( while (true) { + ASSERT_TRUE(gen.EmitStatement(loop)) << gen.error(); + EXPECT_EQ(gen.result(), R"( while (true) { continue; } )"); diff --git a/src/writer/hlsl/generator_impl_discard_test.cc b/src/writer/hlsl/generator_impl_discard_test.cc index e738ef7578..e7a5cca070 100644 --- a/src/writer/hlsl/generator_impl_discard_test.cc +++ b/src/writer/hlsl/generator_impl_discard_test.cc @@ -29,8 +29,8 @@ TEST_F(HlslGeneratorImplTest_Discard, Emit_Discard) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitStatement(out, stmt)) << gen.error(); - EXPECT_EQ(result(), " discard;\n"); + ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.error(); + EXPECT_EQ(gen.result(), " discard;\n"); } } // namespace diff --git a/src/writer/hlsl/generator_impl_function_test.cc b/src/writer/hlsl/generator_impl_function_test.cc index 7af36c4b55..6150010a01 100644 --- a/src/writer/hlsl/generator_impl_function_test.cc +++ b/src/writer/hlsl/generator_impl_function_test.cc @@ -38,8 +38,8 @@ TEST_F(HlslGeneratorImplTest_Function, Emit_Function) { gen.increment_indent(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), R"( void my_func() { + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"( void my_func() { return; } )"); @@ -55,8 +55,8 @@ TEST_F(HlslGeneratorImplTest_Function, Emit_Function_Name_Collision) { gen.increment_indent(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr(R"( void tint_symbol() { + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr(R"( void tint_symbol() { return; })")); } @@ -72,8 +72,8 @@ TEST_F(HlslGeneratorImplTest_Function, Emit_Function_WithParams) { gen.increment_indent(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), R"( void my_func(float a, int b) { + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"( void my_func(float a, int b) { return; } )"); @@ -88,8 +88,8 @@ TEST_F(HlslGeneratorImplTest_Function, GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), R"(void main() { + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(void main() { return; } )"); @@ -104,8 +104,8 @@ TEST_F(HlslGeneratorImplTest_Function, PtrParameter) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr(R"(float f(inout float foo) { + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr(R"(float f(inout float foo) { return foo; } )")); @@ -122,8 +122,8 @@ TEST_F(HlslGeneratorImplTest_Function, GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), R"(struct tint_symbol_1 { + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(struct tint_symbol_1 { float foo : TEXCOORD0; }; struct tint_symbol_2 { @@ -152,8 +152,8 @@ TEST_F(HlslGeneratorImplTest_Function, GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), R"(struct tint_symbol_1 { + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(struct tint_symbol_1 { float4 coord : SV_Position; }; struct tint_symbol_2 { @@ -206,8 +206,8 @@ TEST_F(HlslGeneratorImplTest_Function, GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), R"(struct Interface { + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(struct Interface { float4 pos; float col1; float col2; @@ -275,8 +275,8 @@ TEST_F(HlslGeneratorImplTest_Function, GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), R"(struct VertexOutput { + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(struct VertexOutput { float4 pos; }; @@ -340,8 +340,8 @@ TEST_F(HlslGeneratorImplTest_Function, GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), R"(cbuffer cbuffer_ubo : register(b0, space1) { + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(cbuffer cbuffer_ubo : register(b0, space1) { uint4 ubo[1]; }; @@ -381,8 +381,8 @@ TEST_F(HlslGeneratorImplTest_Function, GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), R"(cbuffer cbuffer_uniforms : register(b0, space1) { + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(cbuffer cbuffer_uniforms : register(b0, space1) { uint4 uniforms[1]; }; @@ -423,8 +423,8 @@ TEST_F(HlslGeneratorImplTest_Function, GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(RWByteAddressBuffer coord : register(u0, space1); void frag_main() { @@ -463,8 +463,8 @@ TEST_F(HlslGeneratorImplTest_Function, GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(ByteAddressBuffer coord : register(t0, space1); void frag_main() { @@ -500,8 +500,8 @@ TEST_F(HlslGeneratorImplTest_Function, GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(RWByteAddressBuffer coord : register(u0, space1); void frag_main() { @@ -538,8 +538,8 @@ TEST_F(HlslGeneratorImplTest_Function, GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(RWByteAddressBuffer coord : register(u0, space1); void frag_main() { @@ -578,8 +578,8 @@ TEST_F(HlslGeneratorImplTest_Function, GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), R"(cbuffer cbuffer_coord : register(b0, space1) { + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(cbuffer cbuffer_coord : register(b0, space1) { uint4 coord[1]; }; @@ -624,8 +624,8 @@ TEST_F(HlslGeneratorImplTest_Function, GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(RWByteAddressBuffer coord : register(u0, space1); float sub_func(float param) { @@ -648,8 +648,8 @@ TEST_F(HlslGeneratorImplTest_Function, GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), R"(void tint_symbol() { + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(void tint_symbol() { return; } )"); @@ -666,8 +666,8 @@ TEST_F(HlslGeneratorImplTest_Function, Emit_Decoration_EntryPoint_Compute) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), R"([numthreads(1, 1, 1)] + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"([numthreads(1, 1, 1)] void main() { return; } @@ -684,8 +684,8 @@ TEST_F(HlslGeneratorImplTest_Function, GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), R"([numthreads(2, 4, 6)] + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"([numthreads(2, 4, 6)] void main() { return; } @@ -705,8 +705,8 @@ TEST_F(HlslGeneratorImplTest_Function, GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), R"(static const int width = int(2); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(static const int width = int(2); static const int height = int(3); static const int depth = int(4); @@ -730,8 +730,8 @@ TEST_F(HlslGeneratorImplTest_Function, GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), R"(#ifndef WGSL_SPEC_CONSTANT_7 + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(#ifndef WGSL_SPEC_CONSTANT_7 #define WGSL_SPEC_CONSTANT_7 int(2) #endif static const int width = WGSL_SPEC_CONSTANT_7; @@ -759,8 +759,8 @@ TEST_F(HlslGeneratorImplTest_Function, Emit_Function_WithArrayParams) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr(R"( + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr(R"( struct tint_array_wrapper { float arr[5]; }; @@ -779,8 +779,8 @@ TEST_F(HlslGeneratorImplTest_Function, Emit_Function_WithArrayReturn) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr(R"( + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr(R"( struct tint_array_wrapper { float arr[5]; }; @@ -851,8 +851,8 @@ TEST_F(HlslGeneratorImplTest_Function, GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), R"(RWByteAddressBuffer data : register(u0, space0); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(RWByteAddressBuffer data : register(u0, space0); [numthreads(1, 1, 1)] void a() { diff --git a/src/writer/hlsl/generator_impl_identifier_test.cc b/src/writer/hlsl/generator_impl_identifier_test.cc index 161cab0ae5..4929bc9eaf 100644 --- a/src/writer/hlsl/generator_impl_identifier_test.cc +++ b/src/writer/hlsl/generator_impl_identifier_test.cc @@ -29,8 +29,9 @@ TEST_F(HlslGeneratorImplTest_Identifier, EmitIdentifierExpression) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitExpression(pre, out, i)) << gen.error(); - EXPECT_EQ(result(), "foo"); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, i)) << gen.error(); + EXPECT_EQ(out.str(), "foo"); } } // namespace diff --git a/src/writer/hlsl/generator_impl_if_test.cc b/src/writer/hlsl/generator_impl_if_test.cc index f2aece3b69..e40f842a4b 100644 --- a/src/writer/hlsl/generator_impl_if_test.cc +++ b/src/writer/hlsl/generator_impl_if_test.cc @@ -32,8 +32,8 @@ TEST_F(HlslGeneratorImplTest_If, Emit_If) { GeneratorImpl& gen = Build(); gen.increment_indent(); - ASSERT_TRUE(gen.EmitStatement(out, i)) << gen.error(); - EXPECT_EQ(result(), R"( if (cond) { + ASSERT_TRUE(gen.EmitStatement(i)) << gen.error(); + EXPECT_EQ(gen.result(), R"( if (cond) { return; } )"); @@ -57,8 +57,8 @@ TEST_F(HlslGeneratorImplTest_If, Emit_IfWithElseIf) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitStatement(out, i)) << gen.error(); - EXPECT_EQ(result(), R"( if (cond) { + ASSERT_TRUE(gen.EmitStatement(i)) << gen.error(); + EXPECT_EQ(gen.result(), R"( if (cond) { return; } else { if (else_cond) { @@ -84,8 +84,8 @@ TEST_F(HlslGeneratorImplTest_If, Emit_IfWithElse) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitStatement(out, i)) << gen.error(); - EXPECT_EQ(result(), R"( if (cond) { + ASSERT_TRUE(gen.EmitStatement(i)) << gen.error(); + EXPECT_EQ(gen.result(), R"( if (cond) { return; } else { return; @@ -116,8 +116,8 @@ TEST_F(HlslGeneratorImplTest_If, Emit_IfWithMultiple) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitStatement(out, i)) << gen.error(); - EXPECT_EQ(result(), R"( if (cond) { + ASSERT_TRUE(gen.EmitStatement(i)) << gen.error(); + EXPECT_EQ(gen.result(), R"( if (cond) { return; } else { if (else_cond) { diff --git a/src/writer/hlsl/generator_impl_import_test.cc b/src/writer/hlsl/generator_impl_import_test.cc index 201f34591c..ec81c41ff7 100644 --- a/src/writer/hlsl/generator_impl_import_test.cc +++ b/src/writer/hlsl/generator_impl_import_test.cc @@ -40,8 +40,9 @@ TEST_P(HlslImportData_SingleParamTest, FloatScalar) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitCall(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), std::string(param.hlsl_name) + "(1.0f)"); + std::stringstream out; + ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), std::string(param.hlsl_name) + "(1.0f)"); } INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest_Import, HlslImportData_SingleParamTest, @@ -78,8 +79,9 @@ TEST_P(HlslImportData_SingleIntParamTest, IntScalar) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitCall(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), std::string(param.hlsl_name) + "(1)"); + std::stringstream out; + ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), std::string(param.hlsl_name) + "(1)"); } INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest_Import, HlslImportData_SingleIntParamTest, @@ -95,8 +97,9 @@ TEST_P(HlslImportData_SingleVectorParamTest, FloatVector) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitCall(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), + std::stringstream out; + ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), std::string(param.hlsl_name) + "(float3(1.0f, 2.0f, 3.0f))"); } INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest_Import, @@ -136,8 +139,9 @@ TEST_P(HlslImportData_DualParamTest, FloatScalar) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitCall(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), std::string(param.hlsl_name) + "(1.0f, 2.0f)"); + std::stringstream out; + ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), std::string(param.hlsl_name) + "(1.0f, 2.0f)"); } INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest_Import, HlslImportData_DualParamTest, @@ -159,8 +163,9 @@ TEST_P(HlslImportData_DualParam_VectorTest, FloatVector) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitCall(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), + std::stringstream out; + ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), std::string(param.hlsl_name) + "(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f))"); } @@ -177,8 +182,9 @@ TEST_P(HlslImportData_DualParam_Int_Test, IntScalar) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitCall(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), std::string(param.hlsl_name) + "(1, 2)"); + std::stringstream out; + ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), std::string(param.hlsl_name) + "(1, 2)"); } INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest_Import, HlslImportData_DualParam_Int_Test, @@ -194,8 +200,9 @@ TEST_P(HlslImportData_TripleParamTest, FloatScalar) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitCall(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), std::string(param.hlsl_name) + "(1.0f, 2.0f, 3.0f)"); + std::stringstream out; + ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), std::string(param.hlsl_name) + "(1.0f, 2.0f, 3.0f)"); } INSTANTIATE_TEST_SUITE_P( HlslGeneratorImplTest_Import, @@ -218,8 +225,9 @@ TEST_P(HlslImportData_TripleParam_Int_Test, IntScalar) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitCall(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), std::string(param.hlsl_name) + "(1, 2, 3)"); + std::stringstream out; + ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), std::string(param.hlsl_name) + "(1, 2, 3)"); } INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest_Import, HlslImportData_TripleParam_Int_Test, @@ -233,8 +241,9 @@ TEST_F(HlslGeneratorImplTest_Import, HlslImportData_Determinant) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitCall(pre, out, expr)) << gen.error(); - EXPECT_EQ(result(), std::string("determinant(var)")); + std::stringstream out; + ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.error(); + EXPECT_EQ(out.str(), std::string("determinant(var)")); } } // namespace diff --git a/src/writer/hlsl/generator_impl_intrinsic_test.cc b/src/writer/hlsl/generator_impl_intrinsic_test.cc index 0e5a619440..4ec4192914 100644 --- a/src/writer/hlsl/generator_impl_intrinsic_test.cc +++ b/src/writer/hlsl/generator_impl_intrinsic_test.cc @@ -268,8 +268,9 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Intrinsic_Call) { GeneratorImpl& gen = Build(); gen.increment_indent(); - ASSERT_TRUE(gen.EmitExpression(pre, out, call)) << gen.error(); - EXPECT_EQ(result(), "dot(param1, param2)"); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); + EXPECT_EQ(out.str(), "dot(param1, param2)"); } TEST_F(HlslGeneratorImplTest_Intrinsic, Select_Scalar) { @@ -278,8 +279,9 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Select_Scalar) { GeneratorImpl& gen = Build(); gen.increment_indent(); - ASSERT_TRUE(gen.EmitExpression(pre, out, call)) << gen.error(); - EXPECT_EQ(result(), "(true ? 1.0f : 2.0f)"); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); + EXPECT_EQ(out.str(), "(true ? 1.0f : 2.0f)"); } TEST_F(HlslGeneratorImplTest_Intrinsic, Select_Vector) { @@ -289,8 +291,9 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Select_Vector) { GeneratorImpl& gen = Build(); gen.increment_indent(); - ASSERT_TRUE(gen.EmitExpression(pre, out, call)) << gen.error(); - EXPECT_EQ(result(), "(bool2(true, false) ? int2(1, 2) : int2(3, 4))"); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); + EXPECT_EQ(out.str(), "(bool2(true, false) ? int2(1, 2) : int2(3, 4))"); } TEST_F(HlslGeneratorImplTest_Intrinsic, Modf_Scalar) { @@ -300,8 +303,8 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Modf_Scalar) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("modf(1.0f, res)")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("modf(1.0f, res)")); } TEST_F(HlslGeneratorImplTest_Intrinsic, Modf_Vector) { @@ -311,8 +314,8 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Modf_Vector) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("modf(float3(0.0f, 0.0f, 0.0f), res)")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("modf(float3(0.0f, 0.0f, 0.0f), res)")); } TEST_F(HlslGeneratorImplTest_Intrinsic, Frexp_Scalar_i32) { @@ -322,8 +325,8 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Frexp_Scalar_i32) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr(R"( + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr(R"( float tint_tmp; float tint_tmp_1 = frexp(1.0f, tint_tmp); exp = int(tint_tmp); @@ -338,8 +341,8 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Frexp_Vector_i32) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr(R"( + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr(R"( float3 tint_tmp; float3 tint_tmp_1 = frexp(float3(0.0f, 0.0f, 0.0f), tint_tmp); res = int3(tint_tmp); @@ -354,8 +357,8 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, IsNormal_Scalar) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr(R"( + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr(R"( uint tint_isnormal_exponent = asuint(val) & 0x7f80000; uint tint_isnormal_clamped = clamp(tint_isnormal_exponent, 0x0080000, 0x7f00000); (tint_isnormal_clamped == tint_isnormal_exponent); @@ -369,8 +372,8 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, IsNormal_Vector) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr(R"( + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr(R"( uint3 tint_isnormal_exponent = asuint(val) & 0x7f80000; uint3 tint_isnormal_clamped = clamp(tint_isnormal_exponent, 0x0080000, 0x7f00000); (tint_isnormal_clamped == tint_isnormal_exponent); @@ -384,11 +387,12 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Pack4x8Snorm) { GeneratorImpl& gen = Build(); gen.increment_indent(); - ASSERT_TRUE(gen.EmitExpression(pre, out, call)) << gen.error(); - EXPECT_THAT(pre_result(), HasSubstr("int4 tint_tmp = int4(round(clamp(p1, " + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("int4 tint_tmp = int4(round(clamp(p1, " "-1.0, 1.0) * 127.0)) & 0xff;")); - EXPECT_THAT(result(), HasSubstr("asuint(tint_tmp.x | tint_tmp.y << 8 | " - "tint_tmp.z << 16 | tint_tmp.w << 24)")); + EXPECT_THAT(out.str(), HasSubstr("asuint(tint_tmp.x | tint_tmp.y << 8 | " + "tint_tmp.z << 16 | tint_tmp.w << 24)")); } TEST_F(HlslGeneratorImplTest_Intrinsic, Pack4x8Unorm) { @@ -398,11 +402,12 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Pack4x8Unorm) { GeneratorImpl& gen = Build(); gen.increment_indent(); - ASSERT_TRUE(gen.EmitExpression(pre, out, call)) << gen.error(); - EXPECT_THAT(pre_result(), HasSubstr("uint4 tint_tmp = uint4(round(clamp(p1, " + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("uint4 tint_tmp = uint4(round(clamp(p1, " "0.0, 1.0) * 255.0));")); - EXPECT_THAT(result(), HasSubstr("(tint_tmp.x | tint_tmp.y << 8 | " - "tint_tmp.z << 16 | tint_tmp.w << 24)")); + EXPECT_THAT(out.str(), HasSubstr("(tint_tmp.x | tint_tmp.y << 8 | " + "tint_tmp.z << 16 | tint_tmp.w << 24)")); } TEST_F(HlslGeneratorImplTest_Intrinsic, Pack2x16Snorm) { @@ -412,10 +417,11 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Pack2x16Snorm) { GeneratorImpl& gen = Build(); gen.increment_indent(); - ASSERT_TRUE(gen.EmitExpression(pre, out, call)) << gen.error(); - EXPECT_THAT(pre_result(), HasSubstr("int2 tint_tmp = int2(round(clamp(p1, " + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("int2 tint_tmp = int2(round(clamp(p1, " "-1.0, 1.0) * 32767.0)) & 0xffff;")); - EXPECT_THAT(result(), HasSubstr("asuint(tint_tmp.x | tint_tmp.y << 16)")); + EXPECT_THAT(out.str(), HasSubstr("asuint(tint_tmp.x | tint_tmp.y << 16)")); } TEST_F(HlslGeneratorImplTest_Intrinsic, Pack2x16Unorm) { @@ -425,10 +431,11 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Pack2x16Unorm) { GeneratorImpl& gen = Build(); gen.increment_indent(); - ASSERT_TRUE(gen.EmitExpression(pre, out, call)) << gen.error(); - EXPECT_THAT(pre_result(), HasSubstr("uint2 tint_tmp = uint2(round(clamp(p1, " + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("uint2 tint_tmp = uint2(round(clamp(p1, " "0.0, 1.0) * 65535.0));")); - EXPECT_THAT(result(), HasSubstr("(tint_tmp.x | tint_tmp.y << 16)")); + EXPECT_THAT(out.str(), HasSubstr("(tint_tmp.x | tint_tmp.y << 16)")); } TEST_F(HlslGeneratorImplTest_Intrinsic, Pack2x16Float) { @@ -438,9 +445,10 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Pack2x16Float) { GeneratorImpl& gen = Build(); gen.increment_indent(); - ASSERT_TRUE(gen.EmitExpression(pre, out, call)) << gen.error(); - EXPECT_THAT(pre_result(), HasSubstr("uint2 tint_tmp = f32tof16(p1);")); - EXPECT_THAT(result(), HasSubstr("(tint_tmp.x | tint_tmp.y << 16)")); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("uint2 tint_tmp = f32tof16(p1);")); + EXPECT_THAT(out.str(), HasSubstr("(tint_tmp.x | tint_tmp.y << 16)")); } TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack4x8Snorm) { @@ -450,12 +458,13 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack4x8Snorm) { GeneratorImpl& gen = Build(); gen.increment_indent(); - ASSERT_TRUE(gen.EmitExpression(pre, out, call)) << gen.error(); - EXPECT_THAT(pre_result(), HasSubstr("int tint_tmp_1 = int(p1);")); - EXPECT_THAT(pre_result(), + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("int tint_tmp_1 = int(p1);")); + EXPECT_THAT(gen.result(), HasSubstr("int4 tint_tmp = int4(tint_tmp_1 << 24, tint_tmp_1 " "<< 16, tint_tmp_1 << 8, tint_tmp_1) >> 24;")); - EXPECT_THAT(result(), + EXPECT_THAT(out.str(), HasSubstr("clamp(float4(tint_tmp) / 127.0, -1.0, 1.0)")); } @@ -466,13 +475,14 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack4x8Unorm) { GeneratorImpl& gen = Build(); gen.increment_indent(); - ASSERT_TRUE(gen.EmitExpression(pre, out, call)) << gen.error(); - EXPECT_THAT(pre_result(), HasSubstr("uint tint_tmp_1 = p1;")); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("uint tint_tmp_1 = p1;")); EXPECT_THAT( - pre_result(), + gen.result(), HasSubstr("uint4 tint_tmp = uint4(tint_tmp_1 & 0xff, (tint_tmp_1 >> " "8) & 0xff, (tint_tmp_1 >> 16) & 0xff, tint_tmp_1 >> 24);")); - EXPECT_THAT(result(), HasSubstr("float4(tint_tmp) / 255.0")); + EXPECT_THAT(out.str(), HasSubstr("float4(tint_tmp) / 255.0")); } TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack2x16Snorm) { @@ -482,12 +492,13 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack2x16Snorm) { GeneratorImpl& gen = Build(); gen.increment_indent(); - ASSERT_TRUE(gen.EmitExpression(pre, out, call)) << gen.error(); - EXPECT_THAT(pre_result(), HasSubstr("int tint_tmp_1 = int(p1);")); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("int tint_tmp_1 = int(p1);")); EXPECT_THAT( - pre_result(), + gen.result(), HasSubstr("int2 tint_tmp = int2(tint_tmp_1 << 16, tint_tmp_1) >> 16;")); - EXPECT_THAT(result(), + EXPECT_THAT(out.str(), HasSubstr("clamp(float2(tint_tmp) / 32767.0, -1.0, 1.0)")); } @@ -498,12 +509,13 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack2x16Unorm) { GeneratorImpl& gen = Build(); gen.increment_indent(); - ASSERT_TRUE(gen.EmitExpression(pre, out, call)) << gen.error(); - EXPECT_THAT(pre_result(), HasSubstr("uint tint_tmp_1 = p1;")); - EXPECT_THAT(pre_result(), + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("uint tint_tmp_1 = p1;")); + EXPECT_THAT(gen.result(), HasSubstr("uint2 tint_tmp = uint2(tint_tmp_1 & 0xffff, " "tint_tmp_1 >> 16);")); - EXPECT_THAT(result(), HasSubstr("float2(tint_tmp) / 65535.0")); + EXPECT_THAT(out.str(), HasSubstr("float2(tint_tmp) / 65535.0")); } TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack2x16Float) { @@ -513,9 +525,10 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Unpack2x16Float) { GeneratorImpl& gen = Build(); gen.increment_indent(); - ASSERT_TRUE(gen.EmitExpression(pre, out, call)) << gen.error(); - EXPECT_THAT(pre_result(), HasSubstr("uint tint_tmp = p1;")); - EXPECT_THAT(result(), + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("uint tint_tmp = p1;")); + EXPECT_THAT(out.str(), HasSubstr("f16tof32(uint2(tint_tmp & 0xffff, tint_tmp >> 16))")); } @@ -526,8 +539,8 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, StorageBarrier) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), R"([numthreads(1, 1, 1)] + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"([numthreads(1, 1, 1)] void main() { DeviceMemoryBarrierWithGroupSync(); return; @@ -542,8 +555,8 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, WorkgroupBarrier) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), R"([numthreads(1, 1, 1)] + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"([numthreads(1, 1, 1)] void main() { GroupMemoryBarrierWithGroupSync(); return; @@ -561,8 +574,8 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Ignore) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), R"(int f(int a, int b, int c) { + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(int f(int a, int b, int c) { return ((a + b) * c); } diff --git a/src/writer/hlsl/generator_impl_intrinsic_texture_test.cc b/src/writer/hlsl/generator_impl_intrinsic_texture_test.cc index 82475fcf2e..b868e74f10 100644 --- a/src/writer/hlsl/generator_impl_intrinsic_texture_test.cc +++ b/src/writer/hlsl/generator_impl_intrinsic_texture_test.cc @@ -381,12 +381,12 @@ TEST_P(HlslGeneratorIntrinsicTextureTest, Call) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); auto expected = expected_texture_overload(param.overload); - EXPECT_THAT(result(), HasSubstr(expected.pre)); - EXPECT_THAT(result(), HasSubstr(expected.out)); + EXPECT_THAT(gen.result(), HasSubstr(expected.pre)); + EXPECT_THAT(gen.result(), HasSubstr(expected.out)); } INSTANTIATE_TEST_SUITE_P( diff --git a/src/writer/hlsl/generator_impl_loop_test.cc b/src/writer/hlsl/generator_impl_loop_test.cc index 906d56eda4..a775429aaf 100644 --- a/src/writer/hlsl/generator_impl_loop_test.cc +++ b/src/writer/hlsl/generator_impl_loop_test.cc @@ -33,8 +33,8 @@ TEST_F(HlslGeneratorImplTest_Loop, Emit_Loop) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitStatement(out, l)) << gen.error(); - EXPECT_EQ(result(), R"( while (true) { + ASSERT_TRUE(gen.EmitStatement(l)) << gen.error(); + EXPECT_EQ(gen.result(), R"( while (true) { discard; } )"); @@ -51,8 +51,8 @@ TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopWithContinuing) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitStatement(out, l)) << gen.error(); - EXPECT_EQ(result(), R"( while (true) { + ASSERT_TRUE(gen.EmitStatement(l)) << gen.error(); + EXPECT_EQ(gen.result(), R"( while (true) { discard; { return; @@ -83,8 +83,8 @@ TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopNestedWithContinuing) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitStatement(out, outer)) << gen.error(); - EXPECT_EQ(result(), R"( while (true) { + ASSERT_TRUE(gen.EmitStatement(outer)) << gen.error(); + EXPECT_EQ(gen.result(), R"( while (true) { while (true) { discard; { @@ -137,8 +137,8 @@ TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopWithVarUsedInContinuing) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitStatement(out, outer)) << gen.error(); - EXPECT_EQ(result(), R"( while (true) { + ASSERT_TRUE(gen.EmitStatement(outer)) << gen.error(); + EXPECT_EQ(gen.result(), R"( while (true) { float lhs = 2.400000095f; float other = 0.0f; { diff --git a/src/writer/hlsl/generator_impl_member_accessor_test.cc b/src/writer/hlsl/generator_impl_member_accessor_test.cc index 203551d451..2afc81adc9 100644 --- a/src/writer/hlsl/generator_impl_member_accessor_test.cc +++ b/src/writer/hlsl/generator_impl_member_accessor_test.cc @@ -131,8 +131,8 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor, EmitExpression_MemberAccessor) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), R"(struct Data { + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(struct Data { float mem; }; @@ -181,8 +181,8 @@ TEST_P(HlslGeneratorImplTest_MemberAccessor_StorageBufferLoad, Test) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr(p.expected)); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr(p.expected)); } INSTANTIATE_TEST_SUITE_P( @@ -254,8 +254,8 @@ TEST_P(HlslGeneratorImplTest_MemberAccessor_StorageBufferStore, Test) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr(p.expected)); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr(p.expected)); } INSTANTIATE_TEST_SUITE_P( @@ -339,7 +339,7 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Store_Matrix_Empty) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); auto* expected = R"(void tint_symbol_1(RWByteAddressBuffer buffer, uint offset, float2x3 value) { buffer.Store3((offset + 0u), asuint(value[0u])); @@ -353,7 +353,7 @@ void main() { return; } )"; - EXPECT_EQ(result(), expected); + EXPECT_EQ(gen.result(), expected); } TEST_F(HlslGeneratorImplTest_MemberAccessor, @@ -378,7 +378,7 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor, GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); auto* expected = R"(RWByteAddressBuffer data : register(u0, space1); @@ -387,7 +387,7 @@ void main() { return; } )"; - EXPECT_EQ(result(), expected); + EXPECT_EQ(gen.result(), expected); } TEST_F(HlslGeneratorImplTest_MemberAccessor, @@ -410,7 +410,7 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor, GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); auto* expected = R"(RWByteAddressBuffer data : register(u0, space1); @@ -419,7 +419,7 @@ void main() { return; } )"; - EXPECT_EQ(result(), expected); + EXPECT_EQ(gen.result(), expected); } TEST_F(HlslGeneratorImplTest_MemberAccessor, @@ -443,7 +443,7 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor, GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); auto* expected = R"(RWByteAddressBuffer data : register(u0, space1); @@ -452,7 +452,7 @@ void main() { return; } )"; - EXPECT_EQ(result(), expected); + EXPECT_EQ(gen.result(), expected); } TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Store_ToArray) { @@ -473,7 +473,7 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Store_ToArray) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); auto* expected = R"(RWByteAddressBuffer data : register(u0, space1); @@ -482,7 +482,7 @@ void main() { return; } )"; - EXPECT_EQ(result(), expected); + EXPECT_EQ(gen.result(), expected); } TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Load_MultiLevel) { @@ -514,7 +514,7 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Load_MultiLevel) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); auto* expected = R"(RWByteAddressBuffer data : register(u0, space1); @@ -523,7 +523,7 @@ void main() { return; } )"; - EXPECT_EQ(result(), expected); + EXPECT_EQ(gen.result(), expected); } TEST_F(HlslGeneratorImplTest_MemberAccessor, @@ -558,7 +558,7 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor, GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); auto* expected = R"(RWByteAddressBuffer data : register(u0, space1); @@ -567,7 +567,7 @@ void main() { return; } )"; - EXPECT_EQ(result(), expected); + EXPECT_EQ(gen.result(), expected); } TEST_F(HlslGeneratorImplTest_MemberAccessor, @@ -602,7 +602,7 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor, GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); auto* expected = R"(RWByteAddressBuffer data : register(u0, space1); @@ -611,7 +611,7 @@ void main() { return; } )"; - EXPECT_EQ(result(), expected); + EXPECT_EQ(gen.result(), expected); } TEST_F(HlslGeneratorImplTest_MemberAccessor, @@ -646,7 +646,7 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor, GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); auto* expected = R"(RWByteAddressBuffer data : register(u0, space1); @@ -655,7 +655,7 @@ void main() { return; } )"; - EXPECT_EQ(result(), expected); + EXPECT_EQ(gen.result(), expected); } TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Store_MultiLevel) { @@ -686,7 +686,7 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Store_MultiLevel) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); auto* expected = R"(RWByteAddressBuffer data : register(u0, space1); @@ -695,7 +695,7 @@ void main() { return; } )"; - EXPECT_EQ(result(), expected); + EXPECT_EQ(gen.result(), expected); } TEST_F(HlslGeneratorImplTest_MemberAccessor, @@ -730,7 +730,7 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor, GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); auto* expected = R"(RWByteAddressBuffer data : register(u0, space1); @@ -739,7 +739,7 @@ void main() { return; } )"; - EXPECT_EQ(result(), expected); + EXPECT_EQ(gen.result(), expected); } TEST_F(HlslGeneratorImplTest_MemberAccessor, Swizzle_xyz) { @@ -749,8 +749,8 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor, Swizzle_xyz) { WrapInFunction(var, expr); GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("my_vec.xyz")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("my_vec.xyz")); } TEST_F(HlslGeneratorImplTest_MemberAccessor, Swizzle_gbr) { @@ -760,8 +760,8 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor, Swizzle_gbr) { WrapInFunction(var, expr); GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("my_vec.gbr")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("my_vec.gbr")); } } // namespace diff --git a/src/writer/hlsl/generator_impl_module_constant_test.cc b/src/writer/hlsl/generator_impl_module_constant_test.cc index 8ff9c88584..f84f31d36a 100644 --- a/src/writer/hlsl/generator_impl_module_constant_test.cc +++ b/src/writer/hlsl/generator_impl_module_constant_test.cc @@ -28,8 +28,8 @@ TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_ModuleConstant) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitProgramConstVariable(out, var)) << gen.error(); - EXPECT_EQ(result(), "static const float pos[3] = {1.0f, 2.0f, 3.0f};\n"); + ASSERT_TRUE(gen.EmitProgramConstVariable(var)) << gen.error(); + EXPECT_EQ(gen.result(), "static const float pos[3] = {1.0f, 2.0f, 3.0f};\n"); } TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant) { @@ -40,8 +40,8 @@ TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitProgramConstVariable(out, var)) << gen.error(); - EXPECT_EQ(result(), R"(#ifndef WGSL_SPEC_CONSTANT_23 + ASSERT_TRUE(gen.EmitProgramConstVariable(var)) << gen.error(); + EXPECT_EQ(gen.result(), R"(#ifndef WGSL_SPEC_CONSTANT_23 #define WGSL_SPEC_CONSTANT_23 3.0f #endif static const float pos = WGSL_SPEC_CONSTANT_23; @@ -56,8 +56,8 @@ TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant_NoConstructor) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitProgramConstVariable(out, var)) << gen.error(); - EXPECT_EQ(result(), R"(#ifndef WGSL_SPEC_CONSTANT_23 + ASSERT_TRUE(gen.EmitProgramConstVariable(var)) << gen.error(); + EXPECT_EQ(gen.result(), R"(#ifndef WGSL_SPEC_CONSTANT_23 #error spec constant required for constant id 23 #endif static const float pos = WGSL_SPEC_CONSTANT_23; @@ -76,9 +76,9 @@ TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant_NoId) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitProgramConstVariable(out, a)) << gen.error(); - ASSERT_TRUE(gen.EmitProgramConstVariable(out, b)) << gen.error(); - EXPECT_EQ(result(), R"(#ifndef WGSL_SPEC_CONSTANT_0 + ASSERT_TRUE(gen.EmitProgramConstVariable(a)) << gen.error(); + ASSERT_TRUE(gen.EmitProgramConstVariable(b)) << gen.error(); + EXPECT_EQ(gen.result(), R"(#ifndef WGSL_SPEC_CONSTANT_0 #define WGSL_SPEC_CONSTANT_0 3.0f #endif static const float a = WGSL_SPEC_CONSTANT_0; diff --git a/src/writer/hlsl/generator_impl_return_test.cc b/src/writer/hlsl/generator_impl_return_test.cc index 5a4bf74e5f..177ac25a30 100644 --- a/src/writer/hlsl/generator_impl_return_test.cc +++ b/src/writer/hlsl/generator_impl_return_test.cc @@ -29,8 +29,8 @@ TEST_F(HlslGeneratorImplTest_Return, Emit_Return) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitStatement(out, r)) << gen.error(); - EXPECT_EQ(result(), " return;\n"); + ASSERT_TRUE(gen.EmitStatement(r)) << gen.error(); + EXPECT_EQ(gen.result(), " return;\n"); } TEST_F(HlslGeneratorImplTest_Return, Emit_ReturnWithValue) { @@ -41,8 +41,8 @@ TEST_F(HlslGeneratorImplTest_Return, Emit_ReturnWithValue) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitStatement(out, r)) << gen.error(); - EXPECT_EQ(result(), " return 123;\n"); + ASSERT_TRUE(gen.EmitStatement(r)) << gen.error(); + EXPECT_EQ(gen.result(), " return 123;\n"); } } // namespace diff --git a/src/writer/hlsl/generator_impl_sanitizer_test.cc b/src/writer/hlsl/generator_impl_sanitizer_test.cc index e4e85c08a2..99cd52a3ac 100644 --- a/src/writer/hlsl/generator_impl_sanitizer_test.cc +++ b/src/writer/hlsl/generator_impl_sanitizer_test.cc @@ -45,9 +45,9 @@ TEST_F(HlslSanitizerTest, Call_ArrayLength) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); - auto got = result(); + auto got = gen.result(); auto* expect = R"(ByteAddressBuffer b : register(t1, space2); void a_func() { @@ -85,9 +85,9 @@ TEST_F(HlslSanitizerTest, Call_ArrayLength_OtherMembersInStruct) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); - auto got = result(); + auto got = gen.result(); auto* expect = R"(ByteAddressBuffer b : register(t1, space2); void a_func() { @@ -127,9 +127,9 @@ TEST_F(HlslSanitizerTest, Call_ArrayLength_ViaLets) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); - auto got = result(); + auto got = gen.result(); auto* expect = R"(ByteAddressBuffer b : register(t1, space2); void a_func() { @@ -159,9 +159,9 @@ TEST_F(HlslSanitizerTest, PromoteArrayInitializerToConstVar) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); - auto got = result(); + auto got = gen.result(); auto* expect = R"(struct tint_array_wrapper { int arr[4]; }; @@ -196,9 +196,9 @@ TEST_F(HlslSanitizerTest, PromoteStructInitializerToConstVar) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); - auto got = result(); + auto got = gen.result(); auto* expect = R"(struct S { int a; float3 b; @@ -235,9 +235,9 @@ TEST_F(HlslSanitizerTest, InlinePtrLetsBasic) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); - auto got = result(); + auto got = gen.result(); auto* expect = R"(void main() { int v = 0; int x = v; @@ -278,9 +278,9 @@ TEST_F(HlslSanitizerTest, InlinePtrLetsComplexChain) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); - auto got = result(); + auto got = gen.result(); auto* expect = R"(void main() { float4x4 m = float4x4(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); float f = m[2][1]; @@ -322,9 +322,9 @@ TEST_F(HlslSanitizerTest, InlineParam) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); + ASSERT_TRUE(gen.Generate()) << gen.error(); - auto got = result(); + auto got = gen.result(); auto* expect = R"(int x(inout int p) { return p; } diff --git a/src/writer/hlsl/generator_impl_switch_test.cc b/src/writer/hlsl/generator_impl_switch_test.cc index 6412524d62..c0a92cd3fb 100644 --- a/src/writer/hlsl/generator_impl_switch_test.cc +++ b/src/writer/hlsl/generator_impl_switch_test.cc @@ -46,8 +46,8 @@ TEST_F(HlslGeneratorImplTest_Switch, Emit_Switch) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitStatement(out, s)) << gen.error(); - EXPECT_EQ(result(), R"( switch(cond) { + ASSERT_TRUE(gen.EmitStatement(s)) << gen.error(); + EXPECT_EQ(gen.result(), R"( switch(cond) { case 5: { break; } diff --git a/src/writer/hlsl/generator_impl_test.cc b/src/writer/hlsl/generator_impl_test.cc index adf73e43bf..30cf6593bf 100644 --- a/src/writer/hlsl/generator_impl_test.cc +++ b/src/writer/hlsl/generator_impl_test.cc @@ -24,7 +24,7 @@ using HlslGeneratorImplTest = TestHelper; TEST_F(HlslGeneratorImplTest, ErrorIfSanitizerNotRun) { auto program = std::make_unique(std::move(*this)); GeneratorImpl gen(program.get()); - EXPECT_FALSE(gen.Generate(out)); + EXPECT_FALSE(gen.Generate()); EXPECT_EQ( gen.error(), "error: HLSL writer requires the transform::Hlsl sanitizer to have been " @@ -37,8 +37,8 @@ TEST_F(HlslGeneratorImplTest, Generate) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_EQ(result(), R"(void my_func() { + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(void my_func() { } )"); } diff --git a/src/writer/hlsl/generator_impl_type_test.cc b/src/writer/hlsl/generator_impl_type_test.cc index 98709a086f..feedf4e841 100644 --- a/src/writer/hlsl/generator_impl_type_test.cc +++ b/src/writer/hlsl/generator_impl_type_test.cc @@ -37,10 +37,11 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_Array) { GeneratorImpl& gen = Build(); + std::stringstream out; ASSERT_TRUE(gen.EmitType(out, program->TypeOf(arr), ast::StorageClass::kNone, ast::Access::kReadWrite, "ary")) << gen.error(); - EXPECT_EQ(result(), "bool ary[4]"); + EXPECT_EQ(out.str(), "bool ary[4]"); } TEST_F(HlslGeneratorImplTest_Type, EmitType_ArrayOfArray) { @@ -49,10 +50,11 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_ArrayOfArray) { GeneratorImpl& gen = Build(); + std::stringstream out; ASSERT_TRUE(gen.EmitType(out, program->TypeOf(arr), ast::StorageClass::kNone, ast::Access::kReadWrite, "ary")) << gen.error(); - EXPECT_EQ(result(), "bool ary[5][4]"); + EXPECT_EQ(out.str(), "bool ary[5][4]"); } // TODO(dsinclair): Is this possible? What order should it output in? @@ -63,10 +65,11 @@ TEST_F(HlslGeneratorImplTest_Type, GeneratorImpl& gen = Build(); + std::stringstream out; ASSERT_TRUE(gen.EmitType(out, program->TypeOf(arr), ast::StorageClass::kNone, ast::Access::kReadWrite, "ary")) << gen.error(); - EXPECT_EQ(result(), "bool ary[5][4][1]"); + EXPECT_EQ(out.str(), "bool ary[5][4][1]"); } TEST_F(HlslGeneratorImplTest_Type, EmitType_ArrayOfArrayOfArray) { @@ -75,10 +78,11 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_ArrayOfArrayOfArray) { GeneratorImpl& gen = Build(); + std::stringstream out; ASSERT_TRUE(gen.EmitType(out, program->TypeOf(arr), ast::StorageClass::kNone, ast::Access::kReadWrite, "ary")) << gen.error(); - EXPECT_EQ(result(), "bool ary[6][5][4]"); + EXPECT_EQ(out.str(), "bool ary[6][5][4]"); } TEST_F(HlslGeneratorImplTest_Type, EmitType_Array_WithoutName) { @@ -87,10 +91,11 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_Array_WithoutName) { GeneratorImpl& gen = Build(); + std::stringstream out; ASSERT_TRUE(gen.EmitType(out, program->TypeOf(arr), ast::StorageClass::kNone, ast::Access::kReadWrite, "")) << gen.error(); - EXPECT_EQ(result(), "bool[4]"); + EXPECT_EQ(out.str(), "bool[4]"); } TEST_F(HlslGeneratorImplTest_Type, EmitType_Bool) { @@ -98,10 +103,11 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_Bool) { GeneratorImpl& gen = Build(); + std::stringstream out; ASSERT_TRUE(gen.EmitType(out, bool_, ast::StorageClass::kNone, ast::Access::kReadWrite, "")) << gen.error(); - EXPECT_EQ(result(), "bool"); + EXPECT_EQ(out.str(), "bool"); } TEST_F(HlslGeneratorImplTest_Type, EmitType_F32) { @@ -109,10 +115,11 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_F32) { GeneratorImpl& gen = Build(); + std::stringstream out; ASSERT_TRUE(gen.EmitType(out, f32, ast::StorageClass::kNone, ast::Access::kReadWrite, "")) << gen.error(); - EXPECT_EQ(result(), "float"); + EXPECT_EQ(out.str(), "float"); } TEST_F(HlslGeneratorImplTest_Type, EmitType_I32) { @@ -120,10 +127,11 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_I32) { GeneratorImpl& gen = Build(); + std::stringstream out; ASSERT_TRUE(gen.EmitType(out, i32, ast::StorageClass::kNone, ast::Access::kReadWrite, "")) << gen.error(); - EXPECT_EQ(result(), "int"); + EXPECT_EQ(out.str(), "int"); } TEST_F(HlslGeneratorImplTest_Type, EmitType_Matrix) { @@ -133,10 +141,11 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_Matrix) { GeneratorImpl& gen = Build(); + std::stringstream out; ASSERT_TRUE(gen.EmitType(out, mat2x3, ast::StorageClass::kNone, ast::Access::kReadWrite, "")) << gen.error(); - EXPECT_EQ(result(), "float2x3"); + EXPECT_EQ(out.str(), "float2x3"); } // TODO(dsinclair): How to annotate as workgroup? @@ -147,10 +156,11 @@ TEST_F(HlslGeneratorImplTest_Type, DISABLED_EmitType_Pointer) { GeneratorImpl& gen = Build(); + std::stringstream out; ASSERT_TRUE(gen.EmitType(out, p, ast::StorageClass::kNone, ast::Access::kReadWrite, "")) << gen.error(); - EXPECT_EQ(result(), "float*"); + EXPECT_EQ(out.str(), "float*"); } TEST_F(HlslGeneratorImplTest_Type, EmitType_StructDecl) { @@ -163,8 +173,8 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_StructDecl) { GeneratorImpl& gen = Build(); auto* sem_s = program->TypeOf(s)->As(); - ASSERT_TRUE(gen.EmitStructType(out, sem_s)) << gen.error(); - EXPECT_EQ(result(), R"(struct S { + ASSERT_TRUE(gen.EmitStructType(sem_s)) << gen.error(); + EXPECT_EQ(gen.result(), R"(struct S { int a; float b; }; @@ -187,8 +197,8 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_StructDecl_OmittedIfStorageBuffer) { GeneratorImpl& gen = Build(); auto* sem_s = program->TypeOf(s)->As(); - ASSERT_TRUE(gen.EmitStructType(out, sem_s)) << gen.error(); - EXPECT_EQ(result(), ""); + ASSERT_TRUE(gen.EmitStructType(sem_s)) << gen.error(); + EXPECT_EQ(gen.result(), ""); } TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct) { @@ -201,10 +211,11 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct) { GeneratorImpl& gen = Build(); auto* sem_s = program->TypeOf(s)->As(); + std::stringstream out; ASSERT_TRUE(gen.EmitType(out, sem_s, ast::StorageClass::kNone, ast::Access::kReadWrite, "")) << gen.error(); - EXPECT_EQ(result(), "S"); + EXPECT_EQ(out.str(), "S"); } TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct_NameCollision) { @@ -216,8 +227,8 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct_NameCollision) { GeneratorImpl& gen = SanitizeAndBuild(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr(R"(struct S { + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr(R"(struct S { int tint_symbol; float tint_symbol_1; }; @@ -229,10 +240,11 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_U32) { GeneratorImpl& gen = Build(); + std::stringstream out; ASSERT_TRUE(gen.EmitType(out, u32, ast::StorageClass::kNone, ast::Access::kReadWrite, "")) << gen.error(); - EXPECT_EQ(result(), "uint"); + EXPECT_EQ(out.str(), "uint"); } TEST_F(HlslGeneratorImplTest_Type, EmitType_Vector) { @@ -241,10 +253,11 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_Vector) { GeneratorImpl& gen = Build(); + std::stringstream out; ASSERT_TRUE(gen.EmitType(out, vec3, ast::StorageClass::kNone, ast::Access::kReadWrite, "")) << gen.error(); - EXPECT_EQ(result(), "float3"); + EXPECT_EQ(out.str(), "float3"); } TEST_F(HlslGeneratorImplTest_Type, EmitType_Void) { @@ -252,10 +265,11 @@ TEST_F(HlslGeneratorImplTest_Type, EmitType_Void) { GeneratorImpl& gen = Build(); + std::stringstream out; ASSERT_TRUE(gen.EmitType(out, void_, ast::StorageClass::kNone, ast::Access::kReadWrite, "")) << gen.error(); - EXPECT_EQ(result(), "void"); + EXPECT_EQ(out.str(), "void"); } TEST_F(HlslGeneratorImplTest_Type, EmitSampler) { @@ -263,10 +277,11 @@ TEST_F(HlslGeneratorImplTest_Type, EmitSampler) { GeneratorImpl& gen = Build(); + std::stringstream out; ASSERT_TRUE(gen.EmitType(out, sampler, ast::StorageClass::kNone, ast::Access::kReadWrite, "")) << gen.error(); - EXPECT_EQ(result(), "SamplerState"); + EXPECT_EQ(out.str(), "SamplerState"); } TEST_F(HlslGeneratorImplTest_Type, EmitSamplerComparison) { @@ -274,10 +289,11 @@ TEST_F(HlslGeneratorImplTest_Type, EmitSamplerComparison) { GeneratorImpl& gen = Build(); + std::stringstream out; ASSERT_TRUE(gen.EmitType(out, sampler, ast::StorageClass::kNone, ast::Access::kReadWrite, "")) << gen.error(); - EXPECT_EQ(result(), "SamplerComparisonState"); + EXPECT_EQ(out.str(), "SamplerComparisonState"); } struct HlslDepthTextureData { @@ -305,8 +321,8 @@ TEST_P(HlslDepthTexturesTest, Emit) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr(params.result)); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr(params.result)); } INSTANTIATE_TEST_SUITE_P( HlslGeneratorImplTest_Type, @@ -361,8 +377,8 @@ TEST_P(HlslSampledTexturesTest, Emit) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr(params.result)); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr(params.result)); } INSTANTIATE_TEST_SUITE_P( HlslGeneratorImplTest_Type, @@ -465,10 +481,11 @@ TEST_F(HlslGeneratorImplTest_Type, EmitMultisampledTexture) { GeneratorImpl& gen = Build(); + std::stringstream out; ASSERT_TRUE(gen.EmitType(out, s, ast::StorageClass::kNone, ast::Access::kReadWrite, "")) << gen.error(); - EXPECT_EQ(result(), "Texture2DMS"); + EXPECT_EQ(out.str(), "Texture2DMS"); } struct HlslStorageTextureData { @@ -501,8 +518,8 @@ TEST_P(HlslStorageTexturesTest, Emit) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr(params.result)); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr(params.result)); } INSTANTIATE_TEST_SUITE_P( HlslGeneratorImplTest_Type, diff --git a/src/writer/hlsl/generator_impl_unary_op_test.cc b/src/writer/hlsl/generator_impl_unary_op_test.cc index 83ead64007..667469203b 100644 --- a/src/writer/hlsl/generator_impl_unary_op_test.cc +++ b/src/writer/hlsl/generator_impl_unary_op_test.cc @@ -29,8 +29,9 @@ TEST_F(HlslUnaryOpTest, AddressOf) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitExpression(pre, out, op)) << gen.error(); - EXPECT_EQ(result(), "expr"); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error(); + EXPECT_EQ(out.str(), "expr"); } TEST_F(HlslUnaryOpTest, Complement) { @@ -41,8 +42,9 @@ TEST_F(HlslUnaryOpTest, Complement) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitExpression(pre, out, op)) << gen.error(); - EXPECT_EQ(result(), "~(expr)"); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error(); + EXPECT_EQ(out.str(), "~(expr)"); } TEST_F(HlslUnaryOpTest, Indirection) { @@ -56,8 +58,9 @@ TEST_F(HlslUnaryOpTest, Indirection) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitExpression(pre, out, op)) << gen.error(); - EXPECT_EQ(result(), "expr"); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error(); + EXPECT_EQ(out.str(), "expr"); } TEST_F(HlslUnaryOpTest, Not) { @@ -67,8 +70,9 @@ TEST_F(HlslUnaryOpTest, Not) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitExpression(pre, out, op)) << gen.error(); - EXPECT_EQ(result(), "!(expr)"); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error(); + EXPECT_EQ(out.str(), "!(expr)"); } TEST_F(HlslUnaryOpTest, Negation) { @@ -79,8 +83,9 @@ TEST_F(HlslUnaryOpTest, Negation) { GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitExpression(pre, out, op)) << gen.error(); - EXPECT_EQ(result(), "-(expr)"); + std::stringstream out; + ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.error(); + EXPECT_EQ(out.str(), "-(expr)"); } } // namespace } // namespace hlsl diff --git a/src/writer/hlsl/generator_impl_variable_decl_statement_test.cc b/src/writer/hlsl/generator_impl_variable_decl_statement_test.cc index 2ce7469e1a..5fa60598dd 100644 --- a/src/writer/hlsl/generator_impl_variable_decl_statement_test.cc +++ b/src/writer/hlsl/generator_impl_variable_decl_statement_test.cc @@ -34,8 +34,8 @@ TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitStatement(out, stmt)) << gen.error(); - EXPECT_EQ(result(), " float a = 0.0f;\n"); + ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.error(); + EXPECT_EQ(gen.result(), " float a = 0.0f;\n"); } TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const) { @@ -47,8 +47,8 @@ TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const) { gen.increment_indent(); - ASSERT_TRUE(gen.EmitStatement(out, stmt)) << gen.error(); - EXPECT_EQ(result(), " const float a = 0.0f;\n"); + ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.error(); + EXPECT_EQ(gen.result(), " const float a = 0.0f;\n"); } TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Array) { @@ -60,8 +60,8 @@ TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Array) { gen.increment_indent(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr(" float a[5] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f};\n")); } @@ -74,8 +74,8 @@ TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Private) { gen.increment_indent(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr(" static float a = 0.0f;\n")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr(" static float a = 0.0f;\n")); } TEST_F(HlslGeneratorImplTest_VariableDecl, @@ -87,8 +87,8 @@ TEST_F(HlslGeneratorImplTest_VariableDecl, GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr(R"(float a = initializer; + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr(R"(float a = initializer; )")); } @@ -101,8 +101,8 @@ TEST_F(HlslGeneratorImplTest_VariableDecl, GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitStatement(out, stmt)) << gen.error(); - EXPECT_EQ(result(), R"(float3 a = float3(0.0f, 0.0f, 0.0f); + ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.error(); + EXPECT_EQ(gen.result(), R"(float3 a = float3(0.0f, 0.0f, 0.0f); )"); } @@ -116,8 +116,8 @@ TEST_F(HlslGeneratorImplTest_VariableDecl, GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.EmitStatement(out, stmt)) << gen.error(); - EXPECT_EQ(result(), + ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.error(); + EXPECT_EQ(gen.result(), R"(float2x3 a = float2x3(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); )"); } diff --git a/src/writer/hlsl/generator_impl_workgroup_var_test.cc b/src/writer/hlsl/generator_impl_workgroup_var_test.cc index a965be76f2..626fc90b91 100644 --- a/src/writer/hlsl/generator_impl_workgroup_var_test.cc +++ b/src/writer/hlsl/generator_impl_workgroup_var_test.cc @@ -32,8 +32,8 @@ TEST_F(HlslGeneratorImplTest_WorkgroupVar, Basic) { {Stage(ast::PipelineStage::kCompute)}); GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("groupshared float wg;\n")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("groupshared float wg;\n")); } TEST_F(HlslGeneratorImplTest_WorkgroupVar, Aliased) { @@ -45,8 +45,8 @@ TEST_F(HlslGeneratorImplTest_WorkgroupVar, Aliased) { {Stage(ast::PipelineStage::kCompute)}); GeneratorImpl& gen = Build(); - ASSERT_TRUE(gen.Generate(out)) << gen.error(); - EXPECT_THAT(result(), HasSubstr("groupshared float wg;\n")); + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_THAT(gen.result(), HasSubstr("groupshared float wg;\n")); } } // namespace diff --git a/src/writer/hlsl/test_helper.h b/src/writer/hlsl/test_helper.h index 26c55630f0..dc9420fc41 100644 --- a/src/writer/hlsl/test_helper.h +++ b/src/writer/hlsl/test_helper.h @@ -96,16 +96,6 @@ class TestHelperBase : public BODY, public ProgramBuilder { return *gen_; } - /// @returns the result string - std::string result() const { return out.str(); } - - /// @returns the pre result string - std::string pre_result() const { return pre.str(); } - - /// The output stream - std::ostringstream out; - /// The pre-output stream - std::ostringstream pre; /// The program built with a call to Build() std::unique_ptr program; diff --git a/src/writer/text_generator.cc b/src/writer/text_generator.cc index 2a26d13222..624d72cf13 100644 --- a/src/writer/text_generator.cc +++ b/src/writer/text_generator.cc @@ -31,5 +31,38 @@ void TextGenerator::make_indent(std::ostream& out) const { } } +TextGenerator::LineWriter::LineWriter(TextGenerator* generator) + : gen(generator) {} + +TextGenerator::LineWriter::LineWriter(LineWriter&& other) { + gen = other.gen; + other.gen = nullptr; +} + +TextGenerator::LineWriter::~LineWriter() { + if (gen) { + auto str = os.str(); + if (!str.empty()) { + gen->make_indent(); + gen->out_ << str << std::endl; + } + } +} + +TextGenerator::ScopedParen::ScopedParen(std::ostream& stream) : s(stream) { + s << "("; +} +TextGenerator::ScopedParen::~ScopedParen() { + s << ")"; +} + +TextGenerator::ScopedIndent::ScopedIndent(TextGenerator* generator) + : gen(generator) { + gen->increment_indent(); +} +TextGenerator::ScopedIndent::~ScopedIndent() { + gen->decrement_indent(); +} + } // namespace writer } // namespace tint diff --git a/src/writer/text_generator.h b/src/writer/text_generator.h index ab6d47a3c7..8f68385afb 100644 --- a/src/writer/text_generator.h +++ b/src/writer/text_generator.h @@ -17,6 +17,7 @@ #include #include +#include #include "src/diagnostic/diagnostic.h" @@ -58,6 +59,72 @@ class TextGenerator { std::string error() const { return diagnostics_.str(); } protected: + /// LineWriter is a helper that acts as a string buffer, who's content is + /// emitted to the TextGenerator as a single line on destruction. + struct LineWriter { + public: + /// Constructor + /// @param generator the TextGenerator that the LineWriter will append its + /// content to on destruction + explicit LineWriter(TextGenerator* generator); + /// Move constructor + /// @param rhs the LineWriter to move + LineWriter(LineWriter&& rhs); + /// Destructor + ~LineWriter(); + + /// @returns the ostringstream + operator std::ostream &() { return os; } + + /// @param rhs the value to write to the line + /// @returns the ostream so calls can be chained + template + std::ostream& operator<<(T&& rhs) { + return os << std::forward(rhs); + } + + private: + LineWriter(const LineWriter&) = delete; + LineWriter& operator=(const LineWriter&) = delete; + + std::ostringstream os; + TextGenerator* gen; + }; + + /// Helper for writing a '(' on construction and a ')' destruction. + struct ScopedParen { + /// Constructor + /// @param stream the std::ostream that will be written to + explicit ScopedParen(std::ostream& stream); + /// Destructor + ~ScopedParen(); + + private: + ScopedParen(ScopedParen&& rhs) = delete; + ScopedParen(const ScopedParen&) = delete; + ScopedParen& operator=(const ScopedParen&) = delete; + std::ostream& s; + }; + + /// Helper for incrementing indentation on construction and decrementing + /// indentation on destruction. + struct ScopedIndent { + /// Constructor + /// @param generator the TextGenerator that the ScopedIndent will indent + explicit ScopedIndent(TextGenerator* generator); + /// Destructor + ~ScopedIndent(); + + private: + ScopedIndent(ScopedIndent&& rhs) = delete; + ScopedIndent(const ScopedIndent&) = delete; + ScopedIndent& operator=(const ScopedIndent&) = delete; + TextGenerator* gen; + }; + + /// @returns a new LineWriter, used for buffering and writing a line to out_ + LineWriter line() { return LineWriter(this); } + /// The text output stream std::ostringstream out_; /// Diagnostics generated by the generator diff --git a/test/bug/tint/913.wgsl.expected.hlsl b/test/bug/tint/913.wgsl.expected.hlsl index ada977db3f..1ad9ee7770 100644 --- a/test/bug/tint/913.wgsl.expected.hlsl +++ b/test/bug/tint/913.wgsl.expected.hlsl @@ -26,29 +26,29 @@ void main(tint_symbol_2 tint_symbol_1) { const float4 nonCoveredColor = float4(0.0f, 1.0f, 0.0f, 1.0f); bool success = true; const int scalar_offset = (16u) / 4; - bool tint_tmp_2 = (dstTexCoord.x < uniforms[scalar_offset / 4][scalar_offset % 4]); - if (!tint_tmp_2) { -const int scalar_offset_1 = (20u) / 4; - tint_tmp_2 = (dstTexCoord.y < uniforms[scalar_offset_1 / 4][scalar_offset_1 % 4]); - } - bool tint_tmp_3 = (tint_tmp_2); - if (!tint_tmp_3) { -const int scalar_offset_2 = (16u) / 4; - const int scalar_offset_3 = (24u) / 4; - tint_tmp_3 = (dstTexCoord.x >= (uniforms[scalar_offset_2 / 4][scalar_offset_2 % 4] + uniforms[scalar_offset_3 / 4][scalar_offset_3 % 4])); - } - bool tint_tmp_4 = (tint_tmp_3); + bool tint_tmp_4 = (dstTexCoord.x < uniforms[scalar_offset / 4][scalar_offset % 4]); if (!tint_tmp_4) { -const int scalar_offset_4 = (20u) / 4; - const int scalar_offset_5 = (28u) / 4; - tint_tmp_4 = (dstTexCoord.y >= (uniforms[scalar_offset_4 / 4][scalar_offset_4 % 4] + uniforms[scalar_offset_5 / 4][scalar_offset_5 % 4])); + const int scalar_offset_1 = (20u) / 4; + tint_tmp_4 = (dstTexCoord.y < uniforms[scalar_offset_1 / 4][scalar_offset_1 % 4]); } -if ((tint_tmp_4)) { - bool tint_tmp_5 = success; + bool tint_tmp_3 = (tint_tmp_4); + if (!tint_tmp_3) { + const int scalar_offset_2 = (16u) / 4; + const int scalar_offset_3 = (24u) / 4; + tint_tmp_3 = (dstTexCoord.x >= (uniforms[scalar_offset_2 / 4][scalar_offset_2 % 4] + uniforms[scalar_offset_3 / 4][scalar_offset_3 % 4])); + } + bool tint_tmp_2 = (tint_tmp_3); + if (!tint_tmp_2) { + const int scalar_offset_4 = (20u) / 4; + const int scalar_offset_5 = (28u) / 4; + tint_tmp_2 = (dstTexCoord.y >= (uniforms[scalar_offset_4 / 4][scalar_offset_4 % 4] + uniforms[scalar_offset_5 / 4][scalar_offset_5 % 4])); + } + if ((tint_tmp_2)) { + bool tint_tmp_5 = success; if (tint_tmp_5) { tint_tmp_5 = all((tint_symbol.Load(int3(dstTexCoord, 0), 0) == nonCoveredColor)); } -success = (tint_tmp_5); + success = (tint_tmp_5); } else { const int scalar_offset_6 = (16u) / 4; uint4 ubo_load = uniforms[scalar_offset_6 / 4]; @@ -63,33 +63,33 @@ success = (tint_tmp_5); const float4 dstColor = tint_symbol.Load(int3(dstTexCoord, 0), 0); const int scalar_offset_9 = (4u) / 4; if ((uniforms[scalar_offset_9 / 4][scalar_offset_9 % 4] == 2u)) { - bool tint_tmp_6 = success; - if (tint_tmp_6) { - tint_tmp_6 = aboutEqual(dstColor.r, srcColor.r); - } - bool tint_tmp_7 = (tint_tmp_6); + bool tint_tmp_7 = success; if (tint_tmp_7) { - tint_tmp_7 = aboutEqual(dstColor.g, srcColor.g); + tint_tmp_7 = aboutEqual(dstColor.r, srcColor.r); } -success = (tint_tmp_7); + bool tint_tmp_6 = (tint_tmp_7); + if (tint_tmp_6) { + tint_tmp_6 = aboutEqual(dstColor.g, srcColor.g); + } + success = (tint_tmp_6); } else { - bool tint_tmp_8 = success; - if (tint_tmp_8) { - tint_tmp_8 = aboutEqual(dstColor.r, srcColor.r); - } - bool tint_tmp_9 = (tint_tmp_8); - if (tint_tmp_9) { - tint_tmp_9 = aboutEqual(dstColor.g, srcColor.g); - } - bool tint_tmp_10 = (tint_tmp_9); - if (tint_tmp_10) { - tint_tmp_10 = aboutEqual(dstColor.b, srcColor.b); - } - bool tint_tmp_11 = (tint_tmp_10); + bool tint_tmp_11 = success; if (tint_tmp_11) { - tint_tmp_11 = aboutEqual(dstColor.a, srcColor.a); + tint_tmp_11 = aboutEqual(dstColor.r, srcColor.r); } -success = (tint_tmp_11); + bool tint_tmp_10 = (tint_tmp_11); + if (tint_tmp_10) { + tint_tmp_10 = aboutEqual(dstColor.g, srcColor.g); + } + bool tint_tmp_9 = (tint_tmp_10); + if (tint_tmp_9) { + tint_tmp_9 = aboutEqual(dstColor.b, srcColor.b); + } + bool tint_tmp_8 = (tint_tmp_9); + if (tint_tmp_8) { + tint_tmp_8 = aboutEqual(dstColor.a, srcColor.a); + } + success = (tint_tmp_8); } } const uint outputIndex = ((GlobalInvocationID.y * uint(dstSize.x)) + GlobalInvocationID.x); diff --git a/test/bug/tint/914.wgsl.expected.hlsl b/test/bug/tint/914.wgsl.expected.hlsl index 3a6738efbf..33cd2bbf01 100644 --- a/test/bug/tint/914.wgsl.expected.hlsl +++ b/test/bug/tint/914.wgsl.expected.hlsl @@ -7,12 +7,12 @@ cbuffer cbuffer_uniforms : register(b3, space0) { float mm_readA(uint row, uint col) { const int scalar_offset = (0u) / 4; - bool tint_tmp = (row < uniforms[scalar_offset / 4][scalar_offset % 4]); + bool tint_tmp = (row < uniforms[scalar_offset / 4][scalar_offset % 4]); if (tint_tmp) { -const int scalar_offset_1 = (4u) / 4; - tint_tmp = (col < uniforms[scalar_offset_1 / 4][scalar_offset_1 % 4]); + const int scalar_offset_1 = (4u) / 4; + tint_tmp = (col < uniforms[scalar_offset_1 / 4][scalar_offset_1 % 4]); } -if ((tint_tmp)) { + if ((tint_tmp)) { const int scalar_offset_2 = (4u) / 4; const float result = asfloat(firstMatrix.Load((4u * ((row * uniforms[scalar_offset_2 / 4][scalar_offset_2 % 4]) + col)))); return result; @@ -22,12 +22,12 @@ if ((tint_tmp)) { float mm_readB(uint row, uint col) { const int scalar_offset_3 = (4u) / 4; - bool tint_tmp_1 = (row < uniforms[scalar_offset_3 / 4][scalar_offset_3 % 4]); + bool tint_tmp_1 = (row < uniforms[scalar_offset_3 / 4][scalar_offset_3 % 4]); if (tint_tmp_1) { -const int scalar_offset_4 = (8u) / 4; - tint_tmp_1 = (col < uniforms[scalar_offset_4 / 4][scalar_offset_4 % 4]); + const int scalar_offset_4 = (8u) / 4; + tint_tmp_1 = (col < uniforms[scalar_offset_4 / 4][scalar_offset_4 % 4]); } -if ((tint_tmp_1)) { + if ((tint_tmp_1)) { const int scalar_offset_5 = (8u) / 4; const float result = asfloat(secondMatrix.Load((4u * ((row * uniforms[scalar_offset_5 / 4][scalar_offset_5 % 4]) + col)))); return result; @@ -37,12 +37,12 @@ if ((tint_tmp_1)) { void mm_write(uint row, uint col, float value) { const int scalar_offset_6 = (0u) / 4; - bool tint_tmp_2 = (row < uniforms[scalar_offset_6 / 4][scalar_offset_6 % 4]); + bool tint_tmp_2 = (row < uniforms[scalar_offset_6 / 4][scalar_offset_6 % 4]); if (tint_tmp_2) { -const int scalar_offset_7 = (8u) / 4; - tint_tmp_2 = (col < uniforms[scalar_offset_7 / 4][scalar_offset_7 % 4]); + const int scalar_offset_7 = (8u) / 4; + tint_tmp_2 = (col < uniforms[scalar_offset_7 / 4][scalar_offset_7 % 4]); } -if ((tint_tmp_2)) { + if ((tint_tmp_2)) { const int scalar_offset_8 = (8u) / 4; const uint index = (col + (row * uniforms[scalar_offset_8 / 4][scalar_offset_8 % 4])); resultMatrix.Store((4u * index), asuint(value)); diff --git a/test/intrinsics/gen/pack2x16float/0e97b3.wgsl.expected.hlsl b/test/intrinsics/gen/pack2x16float/0e97b3.wgsl.expected.hlsl index 913266071c..c06e032720 100644 --- a/test/intrinsics/gen/pack2x16float/0e97b3.wgsl.expected.hlsl +++ b/test/intrinsics/gen/pack2x16float/0e97b3.wgsl.expected.hlsl @@ -1,6 +1,6 @@ void pack2x16float_0e97b3() { uint2 tint_tmp = f32tof16(float2(0.0f, 0.0f)); -uint res = (tint_tmp.x | tint_tmp.y << 16); + uint res = (tint_tmp.x | tint_tmp.y << 16); } struct tint_symbol { diff --git a/test/intrinsics/gen/pack2x16snorm/6c169b.wgsl.expected.hlsl b/test/intrinsics/gen/pack2x16snorm/6c169b.wgsl.expected.hlsl index c2d596b2bf..cccbc2d42a 100644 --- a/test/intrinsics/gen/pack2x16snorm/6c169b.wgsl.expected.hlsl +++ b/test/intrinsics/gen/pack2x16snorm/6c169b.wgsl.expected.hlsl @@ -1,6 +1,6 @@ void pack2x16snorm_6c169b() { int2 tint_tmp = int2(round(clamp(float2(0.0f, 0.0f), -1.0, 1.0) * 32767.0)) & 0xffff; -uint res = asuint(tint_tmp.x | tint_tmp.y << 16); + uint res = asuint(tint_tmp.x | tint_tmp.y << 16); } struct tint_symbol { diff --git a/test/intrinsics/gen/pack2x16unorm/0f08e4.wgsl.expected.hlsl b/test/intrinsics/gen/pack2x16unorm/0f08e4.wgsl.expected.hlsl index cf0dbe7032..3495457edd 100644 --- a/test/intrinsics/gen/pack2x16unorm/0f08e4.wgsl.expected.hlsl +++ b/test/intrinsics/gen/pack2x16unorm/0f08e4.wgsl.expected.hlsl @@ -1,6 +1,6 @@ void pack2x16unorm_0f08e4() { uint2 tint_tmp = uint2(round(clamp(float2(0.0f, 0.0f), 0.0, 1.0) * 65535.0)); -uint res = (tint_tmp.x | tint_tmp.y << 16); + uint res = (tint_tmp.x | tint_tmp.y << 16); } struct tint_symbol { diff --git a/test/intrinsics/gen/pack4x8snorm/4d22e7.wgsl.expected.hlsl b/test/intrinsics/gen/pack4x8snorm/4d22e7.wgsl.expected.hlsl index d495e8d995..93c5fcf6fc 100644 --- a/test/intrinsics/gen/pack4x8snorm/4d22e7.wgsl.expected.hlsl +++ b/test/intrinsics/gen/pack4x8snorm/4d22e7.wgsl.expected.hlsl @@ -1,6 +1,6 @@ void pack4x8snorm_4d22e7() { int4 tint_tmp = int4(round(clamp(float4(0.0f, 0.0f, 0.0f, 0.0f), -1.0, 1.0) * 127.0)) & 0xff; -uint res = asuint(tint_tmp.x | tint_tmp.y << 8 | tint_tmp.z << 16 | tint_tmp.w << 24); + uint res = asuint(tint_tmp.x | tint_tmp.y << 8 | tint_tmp.z << 16 | tint_tmp.w << 24); } struct tint_symbol { diff --git a/test/intrinsics/gen/pack4x8unorm/95c456.wgsl.expected.hlsl b/test/intrinsics/gen/pack4x8unorm/95c456.wgsl.expected.hlsl index 6fca7092c6..f22557c18f 100644 --- a/test/intrinsics/gen/pack4x8unorm/95c456.wgsl.expected.hlsl +++ b/test/intrinsics/gen/pack4x8unorm/95c456.wgsl.expected.hlsl @@ -1,6 +1,6 @@ void pack4x8unorm_95c456() { uint4 tint_tmp = uint4(round(clamp(float4(0.0f, 0.0f, 0.0f, 0.0f), 0.0, 1.0) * 255.0)); -uint res = (tint_tmp.x | tint_tmp.y << 8 | tint_tmp.z << 16 | tint_tmp.w << 24); + uint res = (tint_tmp.x | tint_tmp.y << 8 | tint_tmp.z << 16 | tint_tmp.w << 24); } struct tint_symbol { diff --git a/test/intrinsics/gen/unpack2x16float/32a5cf.wgsl.expected.hlsl b/test/intrinsics/gen/unpack2x16float/32a5cf.wgsl.expected.hlsl index 6dc4bda63d..710751791e 100644 --- a/test/intrinsics/gen/unpack2x16float/32a5cf.wgsl.expected.hlsl +++ b/test/intrinsics/gen/unpack2x16float/32a5cf.wgsl.expected.hlsl @@ -1,6 +1,6 @@ void unpack2x16float_32a5cf() { uint tint_tmp = 1u; -float2 res = f16tof32(uint2(tint_tmp & 0xffff, tint_tmp >> 16)); + float2 res = f16tof32(uint2(tint_tmp & 0xffff, tint_tmp >> 16)); } struct tint_symbol { diff --git a/test/intrinsics/gen/unpack2x16snorm/b4aea6.wgsl.expected.hlsl b/test/intrinsics/gen/unpack2x16snorm/b4aea6.wgsl.expected.hlsl index d5314f51a4..ad0d7b3251 100644 --- a/test/intrinsics/gen/unpack2x16snorm/b4aea6.wgsl.expected.hlsl +++ b/test/intrinsics/gen/unpack2x16snorm/b4aea6.wgsl.expected.hlsl @@ -1,7 +1,7 @@ void unpack2x16snorm_b4aea6() { int tint_tmp_1 = int(1u); -int2 tint_tmp = int2(tint_tmp_1 << 16, tint_tmp_1) >> 16; -float2 res = clamp(float2(tint_tmp) / 32767.0, -1.0, 1.0); + int2 tint_tmp = int2(tint_tmp_1 << 16, tint_tmp_1) >> 16; + float2 res = clamp(float2(tint_tmp) / 32767.0, -1.0, 1.0); } struct tint_symbol { diff --git a/test/intrinsics/gen/unpack2x16unorm/7699c0.wgsl.expected.hlsl b/test/intrinsics/gen/unpack2x16unorm/7699c0.wgsl.expected.hlsl index 3fdceeeb37..1afbba38e9 100644 --- a/test/intrinsics/gen/unpack2x16unorm/7699c0.wgsl.expected.hlsl +++ b/test/intrinsics/gen/unpack2x16unorm/7699c0.wgsl.expected.hlsl @@ -1,7 +1,7 @@ void unpack2x16unorm_7699c0() { uint tint_tmp_1 = 1u; -uint2 tint_tmp = uint2(tint_tmp_1 & 0xffff, tint_tmp_1 >> 16); -float2 res = float2(tint_tmp) / 65535.0; + uint2 tint_tmp = uint2(tint_tmp_1 & 0xffff, tint_tmp_1 >> 16); + float2 res = float2(tint_tmp) / 65535.0; } struct tint_symbol { diff --git a/test/intrinsics/gen/unpack4x8snorm/523fb3.wgsl.expected.hlsl b/test/intrinsics/gen/unpack4x8snorm/523fb3.wgsl.expected.hlsl index e02cf5298e..721a798a40 100644 --- a/test/intrinsics/gen/unpack4x8snorm/523fb3.wgsl.expected.hlsl +++ b/test/intrinsics/gen/unpack4x8snorm/523fb3.wgsl.expected.hlsl @@ -1,7 +1,7 @@ void unpack4x8snorm_523fb3() { int tint_tmp_1 = int(1u); -int4 tint_tmp = int4(tint_tmp_1 << 24, tint_tmp_1 << 16, tint_tmp_1 << 8, tint_tmp_1) >> 24; -float4 res = clamp(float4(tint_tmp) / 127.0, -1.0, 1.0); + int4 tint_tmp = int4(tint_tmp_1 << 24, tint_tmp_1 << 16, tint_tmp_1 << 8, tint_tmp_1) >> 24; + float4 res = clamp(float4(tint_tmp) / 127.0, -1.0, 1.0); } struct tint_symbol { diff --git a/test/intrinsics/gen/unpack4x8unorm/750c74.wgsl.expected.hlsl b/test/intrinsics/gen/unpack4x8unorm/750c74.wgsl.expected.hlsl index af35ee20d7..e3a10fec32 100644 --- a/test/intrinsics/gen/unpack4x8unorm/750c74.wgsl.expected.hlsl +++ b/test/intrinsics/gen/unpack4x8unorm/750c74.wgsl.expected.hlsl @@ -1,7 +1,7 @@ void unpack4x8unorm_750c74() { uint tint_tmp_1 = 1u; -uint4 tint_tmp = uint4(tint_tmp_1 & 0xff, (tint_tmp_1 >> 8) & 0xff, (tint_tmp_1 >> 16) & 0xff, tint_tmp_1 >> 24); -float4 res = float4(tint_tmp) / 255.0; + uint4 tint_tmp = uint4(tint_tmp_1 & 0xff, (tint_tmp_1 >> 8) & 0xff, (tint_tmp_1 >> 16) & 0xff, tint_tmp_1 >> 24); + float4 res = float4(tint_tmp) / 255.0; } struct tint_symbol {