diff --git a/src/tint/ir/builder_impl.cc b/src/tint/ir/builder_impl.cc index 1323f17c9c..07226ce502 100644 --- a/src/tint/ir/builder_impl.cc +++ b/src/tint/ir/builder_impl.cc @@ -154,16 +154,14 @@ ResultType BuilderImpl::Build() { auto* sem = program_->Sem().Module(); for (auto* decl : sem->DependencyOrderedDeclarations()) { - bool ok = tint::Switch( + tint::Switch( decl, // [&](const ast::Struct*) { // Will be encoded into the `type::Struct` when used. We will then hoist all // used structs up to module scope when converting IR. - return true; }, [&](const ast::Alias*) { // Folded away and doesn't appear in the IR. - return true; }, // [&](const ast::Variable* var) { // TODO(dsinclair): Implement @@ -175,21 +173,19 @@ ResultType BuilderImpl::Build() { // }, [&](const ast::ConstAssert*) { // Evaluated by the resolver, drop from the IR. - return true; }, [&](Default) { add_error(decl->source, "unknown type: " + std::string(decl->TypeInfo().name)); - return true; }); - if (!ok) { - return utils::Failure; - } + } + if (!diagnostics_.empty()) { + return utils::Failure; } return ResultType{std::move(builder.ir)}; } -bool BuilderImpl::EmitFunction(const ast::Function* ast_func) { +void BuilderImpl::EmitFunction(const ast::Function* ast_func) { // The flow stack should have been emptied when the previous function finished building. TINT_ASSERT(IR, flow_stack.IsEmpty()); @@ -208,9 +204,7 @@ bool BuilderImpl::EmitFunction(const ast::Function* ast_func) { FlowStackScope scope(this, ir_func); current_flow_block = ir_func->start_target; - if (!EmitStatements(ast_func->body->statements)) { - return false; - } + EmitStatements(ast_func->body->statements); // TODO(dsinclair): Store return type and attributes // TODO(dsinclair): Store parameters @@ -224,15 +218,11 @@ bool BuilderImpl::EmitFunction(const ast::Function* ast_func) { TINT_ASSERT(IR, flow_stack.IsEmpty()); current_flow_block = nullptr; current_function_ = nullptr; - - return true; } -bool BuilderImpl::EmitStatements(utils::VectorRef stmts) { +void BuilderImpl::EmitStatements(utils::VectorRef stmts) { for (auto* s : stmts) { - if (!EmitStatement(s)) { - return false; - } + EmitStatement(s); // If the current flow block has a branch target then the rest of the statements in this // block are dead code. Skip them. @@ -240,57 +230,53 @@ bool BuilderImpl::EmitStatements(utils::VectorRef stmts) break; } } - return true; } -bool BuilderImpl::EmitStatement(const ast::Statement* stmt) { - return tint::Switch( +void BuilderImpl::EmitStatement(const ast::Statement* stmt) { + tint::Switch( stmt, // [&](const ast::AssignmentStatement* a) { // TODO(dsinclair): Implement // }, - [&](const ast::BlockStatement* b) { return EmitBlock(b); }, - [&](const ast::BreakStatement* b) { return EmitBreak(b); }, - [&](const ast::BreakIfStatement* b) { return EmitBreakIf(b); }, - [&](const ast::CallStatement* c) { return EmitCall(c); }, + [&](const ast::BlockStatement* b) { EmitBlock(b); }, + [&](const ast::BreakStatement* b) { EmitBreak(b); }, + [&](const ast::BreakIfStatement* b) { EmitBreakIf(b); }, + [&](const ast::CallStatement* c) { EmitCall(c); }, // [&](const ast::CompoundAssignmentStatement* c) { // TODO(dsinclair): Implement // }, - [&](const ast::ContinueStatement* c) { return EmitContinue(c); }, - [&](const ast::DiscardStatement* d) { return EmitDiscard(d); }, - [&](const ast::IfStatement* i) { return EmitIf(i); }, - [&](const ast::LoopStatement* l) { return EmitLoop(l); }, - [&](const ast::ForLoopStatement* l) { return EmitForLoop(l); }, - [&](const ast::WhileStatement* l) { return EmitWhile(l); }, - [&](const ast::ReturnStatement* r) { return EmitReturn(r); }, - [&](const ast::SwitchStatement* s) { return EmitSwitch(s); }, - [&](const ast::VariableDeclStatement* v) { return EmitVariable(v->variable); }, + [&](const ast::ContinueStatement* c) { EmitContinue(c); }, + [&](const ast::DiscardStatement* d) { EmitDiscard(d); }, + [&](const ast::IfStatement* i) { EmitIf(i); }, + [&](const ast::LoopStatement* l) { EmitLoop(l); }, + [&](const ast::ForLoopStatement* l) { EmitForLoop(l); }, + [&](const ast::WhileStatement* l) { EmitWhile(l); }, + [&](const ast::ReturnStatement* r) { EmitReturn(r); }, + [&](const ast::SwitchStatement* s) { EmitSwitch(s); }, + [&](const ast::VariableDeclStatement* v) { EmitVariable(v->variable); }, [&](const ast::ConstAssert*) { - return true; // Not emitted + // Not emitted }, [&](Default) { add_error(stmt->source, "unknown statement type: " + std::string(stmt->TypeInfo().name)); - // TODO(dsinclair): This should return `false`, switch back when all - // the cases are handled. - return true; }); } -bool BuilderImpl::EmitBlock(const ast::BlockStatement* block) { +void BuilderImpl::EmitBlock(const ast::BlockStatement* block) { // Note, this doesn't need to emit a Block as the current block flow node should be // sufficient as the blocks all get flattened. Each flow control node will inject the basic // blocks it requires. - return EmitStatements(block->statements); + EmitStatements(block->statements); } -bool BuilderImpl::EmitIf(const ast::IfStatement* stmt) { +void BuilderImpl::EmitIf(const ast::IfStatement* stmt) { auto* if_node = builder.CreateIf(); // Emit the if condition into the end of the preceding block auto reg = EmitExpression(stmt->condition); if (!reg) { - return false; + return; } if_node->condition = reg.Get(); @@ -302,16 +288,16 @@ bool BuilderImpl::EmitIf(const ast::IfStatement* stmt) { FlowStackScope scope(this, if_node); current_flow_block = if_node->true_.target->As(); - if (!EmitStatement(stmt->body)) { - return false; - } + EmitStatement(stmt->body); + // If the true branch did not execute control flow, then go to the merge target BranchToIfNeeded(if_node->merge.target); current_flow_block = if_node->false_.target->As(); - if (stmt->else_statement && !EmitStatement(stmt->else_statement)) { - return false; + if (stmt->else_statement) { + EmitStatement(stmt->else_statement); } + // If the false branch did not execute control flow, then go to the merge target BranchToIfNeeded(if_node->merge.target); } @@ -323,11 +309,9 @@ bool BuilderImpl::EmitIf(const ast::IfStatement* stmt) { if (IsConnected(if_node->merge.target)) { current_flow_block = if_node->merge.target->As(); } - - return true; } -bool BuilderImpl::EmitLoop(const ast::LoopStatement* stmt) { +void BuilderImpl::EmitLoop(const ast::LoopStatement* stmt) { auto* loop_node = builder.CreateLoop(); BranchTo(loop_node); @@ -338,18 +322,14 @@ bool BuilderImpl::EmitLoop(const ast::LoopStatement* stmt) { FlowStackScope scope(this, loop_node); current_flow_block = loop_node->start.target->As(); - if (!EmitStatement(stmt->body)) { - return false; - } + EmitStatement(stmt->body); // The current block didn't `break`, `return` or `continue`, go to the continuing block. BranchToIfNeeded(loop_node->continuing.target); current_flow_block = loop_node->continuing.target->As(); if (stmt->continuing) { - if (!EmitStatement(stmt->continuing)) { - return false; - } + EmitStatement(stmt->continuing); } // Branch back to the start node if the continue target didn't branch out already @@ -362,10 +342,9 @@ bool BuilderImpl::EmitLoop(const ast::LoopStatement* stmt) { if (!IsConnected(loop_node->merge.target)) { current_flow_block = nullptr; } - return true; } -bool BuilderImpl::EmitWhile(const ast::WhileStatement* stmt) { +void BuilderImpl::EmitWhile(const ast::WhileStatement* stmt) { auto* loop_node = builder.CreateLoop(); // Continue is always empty, just go back to the start TINT_ASSERT(IR, loop_node->continuing.target->Is()); @@ -384,7 +363,7 @@ bool BuilderImpl::EmitWhile(const ast::WhileStatement* stmt) { // Emit the while condition into the start target of the loop auto reg = EmitExpression(stmt->condition); if (!reg) { - return false; + return; } // Create an `if (cond) {} else {break;}` control flow @@ -399,19 +378,16 @@ bool BuilderImpl::EmitWhile(const ast::WhileStatement* stmt) { BranchTo(if_node); current_flow_block = if_node->merge.target->As(); - if (!EmitStatement(stmt->body)) { - return false; - } + EmitStatement(stmt->body); BranchToIfNeeded(loop_node->continuing.target); } // The while loop always has a path to the merge target as the break statement comes before // anything inside the loop. current_flow_block = loop_node->merge.target->As(); - return true; } -bool BuilderImpl::EmitForLoop(const ast::ForLoopStatement* stmt) { +void BuilderImpl::EmitForLoop(const ast::ForLoopStatement* stmt) { auto* loop_node = builder.CreateLoop(); TINT_ASSERT(IR, loop_node->continuing.target->Is()); builder.Branch(loop_node->continuing.target->As(), loop_node->start.target, @@ -419,9 +395,7 @@ bool BuilderImpl::EmitForLoop(const ast::ForLoopStatement* stmt) { if (stmt->initializer) { // Emit the for initializer before branching to the loop - if (!EmitStatement(stmt->initializer)) { - return false; - } + EmitStatement(stmt->initializer); } BranchTo(loop_node); @@ -437,7 +411,7 @@ bool BuilderImpl::EmitForLoop(const ast::ForLoopStatement* stmt) { // Emit the condition into the target target of the loop auto reg = EmitExpression(stmt->condition); if (!reg) { - return false; + return; } // Create an `if (cond) {} else {break;}` control flow @@ -454,32 +428,26 @@ bool BuilderImpl::EmitForLoop(const ast::ForLoopStatement* stmt) { current_flow_block = if_node->merge.target->As(); } - if (!EmitStatement(stmt->body)) { - return false; - } - + EmitStatement(stmt->body); BranchToIfNeeded(loop_node->continuing.target); if (stmt->continuing) { current_flow_block = loop_node->continuing.target->As(); - if (!EmitStatement(stmt->continuing)) { - return false; - } + EmitStatement(stmt->continuing); } } // The while loop always has a path to the merge target as the break statement comes before // anything inside the loop. current_flow_block = loop_node->merge.target->As(); - return true; } -bool BuilderImpl::EmitSwitch(const ast::SwitchStatement* stmt) { +void BuilderImpl::EmitSwitch(const ast::SwitchStatement* stmt) { auto* switch_node = builder.CreateSwitch(); // Emit the condition into the preceding block auto reg = EmitExpression(stmt->condition); if (!reg) { - return false; + return; } switch_node->condition = reg.Get(); @@ -502,9 +470,7 @@ bool BuilderImpl::EmitSwitch(const ast::SwitchStatement* stmt) { } current_flow_block = builder.CreateCase(switch_node, selectors); - if (!EmitStatement(c->Body()->Declaration())) { - return false; - } + EmitStatement(c->Body()->Declaration()); BranchToIfNeeded(switch_node->merge.target); } } @@ -513,25 +479,22 @@ bool BuilderImpl::EmitSwitch(const ast::SwitchStatement* stmt) { if (IsConnected(switch_node->merge.target)) { current_flow_block = switch_node->merge.target->As(); } - - return true; } -bool BuilderImpl::EmitReturn(const ast::ReturnStatement* stmt) { +void BuilderImpl::EmitReturn(const ast::ReturnStatement* stmt) { utils::Vector ret_value; if (stmt->value) { auto ret = EmitExpression(stmt->value); if (!ret) { - return false; + return; } ret_value.Push(ret.Get()); } BranchTo(current_function_->end_target, std::move(ret_value)); - return true; } -bool BuilderImpl::EmitBreak(const ast::BreakStatement*) { +void BuilderImpl::EmitBreak(const ast::BreakStatement*) { auto* current_control = FindEnclosingControl(ControlFlags::kNone); TINT_ASSERT(IR, current_control); @@ -541,13 +504,10 @@ bool BuilderImpl::EmitBreak(const ast::BreakStatement*) { BranchTo(s->merge.target); } else { TINT_UNREACHABLE(IR, diagnostics_); - return false; } - - return true; } -bool BuilderImpl::EmitContinue(const ast::ContinueStatement*) { +void BuilderImpl::EmitContinue(const ast::ContinueStatement*) { auto* current_control = FindEnclosingControl(ControlFlags::kExcludeSwitch); TINT_ASSERT(IR, current_control); @@ -556,27 +516,24 @@ bool BuilderImpl::EmitContinue(const ast::ContinueStatement*) { } else { TINT_UNREACHABLE(IR, diagnostics_); } - - return true; } // Discard is being treated as an instruction. The semantics in WGSL is demote_to_helper, so the // code has to continue as before it just predicates writes. If WGSL grows some kind of terminating // discard that would probably make sense as a FlowNode but would then require figuring out the // multi-level exit that is triggered. -bool BuilderImpl::EmitDiscard(const ast::DiscardStatement*) { +void BuilderImpl::EmitDiscard(const ast::DiscardStatement*) { auto* instr = builder.Discard(); current_flow_block->instructions.Push(instr); - return true; } -bool BuilderImpl::EmitBreakIf(const ast::BreakIfStatement* stmt) { +void BuilderImpl::EmitBreakIf(const ast::BreakIfStatement* stmt) { auto* if_node = builder.CreateIf(); // Emit the break-if condition into the end of the preceding block auto reg = EmitExpression(stmt->condition); if (!reg) { - return false; + return; } if_node->condition = reg.Get(); @@ -601,8 +558,6 @@ bool BuilderImpl::EmitBreakIf(const ast::BreakIfStatement* stmt) { // The `break-if` has to be the last item in the continuing block. The false branch of the // `break-if` will always take us back to the start of the loop. BranchTo(loop->start.target); - - return true; } utils::Result BuilderImpl::EmitExpression(const ast::Expression* expr) { @@ -630,14 +585,11 @@ utils::Result BuilderImpl::EmitExpression(const ast::Expression* expr) { [&](Default) { add_error(expr->source, "unknown expression type: " + std::string(expr->TypeInfo().name)); - // TODO(dsinclair): This should return utils::Failure; Switch back - // once all the above cases are handled. - auto* v = builder.ir.types.Get(); - return builder.Runtime(v); + return utils::Failure; }); } -bool BuilderImpl::EmitVariable(const ast::Variable* var) { +void BuilderImpl::EmitVariable(const ast::Variable* var) { return tint::Switch( // var, // [&](const ast::Var* var) { @@ -650,17 +602,12 @@ bool BuilderImpl::EmitVariable(const ast::Variable* var) { add_error(var->source, "found an `Override` variable. The SubstituteOverrides " "transform must be run before converting to IR"); - return false; }, // [&](const ast::Const* c) { // TODO(dsinclair): Implement // }, [&](Default) { add_error(var->source, "unknown variable: " + std::string(var->TypeInfo().name)); - - // TODO(dsinclair): This should return `false`, switch back when all - // the cases are handled. - return true; }); } @@ -757,8 +704,8 @@ utils::Result BuilderImpl::EmitBitcast(const ast::BitcastExpression* exp return instr->Result(); } -utils::Result BuilderImpl::EmitCall(const ast::CallStatement* stmt) { - return EmitCall(stmt->expr); +void BuilderImpl::EmitCall(const ast::CallStatement* stmt) { + (void)EmitCall(stmt->expr); } utils::Result BuilderImpl::EmitCall(const ast::CallExpression* expr) { @@ -839,17 +786,14 @@ utils::Result BuilderImpl::EmitLiteral(const ast::LiteralExpression* lit return builder.Constant(cv); } -bool BuilderImpl::EmitAttributes(utils::VectorRef attrs) { +void BuilderImpl::EmitAttributes(utils::VectorRef attrs) { for (auto* attr : attrs) { - if (!EmitAttribute(attr)) { - return false; - } + EmitAttribute(attr); } - return true; } -bool BuilderImpl::EmitAttribute(const ast::Attribute* attr) { - return tint::Switch( // +void BuilderImpl::EmitAttribute(const ast::Attribute* attr) { + tint::Switch( // attr, // [&](const ast::WorkgroupAttribute* wg) { // TODO(dsinclair): Implement @@ -882,17 +826,14 @@ bool BuilderImpl::EmitAttribute(const ast::Attribute* attr) { add_error(attr->source, "found an `Id` attribute. The SubstituteOverrides transform " "must be run before converting to IR"); - return false; }, [&](const ast::StructMemberSizeAttribute*) { TINT_ICE(IR, diagnostics_) << "StructMemberSizeAttribute encountered during IR conversion"; - return false; }, [&](const ast::StructMemberAlignAttribute*) { TINT_ICE(IR, diagnostics_) << "StructMemberAlignAttribute encountered during IR conversion"; - return false; }, // [&](const ast::StrideAttribute* s) { // TODO(dsinclair): Implement @@ -902,7 +843,6 @@ bool BuilderImpl::EmitAttribute(const ast::Attribute* attr) { // }, [&](Default) { add_error(attr->source, "unknown attribute: " + std::string(attr->TypeInfo().name)); - return false; }); } diff --git a/src/tint/ir/builder_impl.h b/src/tint/ir/builder_impl.h index eff6040dac..3a1dbbd407 100644 --- a/src/tint/ir/builder_impl.h +++ b/src/tint/ir/builder_impl.h @@ -83,77 +83,63 @@ class BuilderImpl { /// @returns true on success, false otherwise utils::Result Build(); - /// @returns the error - std::string error() const { return diagnostics_.str(); } + /// @returns the diagnostics + diag::List Diagnostics() const { return diagnostics_; } /// Emits a function to the IR. /// @param func the function to emit - /// @returns true if successful, false otherwise - bool EmitFunction(const ast::Function* func); + void EmitFunction(const ast::Function* func); /// Emits a set of statements to the IR. /// @param stmts the statements to emit - /// @returns true if successful, false otherwise. - bool EmitStatements(utils::VectorRef stmts); + void EmitStatements(utils::VectorRef stmts); /// Emits a statement to the IR /// @param stmt the statment to emit - /// @returns true on success, false otherwise. - bool EmitStatement(const ast::Statement* stmt); + void EmitStatement(const ast::Statement* stmt); /// Emits a block statement to the IR. /// @param block the block to emit - /// @returns true if successful, false otherwise. - bool EmitBlock(const ast::BlockStatement* block); + void EmitBlock(const ast::BlockStatement* block); /// Emits an if control node to the IR. /// @param stmt the if statement - /// @returns true if successful, false otherwise. - bool EmitIf(const ast::IfStatement* stmt); + void EmitIf(const ast::IfStatement* stmt); /// Emits a return node to the IR. /// @param stmt the return AST statement - /// @returns true if successful, false otherwise. - bool EmitReturn(const ast::ReturnStatement* stmt); + void EmitReturn(const ast::ReturnStatement* stmt); /// Emits a loop control node to the IR. /// @param stmt the loop statement - /// @returns true if successful, false otherwise. - bool EmitLoop(const ast::LoopStatement* stmt); + void EmitLoop(const ast::LoopStatement* stmt); /// Emits a loop control node to the IR. /// @param stmt the while statement - /// @returns true if successful, false otherwise. - bool EmitWhile(const ast::WhileStatement* stmt); + void EmitWhile(const ast::WhileStatement* stmt); /// Emits a loop control node to the IR. /// @param stmt the for loop statement - /// @returns true if successful, false otherwise. - bool EmitForLoop(const ast::ForLoopStatement* stmt); + void EmitForLoop(const ast::ForLoopStatement* stmt); /// Emits a switch statement /// @param stmt the switch statement - /// @returns true if successful, false otherwise. - bool EmitSwitch(const ast::SwitchStatement* stmt); + void EmitSwitch(const ast::SwitchStatement* stmt); /// Emits a break statement /// @param stmt the break statement - /// @returns true if successful, false otherwise. - bool EmitBreak(const ast::BreakStatement* stmt); + void EmitBreak(const ast::BreakStatement* stmt); /// Emits a continue statement /// @param stmt the continue statement - /// @returns true if successful, false otherwise. - bool EmitContinue(const ast::ContinueStatement* stmt); + void EmitContinue(const ast::ContinueStatement* stmt); /// Emits a discard statement - /// @returns true if successful, false otherwise. - bool EmitDiscard(const ast::DiscardStatement*); + void EmitDiscard(const ast::DiscardStatement*); /// Emits a break-if statement /// @param stmt the break-if statement - /// @returns true if successful, false otherwise. - bool EmitBreakIf(const ast::BreakIfStatement* stmt); + void EmitBreakIf(const ast::BreakIfStatement* stmt); /// Emits an expression /// @param expr the expression to emit @@ -162,8 +148,7 @@ class BuilderImpl { /// Emits a variable /// @param var the variable to emit - /// @returns true if successful, false otherwise - bool EmitVariable(const ast::Variable* var); + void EmitVariable(const ast::Variable* var); /// Emits a binary expression /// @param expr the binary expression @@ -177,8 +162,7 @@ class BuilderImpl { /// Emits a call expression /// @param stmt the call statement - /// @returns the value storing the result if successful, utils::Failure otherwise - utils::Result EmitCall(const ast::CallStatement* stmt); + void EmitCall(const ast::CallStatement* stmt); /// Emits a call expression /// @param expr the call expression @@ -192,13 +176,11 @@ class BuilderImpl { /// Emits a set of attributes /// @param attrs the attributes to emit - /// @returns true if successful, false otherwise - bool EmitAttributes(utils::VectorRef attrs); + void EmitAttributes(utils::VectorRef attrs); /// Emits an attribute /// @param attr the attribute to emit - /// @returns true if successful, false otherwise - bool EmitAttribute(const ast::Attribute* attr); + void EmitAttribute(const ast::Attribute* attr); /// Retrieve the IR Flow node for a given AST node. /// @param n the node to lookup diff --git a/src/tint/ir/builder_impl_test.cc b/src/tint/ir/builder_impl_test.cc index 220a6a741e..cd6bf0bfea 100644 --- a/src/tint/ir/builder_impl_test.cc +++ b/src/tint/ir/builder_impl_test.cc @@ -14,6 +14,7 @@ #include "src/tint/ir/test_helper.h" +#include "gmock/gmock.h" #include "src/tint/ast/case_selector.h" #include "src/tint/ast/int_literal_expression.h" #include "src/tint/constant/scalar.h" @@ -1472,7 +1473,7 @@ TEST_F(IR_BuilderImplTest, EmitLiteral_Bool_True) { auto& b = CreateBuilder(); auto r = b.EmitLiteral(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); ASSERT_TRUE(r.Get()->Is()); auto* val = r.Get()->As()->value; @@ -1486,7 +1487,7 @@ TEST_F(IR_BuilderImplTest, EmitLiteral_Bool_False) { auto& b = CreateBuilder(); auto r = b.EmitLiteral(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); ASSERT_TRUE(r.Get()->Is()); auto* val = r.Get()->As()->value; @@ -1500,7 +1501,7 @@ TEST_F(IR_BuilderImplTest, EmitLiteral_F32) { auto& b = CreateBuilder(); auto r = b.EmitLiteral(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); ASSERT_TRUE(r.Get()->Is()); auto* val = r.Get()->As()->value; @@ -1515,7 +1516,7 @@ TEST_F(IR_BuilderImplTest, EmitLiteral_F16) { auto& b = CreateBuilder(); auto r = b.EmitLiteral(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); ASSERT_TRUE(r.Get()->Is()); auto* val = r.Get()->As()->value; @@ -1529,7 +1530,7 @@ TEST_F(IR_BuilderImplTest, EmitLiteral_I32) { auto& b = CreateBuilder(); auto r = b.EmitLiteral(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); ASSERT_TRUE(r.Get()->Is()); auto* val = r.Get()->As()->value; @@ -1543,7 +1544,7 @@ TEST_F(IR_BuilderImplTest, EmitLiteral_U32) { auto& b = CreateBuilder(); auto r = b.EmitLiteral(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); ASSERT_TRUE(r.Get()->Is()); auto* val = r.Get()->As()->value; @@ -1558,7 +1559,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Add) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1573,7 +1575,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Subtract) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1588,7 +1591,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Multiply) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1603,7 +1607,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Div) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1618,7 +1623,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Modulo) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1633,7 +1639,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_And) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1648,7 +1655,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Or) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1663,7 +1671,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Xor) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1678,7 +1687,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LogicalAnd) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1693,7 +1703,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LogicalOr) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1708,7 +1719,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Equal) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1723,7 +1735,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_NotEqual) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1738,7 +1751,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LessThan) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1753,7 +1767,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_GreaterThan) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1768,7 +1783,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_LessThanEqual) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1783,7 +1799,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_GreaterThanEqual) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1798,7 +1815,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_ShiftLeft) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1813,7 +1831,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_ShiftRight) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1829,7 +1848,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Binary_Compound) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1850,7 +1870,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Bitcast) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1867,8 +1888,8 @@ TEST_F(IR_BuilderImplTest, EmitStatement_Discard) { auto& b = CreateBuilder(); InjectFlowBlock(); - auto r = b.EmitStatement(expr); - ASSERT_TRUE(r) << b.error(); + b.EmitStatement(expr); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1884,8 +1905,8 @@ TEST_F(IR_BuilderImplTest, EmitStatement_UserFunction) { auto& b = CreateBuilder(); InjectFlowBlock(); - auto r = b.EmitStatement(stmt); - ASSERT_TRUE(r) << b.error(); + b.EmitStatement(stmt); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1904,7 +1925,8 @@ TEST_F(IR_BuilderImplTest, DISABLED_EmitExpression_ConstructEmpty) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1912,7 +1934,8 @@ TEST_F(IR_BuilderImplTest, DISABLED_EmitExpression_ConstructEmpty) { )"); } -TEST_F(IR_BuilderImplTest, EmitExpression_Construct) { +// Requires identifier expressions +TEST_F(IR_BuilderImplTest, DISABLED_EmitExpression_Construct) { auto i = GlobalVar("i", builtin::AddressSpace::kPrivate, Expr(1_f)); auto* expr = vec3(ty.f32(), 2_f, 3_f, i); WrapInFunction(expr); @@ -1920,7 +1943,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Construct) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1928,7 +1952,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Construct) { )"); } -TEST_F(IR_BuilderImplTest, EmitExpression_Convert) { +// Requires identifier expressions +TEST_F(IR_BuilderImplTest, DISABLED_EmitExpression_Convert) { auto i = GlobalVar("i", builtin::AddressSpace::kPrivate, Expr(1_i)); auto* expr = Call(ty.f32(), i); WrapInFunction(expr); @@ -1936,7 +1961,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Convert) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); @@ -1961,7 +1987,8 @@ FunctionEnd )"); } -TEST_F(IR_BuilderImplTest, EmitExpression_Builtin) { +// Requires identifier expressions +TEST_F(IR_BuilderImplTest, DISABLED_EmitExpression_Builtin) { auto i = GlobalVar("i", builtin::AddressSpace::kPrivate, Expr(1_f)); auto* expr = Call("asin", i); WrapInFunction(expr); @@ -1969,7 +1996,8 @@ TEST_F(IR_BuilderImplTest, EmitExpression_Builtin) { auto& b = CreateBuilder(); InjectFlowBlock(); auto r = b.EmitExpression(expr); - ASSERT_TRUE(r) << b.error(); + ASSERT_THAT(b.Diagnostics(), testing::IsEmpty()); + ASSERT_TRUE(r); Disassembler d(b.builder.ir); d.EmitBlockInstructions(b.current_flow_block->As()); diff --git a/src/tint/ir/module.cc b/src/tint/ir/module.cc index bf05e082db..e434888653 100644 --- a/src/tint/ir/module.cc +++ b/src/tint/ir/module.cc @@ -28,7 +28,7 @@ Module::Result Module::FromProgram(const Program* program) { BuilderImpl b(program); auto r = b.Build(); if (!r) { - return b.error(); + return b.Diagnostics().str(); } return Result{r.Move()}; diff --git a/src/tint/ir/test_helper.h b/src/tint/ir/test_helper.h index 6e36ed3390..47f88212fc 100644 --- a/src/tint/ir/test_helper.h +++ b/src/tint/ir/test_helper.h @@ -79,7 +79,7 @@ class TestHelperBase : public BASE, public ProgramBuilder { auto m = b.Build(); // Store the error away in case we need it - error_ = b.error(); + error_ = b.Diagnostics().str(); // Explicitly remove program to guard against pointers back to ast. Note, this does mean the // BuilderImpl is pointing to an invalid program. We keep the BuilderImpl around because we