Skip to content

Commit

Permalink
Merge pull request #27 from AntelopeIO/move_correctness
Browse files Browse the repository at this point in the history
Replace `static_cast` of forwarding references with `std::forward`
  • Loading branch information
greg7mdp authored Oct 23, 2024
2 parents 76b55be + 6f2591f commit a45ee4e
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 56 deletions.
44 changes: 22 additions & 22 deletions include/eosio/vm/backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,60 +246,60 @@ namespace eosio { namespace vm {
}

template <typename... Args>
inline bool call_indirect(host_t* host, uint32_t func_index, Args... args) {
inline bool call_indirect(host_t* host, uint32_t func_index, Args&&... args) {
if constexpr (eos_vm_debug) {
ctx->execute_func_table(host, debug_visitor(*ctx), func_index, args...);
ctx->execute_func_table(host, debug_visitor(*ctx), func_index, std::forward<Args>(args)...);
} else {
ctx->execute_func_table(host, interpret_visitor(*ctx), func_index, args...);
ctx->execute_func_table(host, interpret_visitor(*ctx), func_index, std::forward<Args>(args)...);
}
return true;
}

template <typename... Args>
inline bool call(host_t* host, uint32_t func_index, Args... args) {
inline bool call(host_t* host, uint32_t func_index, Args&&... args) {
if constexpr (eos_vm_debug) {
ctx->execute(host, debug_visitor(*ctx), func_index, args...);
ctx->execute(host, debug_visitor(*ctx), func_index, std::forward<Args>(args)...);
} else {
ctx->execute(host, interpret_visitor(*ctx), func_index, args...);
ctx->execute(host, interpret_visitor(*ctx), func_index, std::forward<Args>(args)...);
}
return true;
}

template <typename... Args>
inline bool call(host_t& host, const std::string_view& mod, const std::string_view& func, Args... args) {
inline bool call(host_t& host, const std::string_view& mod, const std::string_view& func, Args&&... args) {
if constexpr (eos_vm_debug) {
ctx->execute(&host, debug_visitor(*ctx), func, args...);
ctx->execute(&host, debug_visitor(*ctx), func, std::forward<Args>(args)...);
} else {
ctx->execute(&host, interpret_visitor(*ctx), func, args...);
ctx->execute(&host, interpret_visitor(*ctx), func, std::forward<Args>(args)...);
}
return true;
}

template <typename... Args>
inline bool call(const std::string_view& mod, const std::string_view& func, Args... args) {
inline bool call(const std::string_view& mod, const std::string_view& func, Args&&... args) {
if constexpr (eos_vm_debug) {
ctx->execute(nullptr, debug_visitor(*ctx), func, args...);
ctx->execute(nullptr, debug_visitor(*ctx), func, std::forward<Args>(args)...);
} else {
ctx->execute(nullptr, interpret_visitor(*ctx), func, args...);
ctx->execute(nullptr, interpret_visitor(*ctx), func, std::forward<Args>(args)...);
}
return true;
}

template <typename... Args>
inline auto call_with_return(host_t& host, const std::string_view& mod, const std::string_view& func, Args... args ) {
inline auto call_with_return(host_t& host, const std::string_view& mod, const std::string_view& func, Args&&... args ) {
if constexpr (eos_vm_debug) {
return ctx->execute(&host, debug_visitor(*ctx), func, args...);
return ctx->execute(&host, debug_visitor(*ctx), func, std::forward<Args>(args)...);
} else {
return ctx->execute(&host, interpret_visitor(*ctx), func, args...);
return ctx->execute(&host, interpret_visitor(*ctx), func, std::forward<Args>(args)...);
}
}

template <typename... Args>
inline auto call_with_return(const std::string_view& mod, const std::string_view& func, Args... args) {
inline auto call_with_return(const std::string_view& mod, const std::string_view& func, Args&&... args) {
if constexpr (eos_vm_debug) {
return ctx->execute(nullptr, debug_visitor(*ctx), func, args...);
return ctx->execute(nullptr, debug_visitor(*ctx), func, std::forward<Args>(args)...);
} else {
return ctx->execute(nullptr, interpret_visitor(*ctx), func, args...);
return ctx->execute(nullptr, interpret_visitor(*ctx), func, std::forward<Args>(args)...);
}
}

Expand All @@ -312,11 +312,11 @@ namespace eosio { namespace vm {
}
}};
try {
auto wd_guard = wd.scoped_run([this,&_timed_out]() {
auto wd_guard = std::forward<Watchdog>(wd).scoped_run([this,&_timed_out]() {
_timed_out = true;
mod->allocator.disable_code();
});
static_cast<F&&>(f)();
std::forward<F>(f)();
} catch(wasm_memory_exception&) {
if (_timed_out) {
throw timeout_exception{ "execution timed out" };
Expand All @@ -328,7 +328,7 @@ namespace eosio { namespace vm {

template <typename Watchdog>
inline void execute_all(Watchdog&& wd, host_t& host) {
timed_run(static_cast<Watchdog&&>(wd), [&]() {
timed_run(std::forward<Watchdog>(wd), [&]() {
for (int i = 0; i < mod->exports.size(); i++) {
if (mod->exports[i].kind == external_kind::Function) {
std::string s{ (const char*)mod->exports[i].field_str.raw(), mod->exports[i].field_str.size() };
Expand All @@ -340,7 +340,7 @@ namespace eosio { namespace vm {

template <typename Watchdog>
inline void execute_all(Watchdog&& wd) {
timed_run(static_cast<Watchdog&&>(wd), [&]() {
timed_run(std::forward<Watchdog>(wd), [&]() {
for (int i = 0; i < mod->exports.size(); i++) {
if (mod->exports[i].kind == external_kind::Function) {
std::string s{ (const char*)mod->exports[i].field_str.raw(), mod->exports[i].field_str.size() };
Expand Down
26 changes: 13 additions & 13 deletions include/eosio/vm/execution_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ namespace eosio { namespace vm {

template <typename Visitor, typename... Args>
inline std::optional<operand_stack_elem> execute(host_type* host, Visitor&& visitor, const std::string_view func,
Args... args) {
Args&&... args) {
uint32_t func_index = _mod->get_exported_function(func);
return derived().execute(host, std::forward<Visitor>(visitor), func_index, std::forward<Args>(args)...);
}
Expand Down Expand Up @@ -311,22 +311,22 @@ namespace eosio { namespace vm {
}

template <typename... Args>
inline std::optional<operand_stack_elem> execute(host_type* host, jit_visitor, uint32_t func_index, Args... args) {
inline std::optional<operand_stack_elem> execute(host_type* host, jit_visitor, uint32_t func_index, Args&&... args) {
auto saved_host = _host;
auto saved_os_size = get_operand_stack().size();
auto g = scope_guard([&](){ _host = saved_host; get_operand_stack().eat(saved_os_size); });

_host = host;

const auto& ft = _mod->jit_mod->get_function_type(func_index);
this->type_check_args(ft, static_cast<Args&&>(args)...);
this->type_check_args(ft, std::forward<Args>(args)... ); // args not modified by type_check_args
native_value result;

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-value"
// Calling execute() with no `args` (i.e. `execute(host_type,jit_visitor,uint32_t)`) results in a "statement has no
// effect [-Werror=unused-value]" warning on this line. Dissable warning.
native_value args_raw[] = { transform_arg( static_cast<Args&&>(args))... };
native_value args_raw[] = { transform_arg( std::forward<Args>(args))... };
#pragma GCC diagnostic pop

try {
Expand Down Expand Up @@ -482,7 +482,7 @@ namespace eosio { namespace vm {
native_value result;
std::memset(&result, 0, sizeof(result));
auto tc = detail::type_converter_t<Host>{_host, get_interface()};
auto transformed_value = detail::resolve_result(tc, static_cast<T&&>(value)).data;
auto transformed_value = detail::resolve_result(tc, std::forward<T>(value)).data;
std::memcpy(&result, &transformed_value, sizeof(transformed_value));
return result;
}
Expand Down Expand Up @@ -750,13 +750,13 @@ namespace eosio { namespace vm {

template <typename Visitor, typename... Args>
inline std::optional<operand_stack_elem> execute_func_table(host_type* host, Visitor&& visitor, uint32_t table_index,
Args... args) {
Args&&... args) {
return execute(host, std::forward<Visitor>(visitor), table_elem(table_index), std::forward<Args>(args)...);
}

template <typename Visitor, typename... Args>
inline std::optional<operand_stack_elem> execute(host_type* host, Visitor&& visitor, const std::string_view func,
Args... args) {
Args&&... args) {
uint32_t func_index = _mod->get_exported_function(func);
return execute(host, std::forward<Visitor>(visitor), func_index, std::forward<Args>(args)...);
}
Expand All @@ -768,7 +768,7 @@ namespace eosio { namespace vm {
}

template <typename Visitor, typename... Args>
inline std::optional<operand_stack_elem> execute(host_type* host, Visitor&& visitor, uint32_t func_index, Args... args) {
inline std::optional<operand_stack_elem> execute(host_type* host, Visitor&& visitor, uint32_t func_index, Args&&... args) {
EOS_VM_ASSERT(func_index < std::numeric_limits<uint32_t>::max(), wasm_interpreter_exception,
"cannot execute function, function not found");

Expand All @@ -789,8 +789,8 @@ namespace eosio { namespace vm {
_last_op_index = last_last_op_index;
});

this->type_check_args(_mod->get_function_type(func_index), static_cast<Args&&>(args)...);
push_args(args...);
this->type_check_args(_mod->get_function_type(func_index), std::forward<Args>(args)...); // args not modified
push_args(std::forward<Args>(args)...);
push_call<true>(func_index);

if (func_index < _mod->get_imported_functions_size()) {
Expand All @@ -799,7 +799,7 @@ namespace eosio { namespace vm {
_state.pc = _mod->get_function_pc(func_index);
setup_locals(func_index);
vm::invoke_with_signal_handler([&]() {
execute(visitor);
execute(std::forward<Visitor>(visitor));
}, &handle_signal, {_mod->allocator.get_code_span(), base_type::get_wasm_allocator()->get_span()});
}

Expand Down Expand Up @@ -840,7 +840,7 @@ namespace eosio { namespace vm {
void push_args(Args&&... args) {
auto tc = detail::type_converter_t<Host>{ _host, get_interface() };
(void)tc;
(... , push_operand(detail::resolve_result(tc, std::move(args))));
(... , push_operand(detail::resolve_result(tc, std::forward<Args>(args))));
}

inline void setup_locals(uint32_t index) {
Expand All @@ -859,7 +859,7 @@ namespace eosio { namespace vm {

#define CREATE_TABLE_ENTRY(NAME, CODE) &&ev_label_##NAME,
#define CREATE_LABEL(NAME, CODE) \
ev_label_##NAME : visitor(ev_variant->template get<eosio::vm::EOS_VM_OPCODE_T(NAME)>()); \
ev_label_##NAME : std::forward<Visitor>(visitor)(ev_variant->template get<eosio::vm::EOS_VM_OPCODE_T(NAME)>()); \
ev_variant = _state.pc; \
goto* dispatch_table[ev_variant->index()];
#define CREATE_EXIT_LABEL(NAME, CODE) ev_label_##NAME : \
Expand Down
2 changes: 1 addition & 1 deletion include/eosio/vm/function_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ namespace eosio { namespace vm {
};

template <typename T, typename U>
inline constexpr U&& make_dependent(U&& u) { return static_cast<U&&>(u); }
inline constexpr U&& make_dependent(U&& u) { return std::forward<U>(u); }
}

template <typename F>
Expand Down
14 changes: 7 additions & 7 deletions include/eosio/vm/host_function.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,9 @@ namespace eosio { namespace vm {
template <typename Type_Converter, typename T>
constexpr auto resolve_result(Type_Converter& tc, T&& val) {
if constexpr (has_to_wasm_v<T, Type_Converter>) {
return tc.as_result(tc.to_wasm(static_cast<T&&>(val)));
return tc.as_result(tc.to_wasm(std::forward<T>(val)));
} else {
return tc.as_result(static_cast<T&&>(val));
return tc.as_result(std::forward<T>(val));
}
}

Expand Down Expand Up @@ -281,7 +281,7 @@ namespace eosio { namespace vm {

template <bool Once, typename T, typename F, typename... Args>
void invoke_on(F&& func, const Args&... args) {
detail::invoke_on_impl<Once, 0, T>(static_cast<F&&>(func), args...);
detail::invoke_on_impl<Once, 0, T>(std::forward<F>(func), args...);
}

#define EOS_VM_INVOKE_ON(TYPE, CONDITION) \
Expand All @@ -304,15 +304,15 @@ namespace eosio { namespace vm {
template <auto F, typename Preconditions, typename Type_Converter, typename Host, typename... Args>
decltype(auto) invoke_impl(Type_Converter& tc, Host* host, Args&&... args) {
if constexpr (std::is_same_v<Host, standalone_function_t>)
return std::invoke(F, static_cast<Args&&>(args)...);
return std::invoke(F, std::forward<Args>(args)...);
else
return std::invoke(F, host, static_cast<Args&&>(args)...);
return std::invoke(F, host, std::forward<Args>(args)...);
}

template <auto F, typename Preconditions, typename Host, typename Args, typename Type_Converter, std::size_t... Is>
decltype(auto) invoke_with_host_impl(Type_Converter& tc, Host* host, Args&& args, std::index_sequence<Is...>) {
detail::preconditions_runner<0, Preconditions>(tc, args);
return invoke_impl<F, Preconditions>(tc, host, std::get<Is>(static_cast<Args&&>(args))...);
return invoke_impl<F, Preconditions>(tc, host, std::get<Is>(std::forward<Args>(args))...);
}

template <auto F, typename Preconditions, typename Args, typename Type_Converter, typename Host, std::size_t... Is>
Expand All @@ -325,7 +325,7 @@ namespace eosio { namespace vm {
void maybe_push_result(Type_Converter& tc, T&& res, std::size_t trim_amt) {
if constexpr (!std::is_same_v<std::decay_t<T>, maybe_void_t>) {
tc.get_interface().trim_operands(trim_amt);
tc.get_interface().push_operand(detail::resolve_result(tc, static_cast<T&&>(res)));
tc.get_interface().push_operand(detail::resolve_result(tc, std::forward<T>(res)));
} else {
tc.get_interface().trim_operands(trim_amt);
}
Expand Down
2 changes: 1 addition & 1 deletion include/eosio/vm/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ namespace eosio { namespace vm {

template<typename F>
struct scope_guard {
scope_guard(F&& f) : _f(static_cast<F&&>(f)) {}
scope_guard(F&& f) : _f(std::move(f)) {}
~scope_guard() { _f(); }
F _f;
};
Expand Down
18 changes: 9 additions & 9 deletions include/eosio/vm/variant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ namespace eosio { namespace vm {
union variant_storage<T0, T1, T2, T3, T...> {
V4
template<typename A>
constexpr variant_storage(A&& arg) : _tail{static_cast<A&&>(arg)} {}
constexpr variant_storage(A&& arg) : _tail{std::forward<A>(arg)} {}
variant_storage<T...> _tail;
};
template<typename T0>
Expand Down Expand Up @@ -139,15 +139,15 @@ namespace eosio { namespace vm {
template<int I, typename Storage>
constexpr decltype(auto) variant_storage_get(Storage&& val) {
if constexpr (I == 0) {
return (static_cast<Storage&&>(val)._t0);
return (std::forward<Storage>(val)._t0);
} else if constexpr (I == 1) {
return (static_cast<Storage&&>(val)._t1);
return (std::forward<Storage>(val)._t1);
} else if constexpr (I == 2) {
return (static_cast<Storage&&>(val)._t2);
return (std::forward<Storage>(val)._t2);
} else if constexpr (I == 3) {
return (static_cast<Storage&&>(val)._t3);
return (std::forward<Storage>(val)._t3);
} else {
return detail::variant_storage_get<I - 4>(static_cast<Storage&&>(val)._tail);
return detail::variant_storage_get<I - 4>(std::forward<Storage>(val)._tail);
}
}
} // namespace detail
Expand Down Expand Up @@ -177,7 +177,7 @@ namespace eosio { namespace vm {
template <typename T, typename = std::enable_if_t<detail::is_valid_alternative_v<std::decay_t<T>, Alternatives...>>>
constexpr variant(T&& alt) :
_which(detail::get_alternatives_index_v<std::decay_t<T>, Alternatives...>),
_storage(static_cast<T&&>(alt)) {
_storage(std::forward<T>(alt)) {
}

template <typename T,
Expand All @@ -186,10 +186,10 @@ namespace eosio { namespace vm {
#if (defined(__GNUC__) && !defined(__clang__))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
_storage = static_cast<T&&>(alt);
_storage = std::forward<T>(alt);
#pragma GCC diagnostic pop
#else
_storage = static_cast<T&&>(alt);
_storage = std::forward<T>(alt);
#endif
_which = detail::get_alternatives_index_v<std::decay_t<T>, Alternatives...>;
return *this;
Expand Down
4 changes: 2 additions & 2 deletions include/eosio/vm/watchdog.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace eosio { namespace vm {
/// be called.
template<typename F>
[[nodiscard]] guard scoped_run(F&& callback) {
return guard(_duration, static_cast<F&&>(callback));
return guard(_duration, std::forward<F>(callback));
}

private:
Expand All @@ -35,7 +35,7 @@ namespace eosio { namespace vm {

template <typename TimeUnits, typename F>
guard(const TimeUnits& duration, F&& callback)
: _callback(static_cast<F&&>(callback)),
: _callback(std::forward<F>(callback)),
_run_state(running),
_duration(duration),
_start(std::chrono::steady_clock::now()) {
Expand Down
2 changes: 1 addition & 1 deletion tools/interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ int main(int argc, char** argv) {
backend<std::nullptr_t, interpreter, default_options> bkend( code, &wa );

// Execute any exported functions provided by the wasm.
bkend.execute_all(wd);
bkend.execute_all(std::move(wd));

} catch ( const eosio::vm::exception& ex ) {
std::cerr << "eos-vm interpreter error\n";
Expand Down

0 comments on commit a45ee4e

Please sign in to comment.