diff --git a/src/reader/spirv/construct.cc b/src/reader/spirv/construct.cc index ded3d71be4..2b5c7fce0d 100644 --- a/src/reader/spirv/construct.cc +++ b/src/reader/spirv/construct.cc @@ -24,7 +24,8 @@ Construct::Construct(const Construct* the_parent, uint32_t the_begin_id, uint32_t the_end_id, uint32_t the_begin_pos, - uint32_t the_end_pos) + uint32_t the_end_pos, + uint32_t the_scope_end_pos) : parent(the_parent), enclosing_loop( // Compute the enclosing loop construct. Doing this in the @@ -61,7 +62,8 @@ Construct::Construct(const Construct* the_parent, begin_id(the_begin_id), end_id(the_end_id), begin_pos(the_begin_pos), - end_pos(the_end_pos) {} + end_pos(the_end_pos), + scope_end_pos(the_scope_end_pos) {} } // namespace spirv } // namespace reader diff --git a/src/reader/spirv/construct.h b/src/reader/spirv/construct.h index 5e6f75469c..151951ad1c 100644 --- a/src/reader/spirv/construct.h +++ b/src/reader/spirv/construct.h @@ -92,19 +92,31 @@ struct Construct { /// @param the_end_id block id of the first block after the construct, or 0 /// @param the_begin_pos block order position of the_begin_id /// @param the_end_pos block order position of the_end_id or a too-large value + /// @param the_scope_end_pos block position of the first block past the end of + /// the WGSL scope Construct(const Construct* the_parent, int the_depth, Kind the_kind, uint32_t the_begin_id, uint32_t the_end_id, uint32_t the_begin_pos, - uint32_t the_end_pos); + uint32_t the_end_pos, + uint32_t the_scope_end_pos); /// @param pos a block position /// @returns true if the given block position is inside this construct. bool ContainsPos(uint32_t pos) const { return begin_pos <= pos && pos < end_pos; } + /// Returns true if the given block position is inside the WGSL scope + /// corresponding to this construct. A loop construct's WGSL scope encloses + /// the associated continue construct. Otherwise the WGSL scope extent is the + /// same as the block extent. + /// @param pos a block position + /// @returns true if the given block position is inside the WGSL scope. + bool ScopeContainsPos(uint32_t pos) const { + return begin_pos <= pos && pos < scope_end_pos; + } /// The nearest enclosing construct other than itself, or nullptr if /// this construct represents the entire function. @@ -136,6 +148,9 @@ struct Construct { /// The position of block |end_id| in the block order, or the number of /// block order elements if |end_id| is 0. const uint32_t end_pos = 0; + /// The position of the first block after the WGSL scope corresponding to + /// this construct. + const uint32_t scope_end_pos = 0; }; using ConstructList = std::vector>; @@ -183,6 +198,10 @@ inline std::ostream& operator<<(std::ostream& o, const Construct& c) { o << " parent:" << ToStringBrief(c.parent); + if (c.scope_end_pos != c.end_pos) { + o << " scope:[" << c.begin_pos << "," << c.scope_end_pos << ")"; + } + if (c.enclosing_loop) { o << " in-l:" << ToStringBrief(c.enclosing_loop); } diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc index df4dc526a1..b5bcb9d92a 100644 --- a/src/reader/spirv/function.cc +++ b/src/reader/spirv/function.cc @@ -903,16 +903,18 @@ bool FunctionEmitter::LabelControlFlowConstructs() { const auto end_pos = end_id == 0 ? uint32_t(block_order_.size()) : GetBlockInfo(end_id)->pos; const auto* parent = enclosing.empty() ? nullptr : enclosing.back(); + auto scope_end_pos = end_pos; // A loop construct is added right after its associated continue construct. // In that case, adjust the parent up. if (k == Construct::kLoop) { assert(parent); assert(parent->kind == Construct::kContinue); + scope_end_pos = parent->end_pos; parent = parent->parent; } - constructs_.push_back( - std::make_unique(parent, static_cast(depth), k, - begin_id, end_id, begin_pos, end_pos)); + constructs_.push_back(std::make_unique( + parent, static_cast(depth), k, begin_id, end_id, begin_pos, + end_pos, scope_end_pos)); Construct* result = constructs_.back().get(); enclosing.push_back(result); return result; @@ -3137,7 +3139,8 @@ const Construct* FunctionEmitter::GetEnclosingScope(uint32_t first_pos, GetBlockInfo(block_order_[first_pos])->construct; assert(enclosing_construct != nullptr); // Constructs are strictly nesting, so follow parent pointers - while (enclosing_construct && !enclosing_construct->ContainsPos(last_pos)) { + while (enclosing_construct && + !enclosing_construct->ScopeContainsPos(last_pos)) { // The scope of a continue construct is enclosed in its associated loop // construct, but they are siblings in our construct tree. const auto* sibling_loop = SiblingLoopConstruct(enclosing_construct); diff --git a/src/reader/spirv/function_cfg_test.cc b/src/reader/spirv/function_cfg_test.cc index 188b3b92a7..7e38f97778 100644 --- a/src/reader/spirv/function_cfg_test.cc +++ b/src/reader/spirv/function_cfg_test.cc @@ -3100,7 +3100,7 @@ TEST_F(SpvParserTest, EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{ Construct{ Function [0,6) begin_id:10 end_id:0 depth:0 parent:null } Construct{ Continue [3,5) begin_id:40 end_id:99 depth:1 parent:Function@10 in-c:Continue@40 } - Construct{ Loop [1,3) begin_id:20 end_id:40 depth:1 parent:Function@10 in-l:Loop@20 } + Construct{ Loop [1,3) begin_id:20 end_id:40 depth:1 parent:Function@10 scope:[1,5) in-l:Loop@20 } })")) << constructs; // The block records the nearest enclosing construct. EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[0].get()); @@ -3244,7 +3244,7 @@ TEST_F(SpvParserTest, Construct{ Function [0,5) begin_id:10 end_id:0 depth:0 parent:null } Construct{ IfSelection [0,2) begin_id:10 end_id:50 depth:1 parent:Function@10 } Construct{ Continue [3,4) begin_id:60 end_id:99 depth:1 parent:Function@10 in-c:Continue@60 } - Construct{ Loop [2,3) begin_id:50 end_id:60 depth:1 parent:Function@10 in-l:Loop@50 } + Construct{ Loop [2,3) begin_id:50 end_id:60 depth:1 parent:Function@10 scope:[2,4) in-l:Loop@50 } })")) << constructs; // The block records the nearest enclosing construct. EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get()); @@ -3466,7 +3466,7 @@ TEST_F(SpvParserTest, LabelControlFlowConstructs_Nest_Loop_Loop) { EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{ Construct{ Function [0,8) begin_id:10 end_id:0 depth:0 parent:null } Construct{ Continue [4,6) begin_id:50 end_id:89 depth:1 parent:Function@10 in-c:Continue@50 } - Construct{ Loop [1,4) begin_id:20 end_id:50 depth:1 parent:Function@10 in-l:Loop@20 } + Construct{ Loop [1,4) begin_id:20 end_id:50 depth:1 parent:Function@10 scope:[1,6) in-l:Loop@20 } Construct{ Continue [2,3) begin_id:30 end_id:40 depth:2 parent:Loop@20 in-l:Loop@20 in-c:Continue@30 } })")) << constructs; // The block records the nearest enclosing construct. @@ -3521,7 +3521,7 @@ TEST_F(SpvParserTest, LabelControlFlowConstructs_Nest_Loop_If) { EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{ Construct{ Function [0,7) begin_id:10 end_id:0 depth:0 parent:null } Construct{ Continue [5,6) begin_id:80 end_id:99 depth:1 parent:Function@10 in-c:Continue@80 } - Construct{ Loop [1,5) begin_id:20 end_id:80 depth:1 parent:Function@10 in-l:Loop@20 } + Construct{ Loop [1,5) begin_id:20 end_id:80 depth:1 parent:Function@10 scope:[1,6) in-l:Loop@20 } Construct{ IfSelection [2,4) begin_id:30 end_id:49 depth:2 parent:Loop@20 in-l:Loop@20 } })")) << constructs; // The block records the nearest enclosing construct. @@ -3572,7 +3572,7 @@ TEST_F(SpvParserTest, LabelControlFlowConstructs_Nest_LoopContinue_If) { EXPECT_THAT(ToString(constructs), Eq(R"(ConstructList{ Construct{ Function [0,6) begin_id:10 end_id:0 depth:0 parent:null } Construct{ Continue [2,5) begin_id:30 end_id:99 depth:1 parent:Function@10 in-c:Continue@30 } - Construct{ Loop [1,2) begin_id:20 end_id:30 depth:1 parent:Function@10 in-l:Loop@20 } + Construct{ Loop [1,2) begin_id:20 end_id:30 depth:1 parent:Function@10 scope:[1,5) in-l:Loop@20 } Construct{ IfSelection [2,4) begin_id:30 end_id:49 depth:2 parent:Continue@30 in-c:Continue@30 } })")) << constructs; // The block records the nearest enclosing construct. @@ -3666,7 +3666,7 @@ TEST_F(SpvParserTest, LabelControlFlowConstructs_Nest_If_MultiBlockLoop) { Construct{ Function [0,7) begin_id:10 end_id:0 depth:0 parent:null } Construct{ IfSelection [0,6) begin_id:10 end_id:99 depth:1 parent:Function@10 } Construct{ Continue [3,5) begin_id:40 end_id:89 depth:2 parent:IfSelection@10 in-c:Continue@40 } - Construct{ Loop [1,3) begin_id:20 end_id:40 depth:2 parent:IfSelection@10 in-l:Loop@20 } + Construct{ Loop [1,3) begin_id:20 end_id:40 depth:2 parent:IfSelection@10 scope:[1,5) in-l:Loop@20 } })")) << constructs; // The block records the nearest enclosing construct. EXPECT_EQ(fe.GetBlockInfo(10)->construct, constructs[1].get()); @@ -13538,7 +13538,7 @@ TEST_F(SpvParserTest, SiblingLoopConstruct_HasSiblingLoop) { EXPECT_EQ(c->kind, Construct::kContinue); EXPECT_THAT(ToString(fe.SiblingLoopConstruct(c)), Eq("Construct{ Loop [1,2) begin_id:20 end_id:30 depth:1 " - "parent:Function@10 in-l:Loop@20 }")); + "parent:Function@10 scope:[1,3) in-l:Loop@20 }")); } } // namespace diff --git a/src/reader/spirv/function_var_test.cc b/src/reader/spirv/function_var_test.cc index c5911758e0..c160a2345a 100644 --- a/src/reader/spirv/function_var_test.cc +++ b/src/reader/spirv/function_var_test.cc @@ -1123,13 +1123,6 @@ TEST_F(SpvParserTest, EmitStatement_Phi_MultiBlockLoopIndex) { EXPECT_TRUE(fe.EmitBody()) << p->error(); EXPECT_THAT(ToString(fe.ast_body()), Eq(R"(Loop{ - VariableDeclStatement{ - Variable{ - x_2 - function - __u32 - } - } VariableDeclStatement{ Variable{ x_2_phi @@ -1181,9 +1174,15 @@ TEST_F(SpvParserTest, EmitStatement_Phi_MultiBlockLoopIndex) { } } Loop{ - Assignment{ - Identifier{x_2} - Identifier{x_2_phi} + VariableDeclStatement{ + Variable{ + x_2 + none + __u32 + { + Identifier{x_2_phi} + } + } } VariableDeclStatement{ Variable{ @@ -1289,20 +1288,6 @@ TEST_F(SpvParserTest, EmitStatement_Phi_ValueFromLoopBodyAndContinuing) { } } Loop{ - VariableDeclStatement{ - Variable{ - x_4 - function - __u32 - } - } - VariableDeclStatement{ - Variable{ - x_6 - function - __u32 - } - } VariableDeclStatement{ Variable{ x_2_phi @@ -1346,20 +1331,32 @@ Loop{ } } } - Assignment{ - Identifier{x_4} - Binary{ - Identifier{x_2} - add - ScalarConstructor{1} + VariableDeclStatement{ + Variable{ + x_4 + none + __u32 + { + Binary{ + Identifier{x_2} + add + ScalarConstructor{1} + } + } } } - Assignment{ - Identifier{x_6} - Binary{ - Identifier{x_4} - add - ScalarConstructor{1} + VariableDeclStatement{ + Variable{ + x_6 + none + __u32 + { + Binary{ + Identifier{x_4} + add + ScalarConstructor{1} + } + } } } If{