Skip to content

Commit

Permalink
Added float and double intrinsics
Browse files Browse the repository at this point in the history
  • Loading branch information
larryk85 committed Mar 14, 2018
1 parent f3d5ccf commit 308e4d9
Show file tree
Hide file tree
Showing 3 changed files with 210 additions and 5 deletions.
7 changes: 4 additions & 3 deletions libraries/chain/include/eosio/chain/wasm_eosio_injection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ namespace eosio { namespace chain { namespace wasm_injections {
if ( exp.kind == IR::ObjectKind::function )
exports++;

uint32_t next_index = module.functions.imports.size() + exports + registered_injected.size();
uint32_t next_index = module.functions.imports.size() + module.functions.defs.size() + exports + registered_injected.size();
return next_index;
}

Expand Down Expand Up @@ -151,6 +151,7 @@ namespace eosio { namespace chain { namespace wasm_injections {
static constexpr bool post = true;
static void init() { checktime_idx = -1; }
static void accept( wasm_ops::instr* inst, wasm_ops::visitor_arg& arg ) {
#if 1
// first add the import for checktime
injector_utils::add_import<ResultType::none, ValueType::i32>( *(arg.module), u8"env", u8"checktime", checktime_idx );

Expand All @@ -166,6 +167,7 @@ namespace eosio { namespace chain { namespace wasm_injections {
std::vector<U8> tmp = chktm.pack();
injected.insert( injected.end(), tmp.begin(), tmp.end() );
arg.new_code->insert( arg.new_code->end(), injected.begin(), injected.end() );
#endif
}
static int32_t checktime_idx;
};
Expand All @@ -183,8 +185,7 @@ namespace eosio { namespace chain { namespace wasm_injections {
call_inst->field = mapped_index;
}
else
if ( call_inst->field > injector_utils::first_imported_index ) {
std::cout << "INDEX " << call_inst->field << "\n";
if ( call_inst->field > injector_utils::first_imported_index-1 ) {
call_inst->field += offset;
}
}
Expand Down
13 changes: 13 additions & 0 deletions libraries/chain/include/eosio/chain/webassembly/wavm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,19 @@ inline auto convert_wasm_to_native(native_to_wasm_t<T> val) {
return T(val);
}

template<>
inline auto convert_wasm_to_native<float32_t>(native_to_wasm_t<float32_t> val) {
// ensure implicit casting doesn't occur
float32_t ret = { *(uint32_t*)&val };
return ret;
}
template<>
inline auto convert_wasm_to_native<float64_t>(native_to_wasm_t<float64_t> val) {
// ensure implicit casting doesn't occur
float64_t ret = { *(uint64_t*)&val };
return ret;
}

template<typename T>
struct wasm_to_value_type;

Expand Down
195 changes: 193 additions & 2 deletions libraries/chain/wasm_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,8 @@ namespace eosio { namespace chain {
IR::Module* module2 = new IR::Module();

Serialization::MemoryInputStream stream((const U8 *) wasm_binary, wasm_binary_size);
Serialization::MemoryInputStream stream2((const U8 *) wasm_binary, wasm_binary_size);
WASM::serialize(stream, *module);
WASM::serializeWithInjection(stream2, *module2);
//WASM::serializeWithInjection(stream, *module);

wasm_constraints::wasm_binary_validation validator( *module );
//validator.validate();
Expand Down Expand Up @@ -571,6 +570,198 @@ class checktime_api : public context_aware_api {
}
};

class softfloat_api : public context_aware_api {
public:
// TODO add traps on truncations for special cases (NaN or outside the range which rounds to an integer)
using context_aware_api::context_aware_api;
// float binops
float32_t _eosio_f32_add( float32_t a, float32_t b ) { return f32_add( a, b ); }
float32_t _eosio_f32_sub( float32_t a, float32_t b ) { return f32_sub( a, b ); }
float32_t _eosio_f32_div( float32_t a, float32_t b ) { return f32_div( a, b ); }
float32_t _eosio_f32_mul( float32_t a, float32_t b ) { return f32_mul( a, b ); }
float32_t _eosio_f32_min( float32_t a, float32_t b ) { return f32_lt( a, b ) ? a : b; }
float32_t _eosio_f32_max( float32_t a, float32_t b ) { return f32_lt( a, b ) ? b : a; }
float32_t _eosio_f32_copysign( float32_t a, float32_t b ) {
uint32_t sign_of_a = a.v >> 31;
uint32_t sign_of_b = b.v >> 31;
a.v &= ~(1 << 31); // clear the sign bit
a.v = a.v | (sign_of_b << 31); // add the sign of b
return a;
}
// float unops
float32_t _eosio_f32_abs( float32_t a ) {
a.v &= ~(1 << 31);
return a;
}
float32_t _eosio_f32_neg( float32_t a ) {
uint32_t sign = a.v >> 31;
a.v &= ~(1 << 31);
a.v |= (!sign << 31);
return a;
}
float32_t _eosio_f32_sqrt( float32_t a ) { return f32_sqrt( a ); }
// ceil, floor, trunc and nearest are lifted from libc
float32_t _eosio_f32_ceil( float32_t a ) {
int e = (int)(a.v >> 23 & 0xff) - 0x7f;
uint32_t m;
if (e >= 23)
return a;
if (e >= 0) {
m = 0x007fffff >> e;
if ((a.v & m) == 0)
return a;
if (a.v >> 31 == 0)
a.v += m;
a.v &= ~m;
} else {
if (a.v >> 31)
a.v = 0x80000000; // return -0.0f
else if (a.v << 1)
a.v = 0x3F800000; // return 1.0f
}
return a;
}
float32_t _eosio_f32_floor( float32_t a ) {
int e = (int)(a.v >> 23 & 0xff) - 0x7f;
uint32_t m;
if (e >= 23)
return a;
if (e >= 0) {
m = 0x007fffff >> e;
if ((a.v & m) == 0)
return a;
if (a.v >> 31)
a.v += m;
a.v &= ~m;
} else {
if (a.v >> 31 == 0)
a.v = 0;
else if (a.v << 1)
a.v = 0x3F800000; // return 1.0f
}
return a;
}
float32_t _eosio_f32_trunc( float32_t a ) {
int e = (int)(a.v >> 23 & 0xff) - 0x7f + 9;
uint32_t m;
if (e >= 23 + 9)
return a;
if (e < 9)
e = 1;
m = -1U >> e;
if ((a.v & m) == 0)
return a;
a.v &= ~m;
return a;
}
float32_t _eosio_f32_nearest( float32_t a ) {
int e = a.v>>23 & 0xff;
int s = a.v>>31;
float32_t y;
if (e >= 0x7f+23)
return a;
if (s)
y = f32_add( f32_sub( a, inv_float_eps ), inv_float_eps );
else
y = f32_sub( f32_add( a, inv_float_eps ), inv_float_eps );
if (f32_eq( y, {0} ) )
return s ? float32_t{0x80000000} : float32_t{0}; // return either -0.0 or 0.0f
return y;
}
// float relops
bool _eosio_f32_eq( float32_t a, float32_t b ) { return f32_eq( a, b ); }
bool _eosio_f32_ne( float32_t a, float32_t b ) { return !f32_eq( a, b ); }
bool _eosio_f32_lt( float32_t a, float32_t b ) { return f32_lt( a, b ); }
bool _eosio_f32_le( float32_t a, float32_t b ) { return f32_le( a, b ); }
bool _eosio_f32_gt( float32_t a, float32_t b ) { return !f32_le( a, b ); }
bool _eosio_f32_ge( float32_t a, float32_t b ) { return !f32_lt( a, b ); }

// double binops
float64_t _eosio_f64_add( float64_t a, float64_t b ) { return f64_add( a, b ); }
float64_t _eosio_f64_sub( float64_t a, float64_t b ) { return f64_sub( a, b ); }
float64_t _eosio_f64_div( float64_t a, float64_t b ) { return f64_div( a, b ); }
float64_t _eosio_f64_mul( float64_t a, float64_t b ) { return f64_mul( a, b ); }
float64_t _eosio_f64_min( float64_t a, float64_t b ) { return f64_lt( a, b ) ? a : b; }
float64_t _eosio_f64_max( float64_t a, float64_t b ) { return f64_lt( a, b ) ? b : a; }
float64_t _eosio_f64_copysign( float64_t a, float64_t b ) {
uint64_t sign_of_a = a.v >> 63;
uint64_t sign_of_b = b.v >> 63;
a.v &= ~(uint64_t(1) << 63); // clear the sign bit
a.v = a.v | (sign_of_b << 63); // add the sign of b
return a;
}

// double unops
float64_t _eosio_f64_abs( float64_t a ) {
a.v &= ~(uint64_t(1) << 63);
return a;
}
float64_t _eosio_f64_neg( float64_t a ) {
uint64_t sign = a.v >> 63;
a.v &= ~(uint64_t(1) << 63);
a.v |= (uint64_t(!sign) << 63);
return a;
}
float64_t _eosio_f64_sqrt( float64_t a ) { return f64_sqrt( a ); }
// ceil, floor, trunc and nearest are lifted from libc
float64_t _eosio_f64_ceil( float64_t a ) {
int e = a.v >> 52 & 0x7ff;
float64_t y;
if (e >= 0x3ff+52 || f64_eq( a, { 0 } ))
return a;
/* y = int(x) - x, where int(x) is an integer neighbor of x */
if (a.v >> 63)
y = f64_sub( f64_add( f64_sub( a, inv_double_eps ), inv_double_eps ), a );
else
y = f64_sub( f64_sub( f64_add( a, inv_double_eps ), inv_double_eps ), a );
/* special case because of non-nearest rounding modes */
if (e <= 0x3ff-1) {
return a.v >> 63 ? float64_t{0x8000000000000000} : float64_t{0xBE99999A3F800000}; //either -0.0 or 1
}
if (f64_lt( y, { 0 } ))
return f64_add( f64_add( a, y ), { 0xBE99999A3F800000 } ); // plus 1
return f64_add( a, y );
}

float64_t _eosio_f64_trunc( float64_t a ) {
int e = (int)(a.v >> 52 & 0x7ff) - 0x3ff + 12;
uint64_t m;
if (e >= 52 + 12)
return a;
if (e < 12)
e = 1;
m = -1ULL >> e;
if ((a.v & m) == 0)
return a;
a.v &= ~m;
return a;
}

// float and double conversions
float64_t _eosio_f32_promote( float32_t a ) { return f32_to_f64( a ); }
float32_t _eosio_f64_demote( float64_t a ) { return f64_to_f32( a ); }
int32_t _eosio_f32_trunc_i32s( float32_t a ) { return f32_to_i32( _eosio_f32_trunc( a ), 0, false ); }
int32_t _eosio_f64_trunc_i32s( float64_t a ) { return f64_to_i32( _eosio_f64_trunc( a ), 0, false ); }
uint32_t _eosio_f32_trunc_i32u( float32_t a ) { return f32_to_ui32( _eosio_f32_trunc( a ), 0, false ); }
uint32_t _eosio_f64_trunc_i32u( float64_t a ) { return f64_to_ui32( _eosio_f64_trunc( a ), 0, false ); }
int64_t _eosio_f32_trunc_i64s( float32_t a ) { return f32_to_i64( _eosio_f32_trunc( a ), 0, false ); }
int64_t _eosio_f64_trunc_i64s( float64_t a ) { return f64_to_i64( _eosio_f64_trunc( a ), 0, false ); }
uint64_t _eosio_f32_trunc_i64u( float32_t a ) { return f32_to_ui64( _eosio_f32_trunc( a ), 0, false ); }
uint64_t _eosio_f64_trunc_i64u( float64_t a ) { return f64_to_ui64( _eosio_f64_trunc( a ), 0, false ); }
float32_t _eosio_i32_to_f32( int32_t a ) { return i32_to_f32( a ); }
float32_t _eosio_i64_to_f32( int64_t a ) { return i64_to_f32( a ); }
float32_t _eosio_ui32_to_f32( uint32_t a ) { return ui32_to_f32( a ); }
float32_t _eosio_ui64_to_f32( uint64_t a ) { return ui64_to_f32( a ); }
float64_t _eosio_i32_to_f64( int32_t a ) { return i32_to_f64( a ); }
float64_t _eosio_i64_to_f64( int64_t a ) { return i64_to_f64( a ); }
float64_t _eosio_ui32_to_f64( uint32_t a ) { return ui32_to_f64( a ); }
float64_t _eosio_ui64_to_f64( uint64_t a ) { return ui64_to_f64( a ); }


private:
static constexpr float32_t inv_float_eps = { 0x4B000000 };
static constexpr float64_t inv_double_eps = { 0x4330000000000000 };
};
class producer_api : public context_aware_api {
public:
using context_aware_api::context_aware_api;
Expand Down

0 comments on commit 308e4d9

Please sign in to comment.