@@ -78,12 +78,28 @@ TEST(analysis, push)
7878 EXPECT_EQ (analysis.push_values [0 ], intx::uint256{0xee } << 240 );
7979}
8080
81+ TEST (analysis, jumpdest_skip)
82+ {
83+ // If the JUMPDEST is the first instruction in a basic block it should be just omitted
84+ // and no new block should be created in this place.
85+
86+ const auto code = bytecode{} + OP_STOP + OP_JUMPDEST;
87+ auto analysis = evmone::analyze (fake_fn_table, rev, &code[0 ], code.size ());
88+
89+ EXPECT_EQ (analysis.blocks .size (), 2 );
90+ ASSERT_EQ (analysis.instrs .size (), 4 );
91+ EXPECT_EQ (analysis.instrs [0 ].fn , fake_fn_table[OPX_BEGINBLOCK]);
92+ EXPECT_EQ (analysis.instrs [1 ].fn , fake_fn_table[OP_STOP]);
93+ EXPECT_EQ (analysis.instrs [2 ].fn , fake_fn_table[OP_JUMPDEST]);
94+ EXPECT_EQ (analysis.instrs [3 ].fn , fake_fn_table[OP_STOP]);
95+ }
96+
8197TEST (analysis, jump1)
8298{
8399 const auto code = jump (add (4 , 2 )) + OP_JUMPDEST + mstore (0 , 3 ) + ret (0 , 0x20 ) + jump (6 );
84100 const auto analysis = analyze (fake_fn_table, rev, &code[0 ], code.size ());
85101
86- ASSERT_EQ (analysis.blocks .size (), 3 );
102+ ASSERT_EQ (analysis.blocks .size (), 4 );
87103 ASSERT_EQ (analysis.jumpdest_offsets .size (), 1 );
88104 ASSERT_EQ (analysis.jumpdest_targets .size (), 1 );
89105 EXPECT_EQ (analysis.jumpdest_offsets [0 ], 6 );
@@ -98,14 +114,15 @@ TEST(analysis, empty)
98114 bytes code;
99115 auto analysis = evmone::analyze (fake_fn_table, rev, &code[0 ], code.size ());
100116
101- EXPECT_EQ (analysis.blocks .size (), 0 );
102- EXPECT_EQ (analysis.instrs .size (), 1 );
103- EXPECT_EQ (analysis.instrs .back ().fn , fake_fn_table[OP_STOP]);
117+ EXPECT_EQ (analysis.blocks .size (), 1 );
118+ EXPECT_EQ (analysis.instrs .size (), 2 );
119+ EXPECT_EQ (analysis.instrs [0 ].fn , fake_fn_table[OPX_BEGINBLOCK]);
120+ EXPECT_EQ (analysis.instrs [1 ].fn , fake_fn_table[OP_STOP]);
104121}
105122
106123TEST (analysis, only_jumpdest)
107124{
108- auto code = from_hex ( " 5b " ) ;
125+ const auto code = bytecode{OP_JUMPDEST} ;
109126 auto analysis = evmone::analyze (fake_fn_table, rev, &code[0 ], code.size ());
110127
111128 ASSERT_EQ (analysis.blocks .size (), 1 );
@@ -117,9 +134,63 @@ TEST(analysis, only_jumpdest)
117134
118135TEST (analysis, jumpi_at_the_end)
119136{
120- auto code = from_hex ( " 57 " ) ;
137+ const auto code = bytecode{OP_JUMPI} ;
121138 auto analysis = evmone::analyze (fake_fn_table, rev, &code[0 ], code.size ());
122139
123- EXPECT_EQ (analysis.blocks .size (), 1 );
124- EXPECT_EQ (analysis.instrs .back ().fn , fake_fn_table[OP_STOP]);
140+ EXPECT_EQ (analysis.blocks .size (), 2 );
141+ EXPECT_EQ (analysis.instrs [0 ].fn , fake_fn_table[OPX_BEGINBLOCK]);
142+ EXPECT_EQ (analysis.instrs [1 ].fn , fake_fn_table[OP_JUMPI]);
143+ EXPECT_EQ (analysis.instrs [2 ].fn , fake_fn_table[OPX_BEGINBLOCK]);
144+ EXPECT_EQ (analysis.instrs [3 ].fn , fake_fn_table[OP_STOP]);
145+ }
146+
147+ TEST (analysis, terminated_last_block)
148+ {
149+ // TODO: Even if the last basic block is properly terminated an additional artificial block
150+ // is going to be created with only STOP instruction.
151+ const auto code = ret (0 , 0 );
152+ auto analysis = evmone::analyze (fake_fn_table, rev, &code[0 ], code.size ());
153+
154+ EXPECT_EQ (analysis.blocks .size (), 2 );
155+ ASSERT_EQ (analysis.instrs .size (), 6 );
156+ EXPECT_EQ (analysis.instrs [0 ].fn , fake_fn_table[OPX_BEGINBLOCK]);
157+ EXPECT_EQ (analysis.instrs [3 ].fn , fake_fn_table[OP_RETURN]);
158+ EXPECT_EQ (analysis.instrs [4 ].fn , fake_fn_table[OPX_BEGINBLOCK]);
159+ EXPECT_EQ (analysis.instrs [5 ].fn , fake_fn_table[OP_STOP]);
160+ }
161+
162+ TEST (analysis, jumpdests_groups)
163+ {
164+ const auto code = 3 * OP_JUMPDEST + push (1 ) + 3 * OP_JUMPDEST + push (2 ) + OP_JUMPI;
165+ auto analysis = evmone::analyze (fake_fn_table, rev, &code[0 ], code.size ());
166+
167+ EXPECT_EQ (analysis.blocks .size (), 7 );
168+ ASSERT_EQ (analysis.instrs .size (), 11 );
169+ EXPECT_EQ (analysis.instrs [0 ].fn , fake_fn_table[OP_JUMPDEST]);
170+ EXPECT_EQ (analysis.instrs [1 ].fn , fake_fn_table[OP_JUMPDEST]);
171+ EXPECT_EQ (analysis.instrs [2 ].fn , fake_fn_table[OP_JUMPDEST]);
172+ EXPECT_EQ (analysis.instrs [3 ].fn , fake_fn_table[OP_PUSH1]);
173+ EXPECT_EQ (analysis.instrs [4 ].fn , fake_fn_table[OP_JUMPDEST]);
174+ EXPECT_EQ (analysis.instrs [5 ].fn , fake_fn_table[OP_JUMPDEST]);
175+ EXPECT_EQ (analysis.instrs [6 ].fn , fake_fn_table[OP_JUMPDEST]);
176+ EXPECT_EQ (analysis.instrs [7 ].fn , fake_fn_table[OP_PUSH1]);
177+ EXPECT_EQ (analysis.instrs [8 ].fn , fake_fn_table[OP_JUMPI]);
178+ EXPECT_EQ (analysis.instrs [9 ].fn , fake_fn_table[OPX_BEGINBLOCK]);
179+ EXPECT_EQ (analysis.instrs [10 ].fn , fake_fn_table[OP_STOP]);
180+
181+
182+ ASSERT_EQ (analysis.jumpdest_offsets .size (), 6 );
183+ ASSERT_EQ (analysis.jumpdest_targets .size (), 6 );
184+ EXPECT_EQ (analysis.jumpdest_offsets [0 ], 0 );
185+ EXPECT_EQ (analysis.jumpdest_targets [0 ], 0 );
186+ EXPECT_EQ (analysis.jumpdest_offsets [1 ], 1 );
187+ EXPECT_EQ (analysis.jumpdest_targets [1 ], 1 );
188+ EXPECT_EQ (analysis.jumpdest_offsets [2 ], 2 );
189+ EXPECT_EQ (analysis.jumpdest_targets [2 ], 2 );
190+ EXPECT_EQ (analysis.jumpdest_offsets [3 ], 5 );
191+ EXPECT_EQ (analysis.jumpdest_targets [3 ], 4 );
192+ EXPECT_EQ (analysis.jumpdest_offsets [4 ], 6 );
193+ EXPECT_EQ (analysis.jumpdest_targets [4 ], 5 );
194+ EXPECT_EQ (analysis.jumpdest_offsets [5 ], 7 );
195+ EXPECT_EQ (analysis.jumpdest_targets [5 ], 6 );
125196}
0 commit comments