Commit 862ddf1e authored by Manos Koukoutos's avatar Manos Koukoutos Committed by V8 LUCI CQ

[wasm] Do not enforce LE for globals and WasmValue

Changes:
- Remove endianness transformations from WasmValue contstructors.
  WasmValue will now use the system's endianness. Remove
  CopyToWithSystemEndianness.
- Remove endianness transformation from global variable load/stores in:
  wasm-compiler.cc, liftoff-compiler.cc, wasm-objects{.cc, -inl.h}, and
  wasm-interpreter.cc
- Adjust SIMD tests that directly access part of a value by changing
  which lane they access within that value. We do that by introducing
  a LANE macro and use it over ReadLittleEndianValue.

Change-Id: I99e97c6eae72e9a135b184633ec266049803bb03
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2944437
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: 's avatarZhi An Ng <zhin@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75085}
parent da438d9e
......@@ -3649,11 +3649,7 @@ Node* WasmGraphBuilder::GlobalGet(uint32_t index) {
GetGlobalBaseAndOffset(mem_type, global, &base, &offset);
// TODO(manoskouk): Cannot use LoadFromObject here due to
// GetGlobalBaseAndOffset pointer arithmetic.
Node* result = gasm_->Load(mem_type, base, offset);
#if defined(V8_TARGET_BIG_ENDIAN)
result = BuildChangeEndiannessLoad(result, mem_type, global.type);
#endif
return result;
return gasm_->Load(mem_type, base, offset);
}
void WasmGraphBuilder::GlobalSet(uint32_t index, Node* val) {
......@@ -3684,9 +3680,6 @@ void WasmGraphBuilder::GlobalSet(uint32_t index, Node* val) {
GetGlobalBaseAndOffset(mem_type, global, &base, &offset);
auto store_rep =
StoreRepresentation(mem_type.representation(), kNoWriteBarrier);
#if defined(V8_TARGET_BIG_ENDIAN)
val = BuildChangeEndiannessStore(val, mem_type.representation(), global.type);
#endif
// TODO(manoskouk): Cannot use StoreToObject here due to
// GetGlobalBaseAndOffset pointer arithmetic.
gasm_->Store(store_rep, base, offset, val);
......
......@@ -1468,9 +1468,7 @@ Handle<WasmStruct> Factory::NewWasmStruct(const wasm::StructType* type,
for (uint32_t i = 0; i < type->field_count(); i++) {
Address address = result.RawFieldAddress(type->field_offset(i));
if (type->field(i).is_numeric()) {
args[i]
.Packed(type->field(i))
.CopyToWithSystemEndianness(reinterpret_cast<byte*>(address));
args[i].Packed(type->field(i)).CopyTo(reinterpret_cast<byte*>(address));
} else {
base::WriteUnalignedValue<Object>(address, *args[i].to_ref());
}
......
......@@ -2271,7 +2271,7 @@ class LiftoffCompiler {
LiftoffRegister value =
pinned.set(__ GetUnusedRegister(reg_class_for(kind), pinned));
LoadType type = LoadType::ForValueKind(kind);
__ Load(value, addr, no_reg, offset, type, pinned, nullptr, true);
__ Load(value, addr, no_reg, offset, type, pinned, nullptr, false);
__ PushRegister(kind, value);
}
......@@ -2312,7 +2312,7 @@ class LiftoffCompiler {
Register addr = GetGlobalBaseAndOffset(global, &pinned, &offset);
LiftoffRegister reg = pinned.set(__ PopToRegister(pinned));
StoreType type = StoreType::ForValueKind(kind);
__ Store(addr, no_reg, offset, reg, type, {}, nullptr, true);
__ Store(addr, no_reg, offset, reg, type, {}, nullptr, false);
}
void TableGet(FullDecoder* decoder, const Value&, Value*,
......
......@@ -160,19 +160,19 @@ Address WasmGlobalObject::address() const {
}
int32_t WasmGlobalObject::GetI32() {
return base::ReadLittleEndianValue<int32_t>(address());
return base::ReadUnalignedValue<int32_t>(address());
}
int64_t WasmGlobalObject::GetI64() {
return base::ReadLittleEndianValue<int64_t>(address());
return base::ReadUnalignedValue<int64_t>(address());
}
float WasmGlobalObject::GetF32() {
return base::ReadLittleEndianValue<float>(address());
return base::ReadUnalignedValue<float>(address());
}
double WasmGlobalObject::GetF64() {
return base::ReadLittleEndianValue<double>(address());
return base::ReadUnalignedValue<double>(address());
}
Handle<Object> WasmGlobalObject::GetRef() {
......@@ -182,19 +182,19 @@ Handle<Object> WasmGlobalObject::GetRef() {
}
void WasmGlobalObject::SetI32(int32_t value) {
base::WriteLittleEndianValue<int32_t>(address(), value);
base::WriteUnalignedValue(address(), value);
}
void WasmGlobalObject::SetI64(int64_t value) {
base::WriteLittleEndianValue<int64_t>(address(), value);
base::WriteUnalignedValue(address(), value);
}
void WasmGlobalObject::SetF32(float value) {
base::WriteLittleEndianValue<float>(address(), value);
base::WriteUnalignedValue(address(), value);
}
void WasmGlobalObject::SetF64(double value) {
base::WriteLittleEndianValue<double>(address(), value);
base::WriteUnalignedValue(address(), value);
}
void WasmGlobalObject::SetExternRef(Handle<Object> value) {
......
......@@ -1612,7 +1612,7 @@ wasm::WasmValue WasmInstanceObject::GetGlobalValue(
switch (global.type.kind()) {
#define CASE_TYPE(valuetype, ctype) \
case wasm::valuetype: \
return wasm::WasmValue(base::ReadLittleEndianValue<ctype>(ptr));
return wasm::WasmValue(base::ReadUnalignedValue<ctype>(ptr));
FOREACH_WASMVALUE_CTYPES(CASE_TYPE)
#undef CASE_TYPE
default:
......@@ -1628,7 +1628,7 @@ wasm::WasmValue WasmStruct::GetFieldValue(uint32_t index) {
switch (field_type.kind()) {
#define CASE_TYPE(valuetype, ctype) \
case wasm::valuetype: \
return wasm::WasmValue(base::ReadLittleEndianValue<ctype>(field_address));
return wasm::WasmValue(base::ReadUnalignedValue<ctype>(field_address));
CASE_TYPE(kI8, int8_t)
CASE_TYPE(kI16, int16_t)
FOREACH_WASMVALUE_CTYPES(CASE_TYPE)
......@@ -1658,7 +1658,7 @@ wasm::WasmValue WasmArray::GetElement(uint32_t index) {
switch (element_type.kind()) {
#define CASE_TYPE(value_type, ctype) \
case wasm::value_type: \
return wasm::WasmValue(base::ReadLittleEndianValue<ctype>(element_address));
return wasm::WasmValue(base::ReadUnalignedValue<ctype>(element_address));
CASE_TYPE(kI8, int8_t)
CASE_TYPE(kI16, int16_t)
FOREACH_WASMVALUE_CTYPES(CASE_TYPE)
......
......@@ -42,7 +42,7 @@ class Simd128 {
explicit Simd128(sType val) { \
base::WriteUnalignedValue<sType>(reinterpret_cast<Address>(val_), val); \
} \
sType to_##name() { \
sType to_##name() const { \
return base::ReadUnalignedValue<sType>(reinterpret_cast<Address>(val_)); \
}
FOREACH_SIMD_TYPE(DEFINE_SIMD_TYPE_SPECIFIC_METHODS)
......@@ -56,7 +56,7 @@ class Simd128 {
const uint8_t* bytes() { return val_; }
template <typename T>
inline T to();
inline T to() const;
private:
uint8_t val_[16] = {0};
......@@ -64,7 +64,7 @@ class Simd128 {
#define DECLARE_CAST(cType, sType, name, size) \
template <> \
inline sType Simd128::to() { \
inline sType Simd128::to() const { \
return to_##name(); \
}
FOREACH_SIMD_TYPE(DECLARE_CAST)
......@@ -95,26 +95,25 @@ class WasmValue {
public:
WasmValue() : type_(kWasmVoid), bit_pattern_{} {}
#define DEFINE_TYPE_SPECIFIC_METHODS(name, localtype, ctype) \
explicit WasmValue(ctype v) : type_(localtype), bit_pattern_{} { \
static_assert(sizeof(ctype) <= sizeof(bit_pattern_), \
"size too big for WasmValue"); \
base::WriteLittleEndianValue<ctype>( \
reinterpret_cast<Address>(bit_pattern_), v); \
} \
ctype to_##name() const { \
DCHECK_EQ(localtype, type_); \
return to_##name##_unchecked(); \
} \
ctype to_##name##_unchecked() const { \
return base::ReadLittleEndianValue<ctype>( \
reinterpret_cast<Address>(bit_pattern_)); \
#define DEFINE_TYPE_SPECIFIC_METHODS(name, localtype, ctype) \
explicit WasmValue(ctype v) : type_(localtype), bit_pattern_{} { \
static_assert(sizeof(ctype) <= sizeof(bit_pattern_), \
"size too big for WasmValue"); \
base::WriteUnalignedValue<ctype>(reinterpret_cast<Address>(bit_pattern_), \
v); \
} \
ctype to_##name() const { \
DCHECK_EQ(localtype, type_); \
return to_##name##_unchecked(); \
} \
ctype to_##name##_unchecked() const { \
return base::ReadUnalignedValue<ctype>( \
reinterpret_cast<Address>(bit_pattern_)); \
}
FOREACH_PRIMITIVE_WASMVAL_TYPE(DEFINE_TYPE_SPECIFIC_METHODS)
#undef DEFINE_TYPE_SPECIFIC_METHODS
// Instantiate a numeric WasmValue from a byte pointer to a little endian
// value.
WasmValue(byte* raw_bytes, ValueType type) : type_(type), bit_pattern_{} {
DCHECK(type_.is_numeric());
memcpy(bit_pattern_, raw_bytes, type.element_size_bytes());
......@@ -123,9 +122,11 @@ class WasmValue {
WasmValue(Handle<Object> ref, ValueType type) : type_(type), bit_pattern_{} {
static_assert(sizeof(Handle<Object>) <= sizeof(bit_pattern_),
"bit_pattern_ must be large enough to fit a Handle");
DCHECK(type.is_reference());
base::WriteUnalignedValue<Handle<Object>>(
reinterpret_cast<Address>(bit_pattern_), ref);
}
Handle<Object> to_ref() const {
DCHECK(type_.is_reference());
return base::ReadUnalignedValue<Handle<Object>>(
......@@ -137,62 +138,18 @@ class WasmValue {
// Checks equality of type and bit pattern (also for float and double values).
bool operator==(const WasmValue& other) const {
return type_ == other.type_ &&
!memcmp(bit_pattern_, other.bit_pattern_, 16);
!memcmp(bit_pattern_, other.bit_pattern_,
type_.is_reference() ? sizeof(Handle<Object>)
: type_.element_size_bytes());
}
// Copy the underlying value to a byte pointer to a little endian value.
void CopyTo(byte* to) const {
STATIC_ASSERT(sizeof(float) == sizeof(Float32));
STATIC_ASSERT(sizeof(double) == sizeof(Float64));
DCHECK(type_.is_numeric());
memcpy(to, bit_pattern_, type_.element_size_bytes());
}
// Store the undelying value to a byte pointer, using the system's endianness.
void CopyToWithSystemEndianness(byte* to) {
DCHECK(type_.is_numeric());
switch (type_.kind()) {
case kI8: {
int8_t value = to_i8();
memcpy(static_cast<void*>(to), &value, sizeof(value));
break;
}
case kI16: {
int16_t value = to_i16();
memcpy(static_cast<void*>(to), &value, sizeof(value));
break;
}
case kI32: {
int32_t value = to_i32();
memcpy(static_cast<void*>(to), &value, sizeof(value));
break;
}
case kI64: {
int64_t value = to_i64();
memcpy(static_cast<void*>(to), &value, sizeof(value));
break;
}
case kF32: {
float value = to_f32();
memcpy(static_cast<void*>(to), &value, sizeof(value));
break;
}
case kF64: {
double value = to_f64();
memcpy(static_cast<void*>(to), &value, sizeof(value));
break;
}
case kS128:
memcpy(static_cast<void*>(to), to_s128().bytes(), kSimd128Size);
break;
case kRtt:
case kRttWithDepth:
case kRef:
case kOptRef:
case kBottom:
case kVoid:
UNREACHABLE();
}
}
// If {packed_type.is_packed()}, create a new value of {packed_type()}.
// Otherwise, return this object.
WasmValue Packed(ValueType packed_type) const {
......
......@@ -1363,9 +1363,9 @@ WASM_EXEC_TEST(I64Global) {
r.builder().WriteMemory<int64_t>(global, 0xFFFFFFFFFFFFFFFFLL);
for (int i = 9; i < 444444; i += 111111) {
int64_t expected = ReadLittleEndianValue<int64_t>(global) & i;
int64_t expected = *global & i;
r.Call(i);
CHECK_EQ(expected, ReadLittleEndianValue<int64_t>(global));
CHECK_EQ(expected, *global);
}
}
......
......@@ -140,7 +140,7 @@ WASM_RELAXED_SIMD_TEST(F32x4Qfma) {
float expected =
ExpectFused(execution_tier) ? x.fused_result : x.unfused_result;
for (int i = 0; i < 4; i++) {
float actual = ReadLittleEndianValue<float>(&g[i]);
float actual = LANE(g, i);
CheckFloatResult(x.a, x.b, expected, actual, true /* exact */);
}
}
......@@ -164,7 +164,7 @@ WASM_RELAXED_SIMD_TEST(F32x4Qfms) {
float expected =
ExpectFused(execution_tier) ? x.fused_result : x.unfused_result;
for (int i = 0; i < 4; i++) {
float actual = ReadLittleEndianValue<float>(&g[i]);
float actual = LANE(g, i);
CheckFloatResult(x.a, x.b, expected, actual, true /* exact */);
}
}
......@@ -188,7 +188,7 @@ WASM_RELAXED_SIMD_TEST(F64x2Qfma) {
double expected =
ExpectFused(execution_tier) ? x.fused_result : x.unfused_result;
for (int i = 0; i < 2; i++) {
double actual = ReadLittleEndianValue<double>(&g[i]);
double actual = LANE(g, i);
CheckDoubleResult(x.a, x.b, expected, actual, true /* exact */);
}
}
......@@ -212,7 +212,7 @@ WASM_RELAXED_SIMD_TEST(F64x2Qfms) {
double expected =
ExpectFused(execution_tier) ? x.fused_result : x.unfused_result;
for (int i = 0; i < 2; i++) {
double actual = ReadLittleEndianValue<double>(&g[i]);
double actual = LANE(g, i);
CheckDoubleResult(x.a, x.b, expected, actual, true /* exact */);
}
}
......
......@@ -45,11 +45,11 @@ WASM_SIMD_LIFTOFF_TEST(S128Global) {
int32_t expected = 0x1234;
for (int i = 0; i < 4; i++) {
WriteLittleEndianValue<int32_t>(&g0[i], expected);
LANE(g0, i) = expected;
}
r.Call();
for (int i = 0; i < 4; i++) {
int32_t actual = ReadLittleEndianValue<int32_t>(&g1[i]);
int32_t actual = LANE(g1, i);
CHECK_EQ(actual, expected);
}
}
......@@ -120,8 +120,8 @@ WASM_SIMD_LIFTOFF_TEST(I8x16Shuffle) {
byte* g0 = r.builder().AddGlobal<byte>(kWasmS128);
byte* g1 = r.builder().AddGlobal<byte>(kWasmS128);
for (int i = 0; i < 16; i++) {
WriteLittleEndianValue<byte>(&g0[i], i);
WriteLittleEndianValue<byte>(&g1[i], i + 16);
LANE(g0, i) = i;
LANE(g1, i) = i + 16;
}
// Output global holding a kWasmS128.
......@@ -145,10 +145,10 @@ WASM_SIMD_LIFTOFF_TEST(I8x16Shuffle) {
// The shuffle pattern only changes the last element.
for (int i = 0; i < 15; i++) {
byte actual = ReadLittleEndianValue<byte>(&output[i]);
byte actual = LANE(output, i);
CHECK_EQ(i, actual);
}
CHECK_EQ(31, ReadLittleEndianValue<byte>(&output[15]));
CHECK_EQ(31, LANE(output, 15));
}
// Exercise logic in Liftoff's implementation of shuffle when inputs to the
......@@ -159,7 +159,7 @@ WASM_SIMD_LIFTOFF_TEST(I8x16Shuffle_SingleOperand) {
byte* g0 = r.builder().AddGlobal<byte>(kWasmS128);
for (int i = 0; i < 16; i++) {
WriteLittleEndianValue<byte>(&g0[i], i);
LANE(g0, i) = i;
}
byte* output = r.builder().AddGlobal<byte>(kWasmS128);
......@@ -181,7 +181,7 @@ WASM_SIMD_LIFTOFF_TEST(I8x16Shuffle_SingleOperand) {
for (int i = 0; i < 16; i++) {
// Check that the output is the reverse of input.
byte actual = ReadLittleEndianValue<byte>(&output[i]);
byte actual = LANE(output, i);
CHECK_EQ(15 - i, actual);
}
}
......
This diff is collapsed.
......@@ -727,8 +727,8 @@ WASM_EXEC_TEST(Select_s128_parameters) {
int32_t* output = r.builder().AddGlobal<int32_t>(kWasmS128);
// select(v128(0, 1, 2, 3), v128(4, 5, 6, 7), 1) == v128(0, 1, 2, 3)
for (int i = 0; i < 4; i++) {
WriteLittleEndianValue<int32_t>(&g0[i], i);
WriteLittleEndianValue<int32_t>(&g1[i], i + 4);
LANE(g0, i) = i;
LANE(g1, i) = i + 4;
}
BUILD(r,
WASM_GLOBAL_SET(2, WASM_SELECT(WASM_GLOBAL_GET(0), WASM_GLOBAL_GET(1),
......@@ -736,7 +736,7 @@ WASM_EXEC_TEST(Select_s128_parameters) {
WASM_ONE);
r.Call(1);
for (int i = 0; i < 4; i++) {
CHECK_EQ(i, ReadLittleEndianValue<int32_t>(&output[i]));
CHECK_EQ(i, LANE(output, i));
}
}
......@@ -2119,11 +2119,11 @@ WASM_EXEC_TEST(Int32Global) {
WASM_GLOBAL_SET(0, WASM_I32_ADD(WASM_GLOBAL_GET(0), WASM_LOCAL_GET(0))),
WASM_ZERO);
WriteLittleEndianValue<int32_t>(global, 116);
*global = 116;
for (int i = 9; i < 444444; i += 111111) {
int32_t expected = ReadLittleEndianValue<int32_t>(global) + i;
int32_t expected = *global + i;
r.Call(i);
CHECK_EQ(expected, ReadLittleEndianValue<int32_t>(global));
CHECK_EQ(expected, *global);
}
}
......@@ -2142,17 +2142,16 @@ WASM_EXEC_TEST(Int32Globals_DontAlias) {
WASM_GLOBAL_GET(g));
// Check that reading/writing global number {g} doesn't alter the others.
WriteLittleEndianValue<int32_t>(globals[g], 116 * g);
*(globals[g]) = 116 * g;
int32_t before[kNumGlobals];
for (int i = 9; i < 444444; i += 111113) {
int32_t sum = ReadLittleEndianValue<int32_t>(globals[g]) + i;
for (int j = 0; j < kNumGlobals; ++j)
before[j] = ReadLittleEndianValue<int32_t>(globals[j]);
int32_t sum = *(globals[g]) + i;
for (int j = 0; j < kNumGlobals; ++j) before[j] = *(globals[j]);
int32_t result = r.Call(i);
CHECK_EQ(sum, result);
for (int j = 0; j < kNumGlobals; ++j) {
int32_t expected = j == g ? sum : before[j];
CHECK_EQ(expected, ReadLittleEndianValue<int32_t>(globals[j]));
CHECK_EQ(expected, *(globals[j]));
}
}
}
......@@ -2168,11 +2167,11 @@ WASM_EXEC_TEST(Float32Global) {
WASM_F32_SCONVERT_I32(WASM_LOCAL_GET(0)))),
WASM_ZERO);
WriteLittleEndianValue<float>(global, 1.25);
*global = 1.25;
for (int i = 9; i < 4444; i += 1111) {
volatile float expected = ReadLittleEndianValue<float>(global) + i;
volatile float expected = *global + i;
r.Call(i);
CHECK_EQ(expected, ReadLittleEndianValue<float>(global));
CHECK_EQ(expected, *global);
}
}
......@@ -2186,11 +2185,11 @@ WASM_EXEC_TEST(Float64Global) {
WASM_F64_SCONVERT_I32(WASM_LOCAL_GET(0)))),
WASM_ZERO);
WriteLittleEndianValue<double>(global, 1.25);
*global = 1.25;
for (int i = 9; i < 4444; i += 1111) {
volatile double expected = ReadLittleEndianValue<double>(global) + i;
volatile double expected = *global + i;
r.Call(i);
CHECK_EQ(expected, ReadLittleEndianValue<double>(global));
CHECK_EQ(expected, *global);
}
}
......@@ -2221,13 +2220,10 @@ WASM_EXEC_TEST(MixedGlobals) {
memory[7] = 0x99;
r.Call(1);
CHECK(static_cast<int32_t>(0xEE55CCAA) ==
ReadLittleEndianValue<int32_t>(var_int32));
CHECK(static_cast<uint32_t>(0xEE55CCAA) ==
ReadLittleEndianValue<uint32_t>(var_uint32));
CHECK(bit_cast<float>(0xEE55CCAA) == ReadLittleEndianValue<float>(var_float));
CHECK(bit_cast<double>(0x99112233EE55CCAAULL) ==
ReadLittleEndianValue<double>(var_double));
CHECK_EQ(static_cast<int32_t>(0xEE55CCAA), *var_int32);
CHECK_EQ(static_cast<uint32_t>(0xEE55CCAA), *var_uint32);
CHECK_EQ(bit_cast<float>(0xEE55CCAA), *var_float);
CHECK_EQ(bit_cast<double>(0x99112233EE55CCAAULL), *var_double);
USE(unused);
}
......
......@@ -36,7 +36,7 @@ void RunI8x16UnOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
r.Call(x);
int8_t expected = expected_op(x);
for (int i = 0; i < 16; i++) {
CHECK_EQ(expected, ReadLittleEndianValue<int8_t>(&g[i]));
CHECK_EQ(expected, LANE(g, i));
}
}
}
......@@ -62,7 +62,7 @@ void RunI8x16BinOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
r.Call(x, y);
T expected = expected_op(x, y);
for (int i = 0; i < 16; i++) {
CHECK_EQ(expected, ReadLittleEndianValue<T>(&g[i]));
CHECK_EQ(expected, LANE(g, i));
}
}
}
......@@ -100,8 +100,8 @@ void RunI8x16ShiftOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
r.Call(x);
int8_t expected = expected_op(x, shift);
for (int i = 0; i < 16; i++) {
CHECK_EQ(expected, ReadLittleEndianValue<int8_t>(&g_imm[i]));
CHECK_EQ(expected, ReadLittleEndianValue<int8_t>(&g_mem[i]));
CHECK_EQ(expected, LANE(g_imm, i));
CHECK_EQ(expected, LANE(g_mem, i));
}
}
}
......@@ -144,7 +144,7 @@ void RunI16x8UnOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
r.Call(x);
int16_t expected = expected_op(x);
for (int i = 0; i < 8; i++) {
CHECK_EQ(expected, ReadLittleEndianValue<int16_t>(&g[i]));
CHECK_EQ(expected, LANE(g, i));
}
}
}
......@@ -170,7 +170,7 @@ void RunI16x8BinOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
r.Call(x, y);
T expected = expected_op(x, y);
for (int i = 0; i < 8; i++) {
CHECK_EQ(expected, ReadLittleEndianValue<T>(&g[i]));
CHECK_EQ(expected, LANE(g, i));
}
}
}
......@@ -207,8 +207,8 @@ void RunI16x8ShiftOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
r.Call(x);
int16_t expected = expected_op(x, shift);
for (int i = 0; i < 8; i++) {
CHECK_EQ(expected, ReadLittleEndianValue<int16_t>(&g_imm[i]));
CHECK_EQ(expected, ReadLittleEndianValue<int16_t>(&g_mem[i]));
CHECK_EQ(expected, LANE(g_imm, i));
CHECK_EQ(expected, LANE(g_mem, i));
}
}
}
......@@ -251,7 +251,7 @@ void RunI32x4UnOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
r.Call(x);
int32_t expected = expected_op(x);
for (int i = 0; i < 4; i++) {
CHECK_EQ(expected, ReadLittleEndianValue<int32_t>(&g[i]));
CHECK_EQ(expected, LANE(g, i));
}
}
}
......@@ -276,7 +276,7 @@ void RunI32x4BinOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
r.Call(x, y);
int32_t expected = expected_op(x, y);
for (int i = 0; i < 4; i++) {
CHECK_EQ(expected, ReadLittleEndianValue<int32_t>(&g[i]));
CHECK_EQ(expected, LANE(g, i));
}
}
}
......@@ -307,8 +307,8 @@ void RunI32x4ShiftOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
r.Call(x);
int32_t expected = expected_op(x, shift);
for (int i = 0; i < 4; i++) {
CHECK_EQ(expected, ReadLittleEndianValue<int32_t>(&g_imm[i]));
CHECK_EQ(expected, ReadLittleEndianValue<int32_t>(&g_mem[i]));
CHECK_EQ(expected, LANE(g_imm, i));
CHECK_EQ(expected, LANE(g_mem, i));
}
}
}
......@@ -330,7 +330,7 @@ void RunI64x2UnOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
r.Call(x);
int64_t expected = expected_op(x);
for (int i = 0; i < 2; i++) {
CHECK_EQ(expected, ReadLittleEndianValue<int64_t>(&g[i]));
CHECK_EQ(expected, LANE(g, i));
}
}
}
......@@ -355,7 +355,7 @@ void RunI64x2BinOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
r.Call(x, y);
int64_t expected = expected_op(x, y);
for (int i = 0; i < 2; i++) {
CHECK_EQ(expected, ReadLittleEndianValue<int64_t>(&g[i]));
CHECK_EQ(expected, LANE(g, i));
}
}
}
......@@ -386,8 +386,8 @@ void RunI64x2ShiftOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
r.Call(x);
int64_t expected = expected_op(x, shift);
for (int i = 0; i < 2; i++) {
CHECK_EQ(expected, ReadLittleEndianValue<int64_t>(&g_imm[i]));
CHECK_EQ(expected, ReadLittleEndianValue<int64_t>(&g_mem[i]));
CHECK_EQ(expected, LANE(g_imm, i));
CHECK_EQ(expected, LANE(g_mem, i));
}
}
}
......@@ -470,7 +470,7 @@ void RunF32x4UnOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
if (!PlatformCanRepresent(expected)) continue;
r.Call(x);
for (int i = 0; i < 4; i++) {
float actual = ReadLittleEndianValue<float>(&g[i]);
float actual = LANE(g, i);
CheckFloatResult(x, x, expected, actual, exact);
}
}
......@@ -484,7 +484,7 @@ void RunF32x4UnOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
if (!PlatformCanRepresent(expected)) continue;
r.Call(x);
for (int i = 0; i < 4; i++) {
float actual = ReadLittleEndianValue<float>(&g[i]);
float actual = LANE(g, i);
CheckFloatResult(x, x, expected, actual, exact);
}
}
......@@ -513,7 +513,7 @@ void RunF32x4BinOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
if (!PlatformCanRepresent(expected)) continue;
r.Call(x, y);
for (int i = 0; i < 4; i++) {
float actual = ReadLittleEndianValue<float>(&g[i]);
float actual = g[i];
CheckFloatResult(x, y, expected, actual, true /* exact */);
}
}
......@@ -529,7 +529,7 @@ void RunF32x4BinOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
if (!PlatformCanRepresent(expected)) continue;
r.Call(x, y);
for (int i = 0; i < 4; i++) {
float actual = ReadLittleEndianValue<float>(&g[i]);
float actual = LANE(g, i);
CheckFloatResult(x, y, expected, actual, true /* exact */);
}
}
......@@ -560,7 +560,7 @@ void RunF32x4CompareOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
r.Call(x, y);
int32_t expected = expected_op(x, y);
for (int i = 0; i < 4; i++) {
CHECK_EQ(expected, ReadLittleEndianValue<int32_t>(&g[i]));
CHECK_EQ(expected, LANE(g, i));
}
}
}
......@@ -643,7 +643,7 @@ void RunF64x2UnOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
if (!PlatformCanRepresent(expected)) continue;
r.Call(x);
for (int i = 0; i < 2; i++) {
double actual = ReadLittleEndianValue<double>(&g[i]);
double actual = LANE(g, i);
CheckDoubleResult(x, x, expected, actual, exact);
}
}
......@@ -657,7 +657,7 @@ void RunF64x2UnOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
if (!PlatformCanRepresent(expected)) continue;
r.Call(x);
for (int i = 0; i < 2; i++) {
double actual = ReadLittleEndianValue<double>(&g[i]);
double actual = LANE(g, i);
CheckDoubleResult(x, x, expected, actual, exact);
}
}
......@@ -686,7 +686,7 @@ void RunF64x2BinOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
if (!PlatformCanRepresent(expected)) continue;
r.Call(x, y);
for (int i = 0; i < 2; i++) {
double actual = ReadLittleEndianValue<double>(&g[i]);
double actual = LANE(g, i);
CheckDoubleResult(x, y, expected, actual, true /* exact */);
}
}
......@@ -701,7 +701,7 @@ void RunF64x2BinOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
if (!PlatformCanRepresent(expected)) continue;
r.Call(x, y);
for (int i = 0; i < 2; i++) {
double actual = ReadLittleEndianValue<double>(&g[i]);
double actual = LANE(g, i);
CheckDoubleResult(x, y, expected, actual, true /* exact */);
}
}
......@@ -737,8 +737,8 @@ void RunF64x2CompareOpTest(TestExecutionTier execution_tier, WasmOpcode opcode,
r.Call(x, y);
int64_t expected0 = expected_op(x, y);
int64_t expected1 = expected_op(y, y);
CHECK_EQ(expected0, ReadLittleEndianValue<int64_t>(&g[0]));
CHECK_EQ(expected1, ReadLittleEndianValue<int64_t>(&g[1]));
CHECK_EQ(expected0, LANE(g, 0));
CHECK_EQ(expected1, LANE(g, 1));
}
}
}
......
......@@ -3698,8 +3698,7 @@ class WasmInterpreterInternals {
case valuetype: { \
uint8_t* ptr = \
WasmInstanceObject::GetGlobalStorage(instance_object_, global); \
WriteLittleEndianValue<ctype>(reinterpret_cast<Address>(ptr), \
Pop().to<ctype>()); \
*reinterpret_cast<ctype*>(ptr) = Pop().to<ctype>(); \
break; \
}
FOREACH_WASMVALUE_CTYPES(CASE_TYPE)
......
......@@ -975,6 +975,15 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) {
#define WASM_SIMD_LOAD_OP_ALIGNMENT(opcode, index, alignment) \
index, WASM_SIMD_OP(opcode), alignment, ZERO_OFFSET
// Load a Simd lane from a numeric pointer. We need this because lanes are
// reversed in big endian. Note: a Simd value has {kSimd128Size / sizeof(*ptr)}
// lanes.
#ifdef V8_TARGET_BIG_ENDIAN
#define LANE(ptr, index) ptr[kSimd128Size / sizeof(*ptr) - (index)-1]
#else
#define LANE(ptr, index) ptr[index]
#endif
//------------------------------------------------------------------------------
// Compilation Hints.
//------------------------------------------------------------------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment