Commit 050dec2b authored by sreten.kovacevic's avatar sreten.kovacevic Committed by Commit Bot

[wasm] Fix issue with wasm-spec-tests on mips big endian

Found issue with BuildChangeEndianness. There is difference between load and store case.

Load depends primarily on MachineRepresentation, while store depends on ValueType.

TEST=wasm-spec-tests/tests/endianness
TEST=wasm-spec-tests/tests/memory
TEST=wasm-spec-tests/tests/memory_trap

Bug: 
Change-Id: I437f611107daad2f425a67fcc068e874822e0f58
Reviewed-on: https://chromium-review.googlesource.com/558882Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Ivica Bogosavljevic <ivica.bogosavljevic@imgtec.com>
Cr-Commit-Position: refs/heads/master@{#46645}
parent 2941d76c
...@@ -1009,8 +1009,157 @@ static bool ReverseBytesSupported(MachineOperatorBuilder* m, ...@@ -1009,8 +1009,157 @@ static bool ReverseBytesSupported(MachineOperatorBuilder* m,
return false; return false;
} }
Node* WasmGraphBuilder::BuildChangeEndianness(Node* node, MachineType memtype, Node* WasmGraphBuilder::BuildChangeEndiannessStore(Node* node,
wasm::ValueType wasmtype) { MachineType memtype,
wasm::ValueType wasmtype) {
Node* result;
Node* value = node;
MachineOperatorBuilder* m = jsgraph()->machine();
int valueSizeInBytes = 1 << ElementSizeLog2Of(wasmtype);
int valueSizeInBits = 8 * valueSizeInBytes;
bool isFloat = false;
switch (wasmtype) {
case wasm::kWasmF64:
value = graph()->NewNode(m->BitcastFloat64ToInt64(), node);
isFloat = true;
case wasm::kWasmI64:
result = jsgraph()->Int64Constant(0);
break;
case wasm::kWasmF32:
value = graph()->NewNode(m->BitcastFloat32ToInt32(), node);
isFloat = true;
case wasm::kWasmI32:
result = jsgraph()->Int32Constant(0);
break;
case wasm::kWasmS128:
DCHECK(ReverseBytesSupported(m, valueSizeInBytes));
break;
default:
UNREACHABLE();
break;
}
if (memtype.representation() == MachineRepresentation::kWord8) {
// No need to change endianness for byte size, return original node
return node;
}
if (wasmtype == wasm::kWasmI64 &&
memtype.representation() < MachineRepresentation::kWord64) {
// In case we store lower part of WasmI64 expression, we can truncate
// upper 32bits
value = graph()->NewNode(m->TruncateInt64ToInt32(), value);
valueSizeInBytes = 1 << ElementSizeLog2Of(wasm::kWasmI32);
valueSizeInBits = 8 * valueSizeInBytes;
if (memtype.representation() == MachineRepresentation::kWord16) {
value =
graph()->NewNode(m->Word32Shl(), value, jsgraph()->Int32Constant(16));
}
} else if (wasmtype == wasm::kWasmI32 &&
memtype.representation() == MachineRepresentation::kWord16) {
value =
graph()->NewNode(m->Word32Shl(), value, jsgraph()->Int32Constant(16));
}
int i;
uint32_t shiftCount;
if (ReverseBytesSupported(m, valueSizeInBytes)) {
switch (valueSizeInBytes) {
case 4:
result = graph()->NewNode(m->Word32ReverseBytes().op(), value);
break;
case 8:
result = graph()->NewNode(m->Word64ReverseBytes().op(), value);
break;
case 16: {
Node* byte_reversed_lanes[4];
for (int lane = 0; lane < 4; lane++) {
byte_reversed_lanes[lane] = graph()->NewNode(
m->Word32ReverseBytes().op(),
graph()->NewNode(jsgraph()->machine()->I32x4ExtractLane(lane),
value));
}
// This is making a copy of the value.
result =
graph()->NewNode(jsgraph()->machine()->S128And(), value, value);
for (int lane = 0; lane < 4; lane++) {
result =
graph()->NewNode(jsgraph()->machine()->I32x4ReplaceLane(3 - lane),
result, byte_reversed_lanes[lane]);
}
break;
}
default:
UNREACHABLE();
break;
}
} else {
for (i = 0, shiftCount = valueSizeInBits - 8; i < valueSizeInBits / 2;
i += 8, shiftCount -= 16) {
Node* shiftLower;
Node* shiftHigher;
Node* lowerByte;
Node* higherByte;
DCHECK(shiftCount > 0);
DCHECK((shiftCount + 8) % 16 == 0);
if (valueSizeInBits > 32) {
shiftLower = graph()->NewNode(m->Word64Shl(), value,
jsgraph()->Int64Constant(shiftCount));
shiftHigher = graph()->NewNode(m->Word64Shr(), value,
jsgraph()->Int64Constant(shiftCount));
lowerByte = graph()->NewNode(
m->Word64And(), shiftLower,
jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF)
<< (valueSizeInBits - 8 - i)));
higherByte = graph()->NewNode(
m->Word64And(), shiftHigher,
jsgraph()->Int64Constant(static_cast<uint64_t>(0xFF) << i));
result = graph()->NewNode(m->Word64Or(), result, lowerByte);
result = graph()->NewNode(m->Word64Or(), result, higherByte);
} else {
shiftLower = graph()->NewNode(m->Word32Shl(), value,
jsgraph()->Int32Constant(shiftCount));
shiftHigher = graph()->NewNode(m->Word32Shr(), value,
jsgraph()->Int32Constant(shiftCount));
lowerByte = graph()->NewNode(
m->Word32And(), shiftLower,
jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF)
<< (valueSizeInBits - 8 - i)));
higherByte = graph()->NewNode(
m->Word32And(), shiftHigher,
jsgraph()->Int32Constant(static_cast<uint32_t>(0xFF) << i));
result = graph()->NewNode(m->Word32Or(), result, lowerByte);
result = graph()->NewNode(m->Word32Or(), result, higherByte);
}
}
}
if (isFloat) {
switch (wasmtype) {
case wasm::kWasmF64:
result = graph()->NewNode(m->BitcastInt64ToFloat64(), result);
break;
case wasm::kWasmF32:
result = graph()->NewNode(m->BitcastInt32ToFloat32(), result);
break;
default:
UNREACHABLE();
break;
}
}
return result;
}
Node* WasmGraphBuilder::BuildChangeEndiannessLoad(Node* node,
MachineType memtype,
wasm::ValueType wasmtype) {
Node* result; Node* result;
Node* value = node; Node* value = node;
MachineOperatorBuilder* m = jsgraph()->machine(); MachineOperatorBuilder* m = jsgraph()->machine();
...@@ -3083,7 +3232,7 @@ Node* WasmGraphBuilder::LoadMem(wasm::ValueType type, MachineType memtype, ...@@ -3083,7 +3232,7 @@ Node* WasmGraphBuilder::LoadMem(wasm::ValueType type, MachineType memtype,
*effect_ = load; *effect_ = load;
#if defined(V8_TARGET_BIG_ENDIAN) #if defined(V8_TARGET_BIG_ENDIAN)
load = BuildChangeEndianness(load, memtype, type); load = BuildChangeEndiannessLoad(load, memtype, type);
#endif #endif
if (type == wasm::kWasmI64 && if (type == wasm::kWasmI64 &&
...@@ -3102,10 +3251,10 @@ Node* WasmGraphBuilder::LoadMem(wasm::ValueType type, MachineType memtype, ...@@ -3102,10 +3251,10 @@ Node* WasmGraphBuilder::LoadMem(wasm::ValueType type, MachineType memtype,
return load; return load;
} }
Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index,
uint32_t offset, uint32_t alignment, Node* val, uint32_t offset, uint32_t alignment, Node* val,
wasm::WasmCodePosition position) { wasm::WasmCodePosition position,
wasm::ValueType type) {
Node* store; Node* store;
// Wasm semantics throw on OOB. Introduce explicit bounds check. // Wasm semantics throw on OOB. Introduce explicit bounds check.
...@@ -3114,7 +3263,7 @@ Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, ...@@ -3114,7 +3263,7 @@ Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index,
} }
#if defined(V8_TARGET_BIG_ENDIAN) #if defined(V8_TARGET_BIG_ENDIAN)
val = BuildChangeEndianness(val, memtype); val = BuildChangeEndiannessStore(val, memtype, type);
#endif #endif
if (memtype.representation() == MachineRepresentation::kWord8 || if (memtype.representation() == MachineRepresentation::kWord8 ||
......
...@@ -237,10 +237,9 @@ class WasmGraphBuilder { ...@@ -237,10 +237,9 @@ class WasmGraphBuilder {
Node* LoadMem(wasm::ValueType type, MachineType memtype, Node* index, Node* LoadMem(wasm::ValueType type, MachineType memtype, Node* index,
uint32_t offset, uint32_t alignment, uint32_t offset, uint32_t alignment,
wasm::WasmCodePosition position); wasm::WasmCodePosition position);
Node* StoreMem(MachineType type, Node* index, uint32_t offset, Node* StoreMem(MachineType memtype, Node* index, uint32_t offset,
uint32_t alignment, Node* val, uint32_t alignment, Node* val, wasm::WasmCodePosition position,
wasm::WasmCodePosition position); wasm::ValueType type = wasm::kWasmStmt);
static void PrintDebugName(Node* node); static void PrintDebugName(Node* node);
Node* Control() { return *control_; } Node* Control() { return *control_; }
...@@ -312,8 +311,10 @@ class WasmGraphBuilder { ...@@ -312,8 +311,10 @@ class WasmGraphBuilder {
void BoundsCheckMem(MachineType memtype, Node* index, uint32_t offset, void BoundsCheckMem(MachineType memtype, Node* index, uint32_t offset,
wasm::WasmCodePosition position); wasm::WasmCodePosition position);
const Operator* GetSafeStoreOperator(int offset, wasm::ValueType type); const Operator* GetSafeStoreOperator(int offset, wasm::ValueType type);
Node* BuildChangeEndianness(Node* node, MachineType type, Node* BuildChangeEndiannessStore(Node* node, MachineType type,
wasm::ValueType wasmtype = wasm::kWasmStmt); wasm::ValueType wasmtype = wasm::kWasmStmt);
Node* BuildChangeEndiannessLoad(Node* node, MachineType type,
wasm::ValueType wasmtype = wasm::kWasmStmt);
Node* MaskShiftCount32(Node* node); Node* MaskShiftCount32(Node* node);
Node* MaskShiftCount64(Node* node); Node* MaskShiftCount64(Node* node);
......
...@@ -1509,7 +1509,7 @@ class WasmFullDecoder : public WasmDecoder { ...@@ -1509,7 +1509,7 @@ class WasmFullDecoder : public WasmDecoder {
Value val = Pop(1, type); Value val = Pop(1, type);
Value index = Pop(0, kWasmI32); Value index = Pop(0, kWasmI32);
BUILD(StoreMem, mem_type, index.node, operand.offset, operand.alignment, BUILD(StoreMem, mem_type, index.node, operand.offset, operand.alignment,
val.node, position()); val.node, position(), type);
return 1 + operand.length; return 1 + operand.length;
} }
......
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