Skip to content

Commit

Permalink
Support EOF execution in advanced
Browse files Browse the repository at this point in the history
  • Loading branch information
gumb0 committed May 31, 2021
1 parent 275d138 commit 5de5588
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 16 deletions.
8 changes: 5 additions & 3 deletions lib/evmone/analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// SPDX-License-Identifier: Apache-2.0

#include "analysis.hpp"
#include "eof.hpp"
#include "opcodes_helpers.h"
#include <cassert>

Expand Down Expand Up @@ -39,7 +40,8 @@ struct block_analysis
}
};

AdvancedCodeAnalysis analyze(evmc_revision rev, const uint8_t* code, size_t code_size) noexcept
AdvancedCodeAnalysis analyze(
evmc_revision rev, const uint8_t* code, size_t code_size, const EOF1Header& header) noexcept
{
const auto& op_tbl = get_op_table(rev);
const auto opx_beginblock_fn = op_tbl[OPX_BEGINBLOCK].fn;
Expand All @@ -57,8 +59,8 @@ AdvancedCodeAnalysis analyze(evmc_revision rev, const uint8_t* code, size_t code
analysis.instrs.emplace_back(opx_beginblock_fn);
auto block = block_analysis{0};

const auto code_end = code + code_size;
auto code_pos = code;
const auto code_end = header.code_end(code, code_size);
auto code_pos = header.code_begin(code);

while (code_pos != code_end)
{
Expand Down
3 changes: 2 additions & 1 deletion lib/evmone/analysis.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

namespace evmone
{
struct EOF1Header;
struct instruction;

/// Compressed information about instruction basic block.
Expand Down Expand Up @@ -149,7 +150,7 @@ inline int find_jumpdest(const AdvancedCodeAnalysis& analysis, int offset) noexc
}

EVMC_EXPORT AdvancedCodeAnalysis analyze(
evmc_revision rev, const uint8_t* code, size_t code_size) noexcept;
evmc_revision rev, const uint8_t* code, size_t code_size, const EOF1Header& header) noexcept;

EVMC_EXPORT const op_table& get_op_table(evmc_revision rev) noexcept;

Expand Down
6 changes: 5 additions & 1 deletion lib/evmone/execution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "execution.hpp"
#include "analysis.hpp"
#include "eof.hpp"
#include <memory>

namespace evmone
Expand All @@ -26,7 +27,10 @@ evmc_result execute(AdvancedExecutionState& state, const AdvancedCodeAnalysis& a
evmc_result execute(evmc_vm* /*unused*/, const evmc_host_interface* host, evmc_host_context* ctx,
evmc_revision rev, const evmc_message* msg, const uint8_t* code, size_t code_size) noexcept
{
const auto analysis = analyze(rev, code, code_size);
EOF1Header eof1_header;
if (is_eof_code(code, code_size))
eof1_header = read_valid_eof1_header(code);
const auto analysis = analyze(rev, code, code_size, eof1_header);
auto state = std::make_unique<AdvancedExecutionState>(*msg, rev, *host, ctx, code, code_size);
return execute(*state, analysis);
}
Expand Down
2 changes: 1 addition & 1 deletion test/bench/helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ inline void analyse(benchmark::State& state, evmc_revision rev, bytes_view code)
auto bytes_analysed = uint64_t{0};
for (auto _ : state)
{
auto r = evmone::analyze(rev, code.data(), code.size());
auto r = evmone::analyze(rev, code.data(), code.size(), {});
benchmark::DoNotOptimize(r);
bytes_analysed += code.size();
}
Expand Down
21 changes: 11 additions & 10 deletions test/unittests/analysis_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <evmc/instructions.h>
#include <evmone/analysis.hpp>
#include <evmone/eof.hpp>
#include <gtest/gtest.h>
#include <test/utils/bytecode.hpp>
#include <test/utils/utils.hpp>
Expand All @@ -16,7 +17,7 @@ const auto& op_tbl = get_op_table(rev);
TEST(analysis, example1)
{
const auto code = push(0x2a) + push(0x1e) + OP_MSTORE8 + OP_MSIZE + push(0) + OP_SSTORE;
const auto analysis = analyze(rev, &code[0], code.size());
const auto analysis = analyze(rev, &code[0], code.size(), {});

ASSERT_EQ(analysis.instrs.size(), 8);

Expand All @@ -38,7 +39,7 @@ TEST(analysis, example1)
TEST(analysis, stack_up_and_down)
{
const auto code = OP_DUP2 + 6 * OP_DUP1 + 10 * OP_POP + push(0);
const auto analysis = analyze(rev, &code[0], code.size());
const auto analysis = analyze(rev, &code[0], code.size(), {});

ASSERT_EQ(analysis.instrs.size(), 20);
EXPECT_EQ(analysis.instrs[0].fn, op_tbl[OPX_BEGINBLOCK].fn);
Expand All @@ -57,7 +58,7 @@ TEST(analysis, push)
{
constexpr auto push_value = 0x8807060504030201;
const auto code = push(push_value) + "7f00ee";
const auto analysis = analyze(rev, &code[0], code.size());
const auto analysis = analyze(rev, &code[0], code.size(), {});

ASSERT_EQ(analysis.instrs.size(), 4);
ASSERT_EQ(analysis.push_values.size(), 1);
Expand All @@ -73,7 +74,7 @@ TEST(analysis, jumpdest_skip)
// and no new block should be created in this place.

const auto code = bytecode{} + OP_STOP + OP_JUMPDEST;
auto analysis = evmone::analyze(rev, &code[0], code.size());
auto analysis = evmone::analyze(rev, &code[0], code.size(), {});

ASSERT_EQ(analysis.instrs.size(), 4);
EXPECT_EQ(analysis.instrs[0].fn, op_tbl[OPX_BEGINBLOCK].fn);
Expand All @@ -85,7 +86,7 @@ TEST(analysis, jumpdest_skip)
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());
const auto analysis = analyze(rev, &code[0], code.size(), {});

ASSERT_EQ(analysis.jumpdest_offsets.size(), 1);
ASSERT_EQ(analysis.jumpdest_targets.size(), 1);
Expand All @@ -99,7 +100,7 @@ TEST(analysis, jump1)
TEST(analysis, empty)
{
bytes code;
auto analysis = evmone::analyze(rev, &code[0], code.size());
auto analysis = evmone::analyze(rev, &code[0], code.size(), {});

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

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

ASSERT_EQ(analysis.instrs.size(), 4);
EXPECT_EQ(analysis.instrs[0].fn, op_tbl[OPX_BEGINBLOCK].fn);
Expand All @@ -134,7 +135,7 @@ TEST(analysis, terminated_last_block)
// TODO: Even if the last basic block is properly terminated an additional artificial block
// is going to be created with only STOP instruction.
const auto code = ret(0, 0);
auto analysis = evmone::analyze(rev, &code[0], code.size());
auto analysis = evmone::analyze(rev, &code[0], code.size(), {});

ASSERT_EQ(analysis.instrs.size(), 6);
EXPECT_EQ(analysis.instrs[0].fn, op_tbl[OPX_BEGINBLOCK].fn);
Expand All @@ -146,7 +147,7 @@ TEST(analysis, terminated_last_block)
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());
auto analysis = evmone::analyze(rev, &code[0], code.size(), {});

ASSERT_EQ(analysis.instrs.size(), 11);
EXPECT_EQ(analysis.instrs[0].fn, op_tbl[OP_JUMPDEST].fn);
Expand Down

0 comments on commit 5de5588

Please sign in to comment.