Skip to content

Commit

Permalink
Keep block info in instruction argument
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed Sep 10, 2019
1 parent 10872e0 commit 2374b96
Show file tree
Hide file tree
Showing 5 changed files with 13 additions and 26 deletions.
10 changes: 4 additions & 6 deletions lib/evmone/analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,8 @@ code_analysis analyze(evmc_revision rev, const uint8_t* code, size_t code_size)
static_cast<int16_t>(block.stack_req) :
std::numeric_limits<int16_t>::max();
const auto stack_max_growth = static_cast<int16_t>(block.stack_max_growth);
analysis.blocks.emplace_back(block_info{block.gas_cost, stack_req, stack_max_growth});
analysis.instrs[block.begin_block_index].arg.number =
static_cast<int>(analysis.blocks.size() - 1);
analysis.instrs[block.begin_block_index].arg.block = {
block.gas_cost, stack_req, stack_max_growth};


// Create new block.
Expand All @@ -173,9 +172,8 @@ code_analysis analyze(evmc_revision rev, const uint8_t* code, size_t code_size)
static_cast<int16_t>(block.stack_req) :
std::numeric_limits<int16_t>::max();
const auto stack_max_growth = static_cast<int16_t>(block.stack_max_growth);
analysis.blocks.emplace_back(block_info{block.gas_cost, stack_req, stack_max_growth});
analysis.instrs[block.begin_block_index].arg.number =
static_cast<int>(analysis.blocks.size() - 1);
analysis.instrs[block.begin_block_index].arg.block = {
block.gas_cost, stack_req, stack_max_growth};

// Make sure the last block is terminated.
// TODO: This is not needed if the last instruction is a terminating one.
Expand Down
1 change: 0 additions & 1 deletion lib/evmone/analysis.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,6 @@ static_assert(sizeof(block_info) == 8);
struct code_analysis
{
std::vector<instr_info> instrs;
std::vector<block_info> blocks;

/// Storage for large push values.
std::vector<intx::uint256> push_values;
Expand Down
2 changes: 1 addition & 1 deletion lib/evmone/instructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1202,7 +1202,7 @@ const instr_info* op_selfdestruct(const instr_info*, execution_state& state) noe

const instr_info* opx_beginblock(const instr_info* instr, execution_state& state) noexcept
{
auto& block = state.analysis->blocks[static_cast<size_t>(instr->arg.number)];
auto& block = instr->arg.block;

if ((state.gas_left -= block.gas_cost) < 0)
return state.exit(EVMC_OUT_OF_GAS);
Expand Down
24 changes: 7 additions & 17 deletions test/unittests/analysis_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ TEST(analysis, example1)
ASSERT_EQ(analysis.instrs.size(), 8);

EXPECT_EQ(analysis.instrs[0].fn, op_table[OPX_BEGINBLOCK]);
EXPECT_EQ(analysis.instrs[0].arg.number, 0);
EXPECT_EQ(analysis.instrs[1].fn, op_table[OP_PUSH1]);
EXPECT_EQ(analysis.instrs[2].fn, op_table[OP_PUSH1]);
EXPECT_EQ(analysis.instrs[3].fn, op_table[OP_MSTORE8]);
Expand All @@ -30,10 +29,9 @@ TEST(analysis, example1)
EXPECT_EQ(analysis.instrs[6].fn, op_table[OP_SSTORE]);
EXPECT_EQ(analysis.instrs[7].fn, op_table[OP_STOP]);

ASSERT_EQ(analysis.blocks.size(), 1);
EXPECT_EQ(analysis.blocks[0].gas_cost, 14);
EXPECT_EQ(analysis.blocks[0].stack_req, 0);
EXPECT_EQ(analysis.blocks[0].stack_max_growth, 2);
EXPECT_EQ(analysis.instrs[0].arg.block.gas_cost, 14);
EXPECT_EQ(analysis.instrs[0].arg.block.stack_req, 0);
EXPECT_EQ(analysis.instrs[0].arg.block.stack_max_growth, 2);
}

TEST(analysis, stack_up_and_down)
Expand All @@ -43,16 +41,15 @@ TEST(analysis, stack_up_and_down)

ASSERT_EQ(analysis.instrs.size(), 20);
EXPECT_EQ(analysis.instrs[0].fn, op_table[OPX_BEGINBLOCK]);
EXPECT_EQ(analysis.instrs[0].arg.number, 0);
EXPECT_EQ(analysis.instrs[1].fn, op_table[OP_DUP2]);
EXPECT_EQ(analysis.instrs[2].fn, op_table[OP_DUP1]);
EXPECT_EQ(analysis.instrs[8].fn, op_table[OP_POP]);
EXPECT_EQ(analysis.instrs[18].fn, op_table[OP_PUSH1]);

ASSERT_EQ(analysis.blocks.size(), 1);
EXPECT_EQ(analysis.blocks[0].gas_cost, 7 * 3 + 10 * 2 + 3);
EXPECT_EQ(analysis.blocks[0].stack_req, 3);
EXPECT_EQ(analysis.blocks[0].stack_max_growth, 7);

EXPECT_EQ(analysis.instrs[0].arg.block.gas_cost, 7 * 3 + 10 * 2 + 3);
EXPECT_EQ(analysis.instrs[0].arg.block.stack_req, 3);
EXPECT_EQ(analysis.instrs[0].arg.block.stack_max_growth, 7);
}

TEST(analysis, push)
Expand All @@ -77,7 +74,6 @@ TEST(analysis, jumpdest_skip)
const auto code = bytecode{} + OP_STOP + OP_JUMPDEST;
auto analysis = evmone::analyze(rev, &code[0], code.size());

EXPECT_EQ(analysis.blocks.size(), 2);
ASSERT_EQ(analysis.instrs.size(), 4);
EXPECT_EQ(analysis.instrs[0].fn, op_table[OPX_BEGINBLOCK]);
EXPECT_EQ(analysis.instrs[1].fn, op_table[OP_STOP]);
Expand All @@ -90,7 +86,6 @@ TEST(analysis, jump1)
const auto code = jump(add(4, 2)) + OP_JUMPDEST + mstore(0, 3) + ret(0, 0x20) + jump(6);
const auto analysis = analyze(rev, &code[0], code.size());

ASSERT_EQ(analysis.blocks.size(), 4);
ASSERT_EQ(analysis.jumpdest_offsets.size(), 1);
ASSERT_EQ(analysis.jumpdest_targets.size(), 1);
EXPECT_EQ(analysis.jumpdest_offsets[0], 6);
Expand All @@ -105,7 +100,6 @@ TEST(analysis, empty)
bytes code;
auto analysis = evmone::analyze(rev, &code[0], code.size());

EXPECT_EQ(analysis.blocks.size(), 1);
ASSERT_EQ(analysis.instrs.size(), 2);
EXPECT_EQ(analysis.instrs[0].fn, op_table[OPX_BEGINBLOCK]);
EXPECT_EQ(analysis.instrs[1].fn, op_table[OP_STOP]);
Expand All @@ -116,7 +110,6 @@ TEST(analysis, only_jumpdest)
const auto code = bytecode{OP_JUMPDEST};
auto analysis = evmone::analyze(rev, &code[0], code.size());

ASSERT_EQ(analysis.blocks.size(), 1);
ASSERT_EQ(analysis.jumpdest_offsets.size(), 1);
ASSERT_EQ(analysis.jumpdest_targets.size(), 1);
EXPECT_EQ(analysis.jumpdest_offsets[0], 0);
Expand All @@ -128,7 +121,6 @@ TEST(analysis, jumpi_at_the_end)
const auto code = bytecode{OP_JUMPI};
auto analysis = evmone::analyze(rev, &code[0], code.size());

EXPECT_EQ(analysis.blocks.size(), 2);
ASSERT_EQ(analysis.instrs.size(), 4);
EXPECT_EQ(analysis.instrs[0].fn, op_table[OPX_BEGINBLOCK]);
EXPECT_EQ(analysis.instrs[1].fn, op_table[OP_JUMPI]);
Expand All @@ -143,7 +135,6 @@ TEST(analysis, terminated_last_block)
const auto code = ret(0, 0);
auto analysis = evmone::analyze(rev, &code[0], code.size());

EXPECT_EQ(analysis.blocks.size(), 2);
ASSERT_EQ(analysis.instrs.size(), 6);
EXPECT_EQ(analysis.instrs[0].fn, op_table[OPX_BEGINBLOCK]);
EXPECT_EQ(analysis.instrs[3].fn, op_table[OP_RETURN]);
Expand All @@ -156,7 +147,6 @@ TEST(analysis, jumpdests_groups)
const auto code = 3 * OP_JUMPDEST + push(1) + 3 * OP_JUMPDEST + push(2) + OP_JUMPI;
auto analysis = evmone::analyze(rev, &code[0], code.size());

EXPECT_EQ(analysis.blocks.size(), 7);
ASSERT_EQ(analysis.instrs.size(), 11);
EXPECT_EQ(analysis.instrs[0].fn, op_table[OP_JUMPDEST]);
EXPECT_EQ(analysis.instrs[1].fn, op_table[OP_JUMPDEST]);
Expand Down
2 changes: 1 addition & 1 deletion test/utils/dump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ void dump(const evmone::code_analysis& analysis)

if (c == OPX_BEGINBLOCK)
{
block = &analysis.blocks[size_t(instr.arg.number)];
block = &instr.arg.block;

const auto get_jumpdest_offset = [&analysis](size_t index) noexcept
{
Expand Down

0 comments on commit 2374b96

Please sign in to comment.