Commit 7c64d883 authored by Deepti Gandluri's avatar Deepti Gandluri Committed by Commit Bot

[wasm] Use DefaultLowering for I64Atomic narrow operations

Clusterfuzz generated test cases for narrow Load, CmpExchg nodes in
which the index is a word64 expression. This was not handled correctly
leading to a malformed graph. Use default lowering for all atomic
narrow operations, and add reduced test cases in wasm cctests with the
same sequence as the ones generated by binaryen for other I64Atomic
operations as well.

Change-Id: I50d63747b16a8f69289ca4e76547b325d84b22d3
Bug: chromium:921366, chromium:920120, chromium:900681
Reviewed-on: https://chromium-review.googlesource.com/c/1423177
Commit-Queue: Deepti Gandluri <gdeepti@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59012}
parent f243c942
...@@ -127,8 +127,7 @@ void Int64Lowering::LowerWord64AtomicBinop(Node* node, const Operator* op) { ...@@ -127,8 +127,7 @@ void Int64Lowering::LowerWord64AtomicBinop(Node* node, const Operator* op) {
} }
void Int64Lowering::LowerWord64AtomicNarrowOp(Node* node, const Operator* op) { void Int64Lowering::LowerWord64AtomicNarrowOp(Node* node, const Operator* op) {
Node* value = node->InputAt(2); DefaultLowering(node, true);
node->ReplaceInput(2, GetReplacementLow(value));
NodeProperties::ChangeOp(node, op); NodeProperties::ChangeOp(node, op);
ReplaceNode(node, node, graph()->NewNode(common()->Int32Constant(0))); ReplaceNode(node, node, graph()->NewNode(common()->Int32Constant(0)));
} }
...@@ -887,6 +886,7 @@ void Int64Lowering::LowerNode(Node* node) { ...@@ -887,6 +886,7 @@ void Int64Lowering::LowerNode(Node* node) {
case IrOpcode::kWord64AtomicLoad: { case IrOpcode::kWord64AtomicLoad: {
DCHECK_EQ(4, node->InputCount()); DCHECK_EQ(4, node->InputCount());
MachineType type = AtomicOpType(node->op()); MachineType type = AtomicOpType(node->op());
DefaultLowering(node, true);
if (type == MachineType::Uint64()) { if (type == MachineType::Uint64()) {
NodeProperties::ChangeOp(node, machine()->Word32AtomicPairLoad()); NodeProperties::ChangeOp(node, machine()->Word32AtomicPairLoad());
ReplaceNodeWithProjections(node); ReplaceNodeWithProjections(node);
...@@ -942,10 +942,7 @@ void Int64Lowering::LowerNode(Node* node) { ...@@ -942,10 +942,7 @@ void Int64Lowering::LowerNode(Node* node) {
} else { } else {
DCHECK(type == MachineType::Uint32() || type == MachineType::Uint16() || DCHECK(type == MachineType::Uint32() || type == MachineType::Uint16() ||
type == MachineType::Uint8()); type == MachineType::Uint8());
Node* old_value = node->InputAt(2); DefaultLowering(node, true);
node->ReplaceInput(2, GetReplacementLow(old_value));
Node* new_value = node->InputAt(3);
node->ReplaceInput(3, GetReplacementLow(new_value));
NodeProperties::ChangeOp(node, NodeProperties::ChangeOp(node,
machine()->Word32AtomicCompareExchange(type)); machine()->Word32AtomicCompareExchange(type));
ReplaceNode(node, node, graph()->NewNode(common()->Int32Constant(0))); ReplaceNode(node, node, graph()->NewNode(common()->Int32Constant(0)));
......
...@@ -520,6 +520,104 @@ WASM_EXEC_TEST(I64AtomicConvertCompareExchange) { ...@@ -520,6 +520,104 @@ WASM_EXEC_TEST(I64AtomicConvertCompareExchange) {
CHECK_EQ(expected, r.builder().ReadMemory(&memory[0])); CHECK_EQ(expected, r.builder().ReadMemory(&memory[0]));
} }
// The WASM_I64_EQ operation is used here to test that the index node
// is lowered correctly.
void RunNonConstIndexTest(ExecutionTier execution_tier, WasmOpcode wasm_op,
Uint64BinOp op) {
EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint32_t, uint64_t> r(execution_tier);
uint64_t* memory =
r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
r.builder().SetHasSharedMemory();
BUILD(r, WASM_I32_CONVERT_I64(WASM_ATOMICS_BINOP(
wasm_op, WASM_I64_EQ(WASM_I64V(1), WASM_I64V(0)),
WASM_GET_LOCAL(0), MachineRepresentation::kWord32)));
uint64_t initial = 0x1111222233334444, local = 0x5555666677778888;
r.builder().WriteMemory(&memory[0], initial);
CHECK_EQ(static_cast<uint32_t>(initial), r.Call(local));
CHECK_EQ(static_cast<uint32_t>(op(initial, local)),
static_cast<uint32_t>(r.builder().ReadMemory(&memory[0])));
}
#define TEST_OPERATION(Name) \
WASM_EXEC_TEST(I64AtomicConstIndex##Name) { \
RunNonConstIndexTest(execution_tier, kExprI64Atomic##Name##32U, Name); \
}
OPERATION_LIST(TEST_OPERATION)
#undef TEST_OPERATION
WASM_EXEC_TEST(I64AtomicNonConstIndexCompareExchange) {
EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint32_t, uint64_t, uint64_t> r(execution_tier);
uint64_t* memory =
r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
r.builder().SetHasSharedMemory();
BUILD(r, WASM_I32_CONVERT_I64(WASM_ATOMICS_TERNARY_OP(
kExprI64AtomicCompareExchange16U,
WASM_I64_EQ(WASM_I64V(1), WASM_I64V(0)), WASM_GET_LOCAL(0),
WASM_GET_LOCAL(1), MachineRepresentation::kWord16)));
uint64_t initial = 4444333322221111, local = 0x9999888877776666;
r.builder().WriteMemory(&memory[0], initial);
CHECK_EQ(static_cast<uint16_t>(initial), r.Call(initial, local));
CHECK_EQ(static_cast<uint16_t>(CompareExchange(initial, initial, local)),
static_cast<uint16_t>(r.builder().ReadMemory(&memory[0])));
}
WASM_EXEC_TEST(I64AtomicNonConstIndexLoad8U) {
EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint32_t> r(execution_tier);
r.builder().SetHasSharedMemory();
uint64_t* memory =
r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
BUILD(r, WASM_I32_CONVERT_I64(WASM_ATOMICS_LOAD_OP(
kExprI64AtomicLoad8U, WASM_I64_EQ(WASM_I64V(1), WASM_I64V(0)),
MachineRepresentation::kWord8)));
uint64_t expected = 0xffffeeeeddddcccc;
r.builder().WriteMemory(&memory[0], expected);
CHECK_EQ(static_cast<uint8_t>(expected), r.Call());
}
WASM_EXEC_TEST(I64AtomicCompareExchangeFail) {
EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_tier);
r.builder().SetHasSharedMemory();
uint64_t* memory =
r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
BUILD(r, WASM_ATOMICS_TERNARY_OP(
kExprI64AtomicCompareExchange, WASM_I32V_1(0), WASM_GET_LOCAL(0),
WASM_GET_LOCAL(1), MachineRepresentation::kWord64));
uint64_t initial = 0x1111222233334444, local = 0x1111111111111111,
test = 0x2222222222222222;
r.builder().WriteMemory(&memory[0], initial);
CHECK_EQ(initial, r.Call(test, local));
// No memory change on failed compare exchange
CHECK_EQ(initial, r.builder().ReadMemory(&memory[0]));
}
WASM_EXEC_TEST(I64AtomicCompareExchange32UFail) {
EXPERIMENTAL_FLAG_SCOPE(threads);
WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_tier);
r.builder().SetHasSharedMemory();
uint64_t* memory =
r.builder().AddMemoryElems<uint64_t>(kWasmPageSize / sizeof(uint64_t));
BUILD(r, WASM_ATOMICS_TERNARY_OP(kExprI64AtomicCompareExchange32U,
WASM_I32V_1(0), WASM_GET_LOCAL(0),
WASM_GET_LOCAL(1),
MachineRepresentation::kWord32));
uint64_t initial = 0x1111222233334444, test = 0xffffffff, local = 0xeeeeeeee;
r.builder().WriteMemory(&memory[0], initial);
CHECK_EQ(static_cast<uint32_t>(initial), r.Call(test, local));
// No memory change on failed compare exchange
CHECK_EQ(initial, r.builder().ReadMemory(&memory[0]));
}
} // namespace test_run_wasm_atomics_64 } // namespace test_run_wasm_atomics_64
} // namespace wasm } // namespace wasm
} // namespace internal } // namespace internal
......
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