diff options
author | Sam Clegg <sbc@chromium.org> | 2024-07-11 16:36:13 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-11 16:36:13 -0700 |
commit | 22c28bd5a108f9bdacd1b60468e312903bcdf451 (patch) | |
tree | a44677277b4b6e215836697946a7e394472cbe0f | |
parent | 363edc7fc9117824615502e02bf2fb2a05eb9c15 (diff) | |
download | binaryen-22c28bd5a108f9bdacd1b60468e312903bcdf451.tar.gz binaryen-22c28bd5a108f9bdacd1b60468e312903bcdf451.tar.bz2 binaryen-22c28bd5a108f9bdacd1b60468e312903bcdf451.zip |
Memory64Lowering: Handle -1 return value from memory.grow (#6733)
This edge case make the lowering a little more tricky.
-rw-r--r-- | src/passes/Memory64Lowering.cpp | 27 | ||||
-rw-r--r-- | test/lit/passes/memory64-lowering.wast | 22 |
2 files changed, 43 insertions, 6 deletions
diff --git a/src/passes/Memory64Lowering.cpp b/src/passes/Memory64Lowering.cpp index c1ce3dd91..879858b71 100644 --- a/src/passes/Memory64Lowering.cpp +++ b/src/passes/Memory64Lowering.cpp @@ -79,9 +79,32 @@ struct Memory64Lowering : public WalkerPass<PostWalker<Memory64Lowering>> { if (memory->is64()) { wrapAddress64(curr->delta, curr->memory); auto* size = static_cast<Expression*>(curr); - extendAddress64(size, curr->memory); + // MemoryGrow returns -1 in case of failure. We cannot just use + // extend_32_u in this case so we handle it as follows: + // + // (if (result i64) + // (i32.eq (i32.const -1) (local.tee $tmp (memory.grow X))) + // (then + // (i64.const -1) + // ) + // (else + // (i32.extend_32_u (local.get $tmp)) + // ) + // ) + Builder builder(module); + auto tmp = builder.addVar(getFunction(), Type::i32); + Expression* isMinusOne = + builder.makeBinary(EqInt32, + builder.makeConst(int32_t(-1)), + builder.makeLocalTee(tmp, size, Type::i32)); + auto* newSize = builder.makeLocalGet(tmp, Type::i32); + builder.makeUnary(UnaryOp::ExtendUInt32, newSize); + Expression* ifExp = + builder.makeIf(isMinusOne, + builder.makeConst(int64_t(-1)), + builder.makeUnary(UnaryOp::ExtendUInt32, newSize)); curr->type = Type::i32; - replaceCurrent(size); + replaceCurrent(ifExp); } } diff --git a/test/lit/passes/memory64-lowering.wast b/test/lit/passes/memory64-lowering.wast index ced069401..4f9d3d050 100644 --- a/test/lit/passes/memory64-lowering.wast +++ b/test/lit/passes/memory64-lowering.wast @@ -225,16 +225,30 @@ ;; CHECK: (func $other ;; CHECK-NEXT: (local $0 i64) + ;; CHECK-NEXT: (local $1 i32) ;; CHECK-NEXT: (local.set $0 ;; CHECK-NEXT: (i64.extend_i32_u ;; CHECK-NEXT: (memory.size) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (i64.extend_i32_u - ;; CHECK-NEXT: (memory.grow - ;; CHECK-NEXT: (i32.wrap_i64 - ;; CHECK-NEXT: (i64.const 1) + ;; CHECK-NEXT: (if (result i64) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: (local.tee $1 + ;; CHECK-NEXT: (memory.grow + ;; CHECK-NEXT: (i32.wrap_i64 + ;; CHECK-NEXT: (i64.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (i64.const -1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (i64.extend_i32_u + ;; CHECK-NEXT: (local.get $1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) |