diff --git a/BUILD.gn b/BUILD.gn index 460221eb34..ca2f5e5c19 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1088,6 +1088,8 @@ source_set("tint_unittests_hlsl_writer_src") { "src/writer/hlsl/generator_impl_unary_op_test.cc", "src/writer/hlsl/generator_impl_variable_decl_statement_test.cc", "src/writer/hlsl/namer_test.cc", + "src/writer/hlsl/test_helper.cc", + "src/writer/hlsl/test_helper.h", ] configs += [ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 825b1fca04..1451fb9c30 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -599,6 +599,8 @@ if (${TINT_BUILD_HLSL_WRITER}) writer/hlsl/generator_impl_unary_op_test.cc writer/hlsl/generator_impl_variable_decl_statement_test.cc writer/hlsl/namer_test.cc + writer/hlsl/test_helper.cc + writer/hlsl/test_helper.h ) endif() diff --git a/src/type_determiner.cc b/src/type_determiner.cc index 6af10e0787..a559d8bdb7 100644 --- a/src/type_determiner.cc +++ b/src/type_determiner.cc @@ -831,6 +831,7 @@ ast::type::Type* TypeDeterminer::GetImportData( const ast::ExpressionList& params, uint32_t* id) { if (path != "GLSL.std.450") { + set_error(source, "unknown import path " + path); return nullptr; } diff --git a/src/writer/hlsl/generator.cc b/src/writer/hlsl/generator.cc index 03d68ac0a8..84c699969e 100644 --- a/src/writer/hlsl/generator.cc +++ b/src/writer/hlsl/generator.cc @@ -26,7 +26,7 @@ Generator::Generator(ast::Module module) Generator::~Generator() = default; bool Generator::Generate() { - auto ret = impl_.Generate(); + auto ret = impl_.Generate(out_); if (!ret) { error_ = impl_.error(); } @@ -34,7 +34,7 @@ bool Generator::Generate() { } std::string Generator::result() const { - return impl_.result(); + return out_.str(); } std::string Generator::error() const { diff --git a/src/writer/hlsl/generator.h b/src/writer/hlsl/generator.h index c3cf47396e..9820fabfab 100644 --- a/src/writer/hlsl/generator.h +++ b/src/writer/hlsl/generator.h @@ -15,6 +15,7 @@ #ifndef SRC_WRITER_HLSL_GENERATOR_H_ #define SRC_WRITER_HLSL_GENERATOR_H_ +#include #include #include "src/writer/hlsl/generator_impl.h" @@ -43,6 +44,7 @@ class Generator : public Text { std::string error() const; private: + std::ostringstream out_; GeneratorImpl impl_; }; diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc index cb9b824bde..c2b90a3975 100644 --- a/src/writer/hlsl/generator_impl.cc +++ b/src/writer/hlsl/generator_impl.cc @@ -102,44 +102,50 @@ GeneratorImpl::GeneratorImpl(ast::Module* module) : module_(module) {} GeneratorImpl::~GeneratorImpl() = default; -bool GeneratorImpl::Generate() { +void GeneratorImpl::make_indent(std::ostream& out) { + for (size_t i = 0; i < indent_; i++) { + out << " "; + } +} + +bool GeneratorImpl::Generate(std::ostream& out) { for (const auto& global : module_->global_variables()) { register_global(global.get()); } for (auto* const alias : module_->alias_types()) { - if (!EmitAliasType(alias)) { + if (!EmitAliasType(out, alias)) { return false; } } if (!module_->alias_types().empty()) { - out_ << std::endl; + out << std::endl; } for (const auto& var : module_->global_variables()) { if (!var->is_const()) { continue; } - if (!EmitProgramConstVariable(var.get())) { + if (!EmitProgramConstVariable(out, var.get())) { return false; } } for (const auto& ep : module_->entry_points()) { - if (!EmitEntryPointData(ep.get())) { + if (!EmitEntryPointData(out, ep.get())) { return false; } } for (const auto& func : module_->functions()) { - if (!EmitFunction(func.get())) { + if (!EmitFunction(out, func.get())) { return false; } } for (const auto& ep : module_->entry_points()) { - if (!EmitEntryPointFunction(ep.get())) { + if (!EmitEntryPointFunction(out, ep.get())) { return false; } - out_ << std::endl; + out << std::endl; } return true; @@ -171,9 +177,9 @@ std::string GeneratorImpl::current_ep_var_name(VarType type) { break; } case VarType::kOut: { - auto out_it = ep_name_to_out_data_.find(current_ep_name_); - if (out_it != ep_name_to_out_data_.end()) { - name = out_it->second.var_name; + auto outit = ep_name_to_out_data_.find(current_ep_name_); + if (outit != ep_name_to_out_data_.end()) { + name = outit->second.var_name; } break; } @@ -181,120 +187,123 @@ std::string GeneratorImpl::current_ep_var_name(VarType type) { return name; } -bool GeneratorImpl::EmitAliasType(const ast::type::AliasType* alias) { - make_indent(); +bool GeneratorImpl::EmitAliasType(std::ostream& out, + const ast::type::AliasType* alias) { + make_indent(out); if (alias->type()->IsStruct()) { - if (!EmitType(alias->type(), namer_.NameFor(alias->name()))) { + if (!EmitType(out, alias->type(), namer_.NameFor(alias->name()))) { return false; } - out_ << ";" << std::endl; + out << ";" << std::endl; } else { - out_ << "typedef "; - if (!EmitType(alias->type(), "")) { + out << "typedef "; + if (!EmitType(out, alias->type(), "")) { return false; } - out_ << " " << namer_.NameFor(alias->name()) << ";" << std::endl; + out << " " << namer_.NameFor(alias->name()) << ";" << std::endl; } return true; } -bool GeneratorImpl::EmitArrayAccessor(ast::ArrayAccessorExpression* expr) { +bool GeneratorImpl::EmitArrayAccessor(std::ostream& out, + ast::ArrayAccessorExpression* expr) { // Handle writing into a storage buffer array if (is_storage_buffer_access(expr)) { - return EmitStorageBufferAccessor(expr, nullptr); + return EmitStorageBufferAccessor(out, expr, nullptr); } - if (!EmitExpression(expr->array())) { + if (!EmitExpression(out, expr->array())) { return false; } - out_ << "["; + out << "["; - if (!EmitExpression(expr->idx_expr())) { + if (!EmitExpression(out, expr->idx_expr())) { return false; } - out_ << "]"; + out << "]"; return true; } -bool GeneratorImpl::EmitAs(ast::AsExpression* expr) { +bool GeneratorImpl::EmitAs(std::ostream& out, ast::AsExpression* expr) { if (!expr->type()->IsF32() && !expr->type()->IsI32() && !expr->type()->IsU32()) { error_ = "Unable to do as cast to type " + expr->type()->type_name(); return false; } - out_ << "as"; - if (!EmitType(expr->type(), "")) { + out << "as"; + if (!EmitType(out, expr->type(), "")) { return false; } - out_ << "("; - if (!EmitExpression(expr->expr())) { + out << "("; + if (!EmitExpression(out, expr->expr())) { return false; } - out_ << ")"; + out << ")"; return true; } -bool GeneratorImpl::EmitAssign(ast::AssignmentStatement* stmt) { - make_indent(); +bool GeneratorImpl::EmitAssign(std::ostream& out, + ast::AssignmentStatement* stmt) { + make_indent(out); // If the LHS is an accessor into a storage buffer then we have to // emit a Store operation instead of an ='s. if (stmt->lhs()->IsMemberAccessor()) { auto* mem = stmt->lhs()->AsMemberAccessor(); if (is_storage_buffer_access(mem)) { - if (!EmitStorageBufferAccessor(mem, stmt->rhs())) { + if (!EmitStorageBufferAccessor(out, mem, stmt->rhs())) { return false; } - out_ << ";" << std::endl; + out << ";" << std::endl; return true; } } else if (stmt->lhs()->IsArrayAccessor()) { auto* ary = stmt->lhs()->AsArrayAccessor(); if (is_storage_buffer_access(ary)) { - if (!EmitStorageBufferAccessor(ary, stmt->rhs())) { + if (!EmitStorageBufferAccessor(out, ary, stmt->rhs())) { return false; } - out_ << ";" << std::endl; + out << ";" << std::endl; return true; } } - if (!EmitExpression(stmt->lhs())) { + if (!EmitExpression(out, stmt->lhs())) { return false; } - out_ << " = "; + out << " = "; - if (!EmitExpression(stmt->rhs())) { + if (!EmitExpression(out, stmt->rhs())) { return false; } - out_ << ";" << std::endl; + out << ";" << std::endl; return true; } -bool GeneratorImpl::EmitBinary(ast::BinaryExpression* expr) { - out_ << "("; +bool GeneratorImpl::EmitBinary(std::ostream& out, ast::BinaryExpression* expr) { + out << "("; - if (!EmitExpression(expr->lhs())) { + if (!EmitExpression(out, expr->lhs())) { return false; } - out_ << " "; + out << " "; switch (expr->op()) { case ast::BinaryOp::kAnd: - out_ << "&"; + out << "&"; break; case ast::BinaryOp::kOr: - out_ << "|"; + out << "|"; break; case ast::BinaryOp::kXor: - out_ << "^"; + out << "^"; break; case ast::BinaryOp::kLogicalAnd: // TODO(dsinclair): Implement support ... @@ -305,100 +314,103 @@ bool GeneratorImpl::EmitBinary(ast::BinaryExpression* expr) { error_ = "|| not supported yet"; return false; case ast::BinaryOp::kEqual: - out_ << "=="; + out << "=="; break; case ast::BinaryOp::kNotEqual: - out_ << "!="; + out << "!="; break; case ast::BinaryOp::kLessThan: - out_ << "<"; + out << "<"; break; case ast::BinaryOp::kGreaterThan: - out_ << ">"; + out << ">"; break; case ast::BinaryOp::kLessThanEqual: - out_ << "<="; + out << "<="; break; case ast::BinaryOp::kGreaterThanEqual: - out_ << ">="; + out << ">="; break; case ast::BinaryOp::kShiftLeft: - out_ << "<<"; + out << "<<"; break; case ast::BinaryOp::kShiftRight: // TODO(dsinclair): MSL is based on C++14, and >> in C++14 has // implementation-defined behaviour for negative LHS. We may have to // generate extra code to implement WGSL-specified behaviour for negative // LHS. - out_ << R"(>>)"; + out << R"(>>)"; break; case ast::BinaryOp::kAdd: - out_ << "+"; + out << "+"; break; case ast::BinaryOp::kSubtract: - out_ << "-"; + out << "-"; break; case ast::BinaryOp::kMultiply: - out_ << "*"; + out << "*"; break; case ast::BinaryOp::kDivide: - out_ << "/"; + out << "/"; break; case ast::BinaryOp::kModulo: - out_ << "%"; + out << "%"; break; case ast::BinaryOp::kNone: error_ = "missing binary operation type"; return false; } - out_ << " "; + out << " "; - if (!EmitExpression(expr->rhs())) { + if (!EmitExpression(out, expr->rhs())) { return false; } - out_ << ")"; + out << ")"; return true; } -bool GeneratorImpl::EmitBlock(const ast::BlockStatement* stmt) { - out_ << "{" << std::endl; +bool GeneratorImpl::EmitBlock(std::ostream& out, + const ast::BlockStatement* stmt) { + out << "{" << std::endl; increment_indent(); for (const auto& s : *stmt) { - if (!EmitStatement(s.get())) { + if (!EmitStatement(out, s.get())) { return false; } } decrement_indent(); - make_indent(); - out_ << "}"; + make_indent(out); + out << "}"; return true; } -bool GeneratorImpl::EmitBlockAndNewline(const ast::BlockStatement* stmt) { - const bool result = EmitBlock(stmt); +bool GeneratorImpl::EmitBlockAndNewline(std::ostream& out, + const ast::BlockStatement* stmt) { + const bool result = EmitBlock(out, stmt); if (result) { - out_ << std::endl; + out << std::endl; } return result; } -bool GeneratorImpl::EmitIndentedBlockAndNewline(ast::BlockStatement* stmt) { - make_indent(); - const bool result = EmitBlock(stmt); +bool GeneratorImpl::EmitIndentedBlockAndNewline(std::ostream& out, + ast::BlockStatement* stmt) { + make_indent(out); + const bool result = EmitBlock(out, stmt); if (result) { - out_ << std::endl; + out << std::endl; } return result; } -bool GeneratorImpl::EmitBreak(ast::BreakStatement*) { - make_indent(); - out_ << "break;" << std::endl; +bool GeneratorImpl::EmitBreak(std::ostream& out, ast::BreakStatement*) { + make_indent(out); + out << "break;" << std::endl; return true; } @@ -445,7 +457,7 @@ std::string GeneratorImpl::generate_intrinsic_name(const std::string& name) { return ""; } -bool GeneratorImpl::EmitCall(ast::CallExpression* expr) { +bool GeneratorImpl::EmitCall(std::ostream& out, ast::CallExpression* expr) { if (!expr->func()->IsIdentifier()) { error_ = "invalid function name"; return 0; @@ -482,11 +494,11 @@ bool GeneratorImpl::EmitCall(ast::CallExpression* expr) { // auto* param1 = param[1].get(); // auto* name1 = generate_name("outer_product_expr_1"); - // make_indent(); - // if (!EmitType(expr->result_type(), "")) { + // make_indent(out); + // if (!EmitType(out, expr->result_type(), "")) { // return false; // } - // out_ << "("; + // out << "("; // auto param1_type = params[1]->result_type()->UnwrapPtrIfNeeded(); // if (!param1_type->IsVector()) { @@ -497,21 +509,21 @@ bool GeneratorImpl::EmitCall(ast::CallExpression* expr) { // for (uint32_t i = 0; i < param1_type->AsVector()->size(); ++i) { // if (i > 0) { - // out_ << ", "; + // out << ", "; // } - // if (!EmitExpression(params[0].get())) { + // if (!EmitExpression(out, params[0].get())) { // return false; // } - // out_ << " * "; + // out << " * "; - // if (!EmitExpression(params[1].get())) { + // if (!EmitExpression(out, params[1].get())) { // return false; // } - // out_ << "[" << i << "]"; + // out << "[" << i << "]"; // } - // out_ << ")"; + // out << ")"; } else { auto name = generate_intrinsic_name(ident->name()); if (name.empty()) { @@ -520,22 +532,22 @@ bool GeneratorImpl::EmitCall(ast::CallExpression* expr) { return false; } - make_indent(); - out_ << name << "("; + make_indent(out); + out << name << "("; bool first = true; for (const auto& param : params) { if (!first) { - out_ << ", "; + out << ", "; } first = false; - if (!EmitExpression(param.get())) { + if (!EmitExpression(out, param.get())) { return false; } } - out_ << ")"; + out << ")"; } return true; } @@ -553,13 +565,13 @@ bool GeneratorImpl::EmitCall(ast::CallExpression* expr) { return false; } - out_ << name << "("; + out << name << "("; bool first = true; if (has_referenced_in_var_needing_struct(func)) { auto var_name = current_ep_var_name(VarType::kIn); if (!var_name.empty()) { - out_ << var_name; + out << var_name; first = false; } } @@ -567,33 +579,34 @@ bool GeneratorImpl::EmitCall(ast::CallExpression* expr) { auto var_name = current_ep_var_name(VarType::kOut); if (!var_name.empty()) { if (!first) { - out_ << ", "; + out << ", "; } first = false; - out_ << var_name; + out << var_name; } } const auto& params = expr->params(); for (const auto& param : params) { if (!first) { - out_ << ", "; + out << ", "; } first = false; - if (!EmitExpression(param.get())) { + if (!EmitExpression(out, param.get())) { return false; } } - out_ << ")"; + out << ")"; } else { - return EmitImportFunction(expr); + return EmitImportFunction(out, expr); } return true; } -bool GeneratorImpl::EmitImportFunction(ast::CallExpression* expr) { +bool GeneratorImpl::EmitImportFunction(std::ostream& out, + ast::CallExpression* expr) { auto* ident = expr->func()->AsIdentifier(); auto* imp = module_->FindImportByName(ident->path()); @@ -639,45 +652,45 @@ bool GeneratorImpl::EmitImportFunction(ast::CallExpression* expr) { case GLSLstd450Tan: case GLSLstd450Tanh: case GLSLstd450Trunc: - out_ << ident->name(); + out << ident->name(); break; case GLSLstd450Fract: - out_ << "frac"; + out << "frac"; break; case GLSLstd450InterpolateAtCentroid: - out_ << "EvaluateAttributeAtCentroid"; + out << "EvaluateAttributeAtCentroid"; break; case GLSLstd450InverseSqrt: - out_ << "rsqrt"; + out << "rsqrt"; break; case GLSLstd450FMix: - out_ << "mix"; + out << "mix"; break; case GLSLstd450SSign: case GLSLstd450FSign: - out_ << "sign"; + out << "sign"; break; case GLSLstd450FAbs: case GLSLstd450SAbs: - out_ << "abs"; + out << "abs"; break; case GLSLstd450FMax: case GLSLstd450NMax: case GLSLstd450SMax: case GLSLstd450UMax: - out_ << "max"; + out << "max"; break; case GLSLstd450FMin: case GLSLstd450NMin: case GLSLstd450SMin: case GLSLstd450UMin: - out_ << "min"; + out << "min"; break; case GLSLstd450FClamp: case GLSLstd450SClamp: case GLSLstd450NClamp: case GLSLstd450UClamp: - out_ << "clamp"; + out << "clamp"; break; // TODO(dsinclair): Determine mappings for the following case GLSLstd450Atanh: @@ -692,172 +705,175 @@ bool GeneratorImpl::EmitImportFunction(ast::CallExpression* expr) { return false; } - out_ << "("; + out << "("; bool first = true; const auto& params = expr->params(); for (const auto& param : params) { if (!first) { - out_ << ", "; + out << ", "; } first = false; - if (!EmitExpression(param.get())) { + if (!EmitExpression(out, param.get())) { return false; } } - out_ << ")"; + out << ")"; return true; } -bool GeneratorImpl::EmitCast(ast::CastExpression* expr) { - if (!EmitType(expr->type(), "")) { +bool GeneratorImpl::EmitCast(std::ostream& out, ast::CastExpression* expr) { + if (!EmitType(out, expr->type(), "")) { return false; } - out_ << "("; - if (!EmitExpression(expr->expr())) { + out << "("; + if (!EmitExpression(out, expr->expr())) { return false; } - out_ << ")"; + out << ")"; return true; } -bool GeneratorImpl::EmitCase(ast::CaseStatement* stmt) { - make_indent(); +bool GeneratorImpl::EmitCase(std::ostream& out, ast::CaseStatement* stmt) { + make_indent(out); if (stmt->IsDefault()) { - out_ << "default:"; + out << "default:"; } else { bool first = true; for (const auto& selector : stmt->selectors()) { if (!first) { - out_ << std::endl; - make_indent(); + out << std::endl; + make_indent(out); } first = false; - out_ << "case "; - if (!EmitLiteral(selector.get())) { + out << "case "; + if (!EmitLiteral(out, selector.get())) { return false; } - out_ << ":"; + out << ":"; } } - out_ << " {" << std::endl; + out << " {" << std::endl; increment_indent(); for (const auto& s : *(stmt->body())) { - if (!EmitStatement(s.get())) { + if (!EmitStatement(out, s.get())) { return false; } } if (!last_is_break_or_fallthrough(stmt->body())) { - make_indent(); - out_ << "break;" << std::endl; + make_indent(out); + out << "break;" << std::endl; } decrement_indent(); - make_indent(); - out_ << "}" << std::endl; + make_indent(out); + out << "}" << std::endl; return true; } -bool GeneratorImpl::EmitConstructor(ast::ConstructorExpression* expr) { +bool GeneratorImpl::EmitConstructor(std::ostream& out, + ast::ConstructorExpression* expr) { if (expr->IsScalarConstructor()) { - return EmitScalarConstructor(expr->AsScalarConstructor()); + return EmitScalarConstructor(out, expr->AsScalarConstructor()); } - return EmitTypeConstructor(expr->AsTypeConstructor()); + return EmitTypeConstructor(out, expr->AsTypeConstructor()); } bool GeneratorImpl::EmitScalarConstructor( + std::ostream& out, ast::ScalarConstructorExpression* expr) { - return EmitLiteral(expr->literal()); + return EmitLiteral(out, expr->literal()); } -bool GeneratorImpl::EmitTypeConstructor(ast::TypeConstructorExpression* expr) { +bool GeneratorImpl::EmitTypeConstructor(std::ostream& out, + ast::TypeConstructorExpression* expr) { if (expr->type()->IsArray()) { - out_ << "{"; + out << "{"; } else { - if (!EmitType(expr->type(), "")) { + if (!EmitType(out, expr->type(), "")) { return false; } - out_ << "("; + out << "("; } // If the type constructor is empty then we need to construct with the zero // value for all components. if (expr->values().empty()) { - if (!EmitZeroValue(expr->type())) { + if (!EmitZeroValue(out, expr->type())) { return false; } } else { bool first = true; for (const auto& e : expr->values()) { if (!first) { - out_ << ", "; + out << ", "; } first = false; - if (!EmitExpression(e.get())) { + if (!EmitExpression(out, e.get())) { return false; } } } if (expr->type()->IsArray()) { - out_ << "}"; + out << "}"; } else { - out_ << ")"; + out << ")"; } return true; } -bool GeneratorImpl::EmitContinue(ast::ContinueStatement*) { - make_indent(); - out_ << "continue;" << std::endl; +bool GeneratorImpl::EmitContinue(std::ostream& out, ast::ContinueStatement*) { + make_indent(out); + out << "continue;" << std::endl; return true; } -bool GeneratorImpl::EmitDiscard(ast::DiscardStatement*) { - make_indent(); +bool GeneratorImpl::EmitDiscard(std::ostream& out, ast::DiscardStatement*) { + make_indent(out); // 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; + out << "discard;" << std::endl; return true; } -bool GeneratorImpl::EmitExpression(ast::Expression* expr) { +bool GeneratorImpl::EmitExpression(std::ostream& out, ast::Expression* expr) { if (expr->IsAs()) { - return EmitAs(expr->AsAs()); + return EmitAs(out, expr->AsAs()); } if (expr->IsArrayAccessor()) { - return EmitArrayAccessor(expr->AsArrayAccessor()); + return EmitArrayAccessor(out, expr->AsArrayAccessor()); } if (expr->IsBinary()) { - return EmitBinary(expr->AsBinary()); + return EmitBinary(out, expr->AsBinary()); } if (expr->IsCall()) { - return EmitCall(expr->AsCall()); + return EmitCall(out, expr->AsCall()); } if (expr->IsCast()) { - return EmitCast(expr->AsCast()); + return EmitCast(out, expr->AsCast()); } if (expr->IsConstructor()) { - return EmitConstructor(expr->AsConstructor()); + return EmitConstructor(out, expr->AsConstructor()); } if (expr->IsIdentifier()) { - return EmitIdentifier(expr->AsIdentifier()); + return EmitIdentifier(out, expr->AsIdentifier()); } if (expr->IsMemberAccessor()) { - return EmitMemberAccessor(expr->AsMemberAccessor()); + return EmitMemberAccessor(out, expr->AsMemberAccessor()); } if (expr->IsUnaryOp()) { - return EmitUnaryOp(expr->AsUnaryOp()); + return EmitUnaryOp(out, expr->AsUnaryOp()); } error_ = "unknown expression type: " + expr->str(); @@ -872,7 +888,8 @@ bool GeneratorImpl::global_is_in_struct(ast::Variable* var) const { var->storage_class() == ast::StorageClass::kOutput); } -bool GeneratorImpl::EmitIdentifier(ast::IdentifierExpression* expr) { +bool GeneratorImpl::EmitIdentifier(std::ostream& out, + ast::IdentifierExpression* expr) { auto* ident = expr->AsIdentifier(); if (ident->has_path()) { // TODO(dsinclair): Handle identifier with path @@ -891,49 +908,49 @@ bool GeneratorImpl::EmitIdentifier(ast::IdentifierExpression* expr) { error_ = "unable to find entry point data for variable"; return false; } - out_ << name << "."; + out << name << "."; } } - out_ << namer_.NameFor(ident->name()); + out << namer_.NameFor(ident->name()); return true; } -bool GeneratorImpl::EmitIf(ast::IfStatement* stmt) { - make_indent(); +bool GeneratorImpl::EmitIf(std::ostream& out, ast::IfStatement* stmt) { + make_indent(out); - out_ << "if ("; - if (!EmitExpression(stmt->condition())) { + out << "if ("; + if (!EmitExpression(out, stmt->condition())) { return false; } - out_ << ") "; + out << ") "; - if (!EmitBlock(stmt->body())) { + if (!EmitBlock(out, stmt->body())) { return false; } for (const auto& e : stmt->else_statements()) { - if (!EmitElse(e.get())) { + if (!EmitElse(out, e.get())) { return false; } } - out_ << std::endl; + out << std::endl; return true; } -bool GeneratorImpl::EmitElse(ast::ElseStatement* stmt) { +bool GeneratorImpl::EmitElse(std::ostream& out, ast::ElseStatement* stmt) { if (stmt->HasCondition()) { - out_ << " else if ("; - if (!EmitExpression(stmt->condition())) { + out << " else if ("; + if (!EmitExpression(out, stmt->condition())) { return false; } - out_ << ") "; + out << ") "; } else { - out_ << " else "; + out << " else "; } - return EmitBlock(stmt->body()); + return EmitBlock(out, stmt->body()); } bool GeneratorImpl::has_referenced_in_var_needing_struct(ast::Function* func) { @@ -989,8 +1006,8 @@ bool GeneratorImpl::has_referenced_var_needing_struct(ast::Function* func) { return false; } -bool GeneratorImpl::EmitFunction(ast::Function* func) { - make_indent(); +bool GeneratorImpl::EmitFunction(std::ostream& out, ast::Function* func) { + make_indent(out); // Entry points will be emitted later, skip for now. if (module_->IsFunctionEntryPoint(func->name())) { @@ -1005,32 +1022,33 @@ bool GeneratorImpl::EmitFunction(ast::Function* func) { if (emit_duplicate_functions) { for (const auto& ep_name : func->ancestor_entry_points()) { - if (!EmitFunctionInternal(func, emit_duplicate_functions, ep_name)) { + if (!EmitFunctionInternal(out, func, emit_duplicate_functions, ep_name)) { return false; } - out_ << std::endl; + out << std::endl; } } else { // Emit as non-duplicated - if (!EmitFunctionInternal(func, false, "")) { + if (!EmitFunctionInternal(out, func, false, "")) { return false; } - out_ << std::endl; + out << std::endl; } return true; } -bool GeneratorImpl::EmitFunctionInternal(ast::Function* func, +bool GeneratorImpl::EmitFunctionInternal(std::ostream& out, + ast::Function* func, bool emit_duplicate_functions, const std::string& ep_name) { auto name = func->name(); - if (!EmitType(func->return_type(), "")) { + if (!EmitType(out, func->return_type(), "")) { return false; } - out_ << " "; + out << " "; if (emit_duplicate_functions) { name = generate_name(name + "_" + ep_name); @@ -1039,7 +1057,7 @@ bool GeneratorImpl::EmitFunctionInternal(ast::Function* func, name = namer_.NameFor(name); } - out_ << name << "("; + out << name << "("; bool first = true; @@ -1050,42 +1068,42 @@ bool GeneratorImpl::EmitFunctionInternal(ast::Function* func, if (emit_duplicate_functions) { auto in_it = ep_name_to_in_data_.find(ep_name); if (in_it != ep_name_to_in_data_.end()) { - out_ << "in " << in_it->second.struct_name << " " - << in_it->second.var_name; + out << "in " << in_it->second.struct_name << " " + << in_it->second.var_name; first = false; } - auto out_it = ep_name_to_out_data_.find(ep_name); - if (out_it != ep_name_to_out_data_.end()) { + auto outit = ep_name_to_out_data_.find(ep_name); + if (outit != ep_name_to_out_data_.end()) { if (!first) { - out_ << ", "; + out << ", "; } - out_ << "out " << out_it->second.struct_name << " " - << out_it->second.var_name; + out << "out " << outit->second.struct_name << " " + << outit->second.var_name; first = false; } } for (const auto& v : func->params()) { if (!first) { - out_ << ", "; + out << ", "; } first = false; - if (!EmitType(v->type(), v->name())) { + if (!EmitType(out, v->type(), v->name())) { return false; } // Array name is output as part of the type if (!v->type()->IsArray()) { - out_ << " " << v->name(); + out << " " << v->name(); } } - out_ << ") "; + out << ") "; current_ep_name_ = ep_name; - if (!EmitBlockAndNewline(func->body())) { + if (!EmitBlockAndNewline(out, func->body())) { return false; } @@ -1094,7 +1112,7 @@ bool GeneratorImpl::EmitFunctionInternal(ast::Function* func, return true; } -bool GeneratorImpl::EmitEntryPointData(ast::EntryPoint* ep) { +bool GeneratorImpl::EmitEntryPointData(std::ostream& out, ast::EntryPoint* ep) { auto* func = module_->FindFunctionByName(ep->function_name()); if (func == nullptr) { error_ = "Unable to find entry point function: " + ep->function_name(); @@ -1102,8 +1120,7 @@ bool GeneratorImpl::EmitEntryPointData(ast::EntryPoint* ep) { } std::vector> in_variables; - std::vector> - out_variables; + std::vector> outvariables; for (auto data : func->referenced_location_variables()) { auto* var = data.first; auto* deco = data.second; @@ -1111,7 +1128,7 @@ bool GeneratorImpl::EmitEntryPointData(ast::EntryPoint* ep) { if (var->storage_class() == ast::StorageClass::kInput) { in_variables.push_back({var, deco}); } else if (var->storage_class() == ast::StorageClass::kOutput) { - out_variables.push_back({var, deco}); + outvariables.push_back({var, deco}); } } @@ -1122,7 +1139,7 @@ bool GeneratorImpl::EmitEntryPointData(ast::EntryPoint* ep) { if (var->storage_class() == ast::StorageClass::kInput) { in_variables.push_back({var, deco}); } else if (var->storage_class() == ast::StorageClass::kOutput) { - out_variables.push_back({var, deco}); + outvariables.push_back({var, deco}); } } @@ -1143,8 +1160,8 @@ bool GeneratorImpl::EmitEntryPointData(ast::EntryPoint* ep) { if (type->IsStruct()) { auto* strct = type->AsStruct(); - out_ << "ConstantBuffer<" << strct->name() << "> " << var->name() - << " : register(b" << binding->value() << ");" << std::endl; + out << "ConstantBuffer<" << strct->name() << "> " << var->name() + << " : register(b" << binding->value() << ");" << std::endl; } else { // TODO(dsinclair): There is outstanding spec work to require all uniform // buffers to be [[block]] decorated, which means structs. This is @@ -1152,22 +1169,22 @@ bool GeneratorImpl::EmitEntryPointData(ast::EntryPoint* ep) { // is not a block. // Relevant: https://github.com/gpuweb/gpuweb/issues/1004 // https://github.com/gpuweb/gpuweb/issues/1008 - out_ << "cbuffer : register(b" << binding->value() << ") {" << std::endl; + out << "cbuffer : register(b" << binding->value() << ") {" << std::endl; increment_indent(); - make_indent(); - if (!EmitType(type, "")) { + make_indent(out); + if (!EmitType(out, type, "")) { return false; } - out_ << " " << var->name() << ";" << std::endl; + out << " " << var->name() << ";" << std::endl; decrement_indent(); - out_ << "};" << std::endl; + out << "};" << std::endl; } emitted_uniform = true; } if (emitted_uniform) { - out_ << std::endl; + out << std::endl; } bool emitted_storagebuffer = false; @@ -1175,12 +1192,12 @@ bool GeneratorImpl::EmitEntryPointData(ast::EntryPoint* ep) { auto* var = data.first; auto* binding = data.second.binding; - out_ << "RWByteAddressBuffer " << var->name() << " : register(u" - << binding->value() << ");" << std::endl; + out << "RWByteAddressBuffer " << var->name() << " : register(u" + << binding->value() << ");" << std::endl; emitted_storagebuffer = true; } if (emitted_storagebuffer) { - out_ << std::endl; + out << std::endl; } auto ep_name = ep->name(); @@ -1198,8 +1215,8 @@ bool GeneratorImpl::EmitEntryPointData(ast::EntryPoint* ep) { auto in_var_name = generate_name(kTintStructInVarPrefix); ep_name_to_in_data_[ep_name] = {in_struct_name, in_var_name}; - make_indent(); - out_ << "struct " << in_struct_name << " {" << std::endl; + make_indent(out); + out << "struct " << in_struct_name << " {" << std::endl; increment_indent(); @@ -1207,63 +1224,63 @@ bool GeneratorImpl::EmitEntryPointData(ast::EntryPoint* ep) { auto* var = data.first; auto* deco = data.second; - make_indent(); - if (!EmitType(var->type(), var->name())) { + make_indent(out); + if (!EmitType(out, var->type(), var->name())) { return false; } - out_ << " " << var->name() << " : "; + out << " " << var->name() << " : "; if (deco->IsLocation()) { if (ep->stage() == ast::PipelineStage::kCompute) { error_ = "invalid location variable for pipeline stage"; return false; } - out_ << "TEXCOORD" << deco->AsLocation()->value(); + out << "TEXCOORD" << deco->AsLocation()->value(); } else if (deco->IsBuiltin()) { auto attr = builtin_to_attribute(deco->AsBuiltin()->value()); if (attr.empty()) { error_ = "unsupported builtin"; return false; } - out_ << attr; + out << attr; } else { error_ = "unsupported variable decoration for entry point output"; return false; } - out_ << ";" << std::endl; + out << ";" << std::endl; } decrement_indent(); - make_indent(); + make_indent(out); - out_ << "};" << std::endl << std::endl; + out << "};" << std::endl << std::endl; } - if (!out_variables.empty()) { - auto out_struct_name = generate_name(ep_name + "_" + kOutStructNameSuffix); - auto out_var_name = generate_name(kTintStructOutVarPrefix); - ep_name_to_out_data_[ep_name] = {out_struct_name, out_var_name}; + if (!outvariables.empty()) { + auto outstruct_name = generate_name(ep_name + "_" + kOutStructNameSuffix); + auto outvar_name = generate_name(kTintStructOutVarPrefix); + ep_name_to_out_data_[ep_name] = {outstruct_name, outvar_name}; - make_indent(); - out_ << "struct " << out_struct_name << " {" << std::endl; + make_indent(out); + out << "struct " << outstruct_name << " {" << std::endl; increment_indent(); - for (auto& data : out_variables) { + for (auto& data : outvariables) { auto* var = data.first; auto* deco = data.second; - make_indent(); - if (!EmitType(var->type(), var->name())) { + make_indent(out); + if (!EmitType(out, var->type(), var->name())) { return false; } - out_ << " " << var->name() << " : "; + out << " " << var->name() << " : "; if (deco->IsLocation()) { auto loc = deco->AsLocation()->value(); if (ep->stage() == ast::PipelineStage::kVertex) { - out_ << "TEXCOORD" << loc; + out << "TEXCOORD" << loc; } else if (ep->stage() == ast::PipelineStage::kFragment) { - out_ << "SV_Target" << loc << ""; + out << "SV_Target" << loc << ""; } else { error_ = "invalid location variable for pipeline stage"; return false; @@ -1274,16 +1291,16 @@ bool GeneratorImpl::EmitEntryPointData(ast::EntryPoint* ep) { error_ = "unsupported builtin"; return false; } - out_ << attr; + out << attr; } else { error_ = "unsupported variable decoration for entry point output"; return false; } - out_ << ";" << std::endl; + out << ";" << std::endl; } decrement_indent(); - make_indent(); - out_ << "};" << std::endl << std::endl; + make_indent(out); + out << "};" << std::endl << std::endl; } return true; @@ -1320,8 +1337,9 @@ std::string GeneratorImpl::builtin_to_attribute(ast::Builtin builtin) const { return ""; } -bool GeneratorImpl::EmitEntryPointFunction(ast::EntryPoint* ep) { - make_indent(); +bool GeneratorImpl::EmitEntryPointFunction(std::ostream& out, + ast::EntryPoint* ep) { + make_indent(out); current_ep_name_ = ep->name(); if (current_ep_name_.empty()) { @@ -1334,64 +1352,64 @@ bool GeneratorImpl::EmitEntryPointFunction(ast::EntryPoint* ep) { return false; } - auto out_data = ep_name_to_out_data_.find(current_ep_name_); - bool has_out_data = out_data != ep_name_to_out_data_.end(); - if (has_out_data) { - out_ << out_data->second.struct_name; + auto outdata = ep_name_to_out_data_.find(current_ep_name_); + bool has_outdata = outdata != ep_name_to_out_data_.end(); + if (has_outdata) { + out << outdata->second.struct_name; } else { - out_ << "void"; + out << "void"; } - out_ << " " << namer_.NameFor(current_ep_name_) << "("; + out << " " << namer_.NameFor(current_ep_name_) << "("; auto in_data = ep_name_to_in_data_.find(current_ep_name_); if (in_data != ep_name_to_in_data_.end()) { - out_ << in_data->second.struct_name << " " << in_data->second.var_name; + out << in_data->second.struct_name << " " << in_data->second.var_name; } - out_ << ") {" << std::endl; + out << ") {" << std::endl; increment_indent(); - if (has_out_data) { - make_indent(); - out_ << out_data->second.struct_name << " " << out_data->second.var_name - << ";" << std::endl; + if (has_outdata) { + make_indent(out); + out << outdata->second.struct_name << " " << outdata->second.var_name << ";" + << std::endl; } generating_entry_point_ = true; for (const auto& s : *(func->body())) { - if (!EmitStatement(s.get())) { + if (!EmitStatement(out, s.get())) { return false; } } generating_entry_point_ = false; decrement_indent(); - make_indent(); - out_ << "}" << std::endl; + make_indent(out); + out << "}" << std::endl; current_ep_name_ = ""; return true; } -bool GeneratorImpl::EmitLiteral(ast::Literal* lit) { +bool GeneratorImpl::EmitLiteral(std::ostream& out, ast::Literal* lit) { if (lit->IsBool()) { - out_ << (lit->AsBool()->IsTrue() ? "true" : "false"); + out << (lit->AsBool()->IsTrue() ? "true" : "false"); } else if (lit->IsFloat()) { - auto flags = out_.flags(); - auto precision = out_.precision(); + auto flags = out.flags(); + auto precision = out.precision(); - out_.flags(flags | std::ios_base::showpoint); - out_.precision(std::numeric_limits::max_digits10); + out.flags(flags | std::ios_base::showpoint); + out.precision(std::numeric_limits::max_digits10); - out_ << lit->AsFloat()->value() << "f"; + out << lit->AsFloat()->value() << "f"; - out_.precision(precision); - out_.flags(flags); + out.precision(precision); + out.flags(flags); } else if (lit->IsSint()) { - out_ << lit->AsSint()->value(); + out << lit->AsSint()->value(); } else if (lit->IsUint()) { - out_ << lit->AsUint()->value() << "u"; + out << lit->AsUint()->value() << "u"; } else { error_ = "unknown literal type"; return false; @@ -1399,17 +1417,17 @@ bool GeneratorImpl::EmitLiteral(ast::Literal* lit) { return true; } -bool GeneratorImpl::EmitZeroValue(ast::type::Type* type) { +bool GeneratorImpl::EmitZeroValue(std::ostream& out, ast::type::Type* type) { if (type->IsBool()) { - out_ << "false"; + out << "false"; } else if (type->IsF32()) { - out_ << "0.0f"; + out << "0.0f"; } else if (type->IsI32()) { - out_ << "0"; + out << "0"; } else if (type->IsU32()) { - out_ << "0u"; + out << "0u"; } else if (type->IsVector()) { - return EmitZeroValue(type->AsVector()->type()); + return EmitZeroValue(out, type->AsVector()->type()); } else { error_ = "Invalid type for zero emission: " + type->type_name(); return false; @@ -1417,55 +1435,55 @@ bool GeneratorImpl::EmitZeroValue(ast::type::Type* type) { return true; } -bool GeneratorImpl::EmitLoop(ast::LoopStatement* stmt) { +bool GeneratorImpl::EmitLoop(std::ostream& out, ast::LoopStatement* stmt) { loop_emission_counter_++; std::string guard = namer_.NameFor("tint_hlsl_is_first_" + std::to_string(loop_emission_counter_)); if (stmt->has_continuing()) { - make_indent(); + make_indent(out); // Continuing variables get their own scope. - out_ << "{" << std::endl; + out << "{" << std::endl; increment_indent(); - make_indent(); - out_ << "bool " << guard << " = true;" << std::endl; + make_indent(out); + out << "bool " << guard << " = true;" << std::endl; } - make_indent(); - out_ << "for(;;) {" << std::endl; + make_indent(out); + out << "for(;;) {" << std::endl; increment_indent(); if (stmt->has_continuing()) { - make_indent(); - out_ << "if (!" << guard << ") "; + make_indent(out); + out << "if (!" << guard << ") "; - if (!EmitBlockAndNewline(stmt->continuing())) { + if (!EmitBlockAndNewline(out, stmt->continuing())) { return false; } - make_indent(); - out_ << guard << " = false;" << std::endl; - out_ << std::endl; + make_indent(out); + out << guard << " = false;" << std::endl; + out << std::endl; } for (const auto& s : *(stmt->body())) { - if (!EmitStatement(s.get())) { + if (!EmitStatement(out, s.get())) { return false; } } decrement_indent(); - make_indent(); - out_ << "}" << std::endl; + make_indent(out); + out << "}" << std::endl; // Close the scope for any continuing variables. if (stmt->has_continuing()) { decrement_indent(); - make_indent(); - out_ << "}" << std::endl; + make_indent(out); + out << "}" << std::endl; } return true; @@ -1478,7 +1496,8 @@ bool GeneratorImpl::EmitLoop(ast::LoopStatement* stmt) { // TODO(dsinclair): Need to support loading through a pointer. The pointer is // just a memory address in the storage buffer, so need to do the correct // calculation. -bool GeneratorImpl::EmitStorageBufferAccessor(ast::Expression* expr, +bool GeneratorImpl::EmitStorageBufferAccessor(std::ostream& out, + ast::Expression* expr, ast::Expression* rhs) { auto* result_type = expr->result_type()->UnwrapAliasPtrAlias(); std::string access_method = rhs != nullptr ? "Store" : "Load"; @@ -1489,11 +1508,11 @@ bool GeneratorImpl::EmitStorageBufferAccessor(ast::Expression* expr, // If we aren't storing then we need to put in the outer cast. if (rhs == nullptr) { if (result_type->is_float_scalar_or_vector()) { - out_ << "asfloat("; + out << "asfloat("; } else if (result_type->is_signed_scalar_or_vector()) { - out_ << "asint("; + out << "asint("; } else if (result_type->is_unsigned_scalar_or_vector()) { - out_ << "asuint("; + out << "asuint("; } } @@ -1502,7 +1521,7 @@ bool GeneratorImpl::EmitStorageBufferAccessor(ast::Expression* expr, error_ = "error emitting storage buffer access"; return false; } - out_ << buffer_name << "." << access_method << "("; + out << buffer_name << "." << access_method << "("; auto* ptr = expr; bool first = true; @@ -1512,7 +1531,7 @@ bool GeneratorImpl::EmitStorageBufferAccessor(ast::Expression* expr, } if (!first) { - out_ << " + "; + out << " + "; } first = false; if (ptr->IsMemberAccessor()) { @@ -1527,7 +1546,7 @@ bool GeneratorImpl::EmitStorageBufferAccessor(ast::Expression* expr, error_ = "missing offset decoration for struct member"; return false; } - out_ << str_member->offset(); + out << str_member->offset(); } else if (res_type->IsVector()) { // This must be a single element swizzle if we've got a vector at this // point. @@ -1541,8 +1560,8 @@ bool GeneratorImpl::EmitStorageBufferAccessor(ast::Expression* expr, // TODO(dsinclair): All our types are currently 4 bytes (f32, i32, u32) // so this is assuming 4. This will need to be fixed when we get f16 or // f64 types. - out_ << "(4 * " << convert_swizzle_to_index(mem->member()->name()) - << ")"; + out << "(4 * " << convert_swizzle_to_index(mem->member()->name()) + << ")"; } else { error_ = "Invalid result type for member accessor: " + res_type->type_name(); @@ -1554,24 +1573,24 @@ bool GeneratorImpl::EmitStorageBufferAccessor(ast::Expression* expr, auto* ary = ptr->AsArrayAccessor(); auto* ary_type = ary->array()->result_type()->UnwrapAliasPtrAlias(); - out_ << "("; + out << "("; // TODO(dsinclair): Handle matrix case and struct case. if (ary_type->IsArray()) { - out_ << ary_type->AsArray()->array_stride(); + out << ary_type->AsArray()->array_stride(); } else if (ary_type->IsVector()) { // TODO(dsinclair): This is a hack. Our vectors can only be f32, i32 // or u32 which are all 4 bytes. When we get f16 or other types we'll // have to ask the type for the byte size. - out_ << "4"; + out << "4"; } else { error_ = "Invalid array type in storage buffer access"; return false; } - out_ << " * "; - if (!EmitExpression(ary->idx_expr())) { + out << " * "; + if (!EmitExpression(out, ary->idx_expr())) { return false; } - out_ << ")"; + out << ")"; ptr = ary->array(); } else { @@ -1581,18 +1600,18 @@ bool GeneratorImpl::EmitStorageBufferAccessor(ast::Expression* expr, } if (rhs != nullptr) { - out_ << ", asuint("; - if (!EmitExpression(rhs)) { + out << ", asuint("; + if (!EmitExpression(out, rhs)) { return false; } - out_ << ")"; + out << ")"; } - out_ << ")"; + out << ")"; // Close the outer cast. if (rhs == nullptr) { - out_ << ")"; + out << ")"; } return true; @@ -1645,118 +1664,121 @@ bool GeneratorImpl::is_storage_buffer_access( return false; } -bool GeneratorImpl::EmitMemberAccessor(ast::MemberAccessorExpression* expr) { +bool GeneratorImpl::EmitMemberAccessor(std::ostream& out, + ast::MemberAccessorExpression* expr) { // Look for storage buffer accesses as we have to convert them into Load // expressions. Stores will be identified in the assignment emission and a // member accessor store of a storage buffer will not get here. if (is_storage_buffer_access(expr)) { - return EmitStorageBufferAccessor(expr, nullptr); + return EmitStorageBufferAccessor(out, expr, nullptr); } - if (!EmitExpression(expr->structure())) { + if (!EmitExpression(out, expr->structure())) { return false; } - out_ << "."; - return EmitExpression(expr->member()); + out << "."; + return EmitExpression(out, expr->member()); } -bool GeneratorImpl::EmitReturn(ast::ReturnStatement* stmt) { - make_indent(); +bool GeneratorImpl::EmitReturn(std::ostream& out, ast::ReturnStatement* stmt) { + make_indent(out); - out_ << "return"; + out << "return"; if (generating_entry_point_) { - auto out_data = ep_name_to_out_data_.find(current_ep_name_); - if (out_data != ep_name_to_out_data_.end()) { - out_ << " " << out_data->second.var_name; + auto outdata = ep_name_to_out_data_.find(current_ep_name_); + if (outdata != ep_name_to_out_data_.end()) { + out << " " << outdata->second.var_name; } } else if (stmt->has_value()) { - out_ << " "; - if (!EmitExpression(stmt->value())) { + out << " "; + if (!EmitExpression(out, stmt->value())) { return false; } } - out_ << ";" << std::endl; + out << ";" << std::endl; return true; } -bool GeneratorImpl::EmitStatement(ast::Statement* stmt) { +bool GeneratorImpl::EmitStatement(std::ostream& out, ast::Statement* stmt) { if (stmt->IsAssign()) { - return EmitAssign(stmt->AsAssign()); + return EmitAssign(out, stmt->AsAssign()); } if (stmt->IsBlock()) { - return EmitIndentedBlockAndNewline(stmt->AsBlock()); + return EmitIndentedBlockAndNewline(out, stmt->AsBlock()); } if (stmt->IsBreak()) { - return EmitBreak(stmt->AsBreak()); + return EmitBreak(out, stmt->AsBreak()); } if (stmt->IsCall()) { - make_indent(); - if (!EmitCall(stmt->AsCall()->expr())) { + make_indent(out); + if (!EmitCall(out, stmt->AsCall()->expr())) { return false; } - out_ << ";" << std::endl; + out << ";" << std::endl; return true; } if (stmt->IsContinue()) { - return EmitContinue(stmt->AsContinue()); + return EmitContinue(out, stmt->AsContinue()); } if (stmt->IsDiscard()) { - return EmitDiscard(stmt->AsDiscard()); + return EmitDiscard(out, stmt->AsDiscard()); } if (stmt->IsFallthrough()) { - make_indent(); - out_ << "/* fallthrough */" << std::endl; + make_indent(out); + out << "/* fallthrough */" << std::endl; return true; } if (stmt->IsIf()) { - return EmitIf(stmt->AsIf()); + return EmitIf(out, stmt->AsIf()); } if (stmt->IsLoop()) { - return EmitLoop(stmt->AsLoop()); + return EmitLoop(out, stmt->AsLoop()); } if (stmt->IsReturn()) { - return EmitReturn(stmt->AsReturn()); + return EmitReturn(out, stmt->AsReturn()); } if (stmt->IsSwitch()) { - return EmitSwitch(stmt->AsSwitch()); + return EmitSwitch(out, stmt->AsSwitch()); } if (stmt->IsVariableDecl()) { - return EmitVariable(stmt->AsVariableDecl()->variable()); + return EmitVariable(out, stmt->AsVariableDecl()->variable()); } error_ = "unknown statement type: " + stmt->str(); return false; } -bool GeneratorImpl::EmitSwitch(ast::SwitchStatement* stmt) { - make_indent(); +bool GeneratorImpl::EmitSwitch(std::ostream& out, ast::SwitchStatement* stmt) { + make_indent(out); - out_ << "switch("; - if (!EmitExpression(stmt->condition())) { + out << "switch("; + if (!EmitExpression(out, stmt->condition())) { return false; } - out_ << ") {" << std::endl; + out << ") {" << std::endl; increment_indent(); for (const auto& s : stmt->body()) { - if (!EmitCase(s.get())) { + if (!EmitCase(out, s.get())) { return false; } } decrement_indent(); - make_indent(); - out_ << "}" << std::endl; + make_indent(out); + out << "}" << std::endl; return true; } -bool GeneratorImpl::EmitType(ast::type::Type* type, const std::string& name) { +bool GeneratorImpl::EmitType(std::ostream& out, + ast::type::Type* type, + const std::string& name) { if (type->IsAlias()) { auto* alias = type->AsAlias(); - out_ << namer_.NameFor(alias->name()); + out << namer_.NameFor(alias->name()); } else if (type->IsArray()) { auto* ary = type->AsArray(); @@ -1773,28 +1795,28 @@ bool GeneratorImpl::EmitType(ast::type::Type* type, const std::string& name) { } base_type = base_type->AsArray()->type(); } - if (!EmitType(base_type, "")) { + if (!EmitType(out, base_type, "")) { return false; } if (!name.empty()) { - out_ << " " << namer_.NameFor(name); + out << " " << namer_.NameFor(name); } for (uint32_t size : sizes) { - out_ << "[" << size << "]"; + out << "[" << size << "]"; } } else if (type->IsBool()) { - out_ << "bool"; + out << "bool"; } else if (type->IsF32()) { - out_ << "float"; + out << "float"; } else if (type->IsI32()) { - out_ << "int"; + out << "int"; } else if (type->IsMatrix()) { auto* mat = type->AsMatrix(); - out_ << "matrix<"; - if (!EmitType(mat->type(), "")) { + out << "matrix<"; + if (!EmitType(out, mat->type(), "")) { return false; } - out_ << ", " << mat->rows() << ", " << mat->columns() << ">"; + out << ", " << mat->rows() << ", " << mat->columns() << ">"; } else if (type->IsPointer()) { // TODO(dsinclair): What do we do with pointers in HLSL? // https://bugs.chromium.org/p/tint/issues/detail?id=183 @@ -1805,43 +1827,43 @@ bool GeneratorImpl::EmitType(ast::type::Type* type, const std::string& name) { // TODO(dsinclair): Block decoration? // if (str->decoration() != ast::StructDecoration::kNone) { // } - out_ << "struct"; + out << "struct"; // If a name was provided for the struct emit it. if (!name.empty()) { - out_ << " " << name; + out << " " << name; } - out_ << " {" << std::endl; + out << " {" << std::endl; increment_indent(); for (const auto& mem : str->members()) { - make_indent(); + make_indent(out); // TODO(dsinclair): Handle [[offset]] annotation on structs // https://bugs.chromium.org/p/tint/issues/detail?id=184 - if (!EmitType(mem->type(), mem->name())) { + if (!EmitType(out, mem->type(), mem->name())) { return false; } // Array member name will be output with the type if (!mem->type()->IsArray()) { - out_ << " " << namer_.NameFor(mem->name()); + out << " " << namer_.NameFor(mem->name()); } - out_ << ";" << std::endl; + out << ";" << std::endl; } decrement_indent(); - make_indent(); + make_indent(out); - out_ << "}"; + out << "}"; } else if (type->IsU32()) { - out_ << "uint"; + out << "uint"; } else if (type->IsVector()) { auto* vec = type->AsVector(); - out_ << "vector<"; - if (!EmitType(vec->type(), "")) { + out << "vector<"; + if (!EmitType(out, vec->type(), "")) { return false; } - out_ << ", " << vec->size() << ">"; + out << ", " << vec->size() << ">"; } else if (type->IsVoid()) { - out_ << "void"; + out << "void"; } else { error_ = "unknown type in EmitType"; return false; @@ -1850,28 +1872,29 @@ bool GeneratorImpl::EmitType(ast::type::Type* type, const std::string& name) { return true; } -bool GeneratorImpl::EmitUnaryOp(ast::UnaryOpExpression* expr) { +bool GeneratorImpl::EmitUnaryOp(std::ostream& out, + ast::UnaryOpExpression* expr) { switch (expr->op()) { case ast::UnaryOp::kNot: - out_ << "!"; + out << "!"; break; case ast::UnaryOp::kNegation: - out_ << "-"; + out << "-"; break; } - out_ << "("; + out << "("; - if (!EmitExpression(expr->expr())) { + if (!EmitExpression(out, expr->expr())) { return false; } - out_ << ")"; + out << ")"; return true; } -bool GeneratorImpl::EmitVariable(ast::Variable* var) { - make_indent(); +bool GeneratorImpl::EmitVariable(std::ostream& out, ast::Variable* var) { + make_indent(out); // TODO(dsinclair): Handle variable decorations if (var->IsDecorated()) { @@ -1880,28 +1903,29 @@ bool GeneratorImpl::EmitVariable(ast::Variable* var) { } if (var->is_const()) { - out_ << "const "; + out << "const "; } - if (!EmitType(var->type(), var->name())) { + if (!EmitType(out, var->type(), var->name())) { return false; } if (!var->type()->IsArray()) { - out_ << " " << var->name(); + out << " " << var->name(); } if (var->constructor() != nullptr) { - out_ << " = "; - if (!EmitExpression(var->constructor())) { + out << " = "; + if (!EmitExpression(out, var->constructor())) { return false; } } - out_ << ";" << std::endl; + out << ";" << std::endl; return true; } -bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) { - make_indent(); +bool GeneratorImpl::EmitProgramConstVariable(std::ostream& out, + const ast::Variable* var) { + make_indent(out); if (var->IsDecorated()) { error_ = "Decorated const values not valid"; @@ -1912,21 +1936,21 @@ bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) { return false; } - out_ << "static const "; - if (!EmitType(var->type(), var->name())) { + out << "static const "; + if (!EmitType(out, var->type(), var->name())) { return false; } if (!var->type()->IsArray()) { - out_ << " " << var->name(); + out << " " << var->name(); } if (var->constructor() != nullptr) { - out_ << " = "; - if (!EmitExpression(var->constructor())) { + out << " = "; + if (!EmitExpression(out, var->constructor())) { return false; } } - out_ << ";" << std::endl; + out << ";" << std::endl; return true; } diff --git a/src/writer/hlsl/generator_impl.h b/src/writer/hlsl/generator_impl.h index c9eae280c7..7908e4263f 100644 --- a/src/writer/hlsl/generator_impl.h +++ b/src/writer/hlsl/generator_impl.h @@ -21,182 +21,247 @@ #include "src/ast/type_constructor_expression.h" #include "src/scope_stack.h" #include "src/writer/hlsl/namer.h" -#include "src/writer/text_generator.h" namespace tint { namespace writer { namespace hlsl { /// Implementation class for HLSL generator -class GeneratorImpl : public TextGenerator { +class GeneratorImpl { public: /// Constructor /// @param module the module to generate explicit GeneratorImpl(ast::Module* module); ~GeneratorImpl(); + /// Increment the emitter indent level + void increment_indent() { indent_ += 2; } + /// Decrement the emiter indent level + void decrement_indent() { + if (indent_ < 2) { + indent_ = 0; + return; + } + indent_ -= 2; + } + + /// Writes the current indent to the output stream + /// @param out the output stream + void make_indent(std::ostream& out); + + /// @returns the error + std::string error() const { return error_; } + + /// @param out the output stream /// @returns true on successful generation; false otherwise - bool Generate(); + bool Generate(std::ostream& out); /// Handles generating an alias + /// @param out the output stream /// @param alias the alias to generate /// @returns true if the alias was emitted - bool EmitAliasType(const ast::type::AliasType* alias); + bool EmitAliasType(std::ostream& out, const ast::type::AliasType* alias); /// Handles an array accessor expression + /// @param out the output stream /// @param expr the expression to emit /// @returns true if the array accessor was emitted - bool EmitArrayAccessor(ast::ArrayAccessorExpression* expr); + bool EmitArrayAccessor(std::ostream& out, ast::ArrayAccessorExpression* expr); /// Handles generating an as expression + /// @param out the output stream /// @param expr the as expression /// @returns true if the as was emitted - bool EmitAs(ast::AsExpression* expr); + bool EmitAs(std::ostream& out, ast::AsExpression* 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(ast::AssignmentStatement* stmt); + bool EmitAssign(std::ostream& out, ast::AssignmentStatement* stmt); /// Handles generating a binary expression + /// @param out the output stream /// @param expr the binary expression /// @returns true if the expression was emitted, false otherwise - bool EmitBinary(ast::BinaryExpression* expr); + bool EmitBinary(std::ostream& out, ast::BinaryExpression* expr); /// 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(const ast::BlockStatement* stmt); + 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(ast::BlockStatement* stmt); + 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(const ast::BlockStatement* stmt); + bool EmitBlockAndNewline(std::ostream& out, 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(ast::BreakStatement* stmt); + bool EmitBreak(std::ostream& out, ast::BreakStatement* stmt); /// Handles generating a call expression + /// @param out the output stream /// @param expr the call expression /// @returns true if the call expression is emitted - bool EmitCall(ast::CallExpression* expr); + bool EmitCall(std::ostream& out, ast::CallExpression* expr); /// Handles a case statement + /// @param out the output stream /// @param stmt the statement /// @returns true if the statment was emitted successfully - bool EmitCase(ast::CaseStatement* stmt); + bool EmitCase(std::ostream& out, ast::CaseStatement* stmt); /// Handles generating a cast expression + /// @param out the output stream /// @param expr the cast expression /// @returns true if the cast was emitted - bool EmitCast(ast::CastExpression* expr); + bool EmitCast(std::ostream& out, ast::CastExpression* expr); /// Handles generating constructor expressions + /// @param out the output stream /// @param expr the constructor expression /// @returns true if the expression was emitted - bool EmitConstructor(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(ast::DiscardStatement* stmt); + bool EmitDiscard(std::ostream& out, ast::DiscardStatement* stmt); /// Handles generating a scalar constructor + /// @param out the output stream /// @param expr the scalar constructor expression /// @returns true if the scalar constructor is emitted - bool EmitScalarConstructor(ast::ScalarConstructorExpression* expr); + bool EmitScalarConstructor(std::ostream& out, + ast::ScalarConstructorExpression* expr); /// Handles emitting a type constructor + /// @param out the output stream /// @param expr the type constructor expression /// @returns true if the constructor is emitted - bool EmitTypeConstructor(ast::TypeConstructorExpression* expr); + 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(ast::ContinueStatement* stmt); + bool EmitContinue(std::ostream& out, ast::ContinueStatement* stmt); /// Handles generating an else statement + /// @param out the output stream /// @param stmt the statement to emit /// @returns true if the statement was emitted - bool EmitElse(ast::ElseStatement* stmt); + bool EmitElse(std::ostream& out, ast::ElseStatement* stmt); /// Handles generate an Expression + /// @param out the output stream /// @param expr the expression /// @returns true if the expression was emitted - bool EmitExpression(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(ast::Function* func); + bool EmitFunction(std::ostream& out, ast::Function* func); /// Internal helper for emitting functions + /// @param out the output stream /// @param func the function to emit /// @param emit_duplicate_functions set true if we need to duplicate per entry /// point /// @param ep_name the current entry point or blank if none set /// @returns true if the function was emitted. - bool EmitFunctionInternal(ast::Function* func, + bool EmitFunctionInternal(std::ostream& out, + ast::Function* func, bool emit_duplicate_functions, const std::string& ep_name); /// Handles emitting information for an entry point + /// @param out the output stream /// @param ep the entry point /// @returns true if the entry point data was emitted - bool EmitEntryPointData(ast::EntryPoint* ep); + bool EmitEntryPointData(std::ostream& out, ast::EntryPoint* ep); /// Handles emitting the entry point function + /// @param out the output stream /// @param ep the entry point /// @returns true if the entry point function was emitted - bool EmitEntryPointFunction(ast::EntryPoint* ep); + bool EmitEntryPointFunction(std::ostream& out, ast::EntryPoint* ep); /// 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(ast::IfStatement* stmt); + bool EmitIf(std::ostream& out, ast::IfStatement* stmt); /// Handles genreating an import expression + /// @param out the output stream /// @param expr the expression /// @returns true if the expression was successfully emitted. - bool EmitImportFunction(ast::CallExpression* expr); + bool EmitImportFunction(std::ostream& out, ast::CallExpression* expr); /// Handles a literal + /// @param out the output stream /// @param lit the literal to emit /// @returns true if the literal was successfully emitted - bool EmitLiteral(ast::Literal* lit); + 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(ast::LoopStatement* stmt); + bool EmitLoop(std::ostream& out, ast::LoopStatement* stmt); /// Handles generating an identifier expression + /// @param out the output stream /// @param expr the identifier expression /// @returns true if the identifeir was emitted - bool EmitIdentifier(ast::IdentifierExpression* expr); + bool EmitIdentifier(std::ostream& out, ast::IdentifierExpression* expr); /// Handles a member accessor expression + /// @param out the output stream /// @param expr the member accessor expression /// @returns true if the member accessor was emitted - bool EmitMemberAccessor(ast::MemberAccessorExpression* expr); + bool EmitMemberAccessor(std::ostream& out, + ast::MemberAccessorExpression* expr); /// Handles a storage buffer accessor expression + /// @param out the output stream /// @param expr the storage buffer accessor expression /// @param rhs the right side of a store expression. Set to nullptr for a load /// @returns true if the storage buffer accessor was emitted - bool EmitStorageBufferAccessor(ast::Expression* expr, ast::Expression* rhs); + bool EmitStorageBufferAccessor(std::ostream& out, + ast::Expression* expr, + ast::Expression* rhs); /// Handles return statements + /// @param out the output stream /// @param stmt the statement to emit /// @returns true if the statement was successfully emitted - bool EmitReturn(ast::ReturnStatement* stmt); + bool EmitReturn(std::ostream& out, 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(ast::Statement* stmt); + bool EmitStatement(std::ostream& out, 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(ast::SwitchStatement* stmt); + bool EmitSwitch(std::ostream& out, ast::SwitchStatement* stmt); /// Handles generating type + /// @param out the output stream /// @param type the type to generate /// @param name the name of the variable, only used for array emission /// @returns true if the type is emitted - bool EmitType(ast::type::Type* type, const std::string& name); + bool EmitType(std::ostream& out, + ast::type::Type* type, + const std::string& name); /// Handles a unary op expression + /// @param out the output stream /// @param expr the expression to emit /// @returns true if the expression was emitted - bool EmitUnaryOp(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(ast::type::Type* type); + bool EmitZeroValue(std::ostream& out, ast::type::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(ast::Variable* var); + bool EmitVariable(std::ostream& out, 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(const ast::Variable* var); + bool EmitProgramConstVariable(std::ostream& out, const ast::Variable* var); /// Returns true if the accessor is accessing a storage buffer. /// @param expr the expression to check @@ -252,6 +317,9 @@ class GeneratorImpl : public TextGenerator { std::string current_ep_var_name(VarType type); + std::string error_; + size_t indent_ = 0; + Namer namer_; ast::Module* module_ = nullptr; std::string current_ep_name_; diff --git a/src/writer/hlsl/generator_impl_alias_type_test.cc b/src/writer/hlsl/generator_impl_alias_type_test.cc index fd24703ed6..c68de9f679 100644 --- a/src/writer/hlsl/generator_impl_alias_type_test.cc +++ b/src/writer/hlsl/generator_impl_alias_type_test.cc @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "gtest/gtest.h" #include "src/ast/module.h" #include "src/ast/struct.h" #include "src/ast/struct_member.h" @@ -21,38 +20,35 @@ #include "src/ast/type/f32_type.h" #include "src/ast/type/i32_type.h" #include "src/ast/type/struct_type.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_AliasType : public TestHelper, + public testing::Test {}; -TEST_F(HlslGeneratorImplTest, EmitAliasType_F32) { +TEST_F(HlslGeneratorImplTest_AliasType, EmitAliasType_F32) { ast::type::F32Type f32; ast::type::AliasType alias("a", &f32); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitAliasType(&alias)) << g.error(); - EXPECT_EQ(g.result(), R"(typedef float a; + ASSERT_TRUE(gen().EmitAliasType(out(), &alias)) << gen().error(); + EXPECT_EQ(result(), R"(typedef float a; )"); } -TEST_F(HlslGeneratorImplTest, EmitAliasType_NameCollision) { +TEST_F(HlslGeneratorImplTest_AliasType, EmitAliasType_NameCollision) { ast::type::F32Type f32; ast::type::AliasType alias("float", &f32); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitAliasType(&alias)) << g.error(); - EXPECT_EQ(g.result(), R"(typedef float float_tint_0; + ASSERT_TRUE(gen().EmitAliasType(out(), &alias)) << gen().error(); + EXPECT_EQ(result(), R"(typedef float float_tint_0; )"); } -TEST_F(HlslGeneratorImplTest, EmitAliasType_Struct) { +TEST_F(HlslGeneratorImplTest_AliasType, EmitAliasType_Struct) { ast::type::I32Type i32; ast::type::F32Type f32; @@ -73,8 +69,8 @@ TEST_F(HlslGeneratorImplTest, EmitAliasType_Struct) { ast::Module m; GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitAliasType(&alias)) << g.error(); - EXPECT_EQ(g.result(), R"(struct a { + ASSERT_TRUE(gen().EmitAliasType(out(), &alias)) << gen().error(); + EXPECT_EQ(result(), R"(struct a { float a; int b; }; diff --git a/src/writer/hlsl/generator_impl_array_accessor_test.cc b/src/writer/hlsl/generator_impl_array_accessor_test.cc index ecd5310189..ce7371dc08 100644 --- a/src/writer/hlsl/generator_impl_array_accessor_test.cc +++ b/src/writer/hlsl/generator_impl_array_accessor_test.cc @@ -14,23 +14,23 @@ #include -#include "gtest/gtest.h" #include "src/ast/array_accessor_expression.h" #include "src/ast/identifier_expression.h" #include "src/ast/module.h" #include "src/ast/scalar_constructor_expression.h" #include "src/ast/sint_literal.h" #include "src/ast/type/i32_type.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_Expression : public TestHelper, + public testing::Test {}; -TEST_F(HlslGeneratorImplTest, EmitExpression_ArrayAccessor) { +TEST_F(HlslGeneratorImplTest_Expression, EmitExpression_ArrayAccessor) { ast::type::I32Type i32; auto lit = std::make_unique(&i32, 5); auto idx = std::make_unique(std::move(lit)); @@ -38,22 +38,18 @@ TEST_F(HlslGeneratorImplTest, EmitExpression_ArrayAccessor) { ast::ArrayAccessorExpression expr(std::move(ary), std::move(idx)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitExpression(&expr)) << g.error(); - EXPECT_EQ(g.result(), "ary[5]"); + ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "ary[5]"); } -TEST_F(HlslGeneratorImplTest, EmitArrayAccessor) { +TEST_F(HlslGeneratorImplTest_Expression, EmitArrayAccessor) { auto ary = std::make_unique("ary"); auto idx = std::make_unique("idx"); ast::ArrayAccessorExpression expr(std::move(ary), std::move(idx)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitExpression(&expr)) << g.error(); - EXPECT_EQ(g.result(), "ary[idx]"); + ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "ary[idx]"); } } // namespace diff --git a/src/writer/hlsl/generator_impl_as_test.cc b/src/writer/hlsl/generator_impl_as_test.cc index c7975ce83e..710b57e725 100644 --- a/src/writer/hlsl/generator_impl_as_test.cc +++ b/src/writer/hlsl/generator_impl_as_test.cc @@ -14,53 +14,46 @@ #include -#include "gtest/gtest.h" #include "src/ast/as_expression.h" #include "src/ast/identifier_expression.h" #include "src/ast/module.h" #include "src/ast/type/f32_type.h" #include "src/ast/type/i32_type.h" #include "src/ast/type/u32_type.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_As : public TestHelper, public testing::Test {}; -TEST_F(HlslGeneratorImplTest, EmitExpression_As_Float) { +TEST_F(HlslGeneratorImplTest_As, EmitExpression_As_Float) { ast::type::F32Type f32; auto id = std::make_unique("id"); ast::AsExpression as(&f32, std::move(id)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitExpression(&as)) << g.error(); - EXPECT_EQ(g.result(), "asfloat(id)"); + ASSERT_TRUE(gen().EmitExpression(out(), &as)) << gen().error(); + EXPECT_EQ(result(), "asfloat(id)"); } -TEST_F(HlslGeneratorImplTest, EmitExpression_As_Int) { +TEST_F(HlslGeneratorImplTest_As, EmitExpression_As_Int) { ast::type::I32Type i32; auto id = std::make_unique("id"); ast::AsExpression as(&i32, std::move(id)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitExpression(&as)) << g.error(); - EXPECT_EQ(g.result(), "asint(id)"); + ASSERT_TRUE(gen().EmitExpression(out(), &as)) << gen().error(); + EXPECT_EQ(result(), "asint(id)"); } -TEST_F(HlslGeneratorImplTest, EmitExpression_As_Uint) { +TEST_F(HlslGeneratorImplTest_As, EmitExpression_As_Uint) { ast::type::U32Type u32; auto id = std::make_unique("id"); ast::AsExpression as(&u32, std::move(id)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitExpression(&as)) << g.error(); - EXPECT_EQ(g.result(), "asuint(id)"); + ASSERT_TRUE(gen().EmitExpression(out(), &as)) << gen().error(); + EXPECT_EQ(result(), "asuint(id)"); } } // namespace diff --git a/src/writer/hlsl/generator_impl_assign_test.cc b/src/writer/hlsl/generator_impl_assign_test.cc index b8e551aacc..5781d97ace 100644 --- a/src/writer/hlsl/generator_impl_assign_test.cc +++ b/src/writer/hlsl/generator_impl_assign_test.cc @@ -15,30 +15,27 @@ #include #include -#include "gtest/gtest.h" #include "src/ast/assignment_statement.h" #include "src/ast/identifier_expression.h" #include "src/ast/module.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_Assign : public TestHelper, public testing::Test {}; -TEST_F(HlslGeneratorImplTest, Emit_Assign) { +TEST_F(HlslGeneratorImplTest_Assign, Emit_Assign) { auto lhs = std::make_unique("lhs"); auto rhs = std::make_unique("rhs"); ast::AssignmentStatement assign(std::move(lhs), std::move(rhs)); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); + gen().increment_indent(); - ASSERT_TRUE(g.EmitStatement(&assign)) << g.error(); - EXPECT_EQ(g.result(), " lhs = rhs;\n"); + ASSERT_TRUE(gen().EmitStatement(out(), &assign)) << gen().error(); + EXPECT_EQ(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 44a393ca81..717148abd6 100644 --- a/src/writer/hlsl/generator_impl_binary_test.cc +++ b/src/writer/hlsl/generator_impl_binary_test.cc @@ -14,11 +14,10 @@ #include -#include "gtest/gtest.h" #include "src/ast/binary_expression.h" #include "src/ast/identifier_expression.h" #include "src/ast/module.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { @@ -33,7 +32,9 @@ inline std::ostream& operator<<(std::ostream& out, BinaryData data) { out << data.op; return out; } -using HlslBinaryTest = testing::TestWithParam; + +class HlslBinaryTest : public TestHelper, + public testing::TestWithParam {}; TEST_P(HlslBinaryTest, Emit) { auto params = GetParam(); @@ -42,10 +43,8 @@ TEST_P(HlslBinaryTest, Emit) { ast::BinaryExpression expr(params.op, std::move(left), std::move(right)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitExpression(&expr)) << g.error(); - EXPECT_EQ(g.result(), params.result); + ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), params.result); } INSTANTIATE_TEST_SUITE_P( HlslGeneratorImplTest, diff --git a/src/writer/hlsl/generator_impl_block_test.cc b/src/writer/hlsl/generator_impl_block_test.cc index 772274f682..1d44592967 100644 --- a/src/writer/hlsl/generator_impl_block_test.cc +++ b/src/writer/hlsl/generator_impl_block_test.cc @@ -14,43 +14,38 @@ #include -#include "gtest/gtest.h" #include "src/ast/block_statement.h" #include "src/ast/discard_statement.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_Block : public TestHelper, public testing::Test {}; -TEST_F(HlslGeneratorImplTest, Emit_Block) { +TEST_F(HlslGeneratorImplTest_Block, Emit_Block) { ast::BlockStatement b; b.append(std::make_unique()); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); + gen().increment_indent(); - ASSERT_TRUE(g.EmitStatement(&b)) << g.error(); - EXPECT_EQ(g.result(), R"( { + ASSERT_TRUE(gen().EmitStatement(out(), &b)) << gen().error(); + EXPECT_EQ(result(), R"( { discard; } )"); } -TEST_F(HlslGeneratorImplTest, Emit_Block_WithoutNewline) { +TEST_F(HlslGeneratorImplTest_Block, Emit_Block_WithoutNewline) { ast::BlockStatement b; b.append(std::make_unique()); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); + gen().increment_indent(); - ASSERT_TRUE(g.EmitBlock(&b)) << g.error(); - EXPECT_EQ(g.result(), R"({ + ASSERT_TRUE(gen().EmitBlock(out(), &b)) << gen().error(); + EXPECT_EQ(result(), R"({ discard; })"); } diff --git a/src/writer/hlsl/generator_impl_break_test.cc b/src/writer/hlsl/generator_impl_break_test.cc index ad53672100..eafd1889d8 100644 --- a/src/writer/hlsl/generator_impl_break_test.cc +++ b/src/writer/hlsl/generator_impl_break_test.cc @@ -15,27 +15,24 @@ #include #include -#include "gtest/gtest.h" #include "src/ast/break_statement.h" #include "src/ast/module.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_Break : public TestHelper, public testing::Test {}; -TEST_F(HlslGeneratorImplTest, Emit_Break) { +TEST_F(HlslGeneratorImplTest_Break, Emit_Break) { ast::BreakStatement b; - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); + gen().increment_indent(); - ASSERT_TRUE(g.EmitStatement(&b)) << g.error(); - EXPECT_EQ(g.result(), " break;\n"); + ASSERT_TRUE(gen().EmitStatement(out(), &b)) << gen().error(); + EXPECT_EQ(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 e1082a0fbd..3405d1b80d 100644 --- a/src/writer/hlsl/generator_impl_call_test.cc +++ b/src/writer/hlsl/generator_impl_call_test.cc @@ -14,23 +14,22 @@ #include -#include "gtest/gtest.h" #include "src/ast/call_expression.h" #include "src/ast/call_statement.h" #include "src/ast/function.h" #include "src/ast/identifier_expression.h" #include "src/ast/module.h" #include "src/ast/type/void_type.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_Call : public TestHelper, public testing::Test {}; -TEST_F(HlslGeneratorImplTest, EmitExpression_Call_WithoutParams) { +TEST_F(HlslGeneratorImplTest_Call, EmitExpression_Call_WithoutParams) { ast::type::VoidType void_type; auto id = std::make_unique("my_func"); @@ -38,16 +37,13 @@ TEST_F(HlslGeneratorImplTest, EmitExpression_Call_WithoutParams) { auto func = std::make_unique("my_func", ast::VariableList{}, &void_type); + mod()->AddFunction(std::move(func)); - ast::Module m; - m.AddFunction(std::move(func)); - - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitExpression(&call)) << g.error(); - EXPECT_EQ(g.result(), "my_func()"); + ASSERT_TRUE(gen().EmitExpression(out(), &call)) << gen().error(); + EXPECT_EQ(result(), "my_func()"); } -TEST_F(HlslGeneratorImplTest, EmitExpression_Call_WithParams) { +TEST_F(HlslGeneratorImplTest_Call, EmitExpression_Call_WithParams) { ast::type::VoidType void_type; auto id = std::make_unique("my_func"); @@ -58,16 +54,13 @@ TEST_F(HlslGeneratorImplTest, EmitExpression_Call_WithParams) { auto func = std::make_unique("my_func", ast::VariableList{}, &void_type); + mod()->AddFunction(std::move(func)); - ast::Module m; - m.AddFunction(std::move(func)); - - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitExpression(&call)) << g.error(); - EXPECT_EQ(g.result(), "my_func(param1, param2)"); + ASSERT_TRUE(gen().EmitExpression(out(), &call)) << gen().error(); + EXPECT_EQ(result(), "my_func(param1, param2)"); } -TEST_F(HlslGeneratorImplTest, EmitStatement_Call) { +TEST_F(HlslGeneratorImplTest_Call, EmitStatement_Call) { ast::type::VoidType void_type; auto id = std::make_unique("my_func"); @@ -79,14 +72,10 @@ TEST_F(HlslGeneratorImplTest, EmitStatement_Call) { auto func = std::make_unique("my_func", ast::VariableList{}, &void_type); - - ast::Module m; - m.AddFunction(std::move(func)); - - GeneratorImpl g(&m); - g.increment_indent(); - ASSERT_TRUE(g.EmitStatement(&call)) << g.error(); - EXPECT_EQ(g.result(), " my_func(param1, param2);\n"); + mod()->AddFunction(std::move(func)); + gen().increment_indent(); + ASSERT_TRUE(gen().EmitStatement(out(), &call)) << gen().error(); + EXPECT_EQ(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 acc0c8bd7b..05d06c393c 100644 --- a/src/writer/hlsl/generator_impl_case_test.cc +++ b/src/writer/hlsl/generator_impl_case_test.cc @@ -14,7 +14,6 @@ #include -#include "gtest/gtest.h" #include "src/ast/break_statement.h" #include "src/ast/case_statement.h" #include "src/ast/fallthrough_statement.h" @@ -22,16 +21,16 @@ #include "src/ast/module.h" #include "src/ast/sint_literal.h" #include "src/ast/type/i32_type.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_Case : public TestHelper, public testing::Test {}; -TEST_F(HlslGeneratorImplTest, Emit_Case) { +TEST_F(HlslGeneratorImplTest_Case, Emit_Case) { ast::type::I32Type i32; auto body = std::make_unique(); @@ -41,36 +40,32 @@ TEST_F(HlslGeneratorImplTest, Emit_Case) { lit.push_back(std::make_unique(&i32, 5)); ast::CaseStatement c(std::move(lit), std::move(body)); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); + gen().increment_indent(); - ASSERT_TRUE(g.EmitCase(&c)) << g.error(); - EXPECT_EQ(g.result(), R"( case 5: { + ASSERT_TRUE(gen().EmitCase(out(), &c)) << gen().error(); + EXPECT_EQ(result(), R"( case 5: { break; } )"); } -TEST_F(HlslGeneratorImplTest, Emit_Case_BreaksByDefault) { +TEST_F(HlslGeneratorImplTest_Case, Emit_Case_BreaksByDefault) { ast::type::I32Type i32; ast::CaseSelectorList lit; lit.push_back(std::make_unique(&i32, 5)); ast::CaseStatement c(std::move(lit), std::make_unique()); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); + gen().increment_indent(); - ASSERT_TRUE(g.EmitCase(&c)) << g.error(); - EXPECT_EQ(g.result(), R"( case 5: { + ASSERT_TRUE(gen().EmitCase(out(), &c)) << gen().error(); + EXPECT_EQ(result(), R"( case 5: { break; } )"); } -TEST_F(HlslGeneratorImplTest, Emit_Case_WithFallthrough) { +TEST_F(HlslGeneratorImplTest_Case, Emit_Case_WithFallthrough) { ast::type::I32Type i32; auto body = std::make_unique(); @@ -80,18 +75,16 @@ TEST_F(HlslGeneratorImplTest, Emit_Case_WithFallthrough) { lit.push_back(std::make_unique(&i32, 5)); ast::CaseStatement c(std::move(lit), std::move(body)); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); + gen().increment_indent(); - ASSERT_TRUE(g.EmitCase(&c)) << g.error(); - EXPECT_EQ(g.result(), R"( case 5: { + ASSERT_TRUE(gen().EmitCase(out(), &c)) << gen().error(); + EXPECT_EQ(result(), R"( case 5: { /* fallthrough */ } )"); } -TEST_F(HlslGeneratorImplTest, Emit_Case_MultipleSelectors) { +TEST_F(HlslGeneratorImplTest_Case, Emit_Case_MultipleSelectors) { ast::type::I32Type i32; auto body = std::make_unique(); @@ -102,31 +95,27 @@ TEST_F(HlslGeneratorImplTest, Emit_Case_MultipleSelectors) { lit.push_back(std::make_unique(&i32, 6)); ast::CaseStatement c(std::move(lit), std::move(body)); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); + gen().increment_indent(); - ASSERT_TRUE(g.EmitCase(&c)) << g.error(); - EXPECT_EQ(g.result(), R"( case 5: + ASSERT_TRUE(gen().EmitCase(out(), &c)) << gen().error(); + EXPECT_EQ(result(), R"( case 5: case 6: { break; } )"); } -TEST_F(HlslGeneratorImplTest, Emit_Case_Default) { +TEST_F(HlslGeneratorImplTest_Case, Emit_Case_Default) { ast::CaseStatement c; auto body = std::make_unique(); body->append(std::make_unique()); c.set_body(std::move(body)); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); + gen().increment_indent(); - ASSERT_TRUE(g.EmitCase(&c)) << g.error(); - EXPECT_EQ(g.result(), R"( default: { + ASSERT_TRUE(gen().EmitCase(out(), &c)) << gen().error(); + EXPECT_EQ(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 c9d6f87b35..1e782b3dd5 100644 --- a/src/writer/hlsl/generator_impl_cast_test.cc +++ b/src/writer/hlsl/generator_impl_cast_test.cc @@ -14,43 +14,38 @@ #include -#include "gtest/gtest.h" #include "src/ast/cast_expression.h" #include "src/ast/identifier_expression.h" #include "src/ast/module.h" #include "src/ast/type/f32_type.h" #include "src/ast/type/vector_type.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_Cast : public TestHelper, public testing::Test {}; -TEST_F(HlslGeneratorImplTest, EmitExpression_Cast_Scalar) { +TEST_F(HlslGeneratorImplTest_Cast, EmitExpression_Cast_Scalar) { ast::type::F32Type f32; auto id = std::make_unique("id"); ast::CastExpression cast(&f32, std::move(id)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitExpression(&cast)) << g.error(); - EXPECT_EQ(g.result(), "float(id)"); + ASSERT_TRUE(gen().EmitExpression(out(), &cast)) << gen().error(); + EXPECT_EQ(result(), "float(id)"); } -TEST_F(HlslGeneratorImplTest, EmitExpression_Cast_Vector) { +TEST_F(HlslGeneratorImplTest_Cast, EmitExpression_Cast_Vector) { ast::type::F32Type f32; ast::type::VectorType vec3(&f32, 3); auto id = std::make_unique("id"); ast::CastExpression cast(&vec3, std::move(id)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitExpression(&cast)) << g.error(); - EXPECT_EQ(g.result(), "vector(id)"); + ASSERT_TRUE(gen().EmitExpression(out(), &cast)) << gen().error(); + EXPECT_EQ(result(), "vector(id)"); } } // namespace diff --git a/src/writer/hlsl/generator_impl_constructor_test.cc b/src/writer/hlsl/generator_impl_constructor_test.cc index 823fa21835..f9b2b2bfe9 100644 --- a/src/writer/hlsl/generator_impl_constructor_test.cc +++ b/src/writer/hlsl/generator_impl_constructor_test.cc @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "gtest/gtest.h" #include "src/ast/bool_literal.h" #include "src/ast/float_literal.h" #include "src/ast/module.h" @@ -27,61 +26,54 @@ #include "src/ast/type/vector_type.h" #include "src/ast/type_constructor_expression.h" #include "src/ast/uint_literal.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_Constructor : public TestHelper, + public testing::Test {}; -TEST_F(HlslGeneratorImplTest, EmitConstructor_Bool) { +TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Bool) { ast::type::BoolType bool_type; auto lit = std::make_unique(&bool_type, false); ast::ScalarConstructorExpression expr(std::move(lit)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error(); - EXPECT_EQ(g.result(), "false"); + ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "false"); } -TEST_F(HlslGeneratorImplTest, EmitConstructor_Int) { +TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Int) { ast::type::I32Type i32; auto lit = std::make_unique(&i32, -12345); ast::ScalarConstructorExpression expr(std::move(lit)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error(); - EXPECT_EQ(g.result(), "-12345"); + ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "-12345"); } -TEST_F(HlslGeneratorImplTest, EmitConstructor_UInt) { +TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_UInt) { ast::type::U32Type u32; auto lit = std::make_unique(&u32, 56779); ast::ScalarConstructorExpression expr(std::move(lit)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error(); - EXPECT_EQ(g.result(), "56779u"); + ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "56779u"); } -TEST_F(HlslGeneratorImplTest, EmitConstructor_Float) { +TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Float) { ast::type::F32Type f32; // Use a number close to 1<<30 but whose decimal representation ends in 0. auto lit = std::make_unique(&f32, float((1 << 30) - 4)); ast::ScalarConstructorExpression expr(std::move(lit)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error(); - EXPECT_EQ(g.result(), "1.07374182e+09f"); + ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "1.07374182e+09f"); } -TEST_F(HlslGeneratorImplTest, EmitConstructor_Type_Float) { +TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Float) { ast::type::F32Type f32; auto lit = std::make_unique(&f32, -1.2e-5); @@ -91,13 +83,11 @@ TEST_F(HlslGeneratorImplTest, EmitConstructor_Type_Float) { ast::TypeConstructorExpression expr(&f32, std::move(values)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error(); - EXPECT_EQ(g.result(), "float(-1.20000004e-05f)"); + ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "float(-1.20000004e-05f)"); } -TEST_F(HlslGeneratorImplTest, EmitConstructor_Type_Bool) { +TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Bool) { ast::type::BoolType b; auto lit = std::make_unique(&b, true); @@ -107,13 +97,11 @@ TEST_F(HlslGeneratorImplTest, EmitConstructor_Type_Bool) { ast::TypeConstructorExpression expr(&b, std::move(values)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error(); - EXPECT_EQ(g.result(), "bool(true)"); + ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "bool(true)"); } -TEST_F(HlslGeneratorImplTest, EmitConstructor_Type_Int) { +TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Int) { ast::type::I32Type i32; auto lit = std::make_unique(&i32, -12345); @@ -123,13 +111,11 @@ TEST_F(HlslGeneratorImplTest, EmitConstructor_Type_Int) { ast::TypeConstructorExpression expr(&i32, std::move(values)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error(); - EXPECT_EQ(g.result(), "int(-12345)"); + ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "int(-12345)"); } -TEST_F(HlslGeneratorImplTest, EmitConstructor_Type_Uint) { +TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Uint) { ast::type::U32Type u32; auto lit = std::make_unique(&u32, 12345); @@ -139,13 +125,11 @@ TEST_F(HlslGeneratorImplTest, EmitConstructor_Type_Uint) { ast::TypeConstructorExpression expr(&u32, std::move(values)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error(); - EXPECT_EQ(g.result(), "uint(12345u)"); + ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "uint(12345u)"); } -TEST_F(HlslGeneratorImplTest, EmitConstructor_Type_Vec) { +TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec) { ast::type::F32Type f32; ast::type::VectorType vec(&f32, 3); @@ -162,27 +146,23 @@ TEST_F(HlslGeneratorImplTest, EmitConstructor_Type_Vec) { ast::TypeConstructorExpression expr(&vec, std::move(values)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error(); - EXPECT_EQ(g.result(), + ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "vector(1.00000000f, 2.00000000f, 3.00000000f)"); } -TEST_F(HlslGeneratorImplTest, EmitConstructor_Type_Vec_Empty) { +TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec_Empty) { ast::type::F32Type f32; ast::type::VectorType vec(&f32, 3); ast::ExpressionList values; ast::TypeConstructorExpression expr(&vec, std::move(values)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error(); - EXPECT_EQ(g.result(), "vector(0.0f)"); + ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "vector(0.0f)"); } -TEST_F(HlslGeneratorImplTest, EmitConstructor_Type_Mat) { +TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Mat) { ast::type::F32Type f32; ast::type::MatrixType mat(&f32, 3, 2); // 3 ROWS, 2 COLUMNS ast::type::VectorType vec(&f32, 3); @@ -214,19 +194,17 @@ TEST_F(HlslGeneratorImplTest, EmitConstructor_Type_Mat) { ast::TypeConstructorExpression expr(&mat, std::move(mat_values)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error(); + ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error(); // A matrix of type T with n columns and m rows can also be constructed from // n vectors of type T with m components. - EXPECT_EQ(g.result(), + EXPECT_EQ(result(), std::string("matrix(vector(1.00000000f, " "2.00000000f, 3.00000000f), ") + "vector(3.00000000f, 4.00000000f, 5.00000000f))"); } -TEST_F(HlslGeneratorImplTest, EmitConstructor_Type_Array) { +TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Array) { ast::type::F32Type f32; ast::type::VectorType vec(&f32, 3); ast::type::ArrayType ary(&vec, 3); @@ -255,10 +233,8 @@ TEST_F(HlslGeneratorImplTest, EmitConstructor_Type_Array) { ast::TypeConstructorExpression expr(&ary, std::move(ary_values)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error(); - EXPECT_EQ(g.result(), + ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), std::string("{") + "vector(1.00000000f, 2.00000000f, 3.00000000f), " + "vector(4.00000000f, 5.00000000f, 6.00000000f), " + @@ -266,7 +242,8 @@ TEST_F(HlslGeneratorImplTest, EmitConstructor_Type_Array) { } // TODO(dsinclair): Add struct constructor test. -TEST_F(HlslGeneratorImplTest, DISABLED_EmitConstructor_Type_Struct) {} +TEST_F(HlslGeneratorImplTest_Constructor, + DISABLED_EmitConstructor_Type_Struct) {} } // namespace } // namespace hlsl diff --git a/src/writer/hlsl/generator_impl_continue_test.cc b/src/writer/hlsl/generator_impl_continue_test.cc index 1aa0238d10..97b4ae09bb 100644 --- a/src/writer/hlsl/generator_impl_continue_test.cc +++ b/src/writer/hlsl/generator_impl_continue_test.cc @@ -15,27 +15,25 @@ #include #include -#include "gtest/gtest.h" #include "src/ast/continue_statement.h" #include "src/ast/module.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_Continue : public TestHelper, + public testing::Test {}; -TEST_F(HlslGeneratorImplTest, Emit_Continue) { +TEST_F(HlslGeneratorImplTest_Continue, Emit_Continue) { ast::ContinueStatement c; - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); + gen().increment_indent(); - ASSERT_TRUE(g.EmitStatement(&c)) << g.error(); - EXPECT_EQ(g.result(), " continue;\n"); + ASSERT_TRUE(gen().EmitStatement(out(), &c)) << gen().error(); + EXPECT_EQ(result(), " continue;\n"); } } // namespace diff --git a/src/writer/hlsl/generator_impl_discard_test.cc b/src/writer/hlsl/generator_impl_discard_test.cc index 4dfa099cb4..bbd4383e5d 100644 --- a/src/writer/hlsl/generator_impl_discard_test.cc +++ b/src/writer/hlsl/generator_impl_discard_test.cc @@ -12,27 +12,25 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "gtest/gtest.h" #include "src/ast/discard_statement.h" #include "src/ast/module.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_Discard : public TestHelper, + public testing::Test {}; -TEST_F(HlslGeneratorImplTest, Emit_Discard) { +TEST_F(HlslGeneratorImplTest_Discard, Emit_Discard) { ast::DiscardStatement stmt; - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); + gen().increment_indent(); - ASSERT_TRUE(g.EmitStatement(&stmt)) << g.error(); - EXPECT_EQ(g.result(), " discard;\n"); + ASSERT_TRUE(gen().EmitStatement(out(), &stmt)) << gen().error(); + EXPECT_EQ(result(), " discard;\n"); } } // namespace diff --git a/src/writer/hlsl/generator_impl_entry_point_test.cc b/src/writer/hlsl/generator_impl_entry_point_test.cc index d7a55a929b..2177806344 100644 --- a/src/writer/hlsl/generator_impl_entry_point_test.cc +++ b/src/writer/hlsl/generator_impl_entry_point_test.cc @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "gtest/gtest.h" #include "src/ast/assignment_statement.h" #include "src/ast/decorated_variable.h" #include "src/ast/entry_point.h" @@ -27,16 +26,17 @@ #include "src/ast/variable.h" #include "src/context.h" #include "src/type_determiner.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_EntryPoint : public TestHelper, + public testing::Test {}; -TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Vertex_Input) { +TEST_F(HlslGeneratorImplTest_EntryPoint, EmitEntryPointData_Vertex_Input) { // [[location 0]] var foo : f32; // [[location 1]] var bar : i32; // @@ -60,14 +60,11 @@ TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Vertex_Input) { decos.push_back(std::make_unique(1)); bar_var->set_decorations(std::move(decos)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - td.RegisterVariableForTesting(foo_var.get()); - td.RegisterVariableForTesting(bar_var.get()); + td().RegisterVariableForTesting(foo_var.get()); + td().RegisterVariableForTesting(bar_var.get()); - mod.AddGlobalVariable(std::move(foo_var)); - mod.AddGlobalVariable(std::move(bar_var)); + mod()->AddGlobalVariable(std::move(foo_var)); + mod()->AddGlobalVariable(std::move(bar_var)); ast::VariableList params; auto func = @@ -82,19 +79,17 @@ TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Vertex_Input) { std::make_unique("bar"))); func->set_body(std::move(body)); - mod.AddFunction(std::move(func)); + mod()->AddFunction(std::move(func)); auto ep = std::make_unique(ast::PipelineStage::kVertex, "", "vtx_main"); auto* ep_ptr = ep.get(); - mod.AddEntryPoint(std::move(ep)); + mod()->AddEntryPoint(std::move(ep)); - ASSERT_TRUE(td.Determine()) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.EmitEntryPointData(ep_ptr)) << g.error(); - EXPECT_EQ(g.result(), R"(struct vtx_main_in { + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(gen().EmitEntryPointData(out(), ep_ptr)) << gen().error(); + EXPECT_EQ(result(), R"(struct vtx_main_in { float foo : TEXCOORD0; int bar : TEXCOORD1; }; @@ -102,7 +97,7 @@ TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Vertex_Input) { )"); } -TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Vertex_Output) { +TEST_F(HlslGeneratorImplTest_EntryPoint, EmitEntryPointData_Vertex_Output) { // [[location 0]] var foo : f32; // [[location 1]] var bar : i32; // @@ -126,14 +121,11 @@ TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Vertex_Output) { decos.push_back(std::make_unique(1)); bar_var->set_decorations(std::move(decos)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - td.RegisterVariableForTesting(foo_var.get()); - td.RegisterVariableForTesting(bar_var.get()); + td().RegisterVariableForTesting(foo_var.get()); + td().RegisterVariableForTesting(bar_var.get()); - mod.AddGlobalVariable(std::move(foo_var)); - mod.AddGlobalVariable(std::move(bar_var)); + mod()->AddGlobalVariable(std::move(foo_var)); + mod()->AddGlobalVariable(std::move(bar_var)); ast::VariableList params; auto func = @@ -148,19 +140,17 @@ TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Vertex_Output) { std::make_unique("bar"))); func->set_body(std::move(body)); - mod.AddFunction(std::move(func)); + mod()->AddFunction(std::move(func)); auto ep = std::make_unique(ast::PipelineStage::kVertex, "", "vtx_main"); auto* ep_ptr = ep.get(); - mod.AddEntryPoint(std::move(ep)); + mod()->AddEntryPoint(std::move(ep)); - ASSERT_TRUE(td.Determine()) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.EmitEntryPointData(ep_ptr)) << g.error(); - EXPECT_EQ(g.result(), R"(struct vtx_main_out { + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(gen().EmitEntryPointData(out(), ep_ptr)) << gen().error(); + EXPECT_EQ(result(), R"(struct vtx_main_out { float foo : TEXCOORD0; int bar : TEXCOORD1; }; @@ -168,7 +158,7 @@ TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Vertex_Output) { )"); } -TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Fragment_Input) { +TEST_F(HlslGeneratorImplTest_EntryPoint, EmitEntryPointData_Fragment_Input) { // [[location 0]] var foo : f32; // [[location 1]] var bar : i32; // @@ -192,14 +182,11 @@ TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Fragment_Input) { decos.push_back(std::make_unique(1)); bar_var->set_decorations(std::move(decos)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - td.RegisterVariableForTesting(foo_var.get()); - td.RegisterVariableForTesting(bar_var.get()); + td().RegisterVariableForTesting(foo_var.get()); + td().RegisterVariableForTesting(bar_var.get()); - mod.AddGlobalVariable(std::move(foo_var)); - mod.AddGlobalVariable(std::move(bar_var)); + mod()->AddGlobalVariable(std::move(foo_var)); + mod()->AddGlobalVariable(std::move(bar_var)); ast::VariableList params; auto func = @@ -214,19 +201,17 @@ TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Fragment_Input) { std::make_unique("bar"))); func->set_body(std::move(body)); - mod.AddFunction(std::move(func)); + mod()->AddFunction(std::move(func)); auto ep = std::make_unique(ast::PipelineStage::kFragment, "main", "frag_main"); auto* ep_ptr = ep.get(); - mod.AddEntryPoint(std::move(ep)); + mod()->AddEntryPoint(std::move(ep)); - ASSERT_TRUE(td.Determine()) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.EmitEntryPointData(ep_ptr)) << g.error(); - EXPECT_EQ(g.result(), R"(struct main_in { + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(gen().EmitEntryPointData(out(), ep_ptr)) << gen().error(); + EXPECT_EQ(result(), R"(struct main_in { float foo : TEXCOORD0; int bar : TEXCOORD1; }; @@ -234,7 +219,7 @@ TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Fragment_Input) { )"); } -TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Fragment_Output) { +TEST_F(HlslGeneratorImplTest_EntryPoint, EmitEntryPointData_Fragment_Output) { // [[location 0]] var foo : f32; // [[location 1]] var bar : i32; // @@ -258,14 +243,11 @@ TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Fragment_Output) { decos.push_back(std::make_unique(1)); bar_var->set_decorations(std::move(decos)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - td.RegisterVariableForTesting(foo_var.get()); - td.RegisterVariableForTesting(bar_var.get()); + td().RegisterVariableForTesting(foo_var.get()); + td().RegisterVariableForTesting(bar_var.get()); - mod.AddGlobalVariable(std::move(foo_var)); - mod.AddGlobalVariable(std::move(bar_var)); + mod()->AddGlobalVariable(std::move(foo_var)); + mod()->AddGlobalVariable(std::move(bar_var)); ast::VariableList params; auto func = @@ -280,19 +262,17 @@ TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Fragment_Output) { std::make_unique("bar"))); func->set_body(std::move(body)); - mod.AddFunction(std::move(func)); + mod()->AddFunction(std::move(func)); auto ep = std::make_unique(ast::PipelineStage::kFragment, "main", "frag_main"); auto* ep_ptr = ep.get(); - mod.AddEntryPoint(std::move(ep)); + mod()->AddEntryPoint(std::move(ep)); - ASSERT_TRUE(td.Determine()) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.EmitEntryPointData(ep_ptr)) << g.error(); - EXPECT_EQ(g.result(), R"(struct main_out { + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(gen().EmitEntryPointData(out(), ep_ptr)) << gen().error(); + EXPECT_EQ(result(), R"(struct main_out { float foo : SV_Target0; int bar : SV_Target1; }; @@ -300,7 +280,7 @@ TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Fragment_Output) { )"); } -TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Compute_Input) { +TEST_F(HlslGeneratorImplTest_EntryPoint, EmitEntryPointData_Compute_Input) { // [[location 0]] var foo : f32; // [[location 1]] var bar : i32; // @@ -321,14 +301,11 @@ TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Compute_Input) { decos.push_back(std::make_unique(1)); bar_var->set_decorations(std::move(decos)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - td.RegisterVariableForTesting(foo_var.get()); - td.RegisterVariableForTesting(bar_var.get()); + td().RegisterVariableForTesting(foo_var.get()); + td().RegisterVariableForTesting(bar_var.get()); - mod.AddGlobalVariable(std::move(foo_var)); - mod.AddGlobalVariable(std::move(bar_var)); + mod()->AddGlobalVariable(std::move(foo_var)); + mod()->AddGlobalVariable(std::move(bar_var)); ast::VariableList params; auto func = @@ -343,22 +320,20 @@ TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Compute_Input) { std::make_unique("bar"))); func->set_body(std::move(body)); - mod.AddFunction(std::move(func)); + mod()->AddFunction(std::move(func)); auto ep = std::make_unique(ast::PipelineStage::kCompute, "main", "comp_main"); auto* ep_ptr = ep.get(); - mod.AddEntryPoint(std::move(ep)); + mod()->AddEntryPoint(std::move(ep)); - ASSERT_TRUE(td.Determine()) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_FALSE(g.EmitEntryPointData(ep_ptr)) << g.error(); - EXPECT_EQ(g.error(), R"(invalid location variable for pipeline stage)"); + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_FALSE(gen().EmitEntryPointData(out(), ep_ptr)) << gen().error(); + EXPECT_EQ(gen().error(), R"(invalid location variable for pipeline stage)"); } -TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Compute_Output) { +TEST_F(HlslGeneratorImplTest_EntryPoint, EmitEntryPointData_Compute_Output) { // [[location 0]] var foo : f32; // [[location 1]] var bar : i32; // @@ -379,14 +354,11 @@ TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Compute_Output) { decos.push_back(std::make_unique(1)); bar_var->set_decorations(std::move(decos)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - td.RegisterVariableForTesting(foo_var.get()); - td.RegisterVariableForTesting(bar_var.get()); + td().RegisterVariableForTesting(foo_var.get()); + td().RegisterVariableForTesting(bar_var.get()); - mod.AddGlobalVariable(std::move(foo_var)); - mod.AddGlobalVariable(std::move(bar_var)); + mod()->AddGlobalVariable(std::move(foo_var)); + mod()->AddGlobalVariable(std::move(bar_var)); ast::VariableList params; auto func = @@ -401,22 +373,20 @@ TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Compute_Output) { std::make_unique("bar"))); func->set_body(std::move(body)); - mod.AddFunction(std::move(func)); + mod()->AddFunction(std::move(func)); auto ep = std::make_unique(ast::PipelineStage::kCompute, "main", "comp_main"); auto* ep_ptr = ep.get(); - mod.AddEntryPoint(std::move(ep)); + mod()->AddEntryPoint(std::move(ep)); - ASSERT_TRUE(td.Determine()) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_FALSE(g.EmitEntryPointData(ep_ptr)) << g.error(); - EXPECT_EQ(g.error(), R"(invalid location variable for pipeline stage)"); + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_FALSE(gen().EmitEntryPointData(out(), ep_ptr)) << gen().error(); + EXPECT_EQ(gen().error(), R"(invalid location variable for pipeline stage)"); } -TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Builtins) { +TEST_F(HlslGeneratorImplTest_EntryPoint, EmitEntryPointData_Builtins) { // [[builtin frag_coord]] var coord : vec4; // [[builtin frag_depth]] var depth : f32; // @@ -448,14 +418,11 @@ TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Builtins) { std::make_unique(ast::Builtin::kFragDepth)); depth_var->set_decorations(std::move(decos)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - td.RegisterVariableForTesting(coord_var.get()); - td.RegisterVariableForTesting(depth_var.get()); + td().RegisterVariableForTesting(coord_var.get()); + td().RegisterVariableForTesting(depth_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); - mod.AddGlobalVariable(std::move(depth_var)); + mod()->AddGlobalVariable(std::move(coord_var)); + mod()->AddGlobalVariable(std::move(depth_var)); ast::VariableList params; auto func = std::make_unique("frag_main", std::move(params), @@ -469,19 +436,17 @@ TEST_F(HlslGeneratorImplTest, EmitEntryPointData_Builtins) { std::make_unique("x")))); func->set_body(std::move(body)); - mod.AddFunction(std::move(func)); + mod()->AddFunction(std::move(func)); auto ep = std::make_unique(ast::PipelineStage::kFragment, "main", "frag_main"); auto* ep_ptr = ep.get(); - mod.AddEntryPoint(std::move(ep)); + mod()->AddEntryPoint(std::move(ep)); - ASSERT_TRUE(td.Determine()) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.EmitEntryPointData(ep_ptr)) << g.error(); - EXPECT_EQ(g.result(), R"(struct main_in { + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(gen().EmitEntryPointData(out(), ep_ptr)) << gen().error(); + EXPECT_EQ(result(), R"(struct main_in { vector coord : SV_Position; }; diff --git a/src/writer/hlsl/generator_impl_function_test.cc b/src/writer/hlsl/generator_impl_function_test.cc index 9170fc7b47..51b6830dda 100644 --- a/src/writer/hlsl/generator_impl_function_test.cc +++ b/src/writer/hlsl/generator_impl_function_test.cc @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "gtest/gtest.h" #include "src/ast/assignment_statement.h" #include "src/ast/binary_expression.h" #include "src/ast/binding_decoration.h" @@ -42,16 +41,17 @@ #include "src/ast/variable_decl_statement.h" #include "src/context.h" #include "src/type_determiner.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_Function : public TestHelper, + public testing::Test {}; -TEST_F(HlslGeneratorImplTest, Emit_Function) { +TEST_F(HlslGeneratorImplTest_Function, Emit_Function) { ast::type::VoidType void_type; auto func = std::make_unique("my_func", ast::VariableList{}, @@ -61,21 +61,18 @@ TEST_F(HlslGeneratorImplTest, Emit_Function) { body->append(std::make_unique()); func->set_body(std::move(body)); - ast::Module m; - m.AddFunction(std::move(func)); + mod()->AddFunction(std::move(func)); + gen().increment_indent(); - GeneratorImpl g(&m); - g.increment_indent(); - - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"( void my_func() { + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"( void my_func() { return; } )"); } -TEST_F(HlslGeneratorImplTest, Emit_Function_Name_Collision) { +TEST_F(HlslGeneratorImplTest_Function, Emit_Function_Name_Collision) { ast::type::VoidType void_type; auto func = std::make_unique("GeometryShader", @@ -85,21 +82,18 @@ TEST_F(HlslGeneratorImplTest, Emit_Function_Name_Collision) { body->append(std::make_unique()); func->set_body(std::move(body)); - ast::Module m; - m.AddFunction(std::move(func)); + mod()->AddFunction(std::move(func)); + gen().increment_indent(); - GeneratorImpl g(&m); - g.increment_indent(); - - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"( void GeometryShader_tint_0() { + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"( void GeometryShader_tint_0() { return; } )"); } -TEST_F(HlslGeneratorImplTest, Emit_Function_WithParams) { +TEST_F(HlslGeneratorImplTest_Function, Emit_Function_WithParams) { ast::type::F32Type f32; ast::type::I32Type i32; @@ -117,21 +111,18 @@ TEST_F(HlslGeneratorImplTest, Emit_Function_WithParams) { body->append(std::make_unique()); func->set_body(std::move(body)); - ast::Module m; - m.AddFunction(std::move(func)); + mod()->AddFunction(std::move(func)); + gen().increment_indent(); - GeneratorImpl g(&m); - g.increment_indent(); - - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"( void my_func(float a, int b) { + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"( void my_func(float a, int b) { return; } )"); } -TEST_F(HlslGeneratorImplTest, Emit_Function_EntryPoint_NoName) { +TEST_F(HlslGeneratorImplTest_Function, Emit_Function_EntryPoint_NoName) { ast::type::VoidType void_type; auto func = std::make_unique("frag_main", ast::VariableList{}, @@ -139,19 +130,17 @@ TEST_F(HlslGeneratorImplTest, Emit_Function_EntryPoint_NoName) { auto ep = std::make_unique(ast::PipelineStage::kFragment, "", "frag_main"); - ast::Module m; - m.AddFunction(std::move(func)); - m.AddEntryPoint(std::move(ep)); + mod()->AddFunction(std::move(func)); + mod()->AddEntryPoint(std::move(ep)); - GeneratorImpl g(&m); - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"(void frag_main() { + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"(void frag_main() { } )"); } -TEST_F(HlslGeneratorImplTest, Emit_Function_EntryPoint_WithInOutVars) { +TEST_F(HlslGeneratorImplTest_Function, Emit_Function_EntryPoint_WithInOutVars) { ast::type::VoidType void_type; ast::type::F32Type f32; @@ -167,14 +156,11 @@ TEST_F(HlslGeneratorImplTest, Emit_Function_EntryPoint_WithInOutVars) { decos.push_back(std::make_unique(1)); bar_var->set_decorations(std::move(decos)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - td.RegisterVariableForTesting(foo_var.get()); - td.RegisterVariableForTesting(bar_var.get()); + td().RegisterVariableForTesting(foo_var.get()); + td().RegisterVariableForTesting(bar_var.get()); - mod.AddGlobalVariable(std::move(foo_var)); - mod.AddGlobalVariable(std::move(bar_var)); + mod()->AddGlobalVariable(std::move(foo_var)); + mod()->AddGlobalVariable(std::move(bar_var)); ast::VariableList params; auto func = std::make_unique("frag_main", std::move(params), @@ -187,17 +173,15 @@ TEST_F(HlslGeneratorImplTest, Emit_Function_EntryPoint_WithInOutVars) { body->append(std::make_unique()); func->set_body(std::move(body)); - mod.AddFunction(std::move(func)); + mod()->AddFunction(std::move(func)); auto ep = std::make_unique(ast::PipelineStage::kFragment, "", "frag_main"); - mod.AddEntryPoint(std::move(ep)); + mod()->AddEntryPoint(std::move(ep)); - ASSERT_TRUE(td.Determine()) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"(struct frag_main_in { + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"(struct frag_main_in { float foo : TEXCOORD0; }; @@ -214,7 +198,8 @@ frag_main_out frag_main(frag_main_in tint_in) { )"); } -TEST_F(HlslGeneratorImplTest, Emit_Function_EntryPoint_WithInOut_Builtins) { +TEST_F(HlslGeneratorImplTest_Function, + Emit_Function_EntryPoint_WithInOut_Builtins) { ast::type::VoidType void_type; ast::type::F32Type f32; ast::type::VectorType vec4(&f32, 4); @@ -235,14 +220,11 @@ TEST_F(HlslGeneratorImplTest, Emit_Function_EntryPoint_WithInOut_Builtins) { std::make_unique(ast::Builtin::kFragDepth)); depth_var->set_decorations(std::move(decos)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - td.RegisterVariableForTesting(coord_var.get()); - td.RegisterVariableForTesting(depth_var.get()); + td().RegisterVariableForTesting(coord_var.get()); + td().RegisterVariableForTesting(depth_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); - mod.AddGlobalVariable(std::move(depth_var)); + mod()->AddGlobalVariable(std::move(coord_var)); + mod()->AddGlobalVariable(std::move(depth_var)); ast::VariableList params; auto func = std::make_unique("frag_main", std::move(params), @@ -257,17 +239,15 @@ TEST_F(HlslGeneratorImplTest, Emit_Function_EntryPoint_WithInOut_Builtins) { body->append(std::make_unique()); func->set_body(std::move(body)); - mod.AddFunction(std::move(func)); + mod()->AddFunction(std::move(func)); auto ep = std::make_unique(ast::PipelineStage::kFragment, "", "frag_main"); - mod.AddEntryPoint(std::move(ep)); + mod()->AddEntryPoint(std::move(ep)); - ASSERT_TRUE(td.Determine()) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"(struct frag_main_in { + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"(struct frag_main_in { vector coord : SV_Position; }; @@ -284,7 +264,7 @@ frag_main_out frag_main(frag_main_in tint_in) { )"); } -TEST_F(HlslGeneratorImplTest, Emit_Function_EntryPoint_With_Uniform) { +TEST_F(HlslGeneratorImplTest_Function, Emit_Function_EntryPoint_With_Uniform) { ast::type::VoidType void_type; ast::type::F32Type f32; ast::type::VectorType vec4(&f32, 4); @@ -298,12 +278,8 @@ TEST_F(HlslGeneratorImplTest, Emit_Function_EntryPoint_With_Uniform) { decos.push_back(std::make_unique(1)); coord_var->set_decorations(std::move(decos)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - td.RegisterVariableForTesting(coord_var.get()); - - mod.AddGlobalVariable(std::move(coord_var)); + td().RegisterVariableForTesting(coord_var.get()); + mod()->AddGlobalVariable(std::move(coord_var)); ast::VariableList params; auto func = std::make_unique("frag_main", std::move(params), @@ -320,17 +296,15 @@ TEST_F(HlslGeneratorImplTest, Emit_Function_EntryPoint_With_Uniform) { body->append(std::make_unique()); func->set_body(std::move(body)); - mod.AddFunction(std::move(func)); + mod()->AddFunction(std::move(func)); auto ep = std::make_unique(ast::PipelineStage::kFragment, "", "frag_main"); - mod.AddEntryPoint(std::move(ep)); + mod()->AddEntryPoint(std::move(ep)); - ASSERT_TRUE(td.Determine()) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"(cbuffer : register(b0) { + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"(cbuffer : register(b0) { vector coord; }; @@ -342,7 +316,8 @@ void frag_main() { )"); } -TEST_F(HlslGeneratorImplTest, Emit_Function_EntryPoint_With_UniformStruct) { +TEST_F(HlslGeneratorImplTest_Function, + Emit_Function_EntryPoint_With_UniformStruct) { ast::type::VoidType void_type; ast::type::F32Type f32; ast::type::VectorType vec4(&f32, 4); @@ -358,23 +333,19 @@ TEST_F(HlslGeneratorImplTest, Emit_Function_EntryPoint_With_UniformStruct) { s.set_name("Uniforms"); auto alias = std::make_unique("Uniforms", &s); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - auto coord_var = std::make_unique(std::make_unique( "uniforms", ast::StorageClass::kUniform, alias.get())); - mod.AddAliasType(alias.get()); + mod()->AddAliasType(alias.get()); ast::VariableDecorationList decos; decos.push_back(std::make_unique(0)); decos.push_back(std::make_unique(1)); coord_var->set_decorations(std::move(decos)); - td.RegisterVariableForTesting(coord_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); + td().RegisterVariableForTesting(coord_var.get()); + mod()->AddGlobalVariable(std::move(coord_var)); ast::VariableList params; auto func = std::make_unique("frag_main", std::move(params), @@ -393,17 +364,15 @@ TEST_F(HlslGeneratorImplTest, Emit_Function_EntryPoint_With_UniformStruct) { body->append(std::make_unique()); func->set_body(std::move(body)); - mod.AddFunction(std::move(func)); + mod()->AddFunction(std::move(func)); auto ep = std::make_unique(ast::PipelineStage::kFragment, "", "frag_main"); - mod.AddEntryPoint(std::move(ep)); + mod()->AddEntryPoint(std::move(ep)); - ASSERT_TRUE(td.Determine()) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"(struct Uniforms { + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"(struct Uniforms { vector coord; }; @@ -417,7 +386,7 @@ void frag_main() { )"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_Function, Emit_Function_EntryPoint_With_StorageBuffer_Read) { ast::type::VoidType void_type; ast::type::F32Type f32; @@ -449,11 +418,8 @@ TEST_F(HlslGeneratorImplTest, decos.push_back(std::make_unique(1)); coord_var->set_decorations(std::move(decos)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - td.RegisterVariableForTesting(coord_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); + td().RegisterVariableForTesting(coord_var.get()); + mod()->AddGlobalVariable(std::move(coord_var)); ast::VariableList params; auto func = std::make_unique("frag_main", std::move(params), @@ -470,17 +436,15 @@ TEST_F(HlslGeneratorImplTest, body->append(std::make_unique()); func->set_body(std::move(body)); - mod.AddFunction(std::move(func)); + mod()->AddFunction(std::move(func)); auto ep = std::make_unique(ast::PipelineStage::kFragment, "", "frag_main"); - mod.AddEntryPoint(std::move(ep)); + mod()->AddEntryPoint(std::move(ep)); - ASSERT_TRUE(td.Determine()) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"(RWByteAddressBuffer coord : register(u0); + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"(RWByteAddressBuffer coord : register(u0); void frag_main() { float v = asfloat(coord.Load(4)); @@ -490,7 +454,7 @@ void frag_main() { )"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_Function, Emit_Function_EntryPoint_With_StorageBuffer_Store) { ast::type::VoidType void_type; ast::type::F32Type f32; @@ -522,12 +486,9 @@ TEST_F(HlslGeneratorImplTest, decos.push_back(std::make_unique(1)); coord_var->set_decorations(std::move(decos)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - td.RegisterVariableForTesting(coord_var.get()); + td().RegisterVariableForTesting(coord_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); + mod()->AddGlobalVariable(std::move(coord_var)); ast::VariableList params; auto func = std::make_unique("frag_main", std::move(params), @@ -545,17 +506,15 @@ TEST_F(HlslGeneratorImplTest, body->append(std::make_unique()); func->set_body(std::move(body)); - mod.AddFunction(std::move(func)); + mod()->AddFunction(std::move(func)); auto ep = std::make_unique(ast::PipelineStage::kFragment, "", "frag_main"); - mod.AddEntryPoint(std::move(ep)); + mod()->AddEntryPoint(std::move(ep)); - ASSERT_TRUE(td.Determine()) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"(RWByteAddressBuffer coord : register(u0); + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"(RWByteAddressBuffer coord : register(u0); void frag_main() { coord.Store(4, asuint(2.00000000f)); @@ -565,7 +524,7 @@ void frag_main() { )"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_Function, Emit_Function_Called_By_EntryPoints_WithLocationGlobals_And_Params) { ast::type::VoidType void_type; ast::type::F32Type f32; @@ -587,16 +546,13 @@ TEST_F(HlslGeneratorImplTest, decos.push_back(std::make_unique(0)); val_var->set_decorations(std::move(decos)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - td.RegisterVariableForTesting(foo_var.get()); - td.RegisterVariableForTesting(bar_var.get()); - td.RegisterVariableForTesting(val_var.get()); + td().RegisterVariableForTesting(foo_var.get()); + td().RegisterVariableForTesting(bar_var.get()); + td().RegisterVariableForTesting(val_var.get()); - mod.AddGlobalVariable(std::move(foo_var)); - mod.AddGlobalVariable(std::move(bar_var)); - mod.AddGlobalVariable(std::move(val_var)); + mod()->AddGlobalVariable(std::move(foo_var)); + mod()->AddGlobalVariable(std::move(bar_var)); + mod()->AddGlobalVariable(std::move(val_var)); ast::VariableList params; params.push_back(std::make_unique( @@ -615,7 +571,7 @@ TEST_F(HlslGeneratorImplTest, std::make_unique("foo"))); sub_func->set_body(std::move(body)); - mod.AddFunction(std::move(sub_func)); + mod()->AddFunction(std::move(sub_func)); auto func_1 = std::make_unique("frag_1_main", std::move(params), &void_type); @@ -633,17 +589,15 @@ TEST_F(HlslGeneratorImplTest, body->append(std::make_unique()); func_1->set_body(std::move(body)); - mod.AddFunction(std::move(func_1)); + mod()->AddFunction(std::move(func_1)); auto ep1 = std::make_unique(ast::PipelineStage::kFragment, "ep_1", "frag_1_main"); - mod.AddEntryPoint(std::move(ep1)); + mod()->AddEntryPoint(std::move(ep1)); - ASSERT_TRUE(td.Determine()) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"(struct ep_1_in { + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"(struct ep_1_in { float foo : TEXCOORD0; }; @@ -667,7 +621,7 @@ ep_1_out ep_1(ep_1_in tint_in) { )"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_Function, Emit_Function_Called_By_EntryPoints_NoUsedGlobals) { ast::type::VoidType void_type; ast::type::F32Type f32; @@ -682,12 +636,9 @@ TEST_F(HlslGeneratorImplTest, std::make_unique(ast::Builtin::kFragDepth)); depth_var->set_decorations(std::move(decos)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - td.RegisterVariableForTesting(depth_var.get()); + td().RegisterVariableForTesting(depth_var.get()); - mod.AddGlobalVariable(std::move(depth_var)); + mod()->AddGlobalVariable(std::move(depth_var)); ast::VariableList params; params.push_back(std::make_unique( @@ -700,7 +651,7 @@ TEST_F(HlslGeneratorImplTest, std::make_unique("param"))); sub_func->set_body(std::move(body)); - mod.AddFunction(std::move(sub_func)); + mod()->AddFunction(std::move(sub_func)); auto func_1 = std::make_unique("frag_1_main", std::move(params), &void_type); @@ -718,17 +669,15 @@ TEST_F(HlslGeneratorImplTest, body->append(std::make_unique()); func_1->set_body(std::move(body)); - mod.AddFunction(std::move(func_1)); + mod()->AddFunction(std::move(func_1)); auto ep1 = std::make_unique(ast::PipelineStage::kFragment, "ep_1", "frag_1_main"); - mod.AddEntryPoint(std::move(ep1)); + mod()->AddEntryPoint(std::move(ep1)); - ASSERT_TRUE(td.Determine()) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"(struct ep_1_out { + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"(struct ep_1_out { float depth : SV_Depth; }; @@ -745,7 +694,7 @@ ep_1_out ep_1() { )"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_Function, Emit_Function_Called_By_EntryPoints_WithBuiltinGlobals_And_Params) { ast::type::VoidType void_type; ast::type::F32Type f32; @@ -767,14 +716,11 @@ TEST_F(HlslGeneratorImplTest, std::make_unique(ast::Builtin::kFragDepth)); depth_var->set_decorations(std::move(decos)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - td.RegisterVariableForTesting(coord_var.get()); - td.RegisterVariableForTesting(depth_var.get()); + td().RegisterVariableForTesting(coord_var.get()); + td().RegisterVariableForTesting(depth_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); - mod.AddGlobalVariable(std::move(depth_var)); + mod()->AddGlobalVariable(std::move(coord_var)); + mod()->AddGlobalVariable(std::move(depth_var)); ast::VariableList params; params.push_back(std::make_unique( @@ -792,7 +738,7 @@ TEST_F(HlslGeneratorImplTest, std::make_unique("param"))); sub_func->set_body(std::move(body)); - mod.AddFunction(std::move(sub_func)); + mod()->AddFunction(std::move(sub_func)); auto func_1 = std::make_unique("frag_1_main", std::move(params), &void_type); @@ -810,17 +756,15 @@ TEST_F(HlslGeneratorImplTest, body->append(std::make_unique()); func_1->set_body(std::move(body)); - mod.AddFunction(std::move(func_1)); + mod()->AddFunction(std::move(func_1)); auto ep1 = std::make_unique(ast::PipelineStage::kFragment, "ep_1", "frag_1_main"); - mod.AddEntryPoint(std::move(ep1)); + mod()->AddEntryPoint(std::move(ep1)); - ASSERT_TRUE(td.Determine()) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"(struct ep_1_in { + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"(struct ep_1_in { vector coord : SV_Position; }; @@ -842,7 +786,7 @@ ep_1_out ep_1(ep_1_in tint_in) { )"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_Function, DISABLED_Emit_Function_Called_By_EntryPoint_With_Uniform) { ast::type::VoidType void_type; ast::type::F32Type f32; @@ -857,12 +801,9 @@ TEST_F(HlslGeneratorImplTest, decos.push_back(std::make_unique(1)); coord_var->set_decorations(std::move(decos)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - td.RegisterVariableForTesting(coord_var.get()); + td().RegisterVariableForTesting(coord_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); + mod()->AddGlobalVariable(std::move(coord_var)); ast::VariableList params; params.push_back(std::make_unique( @@ -877,7 +818,7 @@ TEST_F(HlslGeneratorImplTest, std::make_unique("x")))); sub_func->set_body(std::move(body)); - mod.AddFunction(std::move(sub_func)); + mod()->AddFunction(std::move(sub_func)); auto func = std::make_unique("frag_main", std::move(params), &void_type); @@ -897,20 +838,18 @@ TEST_F(HlslGeneratorImplTest, body->append(std::make_unique()); func->set_body(std::move(body)); - mod.AddFunction(std::move(func)); + mod()->AddFunction(std::move(func)); auto ep = std::make_unique(ast::PipelineStage::kFragment, "", "frag_main"); - mod.AddEntryPoint(std::move(ep)); + mod()->AddEntryPoint(std::move(ep)); - ASSERT_TRUE(td.Determine()) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"( ... )"); + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"( ... )"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_Function, DISABLED_Emit_Function_Called_By_EntryPoint_With_StorageBuffer) { ast::type::VoidType void_type; ast::type::F32Type f32; @@ -925,12 +864,9 @@ TEST_F(HlslGeneratorImplTest, decos.push_back(std::make_unique(1)); coord_var->set_decorations(std::move(decos)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - td.RegisterVariableForTesting(coord_var.get()); + td().RegisterVariableForTesting(coord_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); + mod()->AddGlobalVariable(std::move(coord_var)); ast::VariableList params; params.push_back(std::make_unique( @@ -945,7 +881,7 @@ TEST_F(HlslGeneratorImplTest, std::make_unique("x")))); sub_func->set_body(std::move(body)); - mod.AddFunction(std::move(sub_func)); + mod()->AddFunction(std::move(sub_func)); auto func = std::make_unique("frag_main", std::move(params), &void_type); @@ -965,20 +901,18 @@ TEST_F(HlslGeneratorImplTest, body->append(std::make_unique()); func->set_body(std::move(body)); - mod.AddFunction(std::move(func)); + mod()->AddFunction(std::move(func)); auto ep = std::make_unique(ast::PipelineStage::kFragment, "", "frag_main"); - mod.AddEntryPoint(std::move(ep)); + mod()->AddEntryPoint(std::move(ep)); - ASSERT_TRUE(td.Determine()) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"( ... )"); + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"( ... )"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_Function, DISABLED_Emit_Function_Called_Two_EntryPoints_WithGlobals) { ast::type::VoidType void_type; ast::type::F32Type f32; @@ -995,14 +929,11 @@ TEST_F(HlslGeneratorImplTest, decos.push_back(std::make_unique(1)); bar_var->set_decorations(std::move(decos)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - td.RegisterVariableForTesting(foo_var.get()); - td.RegisterVariableForTesting(bar_var.get()); + td().RegisterVariableForTesting(foo_var.get()); + td().RegisterVariableForTesting(bar_var.get()); - mod.AddGlobalVariable(std::move(foo_var)); - mod.AddGlobalVariable(std::move(bar_var)); + mod()->AddGlobalVariable(std::move(foo_var)); + mod()->AddGlobalVariable(std::move(bar_var)); ast::VariableList params; auto sub_func = @@ -1016,7 +947,7 @@ TEST_F(HlslGeneratorImplTest, std::make_unique("foo"))); sub_func->set_body(std::move(body)); - mod.AddFunction(std::move(sub_func)); + mod()->AddFunction(std::move(sub_func)); auto func_1 = std::make_unique("frag_1_main", std::move(params), &void_type); @@ -1030,20 +961,18 @@ TEST_F(HlslGeneratorImplTest, body->append(std::make_unique()); func_1->set_body(std::move(body)); - mod.AddFunction(std::move(func_1)); + mod()->AddFunction(std::move(func_1)); auto ep1 = std::make_unique(ast::PipelineStage::kFragment, "ep_1", "frag_1_main"); auto ep2 = std::make_unique(ast::PipelineStage::kFragment, "ep_2", "frag_1_main"); - mod.AddEntryPoint(std::move(ep1)); - mod.AddEntryPoint(std::move(ep2)); + mod()->AddEntryPoint(std::move(ep1)); + mod()->AddEntryPoint(std::move(ep2)); - ASSERT_TRUE(td.Determine()) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"(struct ep_1_in { + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"(struct ep_1_in { float foo : TEXCOORD0; }; @@ -1084,7 +1013,7 @@ ep_2_out ep_2(ep_2_in tint_in) { )"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_Function, DISABLED_Emit_Function_EntryPoints_WithGlobal_Nested_Return) { ast::type::VoidType void_type; ast::type::F32Type f32; @@ -1096,11 +1025,8 @@ TEST_F(HlslGeneratorImplTest, decos.push_back(std::make_unique(1)); bar_var->set_decorations(std::move(decos)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - td.RegisterVariableForTesting(bar_var.get()); - mod.AddGlobalVariable(std::move(bar_var)); + td().RegisterVariableForTesting(bar_var.get()); + mod()->AddGlobalVariable(std::move(bar_var)); ast::VariableList params; auto func_1 = std::make_unique("frag_1_main", @@ -1127,17 +1053,15 @@ TEST_F(HlslGeneratorImplTest, body->append(std::make_unique()); func_1->set_body(std::move(body)); - mod.AddFunction(std::move(func_1)); + mod()->AddFunction(std::move(func_1)); auto ep1 = std::make_unique(ast::PipelineStage::kFragment, "ep_1", "frag_1_main"); - mod.AddEntryPoint(std::move(ep1)); + mod()->AddEntryPoint(std::move(ep1)); - ASSERT_TRUE(td.Determine()) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"(struct ep_1_out { + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"(struct ep_1_out { float bar : SV_Target0; }; @@ -1153,15 +1077,11 @@ ep_1_out ep_1() { )"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_Function, Emit_Function_Called_Two_EntryPoints_WithoutGlobals) { ast::type::VoidType void_type; ast::type::F32Type f32; - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - ast::VariableList params; auto sub_func = std::make_unique("sub_func", std::move(params), &f32); @@ -1172,7 +1092,7 @@ TEST_F(HlslGeneratorImplTest, std::make_unique(&f32, 1.0)))); sub_func->set_body(std::move(body)); - mod.AddFunction(std::move(sub_func)); + mod()->AddFunction(std::move(sub_func)); auto func_1 = std::make_unique("frag_1_main", std::move(params), &void_type); @@ -1188,20 +1108,19 @@ TEST_F(HlslGeneratorImplTest, body->append(std::make_unique()); func_1->set_body(std::move(body)); - mod.AddFunction(std::move(func_1)); + mod()->AddFunction(std::move(func_1)); auto ep1 = std::make_unique(ast::PipelineStage::kFragment, "ep_1", "frag_1_main"); auto ep2 = std::make_unique(ast::PipelineStage::kFragment, "ep_2", "frag_1_main"); - mod.AddEntryPoint(std::move(ep1)); - mod.AddEntryPoint(std::move(ep2)); + mod()->AddEntryPoint(std::move(ep1)); + mod()->AddEntryPoint(std::move(ep2)); - ASSERT_TRUE(td.Determine()) << td.error(); + ASSERT_TRUE(td().Determine()) << td().error(); - GeneratorImpl g(&mod); - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"(float sub_func() { + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"(float sub_func() { return 1.00000000f; } @@ -1217,7 +1136,7 @@ void ep_2() { )"); } -TEST_F(HlslGeneratorImplTest, Emit_Function_EntryPoint_WithName) { +TEST_F(HlslGeneratorImplTest_Function, Emit_Function_EntryPoint_WithName) { ast::type::VoidType void_type; auto func = std::make_unique("comp_main", ast::VariableList{}, @@ -1225,19 +1144,18 @@ TEST_F(HlslGeneratorImplTest, Emit_Function_EntryPoint_WithName) { auto ep = std::make_unique(ast::PipelineStage::kCompute, "my_main", "comp_main"); - ast::Module m; - m.AddFunction(std::move(func)); - m.AddEntryPoint(std::move(ep)); + mod()->AddFunction(std::move(func)); + mod()->AddEntryPoint(std::move(ep)); - GeneratorImpl g(&m); - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"(void my_main() { + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"(void my_main() { } )"); } -TEST_F(HlslGeneratorImplTest, Emit_Function_EntryPoint_WithNameCollision) { +TEST_F(HlslGeneratorImplTest_Function, + Emit_Function_EntryPoint_WithNameCollision) { ast::type::VoidType void_type; auto func = std::make_unique("comp_main", ast::VariableList{}, @@ -1245,19 +1163,17 @@ TEST_F(HlslGeneratorImplTest, Emit_Function_EntryPoint_WithNameCollision) { auto ep = std::make_unique(ast::PipelineStage::kCompute, "GeometryShader", "comp_main"); - ast::Module m; - m.AddFunction(std::move(func)); - m.AddEntryPoint(std::move(ep)); + mod()->AddFunction(std::move(func)); + mod()->AddEntryPoint(std::move(ep)); - GeneratorImpl g(&m); - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"(void GeometryShader_tint_0() { + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"(void GeometryShader_tint_0() { } )"); } -TEST_F(HlslGeneratorImplTest, Emit_Function_WithArrayParams) { +TEST_F(HlslGeneratorImplTest_Function, Emit_Function_WithArrayParams) { ast::type::F32Type f32; ast::type::ArrayType ary(&f32, 5); @@ -1273,14 +1189,11 @@ TEST_F(HlslGeneratorImplTest, Emit_Function_WithArrayParams) { body->append(std::make_unique()); func->set_body(std::move(body)); - ast::Module m; - m.AddFunction(std::move(func)); + mod()->AddFunction(std::move(func)); + gen().increment_indent(); - GeneratorImpl g(&m); - g.increment_indent(); - - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"( void my_func(float a[5]) { + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"( void my_func(float a[5]) { return; } diff --git a/src/writer/hlsl/generator_impl_identifier_test.cc b/src/writer/hlsl/generator_impl_identifier_test.cc index 7f45efd5da..cdd99e77cd 100644 --- a/src/writer/hlsl/generator_impl_identifier_test.cc +++ b/src/writer/hlsl/generator_impl_identifier_test.cc @@ -12,53 +12,43 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "gtest/gtest.h" #include "src/ast/identifier_expression.h" #include "src/ast/module.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_Identifier : public TestHelper, + public testing::Test {}; -TEST_F(HlslGeneratorImplTest, DISABLED_EmitExpression_Identifier) { +TEST_F(HlslGeneratorImplTest_Identifier, DISABLED_EmitExpression_Identifier) { ast::IdentifierExpression i(std::vector{"std", "glsl"}); - - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitExpression(&i)) << g.error(); - EXPECT_EQ(g.result(), "std::glsl"); + ASSERT_TRUE(gen().EmitExpression(out(), &i)) << gen().error(); + EXPECT_EQ(result(), "std::glsl"); } -TEST_F(HlslGeneratorImplTest, EmitIdentifierExpression_Single) { +TEST_F(HlslGeneratorImplTest_Identifier, EmitIdentifierExpression_Single) { ast::IdentifierExpression i("foo"); - - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitExpression(&i)) << g.error(); - EXPECT_EQ(g.result(), "foo"); + ASSERT_TRUE(gen().EmitExpression(out(), &i)) << gen().error(); + EXPECT_EQ(result(), "foo"); } -TEST_F(HlslGeneratorImplTest, EmitIdentifierExpression_Single_WithCollision) { +TEST_F(HlslGeneratorImplTest_Identifier, + EmitIdentifierExpression_Single_WithCollision) { ast::IdentifierExpression i("virtual"); - - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitExpression(&i)) << g.error(); - EXPECT_EQ(g.result(), "virtual_tint_0"); + ASSERT_TRUE(gen().EmitExpression(out(), &i)) << gen().error(); + EXPECT_EQ(result(), "virtual_tint_0"); } // TODO(dsinclair): Handle import names -TEST_F(HlslGeneratorImplTest, DISABLED_EmitIdentifierExpression_MultipleNames) { +TEST_F(HlslGeneratorImplTest_Identifier, + DISABLED_EmitIdentifierExpression_MultipleNames) { ast::IdentifierExpression i({"std", "glsl", "init"}); - - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitExpression(&i)) << g.error(); - EXPECT_EQ(g.result(), "std::glsl::init"); + ASSERT_TRUE(gen().EmitExpression(out(), &i)) << gen().error(); + EXPECT_EQ(result(), "std::glsl::init"); } } // namespace diff --git a/src/writer/hlsl/generator_impl_if_test.cc b/src/writer/hlsl/generator_impl_if_test.cc index f133304a20..cfdc393faa 100644 --- a/src/writer/hlsl/generator_impl_if_test.cc +++ b/src/writer/hlsl/generator_impl_if_test.cc @@ -12,40 +12,36 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "gtest/gtest.h" #include "src/ast/else_statement.h" #include "src/ast/identifier_expression.h" #include "src/ast/if_statement.h" #include "src/ast/module.h" #include "src/ast/return_statement.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_If : public TestHelper, public testing::Test {}; -TEST_F(HlslGeneratorImplTest, Emit_If) { +TEST_F(HlslGeneratorImplTest_If, Emit_If) { auto cond = std::make_unique("cond"); auto body = std::make_unique(); body->append(std::make_unique()); ast::IfStatement i(std::move(cond), std::move(body)); + gen().increment_indent(); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); - - ASSERT_TRUE(g.EmitStatement(&i)) << g.error(); - EXPECT_EQ(g.result(), R"( if (cond) { + ASSERT_TRUE(gen().EmitStatement(out(), &i)) << gen().error(); + EXPECT_EQ(result(), R"( if (cond) { return; } )"); } -TEST_F(HlslGeneratorImplTest, Emit_IfWithElseIf) { +TEST_F(HlslGeneratorImplTest_If, Emit_IfWithElseIf) { auto else_cond = std::make_unique("else_cond"); auto else_body = std::make_unique(); else_body->append(std::make_unique()); @@ -61,12 +57,10 @@ TEST_F(HlslGeneratorImplTest, Emit_IfWithElseIf) { ast::IfStatement i(std::move(cond), std::move(body)); i.set_else_statements(std::move(elses)); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); + gen().increment_indent(); - ASSERT_TRUE(g.EmitStatement(&i)) << g.error(); - EXPECT_EQ(g.result(), R"( if (cond) { + ASSERT_TRUE(gen().EmitStatement(out(), &i)) << gen().error(); + EXPECT_EQ(result(), R"( if (cond) { return; } else if (else_cond) { return; @@ -74,7 +68,7 @@ TEST_F(HlslGeneratorImplTest, Emit_IfWithElseIf) { )"); } -TEST_F(HlslGeneratorImplTest, Emit_IfWithElse) { +TEST_F(HlslGeneratorImplTest_If, Emit_IfWithElse) { auto else_body = std::make_unique(); else_body->append(std::make_unique()); @@ -88,12 +82,10 @@ TEST_F(HlslGeneratorImplTest, Emit_IfWithElse) { ast::IfStatement i(std::move(cond), std::move(body)); i.set_else_statements(std::move(elses)); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); + gen().increment_indent(); - ASSERT_TRUE(g.EmitStatement(&i)) << g.error(); - EXPECT_EQ(g.result(), R"( if (cond) { + ASSERT_TRUE(gen().EmitStatement(out(), &i)) << gen().error(); + EXPECT_EQ(result(), R"( if (cond) { return; } else { return; @@ -101,7 +93,7 @@ TEST_F(HlslGeneratorImplTest, Emit_IfWithElse) { )"); } -TEST_F(HlslGeneratorImplTest, Emit_IfWithMultiple) { +TEST_F(HlslGeneratorImplTest_If, Emit_IfWithMultiple) { auto else_cond = std::make_unique("else_cond"); auto else_body = std::make_unique(); @@ -122,12 +114,10 @@ TEST_F(HlslGeneratorImplTest, Emit_IfWithMultiple) { ast::IfStatement i(std::move(cond), std::move(body)); i.set_else_statements(std::move(elses)); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); + gen().increment_indent(); - ASSERT_TRUE(g.EmitStatement(&i)) << g.error(); - EXPECT_EQ(g.result(), R"( if (cond) { + ASSERT_TRUE(gen().EmitStatement(out(), &i)) << gen().error(); + EXPECT_EQ(result(), R"( if (cond) { return; } else if (else_cond) { return; diff --git a/src/writer/hlsl/generator_impl_import_test.cc b/src/writer/hlsl/generator_impl_import_test.cc index 5ebfd24bdf..a6c5631b8d 100644 --- a/src/writer/hlsl/generator_impl_import_test.cc +++ b/src/writer/hlsl/generator_impl_import_test.cc @@ -16,7 +16,6 @@ #include #include -#include "gtest/gtest.h" #include "src/ast/call_expression.h" #include "src/ast/float_literal.h" #include "src/ast/identifier_expression.h" @@ -30,14 +29,14 @@ #include "src/ast/type_constructor_expression.h" #include "src/context.h" #include "src/type_determiner.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_Import : public TestHelper, public testing::Test {}; struct HlslImportData { const char* name; @@ -47,7 +46,10 @@ inline std::ostream& operator<<(std::ostream& out, HlslImportData data) { out << data.name; return out; } -using HlslImportData_SingleParamTest = testing::TestWithParam; + +class HlslImportData_SingleParamTest + : public TestHelper, + public testing::TestWithParam {}; TEST_P(HlslImportData_SingleParamTest, FloatScalar) { auto param = GetParam(); @@ -61,19 +63,14 @@ TEST_P(HlslImportData_SingleParamTest, FloatScalar) { std::vector{"std", param.name}), std::move(params)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - mod.AddImport(std::make_unique("GLSL.std.450", "std")); + mod()->AddImport(std::make_unique("GLSL.std.450", "std")); - ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.EmitImportFunction(&expr)) << g.error(); - EXPECT_EQ(g.result(), std::string(param.hlsl_name) + "(1.00000000f)"); + ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error(); + ASSERT_TRUE(gen().EmitImportFunction(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), std::string(param.hlsl_name) + "(1.00000000f)"); } INSTANTIATE_TEST_SUITE_P( - HlslGeneratorImplTest, + HlslGeneratorImplTest_Import, HlslImportData_SingleParamTest, testing::Values(HlslImportData{"acos", "acos"}, HlslImportData{"asin", "asin"}, @@ -104,20 +101,21 @@ INSTANTIATE_TEST_SUITE_P( HlslImportData{"tanh", "tanh"}, HlslImportData{"trunc", "trunc"})); -TEST_F(HlslGeneratorImplTest, DISABLED_HlslImportData_Acosh) { +TEST_F(HlslGeneratorImplTest_Import, DISABLED_HlslImportData_Acosh) { FAIL(); } -TEST_F(HlslGeneratorImplTest, DISABLED_HlslImportData_ASinh) { +TEST_F(HlslGeneratorImplTest_Import, DISABLED_HlslImportData_ASinh) { FAIL(); } -TEST_F(HlslGeneratorImplTest, DISABLED_HlslImportData_ATanh) { +TEST_F(HlslGeneratorImplTest_Import, DISABLED_HlslImportData_ATanh) { FAIL(); } -using HlslImportData_SingleIntParamTest = - testing::TestWithParam; +class HlslImportData_SingleIntParamTest + : public TestHelper, + public testing::TestWithParam {}; TEST_P(HlslImportData_SingleIntParamTest, IntScalar) { auto param = GetParam(); @@ -131,23 +129,20 @@ TEST_P(HlslImportData_SingleIntParamTest, IntScalar) { std::vector{"std", param.name}), std::move(params)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - mod.AddImport(std::make_unique("GLSL.std.450", "std")); + mod()->AddImport(std::make_unique("GLSL.std.450", "std")); - ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.EmitImportFunction(&expr)) << g.error(); - EXPECT_EQ(g.result(), std::string(param.hlsl_name) + "(1)"); + ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error(); + ASSERT_TRUE(gen().EmitImportFunction(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), std::string(param.hlsl_name) + "(1)"); } -INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest, +INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest_Import, HlslImportData_SingleIntParamTest, testing::Values(HlslImportData{"sabs", "abs"}, HlslImportData{"ssign", "sign"})); -using HlslImportData_DualParamTest = testing::TestWithParam; +class HlslImportData_DualParamTest + : public TestHelper, + public testing::TestWithParam {}; TEST_P(HlslImportData_DualParamTest, FloatScalar) { auto param = GetParam(); @@ -163,19 +158,14 @@ TEST_P(HlslImportData_DualParamTest, FloatScalar) { std::vector{"std", param.name}), std::move(params)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - mod.AddImport(std::make_unique("GLSL.std.450", "std")); + mod()->AddImport(std::make_unique("GLSL.std.450", "std")); - ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.EmitImportFunction(&expr)) << g.error(); - EXPECT_EQ(g.result(), + ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error(); + ASSERT_TRUE(gen().EmitImportFunction(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), std::string(param.hlsl_name) + "(1.00000000f, 2.00000000f)"); } -INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest, +INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest_Import, HlslImportData_DualParamTest, testing::Values(HlslImportData{"atan2", "atan2"}, HlslImportData{"distance", "distance"}, @@ -187,8 +177,9 @@ INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest, HlslImportData{"reflect", "reflect"}, HlslImportData{"step", "step"})); -using HlslImportData_DualParam_VectorTest = - testing::TestWithParam; +class HlslImportData_DualParam_VectorTest + : public TestHelper, + public testing::TestWithParam {}; TEST_P(HlslImportData_DualParam_VectorTest, FloatVector) { auto param = GetParam(); @@ -220,26 +211,22 @@ TEST_P(HlslImportData_DualParam_VectorTest, FloatVector) { std::vector{"std", param.name}), std::move(params)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - mod.AddImport(std::make_unique("GLSL.std.450", "std")); + mod()->AddImport(std::make_unique("GLSL.std.450", "std")); - ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.EmitImportFunction(&expr)) << g.error(); - EXPECT_EQ(g.result(), + ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error(); + ASSERT_TRUE(gen().EmitImportFunction(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), std::string(param.hlsl_name) + "(vector(1.00000000f, 2.00000000f, 3.00000000f), " "vector(4.00000000f, 5.00000000f, 6.00000000f))"); } -INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest, +INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest_Import, HlslImportData_DualParam_VectorTest, testing::Values(HlslImportData{"cross", "cross"})); -using HlslImportData_DualParam_Int_Test = - testing::TestWithParam; +class HlslImportData_DualParam_Int_Test + : public TestHelper, + public testing::TestWithParam {}; TEST_P(HlslImportData_DualParam_Int_Test, IntScalar) { auto param = GetParam(); @@ -255,25 +242,22 @@ TEST_P(HlslImportData_DualParam_Int_Test, IntScalar) { std::vector{"std", param.name}), std::move(params)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - mod.AddImport(std::make_unique("GLSL.std.450", "std")); + mod()->AddImport(std::make_unique("GLSL.std.450", "std")); - ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.EmitImportFunction(&expr)) << g.error(); - EXPECT_EQ(g.result(), std::string(param.hlsl_name) + "(1, 2)"); + ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error(); + ASSERT_TRUE(gen().EmitImportFunction(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), std::string(param.hlsl_name) + "(1, 2)"); } -INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest, +INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest_Import, HlslImportData_DualParam_Int_Test, testing::Values(HlslImportData{"smax", "max"}, HlslImportData{"smin", "min"}, HlslImportData{"umax", "max"}, HlslImportData{"umin", "min"})); -using HlslImportData_TripleParamTest = testing::TestWithParam; +class HlslImportData_TripleParamTest + : public TestHelper, + public testing::TestWithParam {}; TEST_P(HlslImportData_TripleParamTest, FloatScalar) { auto param = GetParam(); @@ -291,20 +275,15 @@ TEST_P(HlslImportData_TripleParamTest, FloatScalar) { std::vector{"std", param.name}), std::move(params)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - mod.AddImport(std::make_unique("GLSL.std.450", "std")); + mod()->AddImport(std::make_unique("GLSL.std.450", "std")); - ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.EmitImportFunction(&expr)) << g.error(); - EXPECT_EQ(g.result(), std::string(param.hlsl_name) + - "(1.00000000f, 2.00000000f, 3.00000000f)"); + ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error(); + ASSERT_TRUE(gen().EmitImportFunction(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), std::string(param.hlsl_name) + + "(1.00000000f, 2.00000000f, 3.00000000f)"); } INSTANTIATE_TEST_SUITE_P( - HlslGeneratorImplTest, + HlslGeneratorImplTest_Import, HlslImportData_TripleParamTest, testing::Values(HlslImportData{"faceforward", "faceforward"}, HlslImportData{"fma", "fma"}, @@ -312,12 +291,13 @@ INSTANTIATE_TEST_SUITE_P( HlslImportData{"nclamp", "clamp"}, HlslImportData{"smoothstep", "smoothstep"})); -TEST_F(HlslGeneratorImplTest, DISABLED_HlslImportData_FMix) { +TEST_F(HlslGeneratorImplTest_Import, DISABLED_HlslImportData_FMix) { FAIL(); } -using HlslImportData_TripleParam_Int_Test = - testing::TestWithParam; +class HlslImportData_TripleParam_Int_Test + : public TestHelper, + public testing::TestWithParam {}; TEST_P(HlslImportData_TripleParam_Int_Test, IntScalar) { auto param = GetParam(); @@ -335,23 +315,18 @@ TEST_P(HlslImportData_TripleParam_Int_Test, IntScalar) { std::vector{"std", param.name}), std::move(params)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - mod.AddImport(std::make_unique("GLSL.std.450", "std")); + mod()->AddImport(std::make_unique("GLSL.std.450", "std")); - ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.EmitImportFunction(&expr)) << g.error(); - EXPECT_EQ(g.result(), std::string(param.hlsl_name) + "(1, 2, 3)"); + ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error(); + ASSERT_TRUE(gen().EmitImportFunction(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), std::string(param.hlsl_name) + "(1, 2, 3)"); } -INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest, +INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest_Import, HlslImportData_TripleParam_Int_Test, testing::Values(HlslImportData{"sclamp", "clamp"}, HlslImportData{"uclamp", "clamp"})); -TEST_F(HlslGeneratorImplTest, HlslImportData_Determinant) { +TEST_F(HlslGeneratorImplTest_Import, HlslImportData_Determinant) { ast::type::F32Type f32; ast::type::MatrixType mat(&f32, 3, 3); @@ -365,19 +340,14 @@ TEST_F(HlslGeneratorImplTest, HlslImportData_Determinant) { std::vector{"std", "determinant"}), std::move(params)); - Context ctx; - ast::Module mod; - mod.AddGlobalVariable(std::move(var)); - mod.AddImport(std::make_unique("GLSL.std.450", "std")); + mod()->AddGlobalVariable(std::move(var)); + mod()->AddImport(std::make_unique("GLSL.std.450", "std")); - TypeDeterminer td(&ctx, &mod); // Register the global - ASSERT_TRUE(td.Determine()) << td.error(); - ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); - - GeneratorImpl g(&mod); - ASSERT_TRUE(g.EmitImportFunction(&expr)) << g.error(); - EXPECT_EQ(g.result(), std::string("determinant(var)")); + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error(); + ASSERT_TRUE(gen().EmitImportFunction(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), 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 d485b37dea..845628e853 100644 --- a/src/writer/hlsl/generator_impl_intrinsic_test.cc +++ b/src/writer/hlsl/generator_impl_intrinsic_test.cc @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "gtest/gtest.h" #include "src/ast/call_expression.h" #include "src/ast/identifier_expression.h" #include "src/ast/module.h" @@ -20,14 +19,15 @@ #include "src/ast/type/vector_type.h" #include "src/context.h" #include "src/type_determiner.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_Intrinsic : public TestHelper, + public testing::Test {}; struct IntrinsicData { const char* name; @@ -37,16 +37,14 @@ inline std::ostream& operator<<(std::ostream& out, IntrinsicData data) { out << data.name; return out; } -using HlslIntrinsicTest = testing::TestWithParam; +class HlslIntrinsicTest : public TestHelper, + public testing::TestWithParam {}; TEST_P(HlslIntrinsicTest, Emit) { auto param = GetParam(); - - ast::Module m; - GeneratorImpl g(&m); - EXPECT_EQ(g.generate_intrinsic_name(param.name), param.hlsl_name); + EXPECT_EQ(gen().generate_intrinsic_name(param.name), param.hlsl_name); } INSTANTIATE_TEST_SUITE_P( - HlslGeneratorImplTest, + HlslGeneratorImplTest_Intrinsic, HlslIntrinsicTest, testing::Values(IntrinsicData{"any", "any"}, IntrinsicData{"all", "all"}, @@ -64,15 +62,15 @@ INSTANTIATE_TEST_SUITE_P( IntrinsicData{"is_inf", "isinf"}, IntrinsicData{"is_nan", "isnan"})); -TEST_F(HlslGeneratorImplTest, DISABLED_Intrinsic_IsNormal) { +TEST_F(HlslGeneratorImplTest_Intrinsic, DISABLED_Intrinsic_IsNormal) { FAIL(); } -TEST_F(HlslGeneratorImplTest, DISABLED_Intrinsic_Select) { +TEST_F(HlslGeneratorImplTest_Intrinsic, DISABLED_Intrinsic_Select) { FAIL(); } -TEST_F(HlslGeneratorImplTest, DISABLED_Intrinsic_OuterProduct) { +TEST_F(HlslGeneratorImplTest_Intrinsic, DISABLED_Intrinsic_OuterProduct) { ast::type::F32Type f32; ast::type::VectorType vec2(&f32, 2); ast::type::VectorType vec3(&f32, 3); @@ -90,32 +88,25 @@ TEST_F(HlslGeneratorImplTest, DISABLED_Intrinsic_OuterProduct) { std::make_unique("outer_product"), std::move(params)); - Context ctx; - ast::Module m; - TypeDeterminer td(&ctx, &m); - td.RegisterVariableForTesting(a.get()); - td.RegisterVariableForTesting(b.get()); + td().RegisterVariableForTesting(a.get()); + td().RegisterVariableForTesting(b.get()); - m.AddGlobalVariable(std::move(a)); - m.AddGlobalVariable(std::move(b)); + mod()->AddGlobalVariable(std::move(a)); + mod()->AddGlobalVariable(std::move(b)); - ASSERT_TRUE(td.Determine()) << td.error(); - ASSERT_TRUE(td.DetermineResultType(&call)) << td.error(); + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(td().DetermineResultType(&call)) << td().error(); - GeneratorImpl g(&m); - - g.increment_indent(); - ASSERT_TRUE(g.EmitExpression(&call)) << g.error(); - EXPECT_EQ(g.result(), " float3x2(a * b[0], a * b[1], a * b[2])"); + gen().increment_indent(); + ASSERT_TRUE(gen().EmitExpression(out(), &call)) << gen().error(); + EXPECT_EQ(result(), " float3x2(a * b[0], a * b[1], a * b[2])"); } -TEST_F(HlslGeneratorImplTest, Intrinsic_Bad_Name) { - ast::Module m; - GeneratorImpl g(&m); - EXPECT_EQ(g.generate_intrinsic_name("unknown name"), ""); +TEST_F(HlslGeneratorImplTest_Intrinsic, Intrinsic_Bad_Name) { + EXPECT_EQ(gen().generate_intrinsic_name("unknown name"), ""); } -TEST_F(HlslGeneratorImplTest, Intrinsic_Call) { +TEST_F(HlslGeneratorImplTest_Intrinsic, Intrinsic_Call) { ast::ExpressionList params; params.push_back(std::make_unique("param1")); params.push_back(std::make_unique("param2")); @@ -123,11 +114,9 @@ TEST_F(HlslGeneratorImplTest, Intrinsic_Call) { ast::CallExpression call(std::make_unique("dot"), std::move(params)); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); - ASSERT_TRUE(g.EmitExpression(&call)) << g.error(); - EXPECT_EQ(g.result(), " dot(param1, param2)"); + gen().increment_indent(); + ASSERT_TRUE(gen().EmitExpression(out(), &call)) << gen().error(); + EXPECT_EQ(result(), " dot(param1, param2)"); } } // namespace diff --git a/src/writer/hlsl/generator_impl_loop_test.cc b/src/writer/hlsl/generator_impl_loop_test.cc index 1f9dabfd5b..8a92b1c8d8 100644 --- a/src/writer/hlsl/generator_impl_loop_test.cc +++ b/src/writer/hlsl/generator_impl_loop_test.cc @@ -14,7 +14,6 @@ #include -#include "gtest/gtest.h" #include "src/ast/assignment_statement.h" #include "src/ast/discard_statement.h" #include "src/ast/float_literal.h" @@ -25,33 +24,30 @@ #include "src/ast/type/f32_type.h" #include "src/ast/variable.h" #include "src/ast/variable_decl_statement.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_Loop : public TestHelper, public testing::Test {}; -TEST_F(HlslGeneratorImplTest, Emit_Loop) { +TEST_F(HlslGeneratorImplTest_Loop, Emit_Loop) { auto body = std::make_unique(); body->append(std::make_unique()); ast::LoopStatement l(std::move(body), {}); + gen().increment_indent(); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); - - ASSERT_TRUE(g.EmitStatement(&l)) << g.error(); - EXPECT_EQ(g.result(), R"( for(;;) { + ASSERT_TRUE(gen().EmitStatement(out(), &l)) << gen().error(); + EXPECT_EQ(result(), R"( for(;;) { discard; } )"); } -TEST_F(HlslGeneratorImplTest, Emit_LoopWithContinuing) { +TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopWithContinuing) { auto body = std::make_unique(); body->append(std::make_unique()); @@ -59,13 +55,10 @@ TEST_F(HlslGeneratorImplTest, Emit_LoopWithContinuing) { continuing->append(std::make_unique()); ast::LoopStatement l(std::move(body), std::move(continuing)); + gen().increment_indent(); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); - - ASSERT_TRUE(g.EmitStatement(&l)) << g.error(); - EXPECT_EQ(g.result(), R"( { + ASSERT_TRUE(gen().EmitStatement(out(), &l)) << gen().error(); + EXPECT_EQ(result(), R"( { bool tint_hlsl_is_first_1 = true; for(;;) { if (!tint_hlsl_is_first_1) { @@ -79,7 +72,7 @@ TEST_F(HlslGeneratorImplTest, Emit_LoopWithContinuing) { )"); } -TEST_F(HlslGeneratorImplTest, Emit_LoopNestedWithContinuing) { +TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopNestedWithContinuing) { ast::type::F32Type f32; auto body = std::make_unique(); @@ -102,13 +95,10 @@ TEST_F(HlslGeneratorImplTest, Emit_LoopNestedWithContinuing) { std::move(lhs), std::move(rhs))); ast::LoopStatement outer(std::move(body), std::move(continuing)); + gen().increment_indent(); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); - - ASSERT_TRUE(g.EmitStatement(&outer)) << g.error(); - EXPECT_EQ(g.result(), R"( { + ASSERT_TRUE(gen().EmitStatement(out(), &outer)) << gen().error(); + EXPECT_EQ(result(), R"( { bool tint_hlsl_is_first_1 = true; for(;;) { if (!tint_hlsl_is_first_1) { @@ -134,7 +124,7 @@ TEST_F(HlslGeneratorImplTest, Emit_LoopNestedWithContinuing) { // TODO(dsinclair): Handle pulling declared variables up and out of the for() if // there is a continuing block. -TEST_F(HlslGeneratorImplTest, DISABLED_Emit_LoopWithVarUsedInContinuing) { +TEST_F(HlslGeneratorImplTest_Loop, DISABLED_Emit_LoopWithVarUsedInContinuing) { ast::type::F32Type f32; auto var = std::make_unique( @@ -156,13 +146,10 @@ TEST_F(HlslGeneratorImplTest, DISABLED_Emit_LoopWithVarUsedInContinuing) { std::move(lhs), std::move(rhs))); ast::LoopStatement outer(std::move(body), std::move(continuing)); + gen().increment_indent(); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); - - ASSERT_TRUE(g.EmitStatement(&outer)) << g.error(); - EXPECT_EQ(g.result(), R"( { + ASSERT_TRUE(gen().EmitStatement(out(), &outer)) << gen().error(); + EXPECT_EQ(result(), R"( { float lhs; bool tint_hlsl_is_first_1 = true; for(;;) { diff --git a/src/writer/hlsl/generator_impl_member_accessor_test.cc b/src/writer/hlsl/generator_impl_member_accessor_test.cc index 88e3660cbf..34be49008a 100644 --- a/src/writer/hlsl/generator_impl_member_accessor_test.cc +++ b/src/writer/hlsl/generator_impl_member_accessor_test.cc @@ -14,7 +14,6 @@ #include -#include "gtest/gtest.h" #include "src/ast/array_accessor_expression.h" #include "src/ast/assignment_statement.h" #include "src/ast/binary_expression.h" @@ -36,16 +35,17 @@ #include "src/ast/type_constructor_expression.h" #include "src/context.h" #include "src/type_determiner.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_MemberAccessor : public TestHelper, + public testing::Test {}; -TEST_F(HlslGeneratorImplTest, EmitExpression_MemberAccessor) { +TEST_F(HlslGeneratorImplTest_MemberAccessor, EmitExpression_MemberAccessor) { ast::type::F32Type f32; ast::StructMemberList members; @@ -68,20 +68,16 @@ TEST_F(HlslGeneratorImplTest, EmitExpression_MemberAccessor) { ast::MemberAccessorExpression expr(std::move(str), std::move(mem)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - GeneratorImpl g(&mod); - td.RegisterVariableForTesting(str_var.get()); - g.register_global(str_var.get()); - mod.AddGlobalVariable(std::move(str_var)); + td().RegisterVariableForTesting(str_var.get()); + gen().register_global(str_var.get()); + mod()->AddGlobalVariable(std::move(str_var)); - ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); - ASSERT_TRUE(g.EmitExpression(&expr)) << g.error(); - EXPECT_EQ(g.result(), "str.mem"); + ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error(); + ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "str.mem"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_MemberAccessor, EmitExpression_MemberAccessor_StorageBuffer_Load) { // struct Data { // [[offset 0]] a : i32; @@ -119,23 +115,18 @@ TEST_F(HlslGeneratorImplTest, std::make_unique("data"), std::make_unique("b")); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - GeneratorImpl g(&mod); + td().RegisterVariableForTesting(coord_var.get()); + gen().register_global(coord_var.get()); + mod()->AddGlobalVariable(std::move(coord_var)); - td.RegisterVariableForTesting(coord_var.get()); - g.register_global(coord_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(td().DetermineResultType(&expr)); - ASSERT_TRUE(td.Determine()) << td.error(); - ASSERT_TRUE(td.DetermineResultType(&expr)); - - ASSERT_TRUE(g.EmitExpression(&expr)) << g.error(); - EXPECT_EQ(g.result(), "asfloat(data.Load(4))"); + ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "asfloat(data.Load(4))"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_MemberAccessor, EmitExpression_MemberAccessor_StorageBuffer_Load_Int) { // struct Data { // [[offset 0]] a : i32; @@ -173,22 +164,18 @@ TEST_F(HlslGeneratorImplTest, std::make_unique("data"), std::make_unique("a")); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - GeneratorImpl g(&mod); - td.RegisterVariableForTesting(coord_var.get()); - g.register_global(coord_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); + td().RegisterVariableForTesting(coord_var.get()); + gen().register_global(coord_var.get()); + mod()->AddGlobalVariable(std::move(coord_var)); - ASSERT_TRUE(td.Determine()) << td.error(); - ASSERT_TRUE(td.DetermineResultType(&expr)); + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(td().DetermineResultType(&expr)); - ASSERT_TRUE(g.EmitExpression(&expr)) << g.error(); - EXPECT_EQ(g.result(), "asint(data.Load(0))"); + ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "asint(data.Load(0))"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_MemberAccessor, EmitExpression_ArrayAccessor_StorageBuffer_Load_Int_FromArray) { // struct Data { // [[offset 0]] a : [[stride 4]] array; @@ -225,22 +212,18 @@ TEST_F(HlslGeneratorImplTest, std::make_unique( std::make_unique(&i32, 2))); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - GeneratorImpl g(&mod); - td.RegisterVariableForTesting(coord_var.get()); - g.register_global(coord_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); + td().RegisterVariableForTesting(coord_var.get()); + gen().register_global(coord_var.get()); + mod()->AddGlobalVariable(std::move(coord_var)); - ASSERT_TRUE(td.Determine()) << td.error(); - ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error(); - ASSERT_TRUE(g.EmitExpression(&expr)) << g.error(); - EXPECT_EQ(g.result(), "asint(data.Load((4 * 2) + 0))"); + ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "asint(data.Load((4 * 2) + 0))"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_MemberAccessor, EmitExpression_ArrayAccessor_StorageBuffer_Load_Int_FromArray_ExprIdx) { // struct Data { // [[offset 0]] a : [[stride 4]] array; @@ -285,22 +268,18 @@ TEST_F(HlslGeneratorImplTest, std::make_unique( std::make_unique(&i32, 3)))); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - GeneratorImpl g(&mod); - td.RegisterVariableForTesting(coord_var.get()); - g.register_global(coord_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); + td().RegisterVariableForTesting(coord_var.get()); + gen().register_global(coord_var.get()); + mod()->AddGlobalVariable(std::move(coord_var)); - ASSERT_TRUE(td.Determine()) << td.error(); - ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error(); + ASSERT_TRUE(td().Determine()) << td().error(); + ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error(); - ASSERT_TRUE(g.EmitExpression(&expr)) << g.error(); - EXPECT_EQ(g.result(), "asint(data.Load((4 * ((2 + 4) - 3)) + 0))"); + ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "asint(data.Load((4 * ((2 + 4) - 3)) + 0))"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_MemberAccessor, EmitExpression_MemberAccessor_StorageBuffer_Store) { // struct Data { // [[offset 0]] a : i32; @@ -335,15 +314,11 @@ TEST_F(HlslGeneratorImplTest, std::make_unique(std::make_unique( "data", ast::StorageClass::kStorageBuffer, &s)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - GeneratorImpl g(&mod); - td.RegisterVariableForTesting(coord_var.get()); - g.register_global(coord_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); + td().RegisterVariableForTesting(coord_var.get()); + gen().register_global(coord_var.get()); + mod()->AddGlobalVariable(std::move(coord_var)); - ASSERT_TRUE(td.Determine()) << td.error(); + ASSERT_TRUE(td().Determine()) << td().error(); auto lhs = std::make_unique( std::make_unique("data"), @@ -352,13 +327,13 @@ TEST_F(HlslGeneratorImplTest, std::make_unique(&f32, 2.0f)); ast::AssignmentStatement assign(std::move(lhs), std::move(rhs)); - ASSERT_TRUE(td.DetermineResultType(&assign)); - ASSERT_TRUE(g.EmitStatement(&assign)) << g.error(); - EXPECT_EQ(g.result(), R"(data.Store(4, asuint(2.00000000f)); + ASSERT_TRUE(td().DetermineResultType(&assign)); + ASSERT_TRUE(gen().EmitStatement(out(), &assign)) << gen().error(); + EXPECT_EQ(result(), R"(data.Store(4, asuint(2.00000000f)); )"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_MemberAccessor, EmitExpression_MemberAccessor_StorageBuffer_Store_ToArray) { // struct Data { // [[offset 0]] a : [[stride 4]] array; @@ -389,15 +364,11 @@ TEST_F(HlslGeneratorImplTest, std::make_unique(std::make_unique( "data", ast::StorageClass::kStorageBuffer, &s)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - GeneratorImpl g(&mod); - td.RegisterVariableForTesting(coord_var.get()); - g.register_global(coord_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); + td().RegisterVariableForTesting(coord_var.get()); + gen().register_global(coord_var.get()); + mod()->AddGlobalVariable(std::move(coord_var)); - ASSERT_TRUE(td.Determine()) << td.error(); + ASSERT_TRUE(td().Determine()) << td().error(); auto lhs = std::make_unique( std::make_unique( @@ -409,13 +380,13 @@ TEST_F(HlslGeneratorImplTest, std::make_unique(&i32, 2)); ast::AssignmentStatement assign(std::move(lhs), std::move(rhs)); - ASSERT_TRUE(td.DetermineResultType(&assign)) << td.error(); - ASSERT_TRUE(g.EmitStatement(&assign)) << g.error(); - EXPECT_EQ(g.result(), R"(data.Store((4 * 2) + 0, asuint(2)); + ASSERT_TRUE(td().DetermineResultType(&assign)) << td().error(); + ASSERT_TRUE(gen().EmitStatement(out(), &assign)) << gen().error(); + EXPECT_EQ(result(), R"(data.Store((4 * 2) + 0, asuint(2)); )"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_MemberAccessor, EmitExpression_MemberAccessor_StorageBuffer_Store_Int) { // struct Data { // [[offset 0]] a : i32; @@ -450,15 +421,11 @@ TEST_F(HlslGeneratorImplTest, std::make_unique(std::make_unique( "data", ast::StorageClass::kStorageBuffer, &s)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - GeneratorImpl g(&mod); - td.RegisterVariableForTesting(coord_var.get()); - g.register_global(coord_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); + td().RegisterVariableForTesting(coord_var.get()); + gen().register_global(coord_var.get()); + mod()->AddGlobalVariable(std::move(coord_var)); - ASSERT_TRUE(td.Determine()) << td.error(); + ASSERT_TRUE(td().Determine()) << td().error(); auto lhs = std::make_unique( std::make_unique("data"), @@ -467,13 +434,13 @@ TEST_F(HlslGeneratorImplTest, std::make_unique(&i32, 2)); ast::AssignmentStatement assign(std::move(lhs), std::move(rhs)); - ASSERT_TRUE(td.DetermineResultType(&assign)); - ASSERT_TRUE(g.EmitStatement(&assign)) << g.error(); - EXPECT_EQ(g.result(), R"(data.Store(0, asuint(2)); + ASSERT_TRUE(td().DetermineResultType(&assign)); + ASSERT_TRUE(gen().EmitStatement(out(), &assign)) << gen().error(); + EXPECT_EQ(result(), R"(data.Store(0, asuint(2)); )"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_MemberAccessor, EmitExpression_MemberAccessor_StorageBuffer_Load_Vec3) { // struct Data { // [[offset 0]] a : vec3; @@ -510,26 +477,22 @@ TEST_F(HlslGeneratorImplTest, std::make_unique(std::make_unique( "data", ast::StorageClass::kStorageBuffer, &s)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - GeneratorImpl g(&mod); - td.RegisterVariableForTesting(coord_var.get()); - g.register_global(coord_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); + td().RegisterVariableForTesting(coord_var.get()); + gen().register_global(coord_var.get()); + mod()->AddGlobalVariable(std::move(coord_var)); - ASSERT_TRUE(td.Determine()) << td.error(); + ASSERT_TRUE(td().Determine()) << td().error(); ast::MemberAccessorExpression expr( std::make_unique("data"), std::make_unique("b")); - ASSERT_TRUE(td.DetermineResultType(&expr)); - ASSERT_TRUE(g.EmitExpression(&expr)) << g.error(); - EXPECT_EQ(g.result(), "asfloat(data.Load3(16))"); + ASSERT_TRUE(td().DetermineResultType(&expr)); + ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "asfloat(data.Load3(16))"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_MemberAccessor, EmitExpression_MemberAccessor_StorageBuffer_Store_Vec3) { // struct Data { // [[offset 0]] a : vec3; @@ -566,15 +529,11 @@ TEST_F(HlslGeneratorImplTest, std::make_unique(std::make_unique( "data", ast::StorageClass::kStorageBuffer, &s)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - GeneratorImpl g(&mod); - td.RegisterVariableForTesting(coord_var.get()); - g.register_global(coord_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); + td().RegisterVariableForTesting(coord_var.get()); + gen().register_global(coord_var.get()); + mod()->AddGlobalVariable(std::move(coord_var)); - ASSERT_TRUE(td.Determine()) << td.error(); + ASSERT_TRUE(td().Determine()) << td().error(); auto lit1 = std::make_unique(&f32, 1.f); auto lit2 = std::make_unique(&f32, 2.f); @@ -595,15 +554,15 @@ TEST_F(HlslGeneratorImplTest, ast::AssignmentStatement assign(std::move(lhs), std::move(rhs)); - ASSERT_TRUE(td.DetermineResultType(&assign)); - ASSERT_TRUE(g.EmitStatement(&assign)) << g.error(); + ASSERT_TRUE(td().DetermineResultType(&assign)); + ASSERT_TRUE(gen().EmitStatement(out(), &assign)) << gen().error(); EXPECT_EQ( - g.result(), + result(), R"(data.Store3(16, asuint(vector(1.00000000f, 2.00000000f, 3.00000000f))); )"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_MemberAccessor, EmitExpression_MemberAccessor_StorageBuffer_Load_MultiLevel) { // struct Data { // [[offset 0]] a : vec3; @@ -656,15 +615,11 @@ TEST_F(HlslGeneratorImplTest, std::make_unique(std::make_unique( "data", ast::StorageClass::kStorageBuffer, &pre)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - GeneratorImpl g(&mod); - td.RegisterVariableForTesting(coord_var.get()); - g.register_global(coord_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); + td().RegisterVariableForTesting(coord_var.get()); + gen().register_global(coord_var.get()); + mod()->AddGlobalVariable(std::move(coord_var)); - ASSERT_TRUE(td.Determine()) << td.error(); + ASSERT_TRUE(td().Determine()) << td().error(); ast::MemberAccessorExpression expr( std::make_unique( @@ -675,12 +630,12 @@ TEST_F(HlslGeneratorImplTest, std::make_unique(&i32, 2))), std::make_unique("b")); - ASSERT_TRUE(td.DetermineResultType(&expr)); - ASSERT_TRUE(g.EmitExpression(&expr)) << g.error(); - EXPECT_EQ(g.result(), "asfloat(data.Load3(16 + (32 * 2) + 0))"); + ASSERT_TRUE(td().DetermineResultType(&expr)); + ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "asfloat(data.Load3(16 + (32 * 2) + 0))"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_MemberAccessor, EmitExpression_MemberAccessor_StorageBuffer_Load_MultiLevel_Swizzle) { // struct Data { // [[offset 0]] a : vec3; @@ -733,15 +688,11 @@ TEST_F(HlslGeneratorImplTest, std::make_unique(std::make_unique( "data", ast::StorageClass::kStorageBuffer, &pre)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - GeneratorImpl g(&mod); - td.RegisterVariableForTesting(coord_var.get()); - g.register_global(coord_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); + td().RegisterVariableForTesting(coord_var.get()); + gen().register_global(coord_var.get()); + mod()->AddGlobalVariable(std::move(coord_var)); - ASSERT_TRUE(td.Determine()) << td.error(); + ASSERT_TRUE(td().Determine()) << td().error(); ast::MemberAccessorExpression expr( std::make_unique( @@ -754,13 +705,13 @@ TEST_F(HlslGeneratorImplTest, std::make_unique("b")), std::make_unique("xy")); - ASSERT_TRUE(td.DetermineResultType(&expr)); - ASSERT_TRUE(g.EmitExpression(&expr)) << g.error(); - EXPECT_EQ(g.result(), "asfloat(data.Load3(16 + (32 * 2) + 0)).xy"); + ASSERT_TRUE(td().DetermineResultType(&expr)); + ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "asfloat(data.Load3(16 + (32 * 2) + 0)).xy"); } TEST_F( - HlslGeneratorImplTest, + HlslGeneratorImplTest_MemberAccessor, EmitExpression_MemberAccessor_StorageBuffer_Load_MultiLevel_Swizzle_SingleLetter) { // struct Data { // [[offset 0]] a : vec3; @@ -813,15 +764,11 @@ TEST_F( std::make_unique(std::make_unique( "data", ast::StorageClass::kStorageBuffer, &pre)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - GeneratorImpl g(&mod); - td.RegisterVariableForTesting(coord_var.get()); - g.register_global(coord_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); + td().RegisterVariableForTesting(coord_var.get()); + gen().register_global(coord_var.get()); + mod()->AddGlobalVariable(std::move(coord_var)); - ASSERT_TRUE(td.Determine()) << td.error(); + ASSERT_TRUE(td().Determine()) << td().error(); ast::MemberAccessorExpression expr( std::make_unique( @@ -834,12 +781,12 @@ TEST_F( std::make_unique("b")), std::make_unique("g")); - ASSERT_TRUE(td.DetermineResultType(&expr)); - ASSERT_TRUE(g.EmitExpression(&expr)) << g.error(); - EXPECT_EQ(g.result(), "asfloat(data.Load((4 * 1) + 16 + (32 * 2) + 0))"); + ASSERT_TRUE(td().DetermineResultType(&expr)); + ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "asfloat(data.Load((4 * 1) + 16 + (32 * 2) + 0))"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_MemberAccessor, EmitExpression_MemberAccessor_StorageBuffer_Load_MultiLevel_Index) { // struct Data { // [[offset 0]] a : vec3; @@ -892,15 +839,11 @@ TEST_F(HlslGeneratorImplTest, std::make_unique(std::make_unique( "data", ast::StorageClass::kStorageBuffer, &pre)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - GeneratorImpl g(&mod); - td.RegisterVariableForTesting(coord_var.get()); - g.register_global(coord_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); + td().RegisterVariableForTesting(coord_var.get()); + gen().register_global(coord_var.get()); + mod()->AddGlobalVariable(std::move(coord_var)); - ASSERT_TRUE(td.Determine()) << td.error(); + ASSERT_TRUE(td().Determine()) << td().error(); ast::ArrayAccessorExpression expr( std::make_unique( @@ -914,12 +857,12 @@ TEST_F(HlslGeneratorImplTest, std::make_unique( std::make_unique(&i32, 1))); - ASSERT_TRUE(td.DetermineResultType(&expr)); - ASSERT_TRUE(g.EmitExpression(&expr)) << g.error(); - EXPECT_EQ(g.result(), "asfloat(data.Load((4 * 1) + 16 + (32 * 2) + 0))"); + ASSERT_TRUE(td().DetermineResultType(&expr)); + ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error(); + EXPECT_EQ(result(), "asfloat(data.Load((4 * 1) + 16 + (32 * 2) + 0))"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_MemberAccessor, EmitExpression_MemberAccessor_StorageBuffer_Store_MultiLevel) { // struct Data { // [[offset 0]] a : vec3; @@ -972,15 +915,11 @@ TEST_F(HlslGeneratorImplTest, std::make_unique(std::make_unique( "data", ast::StorageClass::kStorageBuffer, &pre)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - GeneratorImpl g(&mod); - td.RegisterVariableForTesting(coord_var.get()); - g.register_global(coord_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); + td().RegisterVariableForTesting(coord_var.get()); + gen().register_global(coord_var.get()); + mod()->AddGlobalVariable(std::move(coord_var)); - ASSERT_TRUE(td.Determine()) << td.error(); + ASSERT_TRUE(td().Determine()) << td().error(); auto lhs = std::make_unique( std::make_unique( @@ -1007,15 +946,15 @@ TEST_F(HlslGeneratorImplTest, ast::AssignmentStatement assign(std::move(lhs), std::move(rhs)); - ASSERT_TRUE(td.DetermineResultType(&assign)); - ASSERT_TRUE(g.EmitStatement(&assign)) << g.error(); + ASSERT_TRUE(td().DetermineResultType(&assign)); + ASSERT_TRUE(gen().EmitStatement(out(), &assign)) << gen().error(); EXPECT_EQ( - g.result(), + result(), R"(data.Store3(16 + (32 * 2) + 0, asuint(vector(1.00000000f, 2.00000000f, 3.00000000f))); )"); } -TEST_F(HlslGeneratorImplTest, +TEST_F(HlslGeneratorImplTest_MemberAccessor, EmitExpression_MemberAccessor_StorageBuffer_Store_Swizzle_SingleLetter) { // struct Data { // [[offset 0]] a : vec3; @@ -1068,15 +1007,11 @@ TEST_F(HlslGeneratorImplTest, std::make_unique(std::make_unique( "data", ast::StorageClass::kStorageBuffer, &pre)); - Context ctx; - ast::Module mod; - TypeDeterminer td(&ctx, &mod); - GeneratorImpl g(&mod); - td.RegisterVariableForTesting(coord_var.get()); - g.register_global(coord_var.get()); - mod.AddGlobalVariable(std::move(coord_var)); + td().RegisterVariableForTesting(coord_var.get()); + gen().register_global(coord_var.get()); + mod()->AddGlobalVariable(std::move(coord_var)); - ASSERT_TRUE(td.Determine()) << td.error(); + ASSERT_TRUE(td().Determine()) << td().error(); auto lhs = std::make_unique( std::make_unique( @@ -1094,9 +1029,9 @@ TEST_F(HlslGeneratorImplTest, ast::AssignmentStatement assign(std::move(lhs), std::move(rhs)); - ASSERT_TRUE(td.DetermineResultType(&assign)); - ASSERT_TRUE(g.EmitStatement(&assign)) << g.error(); - EXPECT_EQ(g.result(), + ASSERT_TRUE(td().DetermineResultType(&assign)); + ASSERT_TRUE(gen().EmitStatement(out(), &assign)) << gen().error(); + EXPECT_EQ(result(), R"(data.Store((4 * 1) + 16 + (32 * 2) + 0, asuint(1.00000000f)); )"); } diff --git a/src/writer/hlsl/generator_impl_module_constant_test.cc b/src/writer/hlsl/generator_impl_module_constant_test.cc index 74226e1c0a..d787c2317c 100644 --- a/src/writer/hlsl/generator_impl_module_constant_test.cc +++ b/src/writer/hlsl/generator_impl_module_constant_test.cc @@ -15,7 +15,6 @@ #include #include -#include "gtest/gtest.h" #include "src/ast/float_literal.h" #include "src/ast/module.h" #include "src/ast/scalar_constructor_expression.h" @@ -23,16 +22,17 @@ #include "src/ast/type/f32_type.h" #include "src/ast/type_constructor_expression.h" #include "src/ast/variable.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_ModuleConstant : public TestHelper, + public testing::Test {}; -TEST_F(HlslGeneratorImplTest, Emit_ModuleConstant) { +TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_ModuleConstant) { ast::type::F32Type f32; ast::type::ArrayType ary(&f32, 3); @@ -50,11 +50,10 @@ TEST_F(HlslGeneratorImplTest, Emit_ModuleConstant) { var->set_constructor( std::make_unique(&ary, std::move(exprs))); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitProgramConstVariable(var.get())) << g.error(); + ASSERT_TRUE(gen().EmitProgramConstVariable(out(), var.get())) + << gen().error(); EXPECT_EQ( - g.result(), + result(), "static const float pos[3] = {1.00000000f, 2.00000000f, 3.00000000f};\n"); } diff --git a/src/writer/hlsl/generator_impl_return_test.cc b/src/writer/hlsl/generator_impl_return_test.cc index f160d3bfb6..2662bd2257 100644 --- a/src/writer/hlsl/generator_impl_return_test.cc +++ b/src/writer/hlsl/generator_impl_return_test.cc @@ -15,40 +15,33 @@ #include #include -#include "gtest/gtest.h" #include "src/ast/identifier_expression.h" #include "src/ast/module.h" #include "src/ast/return_statement.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_Return : public TestHelper, public testing::Test {}; -TEST_F(HlslGeneratorImplTest, Emit_Return) { +TEST_F(HlslGeneratorImplTest_Return, Emit_Return) { ast::ReturnStatement r; + gen().increment_indent(); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); - - ASSERT_TRUE(g.EmitStatement(&r)) << g.error(); - EXPECT_EQ(g.result(), " return;\n"); + ASSERT_TRUE(gen().EmitStatement(out(), &r)) << gen().error(); + EXPECT_EQ(result(), " return;\n"); } -TEST_F(HlslGeneratorImplTest, Emit_ReturnWithValue) { +TEST_F(HlslGeneratorImplTest_Return, Emit_ReturnWithValue) { auto expr = std::make_unique("expr"); ast::ReturnStatement r(std::move(expr)); + gen().increment_indent(); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); - - ASSERT_TRUE(g.EmitStatement(&r)) << g.error(); - EXPECT_EQ(g.result(), " return expr;\n"); + ASSERT_TRUE(gen().EmitStatement(out(), &r)) << gen().error(); + EXPECT_EQ(result(), " return expr;\n"); } } // namespace diff --git a/src/writer/hlsl/generator_impl_switch_test.cc b/src/writer/hlsl/generator_impl_switch_test.cc index 8648893091..3b0b5bf4e6 100644 --- a/src/writer/hlsl/generator_impl_switch_test.cc +++ b/src/writer/hlsl/generator_impl_switch_test.cc @@ -14,7 +14,6 @@ #include -#include "gtest/gtest.h" #include "src/ast/break_statement.h" #include "src/ast/case_statement.h" #include "src/ast/identifier_expression.h" @@ -22,16 +21,16 @@ #include "src/ast/sint_literal.h" #include "src/ast/switch_statement.h" #include "src/ast/type/i32_type.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_Switch : public TestHelper, public testing::Test {}; -TEST_F(HlslGeneratorImplTest, Emit_Switch) { +TEST_F(HlslGeneratorImplTest_Switch, Emit_Switch) { auto def = std::make_unique(); auto def_body = std::make_unique(); def_body->append(std::make_unique()); @@ -53,13 +52,10 @@ TEST_F(HlslGeneratorImplTest, Emit_Switch) { auto cond = std::make_unique("cond"); ast::SwitchStatement s(std::move(cond), std::move(body)); + gen().increment_indent(); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); - - ASSERT_TRUE(g.EmitStatement(&s)) << g.error(); - EXPECT_EQ(g.result(), R"( switch(cond) { + ASSERT_TRUE(gen().EmitStatement(out(), &s)) << gen().error(); + EXPECT_EQ(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 b1b16dbe73..5ddbeb01b0 100644 --- a/src/writer/hlsl/generator_impl_test.cc +++ b/src/writer/hlsl/generator_impl_test.cc @@ -12,35 +12,31 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "src/writer/hlsl/generator_impl.h" - #include -#include "gtest/gtest.h" #include "src/ast/entry_point.h" #include "src/ast/function.h" #include "src/ast/identifier_expression.h" #include "src/ast/module.h" #include "src/ast/type/void_type.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest : public TestHelper, public testing::Test {}; TEST_F(HlslGeneratorImplTest, DISABLED_Generate) { ast::type::VoidType void_type; - ast::Module m; - m.AddFunction(std::make_unique("my_func", ast::VariableList{}, - &void_type)); - m.AddEntryPoint(std::make_unique( + mod()->AddFunction(std::make_unique( + "my_func", ast::VariableList{}, &void_type)); + mod()->AddEntryPoint(std::make_unique( ast::PipelineStage::kFragment, "my_func", "")); - GeneratorImpl g(&m); - ASSERT_TRUE(g.Generate()) << g.error(); - EXPECT_EQ(g.result(), R"(#import + ASSERT_TRUE(gen().Generate(out())) << gen().error(); + EXPECT_EQ(result(), R"(#import void my_func() { } @@ -48,30 +44,23 @@ void my_func() { } TEST_F(HlslGeneratorImplTest, InputStructName) { - ast::Module m; - GeneratorImpl g(&m); - ASSERT_EQ(g.generate_name("func_main_in"), "func_main_in"); + ASSERT_EQ(gen().generate_name("func_main_in"), "func_main_in"); } TEST_F(HlslGeneratorImplTest, InputStructName_ConflictWithExisting) { - ast::Module m; - GeneratorImpl g(&m); - // Register the struct name as existing. - auto* namer = g.namer_for_testing(); + auto* namer = gen().namer_for_testing(); namer->NameFor("func_main_out"); - ASSERT_EQ(g.generate_name("func_main_out"), "func_main_out_0"); + ASSERT_EQ(gen().generate_name("func_main_out"), "func_main_out_0"); } TEST_F(HlslGeneratorImplTest, NameConflictWith_InputStructName) { - ast::Module m; - GeneratorImpl g(&m); - ASSERT_EQ(g.generate_name("func_main_in"), "func_main_in"); + ASSERT_EQ(gen().generate_name("func_main_in"), "func_main_in"); ast::IdentifierExpression ident("func_main_in"); - ASSERT_TRUE(g.EmitIdentifier(&ident)); - EXPECT_EQ(g.result(), "func_main_in_0"); + ASSERT_TRUE(gen().EmitIdentifier(out(), &ident)); + EXPECT_EQ(result(), "func_main_in_0"); } struct HlslBuiltinData { @@ -82,13 +71,12 @@ inline std::ostream& operator<<(std::ostream& out, HlslBuiltinData data) { out << data.builtin; return out; } -using HlslBuiltinConversionTest = testing::TestWithParam; +class HlslBuiltinConversionTest + : public TestHelper, + public testing::TestWithParam {}; TEST_P(HlslBuiltinConversionTest, Emit) { auto params = GetParam(); - - ast::Module m; - GeneratorImpl g(&m); - EXPECT_EQ(g.builtin_to_attribute(params.builtin), + EXPECT_EQ(gen().builtin_to_attribute(params.builtin), std::string(params.attribute_name)); } INSTANTIATE_TEST_SUITE_P( diff --git a/src/writer/hlsl/generator_impl_type_test.cc b/src/writer/hlsl/generator_impl_type_test.cc index 6b27c00e3e..96c464bdc4 100644 --- a/src/writer/hlsl/generator_impl_type_test.cc +++ b/src/writer/hlsl/generator_impl_type_test.cc @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "gtest/gtest.h" #include "src/ast/module.h" #include "src/ast/struct.h" #include "src/ast/struct_decoration.h" @@ -29,170 +28,142 @@ #include "src/ast/type/u32_type.h" #include "src/ast/type/vector_type.h" #include "src/ast/type/void_type.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_Type : public TestHelper, public testing::Test {}; -TEST_F(HlslGeneratorImplTest, EmitType_Alias) { +TEST_F(HlslGeneratorImplTest_Type, EmitType_Alias) { ast::type::F32Type f32; ast::type::AliasType alias("alias", &f32); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitType(&alias, "")) << g.error(); - EXPECT_EQ(g.result(), "alias"); + ASSERT_TRUE(gen().EmitType(out(), &alias, "")) << gen().error(); + EXPECT_EQ(result(), "alias"); } -TEST_F(HlslGeneratorImplTest, EmitType_Alias_NameCollision) { +TEST_F(HlslGeneratorImplTest_Type, EmitType_Alias_NameCollision) { ast::type::F32Type f32; ast::type::AliasType alias("bool", &f32); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitType(&alias, "")) << g.error(); - EXPECT_EQ(g.result(), "bool_tint_0"); + ASSERT_TRUE(gen().EmitType(out(), &alias, "")) << gen().error(); + EXPECT_EQ(result(), "bool_tint_0"); } -TEST_F(HlslGeneratorImplTest, EmitType_Array) { +TEST_F(HlslGeneratorImplTest_Type, EmitType_Array) { ast::type::BoolType b; ast::type::ArrayType a(&b, 4); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitType(&a, "ary")) << g.error(); - EXPECT_EQ(g.result(), "bool ary[4]"); + ASSERT_TRUE(gen().EmitType(out(), &a, "ary")) << gen().error(); + EXPECT_EQ(result(), "bool ary[4]"); } -TEST_F(HlslGeneratorImplTest, EmitType_ArrayOfArray) { +TEST_F(HlslGeneratorImplTest_Type, EmitType_ArrayOfArray) { ast::type::BoolType b; ast::type::ArrayType a(&b, 4); ast::type::ArrayType c(&a, 5); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitType(&c, "ary")) << g.error(); - EXPECT_EQ(g.result(), "bool ary[5][4]"); + ASSERT_TRUE(gen().EmitType(out(), &c, "ary")) << gen().error(); + EXPECT_EQ(result(), "bool ary[5][4]"); } // TODO(dsinclair): Is this possible? What order should it output in? -TEST_F(HlslGeneratorImplTest, DISABLED_EmitType_ArrayOfArrayOfRuntimeArray) { +TEST_F(HlslGeneratorImplTest_Type, + DISABLED_EmitType_ArrayOfArrayOfRuntimeArray) { ast::type::BoolType b; ast::type::ArrayType a(&b, 4); ast::type::ArrayType c(&a, 5); ast::type::ArrayType d(&c); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitType(&c, "ary")) << g.error(); - EXPECT_EQ(g.result(), "bool ary[5][4][1]"); + ASSERT_TRUE(gen().EmitType(out(), &c, "ary")) << gen().error(); + EXPECT_EQ(result(), "bool ary[5][4][1]"); } -TEST_F(HlslGeneratorImplTest, EmitType_ArrayOfArrayOfArray) { +TEST_F(HlslGeneratorImplTest_Type, EmitType_ArrayOfArrayOfArray) { ast::type::BoolType b; ast::type::ArrayType a(&b, 4); ast::type::ArrayType c(&a, 5); ast::type::ArrayType d(&c, 6); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitType(&d, "ary")) << g.error(); - EXPECT_EQ(g.result(), "bool ary[6][5][4]"); + ASSERT_TRUE(gen().EmitType(out(), &d, "ary")) << gen().error(); + EXPECT_EQ(result(), "bool ary[6][5][4]"); } -TEST_F(HlslGeneratorImplTest, EmitType_Array_NameCollision) { +TEST_F(HlslGeneratorImplTest_Type, EmitType_Array_NameCollision) { ast::type::BoolType b; ast::type::ArrayType a(&b, 4); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitType(&a, "bool")) << g.error(); - EXPECT_EQ(g.result(), "bool bool_tint_0[4]"); + ASSERT_TRUE(gen().EmitType(out(), &a, "bool")) << gen().error(); + EXPECT_EQ(result(), "bool bool_tint_0[4]"); } -TEST_F(HlslGeneratorImplTest, EmitType_Array_WithoutName) { +TEST_F(HlslGeneratorImplTest_Type, EmitType_Array_WithoutName) { ast::type::BoolType b; ast::type::ArrayType a(&b, 4); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitType(&a, "")) << g.error(); - EXPECT_EQ(g.result(), "bool[4]"); + ASSERT_TRUE(gen().EmitType(out(), &a, "")) << gen().error(); + EXPECT_EQ(result(), "bool[4]"); } -TEST_F(HlslGeneratorImplTest, DISABLED_EmitType_RuntimeArray) { +TEST_F(HlslGeneratorImplTest_Type, DISABLED_EmitType_RuntimeArray) { ast::type::BoolType b; ast::type::ArrayType a(&b); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitType(&a, "ary")) << g.error(); - EXPECT_EQ(g.result(), "bool ary[]"); + ASSERT_TRUE(gen().EmitType(out(), &a, "ary")) << gen().error(); + EXPECT_EQ(result(), "bool ary[]"); } -TEST_F(HlslGeneratorImplTest, DISABLED_EmitType_RuntimeArray_NameCollision) { +TEST_F(HlslGeneratorImplTest_Type, + DISABLED_EmitType_RuntimeArray_NameCollision) { ast::type::BoolType b; ast::type::ArrayType a(&b); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitType(&a, "double")) << g.error(); - EXPECT_EQ(g.result(), "bool double_tint_0[]"); + ASSERT_TRUE(gen().EmitType(out(), &a, "double")) << gen().error(); + EXPECT_EQ(result(), "bool double_tint_0[]"); } -TEST_F(HlslGeneratorImplTest, EmitType_Bool) { +TEST_F(HlslGeneratorImplTest_Type, EmitType_Bool) { ast::type::BoolType b; - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitType(&b, "")) << g.error(); - EXPECT_EQ(g.result(), "bool"); + ASSERT_TRUE(gen().EmitType(out(), &b, "")) << gen().error(); + EXPECT_EQ(result(), "bool"); } -TEST_F(HlslGeneratorImplTest, EmitType_F32) { +TEST_F(HlslGeneratorImplTest_Type, EmitType_F32) { ast::type::F32Type f32; - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitType(&f32, "")) << g.error(); - EXPECT_EQ(g.result(), "float"); + ASSERT_TRUE(gen().EmitType(out(), &f32, "")) << gen().error(); + EXPECT_EQ(result(), "float"); } -TEST_F(HlslGeneratorImplTest, EmitType_I32) { +TEST_F(HlslGeneratorImplTest_Type, EmitType_I32) { ast::type::I32Type i32; - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitType(&i32, "")) << g.error(); - EXPECT_EQ(g.result(), "int"); + ASSERT_TRUE(gen().EmitType(out(), &i32, "")) << gen().error(); + EXPECT_EQ(result(), "int"); } -TEST_F(HlslGeneratorImplTest, EmitType_Matrix) { +TEST_F(HlslGeneratorImplTest_Type, EmitType_Matrix) { ast::type::F32Type f32; ast::type::MatrixType m(&f32, 3, 2); - ast::Module mod; - GeneratorImpl g(&mod); - ASSERT_TRUE(g.EmitType(&m, "")) << g.error(); - EXPECT_EQ(g.result(), "matrix"); + ASSERT_TRUE(gen().EmitType(out(), &m, "")) << gen().error(); + EXPECT_EQ(result(), "matrix"); } // TODO(dsinclair): How to annotate as workgroup? -TEST_F(HlslGeneratorImplTest, DISABLED_EmitType_Pointer) { +TEST_F(HlslGeneratorImplTest_Type, DISABLED_EmitType_Pointer) { ast::type::F32Type f32; ast::type::PointerType p(&f32, ast::StorageClass::kWorkgroup); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitType(&p, "")) << g.error(); - EXPECT_EQ(g.result(), "float*"); + ASSERT_TRUE(gen().EmitType(out(), &p, "")) << gen().error(); + EXPECT_EQ(result(), "float*"); } -TEST_F(HlslGeneratorImplTest, EmitType_Struct) { +TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct) { ast::type::I32Type i32; ast::type::F32Type f32; @@ -210,16 +181,14 @@ TEST_F(HlslGeneratorImplTest, EmitType_Struct) { ast::type::StructType s(std::move(str)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitType(&s, "")) << g.error(); - EXPECT_EQ(g.result(), R"(struct { + ASSERT_TRUE(gen().EmitType(out(), &s, "")) << gen().error(); + EXPECT_EQ(result(), R"(struct { int a; float b; })"); } -TEST_F(HlslGeneratorImplTest, DISABLED_EmitType_Struct_InjectPadding) { +TEST_F(HlslGeneratorImplTest_Type, DISABLED_EmitType_Struct_InjectPadding) { ast::type::I32Type i32; ast::type::F32Type f32; @@ -243,10 +212,8 @@ TEST_F(HlslGeneratorImplTest, DISABLED_EmitType_Struct_InjectPadding) { ast::type::StructType s(std::move(str)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitType(&s, "")) << g.error(); - EXPECT_EQ(g.result(), R"(struct { + ASSERT_TRUE(gen().EmitType(out(), &s, "")) << gen().error(); + EXPECT_EQ(result(), R"(struct { int8_t pad_0[4]; int a; int8_t pad_1[24]; @@ -256,7 +223,7 @@ TEST_F(HlslGeneratorImplTest, DISABLED_EmitType_Struct_InjectPadding) { })"); } -TEST_F(HlslGeneratorImplTest, EmitType_Struct_NameCollision) { +TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct_NameCollision) { ast::type::I32Type i32; ast::type::F32Type f32; @@ -273,17 +240,15 @@ TEST_F(HlslGeneratorImplTest, EmitType_Struct_NameCollision) { ast::type::StructType s(std::move(str)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitType(&s, "")) << g.error(); - EXPECT_EQ(g.result(), R"(struct { + ASSERT_TRUE(gen().EmitType(out(), &s, "")) << gen().error(); + EXPECT_EQ(result(), R"(struct { int double_tint_0; float float_tint_0; })"); } // TODO(dsinclair): How to translate [[block]] -TEST_F(HlslGeneratorImplTest, DISABLED_EmitType_Struct_WithDecoration) { +TEST_F(HlslGeneratorImplTest_Type, DISABLED_EmitType_Struct_WithDecoration) { ast::type::I32Type i32; ast::type::F32Type f32; @@ -302,41 +267,33 @@ TEST_F(HlslGeneratorImplTest, DISABLED_EmitType_Struct_WithDecoration) { ast::type::StructType s(std::move(str)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitType(&s, "")) << g.error(); - EXPECT_EQ(g.result(), R"(struct { + ASSERT_TRUE(gen().EmitType(out(), &s, "")) << gen().error(); + EXPECT_EQ(result(), R"(struct { int a; float b; })"); } -TEST_F(HlslGeneratorImplTest, EmitType_U32) { +TEST_F(HlslGeneratorImplTest_Type, EmitType_U32) { ast::type::U32Type u32; - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitType(&u32, "")) << g.error(); - EXPECT_EQ(g.result(), "uint"); + ASSERT_TRUE(gen().EmitType(out(), &u32, "")) << gen().error(); + EXPECT_EQ(result(), "uint"); } -TEST_F(HlslGeneratorImplTest, EmitType_Vector) { +TEST_F(HlslGeneratorImplTest_Type, EmitType_Vector) { ast::type::F32Type f32; ast::type::VectorType v(&f32, 3); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitType(&v, "")) << g.error(); - EXPECT_EQ(g.result(), "vector"); + ASSERT_TRUE(gen().EmitType(out(), &v, "")) << gen().error(); + EXPECT_EQ(result(), "vector"); } -TEST_F(HlslGeneratorImplTest, EmitType_Void) { +TEST_F(HlslGeneratorImplTest_Type, EmitType_Void) { ast::type::VoidType v; - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitType(&v, "")) << g.error(); - EXPECT_EQ(g.result(), "void"); + ASSERT_TRUE(gen().EmitType(out(), &v, "")) << gen().error(); + EXPECT_EQ(result(), "void"); } } // namespace diff --git a/src/writer/hlsl/generator_impl_unary_op_test.cc b/src/writer/hlsl/generator_impl_unary_op_test.cc index 4f9317745f..ae769429f4 100644 --- a/src/writer/hlsl/generator_impl_unary_op_test.cc +++ b/src/writer/hlsl/generator_impl_unary_op_test.cc @@ -15,11 +15,10 @@ #include #include -#include "gtest/gtest.h" #include "src/ast/identifier_expression.h" #include "src/ast/module.h" #include "src/ast/unary_op_expression.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { @@ -34,19 +33,18 @@ inline std::ostream& operator<<(std::ostream& out, UnaryOpData data) { out << data.op; return out; } -using HlslUnaryOpTest = testing::TestWithParam; +class HlslUnaryOpTest : public TestHelper, + public testing::TestWithParam {}; TEST_P(HlslUnaryOpTest, Emit) { auto params = GetParam(); auto expr = std::make_unique("expr"); ast::UnaryOpExpression op(params.op, std::move(expr)); - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitExpression(&op)) << g.error(); - EXPECT_EQ(g.result(), std::string(params.name) + "(expr)"); + ASSERT_TRUE(gen().EmitExpression(out(), &op)) << gen().error(); + EXPECT_EQ(result(), std::string(params.name) + "(expr)"); } -INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest, +INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest_UnaryOp, HlslUnaryOpTest, testing::Values(UnaryOpData{"!", ast::UnaryOp::kNot}, UnaryOpData{"-", 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 961beefeca..1a85ec9c1f 100644 --- a/src/writer/hlsl/generator_impl_variable_decl_statement_test.cc +++ b/src/writer/hlsl/generator_impl_variable_decl_statement_test.cc @@ -15,7 +15,6 @@ #include #include -#include "gtest/gtest.h" #include "src/ast/identifier_expression.h" #include "src/ast/module.h" #include "src/ast/type/array_type.h" @@ -23,47 +22,42 @@ #include "src/ast/type/vector_type.h" #include "src/ast/variable.h" #include "src/ast/variable_decl_statement.h" -#include "src/writer/hlsl/generator_impl.h" +#include "src/writer/hlsl/test_helper.h" namespace tint { namespace writer { namespace hlsl { namespace { -using HlslGeneratorImplTest = testing::Test; +class HlslGeneratorImplTest_VariableDecl : public TestHelper, + public testing::Test {}; -TEST_F(HlslGeneratorImplTest, Emit_VariableDeclStatement) { +TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement) { ast::type::F32Type f32; auto var = std::make_unique("a", ast::StorageClass::kNone, &f32); ast::VariableDeclStatement stmt(std::move(var)); + gen().increment_indent(); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); - - ASSERT_TRUE(g.EmitStatement(&stmt)) << g.error(); - EXPECT_EQ(g.result(), " float a;\n"); + ASSERT_TRUE(gen().EmitStatement(out(), &stmt)) << gen().error(); + EXPECT_EQ(result(), " float a;\n"); } -TEST_F(HlslGeneratorImplTest, Emit_VariableDeclStatement_Const) { +TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const) { ast::type::F32Type f32; auto var = std::make_unique("a", ast::StorageClass::kNone, &f32); var->set_is_const(true); ast::VariableDeclStatement stmt(std::move(var)); + gen().increment_indent(); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); - - ASSERT_TRUE(g.EmitStatement(&stmt)) << g.error(); - EXPECT_EQ(g.result(), " const float a;\n"); + ASSERT_TRUE(gen().EmitStatement(out(), &stmt)) << gen().error(); + EXPECT_EQ(result(), " const float a;\n"); } -TEST_F(HlslGeneratorImplTest, Emit_VariableDeclStatement_Array) { +TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Array) { ast::type::F32Type f32; ast::type::ArrayType ary(&f32, 5); @@ -71,46 +65,39 @@ TEST_F(HlslGeneratorImplTest, Emit_VariableDeclStatement_Array) { std::make_unique("a", ast::StorageClass::kNone, &ary); ast::VariableDeclStatement stmt(std::move(var)); + gen().increment_indent(); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); - - ASSERT_TRUE(g.EmitStatement(&stmt)) << g.error(); - EXPECT_EQ(g.result(), " float a[5];\n"); + ASSERT_TRUE(gen().EmitStatement(out(), &stmt)) << gen().error(); + EXPECT_EQ(result(), " float a[5];\n"); } -TEST_F(HlslGeneratorImplTest, Emit_VariableDeclStatement_Function) { +TEST_F(HlslGeneratorImplTest_VariableDecl, + Emit_VariableDeclStatement_Function) { ast::type::F32Type f32; auto var = std::make_unique("a", ast::StorageClass::kFunction, &f32); ast::VariableDeclStatement stmt(std::move(var)); + gen().increment_indent(); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); - - ASSERT_TRUE(g.EmitStatement(&stmt)) << g.error(); - EXPECT_EQ(g.result(), " float a;\n"); + ASSERT_TRUE(gen().EmitStatement(out(), &stmt)) << gen().error(); + EXPECT_EQ(result(), " float a;\n"); } -TEST_F(HlslGeneratorImplTest, Emit_VariableDeclStatement_Private) { +TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Private) { ast::type::F32Type f32; auto var = std::make_unique("a", ast::StorageClass::kPrivate, &f32); ast::VariableDeclStatement stmt(std::move(var)); + gen().increment_indent(); - ast::Module m; - GeneratorImpl g(&m); - g.increment_indent(); - - ASSERT_TRUE(g.EmitStatement(&stmt)) << g.error(); - EXPECT_EQ(g.result(), " float a;\n"); + ASSERT_TRUE(gen().EmitStatement(out(), &stmt)) << gen().error(); + EXPECT_EQ(result(), " float a;\n"); } -TEST_F(HlslGeneratorImplTest, Emit_VariableDeclStatement_Initializer_Private) { +TEST_F(HlslGeneratorImplTest_VariableDecl, + Emit_VariableDeclStatement_Initializer_Private) { auto ident = std::make_unique("initializer"); ast::type::F32Type f32; @@ -119,15 +106,13 @@ TEST_F(HlslGeneratorImplTest, Emit_VariableDeclStatement_Initializer_Private) { var->set_constructor(std::move(ident)); ast::VariableDeclStatement stmt(std::move(var)); - - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitStatement(&stmt)) << g.error(); - EXPECT_EQ(g.result(), R"(float a = initializer; + ASSERT_TRUE(gen().EmitStatement(out(), &stmt)) << gen().error(); + EXPECT_EQ(result(), R"(float a = initializer; )"); } -TEST_F(HlslGeneratorImplTest, Emit_VariableDeclStatement_Initializer_ZeroVec) { +TEST_F(HlslGeneratorImplTest_VariableDecl, + Emit_VariableDeclStatement_Initializer_ZeroVec) { ast::type::F32Type f32; ast::type::VectorType vec(&f32, 3); @@ -140,11 +125,8 @@ TEST_F(HlslGeneratorImplTest, Emit_VariableDeclStatement_Initializer_ZeroVec) { var->set_constructor(std::move(zero_vec)); ast::VariableDeclStatement stmt(std::move(var)); - - ast::Module m; - GeneratorImpl g(&m); - ASSERT_TRUE(g.EmitStatement(&stmt)) << g.error(); - EXPECT_EQ(g.result(), R"(vector a = vector(0.0f); + ASSERT_TRUE(gen().EmitStatement(out(), &stmt)) << gen().error(); + EXPECT_EQ(result(), R"(vector a = vector(0.0f); )"); } diff --git a/src/writer/hlsl/test_helper.cc b/src/writer/hlsl/test_helper.cc new file mode 100644 index 0000000000..7e5fc6fe02 --- /dev/null +++ b/src/writer/hlsl/test_helper.cc @@ -0,0 +1,27 @@ +// Copyright 2020 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/writer/hlsl/test_helper.h" + +namespace tint { +namespace writer { +namespace hlsl { + +TestHelper::TestHelper() : td_(&ctx_, &mod_), impl_(&mod_) {} + +TestHelper::~TestHelper() = default; + +} // namespace hlsl +} // namespace writer +} // namespace tint diff --git a/src/writer/hlsl/test_helper.h b/src/writer/hlsl/test_helper.h new file mode 100644 index 0000000000..a8eceed7d4 --- /dev/null +++ b/src/writer/hlsl/test_helper.h @@ -0,0 +1,63 @@ +// Copyright 2020 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_WRITER_HLSL_TEST_HELPER_H_ +#define SRC_WRITER_HLSL_TEST_HELPER_H_ + +#include + +#include "gtest/gtest.h" +#include "src/ast/module.h" +#include "src/context.h" +#include "src/type_determiner.h" +#include "src/writer/hlsl/generator_impl.h" + +namespace tint { +namespace writer { +namespace hlsl { + +/// Helper class for testing +class TestHelper { + public: + TestHelper(); + ~TestHelper(); + + /// @returns the generator implementation + GeneratorImpl& gen() { return impl_; } + + /// @returns the module + ast::Module* mod() { return &mod_; } + + /// @returns the type determiner + TypeDeterminer& td() { return td_; } + + /// @returns the output stream + std::ostream& out() { return out_; } + + /// @returns the result string + std::string result() const { return out_.str(); } + + private: + Context ctx_; + ast::Module mod_; + TypeDeterminer td_; + GeneratorImpl impl_; + std::ostringstream out_; +}; + +} // namespace hlsl +} // namespace writer +} // namespace tint + +#endif // SRC_WRITER_HLSL_TEST_HELPER_H_