Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions include/eosio/vm/backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace eosio { namespace vm {
template<typename Host>
using context = jit_execution_context<Host>;
template<typename Host, typename Options>
using parser = binary_parser<machine_code_writer<jit_execution_context<Host>>, Options>;
using parser = binary_parser<machine_code_writer<jit_execution_context<Host>, detail::get_use_softfloat<Options>()>, Options>;
static constexpr bool is_jit = true;
};

Expand Down Expand Up @@ -87,7 +87,7 @@ namespace eosio { namespace vm {
else
_walloc->reset();
_ctx.reset();
_ctx.execute_start(host, interpret_visitor(_ctx));
_ctx.execute_start(host, visitor_type(_ctx));
return *this;
}

Expand All @@ -96,9 +96,9 @@ namespace eosio { namespace vm {
try {
if constexpr (eos_vm_debug) {
//_ctx.execute_func_table(host, debug_visitor(_ctx), func_index, args...);
_ctx.execute_func_table(host, interpret_visitor(_ctx), func_index, args...);
_ctx.execute_func_table(host, visitor_type(_ctx), func_index, args...);
} else {
_ctx.execute_func_table(host, interpret_visitor(_ctx), func_index, args...);
_ctx.execute_func_table(host, visitor_type(_ctx), func_index, args...);
}
return true;
} catch (...) {
Expand All @@ -112,9 +112,9 @@ namespace eosio { namespace vm {
try {
if constexpr (eos_vm_debug) {
//_ctx.execute(host, debug_visitor(_ctx), func_index, args...);
_ctx.execute(host, interpret_visitor(_ctx), func_index, args...);
_ctx.execute(host, visitor_type(_ctx), func_index, args...);
} else {
_ctx.execute(host, interpret_visitor(_ctx), func_index, args...);
_ctx.execute(host, visitor_type(_ctx), func_index, args...);
}
return true;
} catch (...) {
Expand All @@ -128,9 +128,9 @@ namespace eosio { namespace vm {
try {
if constexpr (eos_vm_debug) {
//_ctx.execute(host, debug_visitor(_ctx), func, args...);
_ctx.execute(host, interpret_visitor(_ctx), func, args...);
_ctx.execute(host, visitor_type(_ctx), func, args...);
} else {
_ctx.execute(host, interpret_visitor(_ctx), func, args...);
_ctx.execute(host, visitor_type(_ctx), func, args...);
}
return true;
} catch (...) {
Expand All @@ -145,9 +145,9 @@ namespace eosio { namespace vm {
try {
if constexpr (eos_vm_debug) {
//return _ctx.execute(host, debug_visitor(_ctx), func, args...);
return _ctx.execute(host, interpret_visitor(_ctx), func, args...);
return _ctx.execute(host, visitor_type(_ctx), func, args...);
} else {
return _ctx.execute(host, interpret_visitor(_ctx), func, args...);
return _ctx.execute(host, visitor_type(_ctx), func, args...);
}
} catch (...) {
initialize(host);
Expand Down Expand Up @@ -202,7 +202,7 @@ namespace eosio { namespace vm {
if constexpr (eos_vm_debug) {
print_result(_ctx.execute(host, debug_visitor(_ctx), s));
} else {
_ctx.execute(host, interpret_visitor(_ctx), s);
_ctx.execute(host, visitor_type(_ctx), s);
}
}
}
Expand Down Expand Up @@ -236,6 +236,7 @@ namespace eosio { namespace vm {
}

private:
using visitor_type = interpret_visitor<typename Impl::template context<Host>, detail::get_use_softfloat<Options>()>;
wasm_allocator* _walloc = nullptr; // non owning pointer
module _mod;
typename Impl::template context<Host> _ctx;
Expand Down
57 changes: 41 additions & 16 deletions include/eosio/vm/interpret_visitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <cmath>
#include <limits>

namespace eosio { namespace vm {

template <typename ExecutionContext>
template <typename ExecutionContext, bool use_softfloat = true>
struct interpret_visitor : base_visitor {
using base_visitor::operator();
interpret_visitor(ExecutionContext& ec) : context(ec) {}
Expand Down Expand Up @@ -792,31 +793,31 @@ namespace eosio { namespace vm {
auto& oper = context.peek_operand().to_f32();
if constexpr (use_softfloat)
oper = _eosio_f32_ceil(oper);
else
else if(!std::isnan(oper))
oper = __builtin_ceilf(oper);
}
[[gnu::always_inline]] inline void operator()(const f32_floor_t& op) {
context.inc_pc();
auto& oper = context.peek_operand().to_f32();
if constexpr (use_softfloat)
oper = _eosio_f32_floor(oper);
else
else if(!std::isnan(oper))
oper = __builtin_floorf(oper);
}
[[gnu::always_inline]] inline void operator()(const f32_trunc_t& op) {
context.inc_pc();
auto& oper = context.peek_operand().to_f32();
if constexpr (use_softfloat)
oper = _eosio_f32_trunc(oper);
else
else if(!std::isnan(oper))
oper = __builtin_trunc(oper);
}
[[gnu::always_inline]] inline void operator()(const f32_nearest_t& op) {
context.inc_pc();
auto& oper = context.peek_operand().to_f32();
if constexpr (use_softfloat)
oper = _eosio_f32_nearest(oper);
else
else if(!std::isnan(oper))
oper = __builtin_nearbyintf(oper);
}
[[gnu::always_inline]] inline void operator()(const f32_sqrt_t& op) {
Expand Down Expand Up @@ -869,17 +870,29 @@ namespace eosio { namespace vm {
auto& lhs = context.peek_operand().to_f32();
if constexpr (use_softfloat)
lhs = _eosio_f32_min(lhs, rhs.to_f32());
else
lhs = __builtin_fminf(lhs, rhs.to_f32());
else {
if(std::isnan(lhs)) {}
else if(std::isnan(rhs.to_f32())) lhs = rhs.to_f32();
else if(lhs == 0.0f && rhs.to_f32() == 0.0f && std::signbit(lhs) != std::signbit(rhs.to_f32()))
lhs = -0.0f;
else
lhs = __builtin_fminf(lhs, rhs.to_f32());
}
}
[[gnu::always_inline]] inline void operator()(const f32_max_t& op) {
context.inc_pc();
const auto& rhs = context.pop_operand();
auto& lhs = context.peek_operand().to_f32();
if constexpr (use_softfloat)
lhs = _eosio_f32_max(lhs, rhs.to_f32());
else
else {
if(std::isnan(lhs)) {}
else if(std::isnan(rhs.to_f32())) lhs = rhs.to_f32();
else if(lhs == 0.0f && rhs.to_f32() == 0.0f && std::signbit(lhs) != std::signbit(rhs.to_f32()))
lhs = 0.0f;
else
lhs = __builtin_fmaxf(lhs, rhs.to_f32());
}
}
[[gnu::always_inline]] inline void operator()(const f32_copysign_t& op) {
context.inc_pc();
Expand Down Expand Up @@ -912,31 +925,31 @@ namespace eosio { namespace vm {
auto& oper = context.peek_operand().to_f64();
if constexpr (use_softfloat)
oper = _eosio_f64_ceil(oper);
else
else if(!std::isnan(oper))
oper = __builtin_ceil(oper);
}
[[gnu::always_inline]] inline void operator()(const f64_floor_t& op) {
context.inc_pc();
auto& oper = context.peek_operand().to_f64();
if constexpr (use_softfloat)
oper = _eosio_f64_floor(oper);
else
else if(!std::isnan(oper))
oper = __builtin_floor(oper);
}
[[gnu::always_inline]] inline void operator()(const f64_trunc_t& op) {
context.inc_pc();
auto& oper = context.peek_operand().to_f64();
if constexpr (use_softfloat)
oper = _eosio_f64_trunc(oper);
else
else if(!std::isnan(oper))
oper = __builtin_trunc(oper);
}
[[gnu::always_inline]] inline void operator()(const f64_nearest_t& op) {
context.inc_pc();
auto& oper = context.peek_operand().to_f64();
if constexpr (use_softfloat)
oper = _eosio_f64_nearest(oper);
else
else if(!std::isnan(oper))
oper = __builtin_nearbyint(oper);
}
[[gnu::always_inline]] inline void operator()(const f64_sqrt_t& op) {
Expand Down Expand Up @@ -989,17 +1002,29 @@ namespace eosio { namespace vm {
auto& lhs = context.peek_operand().to_f64();
if constexpr (use_softfloat)
lhs = _eosio_f64_min(lhs, rhs.to_f64());
else
lhs = __builtin_fmin(lhs, rhs.to_f64());
else {
if(std::isnan(lhs)) {}
else if(std::isnan(rhs.to_f64())) lhs = rhs.to_f64();
else if(lhs == 0.0 && rhs.to_f64() == 0.0 && std::signbit(lhs) != std::signbit(rhs.to_f64()))
lhs = -0.0;
else
lhs = __builtin_fmin(lhs, rhs.to_f64());
}
}
[[gnu::always_inline]] inline void operator()(const f64_max_t& op) {
context.inc_pc();
const auto& rhs = context.pop_operand();
auto& lhs = context.peek_operand().to_f64();
if constexpr (use_softfloat)
lhs = _eosio_f64_max(lhs, rhs.to_f64());
else
lhs = __builtin_fmax(lhs, rhs.to_f64());
else {
if(std::isnan(lhs)) {}
else if(std::isnan(rhs.to_f64())) lhs = rhs.to_f64();
else if(lhs == 0.0 && rhs.to_f64() == 0.0 && std::signbit(lhs) != std::signbit(rhs.to_f64()))
lhs = 0.0;
else
lhs = __builtin_fmax(lhs, rhs.to_f64());
}
}
[[gnu::always_inline]] inline void operator()(const f64_copysign_t& op) {
context.inc_pc();
Expand Down
6 changes: 5 additions & 1 deletion include/eosio/vm/leb128.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,11 @@ namespace eosio { namespace vm {
}
std::cout << std::endl;
}


void to(std::streambuf* out) {
out->sputn(reinterpret_cast<char*>(&storage[0]), bytes_used);
}

private:
std::array<uint8_t, bytes_needed<N>()> storage;
uint8_t bytes_used = bytes_needed<N>();
Expand Down
8 changes: 8 additions & 0 deletions include/eosio/vm/options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ struct options {
bool allow_zero_blocktype = false;
// Determines which components are counted towards max_function_local_bytes
max_func_local_bytes_flags_t max_func_local_bytes_flags = max_func_local_bytes_flags_t::locals | max_func_local_bytes_flags_t::stack;

// Whether to use softfloat.
//
// @warning Hardware floating point is only strictly deterministic
// with jit. When using hardware floating point with the interpreter,
// the behavior depends on the C++ implementation and differs from
// the behavior with softfloat.
static constexpr bool use_softfloat = true;
};

struct default_options {
Expand Down
7 changes: 7 additions & 0 deletions include/eosio/vm/parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,13 @@ namespace eosio { namespace vm {

PARSER_OPTION(allow_zero_blocktype, false, bool)

template<typename Options>
constexpr bool get_use_softfloat(long) { return true; }
template<typename Options>
constexpr auto get_use_softfloat(int) -> decltype(Options::use_softfloat) { return Options::use_softfloat; }
template<typename Options>
constexpr bool get_use_softfloat() { return get_use_softfloat<Options>(0); }

#undef MAX_ELEMENTS
#undef PARSER_OPTION

Expand Down
Loading