diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/Asyncify.cpp | 74 | ||||
-rw-r--r-- | src/wasm/wasm-type.cpp | 45 |
2 files changed, 70 insertions, 49 deletions
diff --git a/src/passes/Asyncify.cpp b/src/passes/Asyncify.cpp index f8fd6085b..05c1c8954 100644 --- a/src/passes/Asyncify.cpp +++ b/src/passes/Asyncify.cpp @@ -1115,9 +1115,7 @@ private: auto* func = getFunction(); Index total = 0; for (Index i = 0; i < numPreservableLocals; i++) { - auto type = func->getLocalType(i); - auto size = type.getByteSize(); - total += size; + total += func->getLocalType(i).getByteSize(); } auto* block = builder->makeBlock(); block->list.push_back(builder->makeIncStackPos(-total)); @@ -1126,19 +1124,31 @@ private: builder->makeLocalSet(tempIndex, builder->makeGetStackPos())); Index offset = 0; for (Index i = 0; i < numPreservableLocals; i++) { - auto type = func->getLocalType(i); - auto size = type.getByteSize(); - assert(size % STACK_ALIGN == 0); - // TODO: higher alignment? - block->list.push_back(builder->makeLocalSet( - i, - builder->makeLoad(size, - true, - offset, - STACK_ALIGN, - builder->makeLocalGet(tempIndex, Type::i32), - type))); - offset += size; + const auto& types = func->getLocalType(i).expand(); + SmallVector<Expression*, 1> loads; + for (Index j = 0; j < types.size(); j++) { + auto type = types[j]; + auto size = type.getByteSize(); + assert(size % STACK_ALIGN == 0); + // TODO: higher alignment? + loads.push_back( + builder->makeLoad(size, + true, + offset, + STACK_ALIGN, + builder->makeLocalGet(tempIndex, Type::i32), + type)); + offset += size; + } + Expression* load; + if (loads.size() == 1) { + load = loads[0]; + } else if (types.size() > 1) { + load = builder->makeTupleMake(std::move(loads)); + } else { + WASM_UNREACHABLE("Unexpected empty type"); + } + block->list.push_back(builder->makeLocalSet(i, load)); } block->finalize(); return block; @@ -1155,18 +1165,26 @@ private: builder->makeLocalSet(tempIndex, builder->makeGetStackPos())); Index offset = 0; for (Index i = 0; i < numPreservableLocals; i++) { - auto type = func->getLocalType(i); - auto size = type.getByteSize(); - assert(size % STACK_ALIGN == 0); - // TODO: higher alignment? - block->list.push_back( - builder->makeStore(size, - offset, - STACK_ALIGN, - builder->makeLocalGet(tempIndex, Type::i32), - builder->makeLocalGet(i, type), - type)); - offset += size; + auto localType = func->getLocalType(i); + const auto& types = localType.expand(); + for (Index j = 0; j < types.size(); j++) { + auto type = types[j]; + auto size = type.getByteSize(); + Expression* localGet = builder->makeLocalGet(i, localType); + if (types.size() > 1) { + localGet = builder->makeTupleExtract(localGet, j); + } + assert(size % STACK_ALIGN == 0); + // TODO: higher alignment? + block->list.push_back( + builder->makeStore(size, + offset, + STACK_ALIGN, + builder->makeLocalGet(tempIndex, Type::i32), + localGet, + type)); + offset += size; + } } block->list.push_back(builder->makeIncStackPos(offset)); block->finalize(); diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index 024894dfb..a98d10be4 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -145,28 +145,31 @@ bool Type::operator<(const Type& other) const { } unsigned Type::getByteSize() const { - assert(isSingle() && "getByteSize does not works with single types"); - Type singleType = *expand().begin(); - switch (singleType.getSingle()) { - case Type::i32: - return 4; - case Type::i64: - return 8; - case Type::f32: - return 4; - case Type::f64: - return 8; - case Type::v128: - return 16; - case Type::funcref: - case Type::anyref: - case Type::nullref: - case Type::exnref: - case Type::none: - case Type::unreachable: - WASM_UNREACHABLE("invalid type"); + // TODO: alignment? + unsigned size = 0; + for (auto t : expand()) { + switch (t.getSingle()) { + case Type::i32: + case Type::f32: + size += 4; + break; + case Type::i64: + case Type::f64: + size += 8; + break; + case Type::v128: + size += 16; + break; + case Type::funcref: + case Type::anyref: + case Type::nullref: + case Type::exnref: + case Type::none: + case Type::unreachable: + WASM_UNREACHABLE("invalid type"); + } } - WASM_UNREACHABLE("invalid type"); + return size; } Type Type::reinterpret() const { |