diff --git a/CHANGELOG.md b/CHANGELOG.md index 491163aba05..bfae16e8918 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,10 @@ full changeset diff at the end of each section. Current Trunk ------------- +- Remove old/broken SpollPointers pass. This pass: Spills values that might be + pointers to the C stack. This allows Boehm-style GC to see them properly. + This can be revived if needed from git history (#3261). + v98 --- diff --git a/src/abi/abi.h b/src/abi/abi.h deleted file mode 100644 index 239efd3f3bd..00000000000 --- a/src/abi/abi.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2017 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef wasm_abi_abi_h -#define wasm_abi_abi_h - -#include "wasm.h" - -namespace wasm { - -namespace ABI { - -// The pointer type. Will need to update this for wasm64 -const static Type PointerType = Type::i32; - -} // namespace ABI - -} // namespace wasm - -#endif // wasm_abi_abi_h diff --git a/src/abi/stack.h b/src/abi/stack.h deleted file mode 100644 index e217d7caaba..00000000000 --- a/src/abi/stack.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2017 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef wasm_abi_stack_h -#define wasm_abi_stack_h - -#include "abi.h" -#include "asmjs/shared-constants.h" -#include "ir/find_all.h" -#include "ir/global-utils.h" -#include "shared-constants.h" -#include "wasm-builder.h" -#include "wasm.h" - -namespace wasm { - -namespace ABI { - -enum { StackAlign = 16 }; - -inline Index stackAlign(Index size) { - return (size + StackAlign - 1) & -StackAlign; -} - -// Allocate some space on the stack, and assign it to a local. -// The local will have the same constant value in all the function, so you can -// just local.get it anywhere there. -// -// FIXME: This function assumes that the stack grows upward, per the convention -// used by fastcomp. The stack grows downward when using the WASM backend. - -inline void -getStackSpace(Index local, Function* func, Index size, Module& wasm) { - // Attempt to locate the stack pointer by recognizing code idioms - // used by Emscripten. First, look for a global initialized to an - // imported variable named "STACKTOP" in environment "env". - auto* stackPointer = - GlobalUtils::getGlobalInitializedToImport(wasm, ENV, "STACKTOP"); - // Starting with Emscripten 1.38.24, the stack pointer variable is - // initialized with a literal constant, eliminating the import that - // we used to locate the stack pointer by name. We must match a more - // complicated idiom, expecting to see the module structured as follows: - // - //(module - // ... - // (export "stackSave" (func $stackSave)) - // ... - // (func $stackSave (; 410 ;) (; has Stack IR ;) (result i32) - // (global.get $STACKTOP) - // ) - // ... - //) - if (!stackPointer) { - auto* stackSaveFunctionExport = wasm.getExportOrNull("stackSave"); - if (stackSaveFunctionExport && - stackSaveFunctionExport->kind == ExternalKind::Function) { - auto* stackSaveFunction = - wasm.getFunction(stackSaveFunctionExport->value); - assert(!stackSaveFunction->imported()); - auto* globalGet = stackSaveFunction->body->dynCast(); - if (globalGet) { - stackPointer = wasm.getGlobal(globalGet->name); - } - } - } - if (!stackPointer) { - Fatal() << "getStackSpace: failed to find the stack pointer"; - } - // align the size - size = stackAlign(size); - // TODO: find existing stack usage, and add on top of that - carefully - Builder builder(wasm); - auto* block = builder.makeBlock(); - block->list.push_back(builder.makeLocalSet( - local, builder.makeGlobalGet(stackPointer->name, PointerType))); - // TODO: add stack max check - Expression* added; - if (PointerType == Type::i32) { - added = builder.makeBinary(AddInt32, - builder.makeLocalGet(local, PointerType), - builder.makeConst(int32_t(size))); - } else { - WASM_UNREACHABLE("unhandled PointerType"); - } - block->list.push_back(builder.makeGlobalSet(stackPointer->name, added)); - auto makeStackRestore = [&]() { - return builder.makeGlobalSet(stackPointer->name, - builder.makeLocalGet(local, PointerType)); - }; - // add stack restores to the returns - FindAllPointers finder(func->body); - for (auto** ptr : finder.list) { - auto* ret = (*ptr)->cast(); - if (ret->value && ret->value->type != Type::unreachable) { - // handle the returned value - auto* block = builder.makeBlock(); - auto temp = builder.addVar(func, ret->value->type); - block->list.push_back(builder.makeLocalSet(temp, ret->value)); - block->list.push_back(makeStackRestore()); - block->list.push_back( - builder.makeReturn(builder.makeLocalGet(temp, ret->value->type))); - block->finalize(); - *ptr = block; - } else { - // restore, then return - *ptr = builder.makeSequence(makeStackRestore(), ret); - } - } - // add stack restores to the body - if (func->body->type == Type::none) { - block->list.push_back(func->body); - block->list.push_back(makeStackRestore()); - } else if (func->body->type == Type::unreachable) { - block->list.push_back(func->body); - // no need to restore the old stack value, we're gone anyhow - } else { - // save the return value - auto temp = builder.addVar(func, func->sig.results); - block->list.push_back(builder.makeLocalSet(temp, func->body)); - block->list.push_back(makeStackRestore()); - block->list.push_back(builder.makeLocalGet(temp, func->sig.results)); - } - block->finalize(); - func->body = block; -} - -} // namespace ABI - -} // namespace wasm - -#endif // wasm_abi_stack_h diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt index 1551ba256cd..00cbaa526e0 100644 --- a/src/passes/CMakeLists.txt +++ b/src/passes/CMakeLists.txt @@ -76,7 +76,6 @@ set(passes_SOURCES SimplifyGlobals.cpp SimplifyLocals.cpp Souperify.cpp - SpillPointers.cpp StackCheck.cpp SSAify.cpp Untee.cpp diff --git a/src/passes/SpillPointers.cpp b/src/passes/SpillPointers.cpp deleted file mode 100644 index 4535105924c..00000000000 --- a/src/passes/SpillPointers.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright 2017 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Spills values that might be pointers to the C stack. This allows -// Boehm-style GC to see them properly. -// -// To reduce the overhead of the extra operations added here, you -// should probably run optimizations after doing it. -// TODO: add a dead store elimination pass, which would help here -// -// * There is currently no check that there is enough stack space. -// - -#include "abi/abi.h" -#include "abi/stack.h" -#include "cfg/liveness-traversal.h" -#include "pass.h" -#include "wasm-builder.h" -#include "wasm.h" - -namespace wasm { - -struct SpillPointers - : public WalkerPass>> { - bool isFunctionParallel() override { return true; } - - Pass* create() override { return new SpillPointers; } - - // a mapping of the pointers to all the spillable things. We need to know - // how to replace them, and as we spill we may modify them. This map - // gives us, for an Expression** seen during the walk (and placed in the - // basic block, which is what we iterate on for efficiency) => the - // current actual pointer, which may have moded - std::unordered_map actualPointers; - - // note calls in basic blocks - template void visitSpillable(T* curr) { - // if in unreachable code, ignore - if (!currBasicBlock) { - return; - } - auto* pointer = getCurrentPointer(); - currBasicBlock->contents.actions.emplace_back(pointer); - // starts out as correct, may change later - actualPointers[pointer] = pointer; - } - - void visitCall(Call* curr) { visitSpillable(curr); } - void visitCallIndirect(CallIndirect* curr) { visitSpillable(curr); } - - // main entry point - - void doWalkFunction(Function* func) { - if (!canRun(func)) { - return; - } - super::doWalkFunction(func); - spillPointers(); - } - - // map pointers to their offset in the spill area - typedef std::unordered_map PointerMap; - - void spillPointers() { - // we only care about possible pointers - auto* func = getFunction(); - PointerMap pointerMap; - for (Index i = 0; i < func->getNumLocals(); i++) { - if (func->getLocalType(i) == ABI::PointerType) { - auto offset = pointerMap.size() * ABI::PointerType.getByteSize(); - pointerMap[i] = offset; - } - } - // find calls and spill around them - bool spilled = false; - Index spillLocal = -1; - for (auto& curr : basicBlocks) { - if (liveBlocks.count(curr.get()) == 0) { - continue; // ignore dead blocks - } - auto& liveness = curr->contents; - auto& actions = liveness.actions; - Index lastCall = -1; - for (Index i = 0; i < actions.size(); i++) { - auto& action = liveness.actions[i]; - if (action.isOther()) { - lastCall = i; - } - } - if (lastCall == Index(-1)) { - continue; // nothing to see here - } - // scan through the block, spilling around the calls - // TODO: we can filter on pointerMap everywhere - SetOfLocals live = liveness.end; - for (int i = int(actions.size()) - 1; i >= 0; i--) { - auto& action = actions[i]; - if (action.isGet()) { - live.insert(action.index); - } else if (action.isSet()) { - live.erase(action.index); - } else if (action.isOther()) { - std::vector toSpill; - for (auto index : live) { - if (pointerMap.count(index) > 0) { - toSpill.push_back(index); - } - } - if (!toSpill.empty()) { - // we now have a call + the information about which locals - // should be spilled - if (!spilled) { - // prepare stack support: get a pointer to stack space big enough - // for all our data - spillLocal = Builder::addVar(func, ABI::PointerType); - spilled = true; - } - // the origin was seen at walk, but the thing may have moved - auto* pointer = actualPointers[action.origin]; - spillPointersAroundCall( - pointer, toSpill, spillLocal, pointerMap, func, getModule()); - } - } else { - WASM_UNREACHABLE("unexpected action"); - } - } - } - if (spilled) { - // get the stack space, and set the local to it - ABI::getStackSpace(spillLocal, - func, - ABI::PointerType.getByteSize() * pointerMap.size(), - *getModule()); - } - } - - void spillPointersAroundCall(Expression** origin, - std::vector& toSpill, - Index spillLocal, - PointerMap& pointerMap, - Function* func, - Module* module) { - auto* call = *origin; - if (call->type == Type::unreachable) { - return; // the call is never reached anyhow, ignore - } - Builder builder(*module); - auto* block = builder.makeBlock(); - // move the operands into locals, as we must spill after they are executed - auto handleOperand = [&](Expression*& operand) { - auto temp = builder.addVar(func, operand->type); - auto* set = builder.makeLocalSet(temp, operand); - block->list.push_back(set); - block->finalize(); - if (actualPointers.count(&operand) > 0) { - // this is something we track, and it's moving - update - actualPointers[&operand] = &set->value; - } - operand = builder.makeLocalGet(temp, operand->type); - }; - if (call->is()) { - for (auto*& operand : call->cast()->operands) { - handleOperand(operand); - } - } else if (call->is()) { - for (auto*& operand : call->cast()->operands) { - handleOperand(operand); - } - handleOperand(call->cast()->target); - } else { - WASM_UNREACHABLE("unexpected expr"); - } - // add the spills - for (auto index : toSpill) { - block->list.push_back( - builder.makeStore(ABI::PointerType.getByteSize(), - pointerMap[index], - ABI::PointerType.getByteSize(), - builder.makeLocalGet(spillLocal, ABI::PointerType), - builder.makeLocalGet(index, ABI::PointerType), - ABI::PointerType)); - } - // add the (modified) call - block->list.push_back(call); - block->finalize(); - *origin = block; - } -}; - -Pass* createSpillPointersPass() { return new SpillPointers(); } - -} // namespace wasm diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp index 67e1ca53b4a..c6d479dfbc6 100644 --- a/src/passes/pass.cpp +++ b/src/passes/pass.cpp @@ -339,9 +339,6 @@ void PassRegistry::registerPasses() { registerPass("souperify-single-use", "emit Souper IR in text form (single-use nodes only)", createSouperifySingleUsePass); - registerPass("spill-pointers", - "spill pointers to the C stack (useful for Boehm-style GC)", - createSpillPointersPass); registerPass("stub-unsupported-js", "stub out unsupported JS operations", createStubUnsupportedJSOpsPass); diff --git a/src/passes/passes.h b/src/passes/passes.h index a36aeb7c396..e88dc835d77 100644 --- a/src/passes/passes.h +++ b/src/passes/passes.h @@ -118,7 +118,6 @@ Pass* createStripProducersPass(); Pass* createStripTargetFeaturesPass(); Pass* createSouperifyPass(); Pass* createSouperifySingleUsePass(); -Pass* createSpillPointersPass(); Pass* createStubUnsupportedJSOpsPass(); Pass* createSSAifyPass(); Pass* createSSAifyNoMergePass(); diff --git a/test/passes/spill-pointers.txt b/test/passes/spill-pointers.txt deleted file mode 100644 index fd7683fda18..00000000000 --- a/test/passes/spill-pointers.txt +++ /dev/null @@ -1,1291 +0,0 @@ -(module - (type $none_=>_none (func)) - (type $i32_=>_i32 (func (param i32) (result i32))) - (type $none_=>_i32 (func (result i32))) - (type $i32_i32_=>_none (func (param i32 i32))) - (type $i32_=>_none (func (param i32))) - (type $f64_=>_none (func (param f64))) - (import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import i32)) - (import "env" "segfault" (func $segfault (param i32))) - (memory $0 10) - (table $0 1 1 funcref) - (global $stack_ptr (mut i32) (global.get $STACKTOP$asm2wasm$import)) - (func $nothing - (nop) - ) - (func $not-alive - (local $x i32) - (local.set $x - (i32.const 1) - ) - (call $nothing) - ) - (func $spill - (local $x i32) - (local $1 i32) - (local.set $1 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $1) - (i32.const 16) - ) - ) - (block - (block - (i32.store - (local.get $1) - (local.get $x) - ) - (call $nothing) - ) - (drop - (local.get $x) - ) - ) - (global.set $stack_ptr - (local.get $1) - ) - ) - (func $ignore-non-pointers - (local $x i32) - (local $y i64) - (local $z f32) - (local $w f64) - (local $4 i32) - (local.set $4 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $4) - (i32.const 16) - ) - ) - (block - (local.set $x - (i32.const 1) - ) - (local.set $y - (i64.const 1) - ) - (local.set $z - (f32.const 1) - ) - (local.set $w - (f64.const 1) - ) - (block - (i32.store - (local.get $4) - (local.get $x) - ) - (call $nothing) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - (drop - (local.get $z) - ) - (drop - (local.get $w) - ) - ) - (global.set $stack_ptr - (local.get $4) - ) - ) - (func $spill4 - (local $x i32) - (local $y i32) - (local $z i32) - (local $w i32) - (local $4 i32) - (local.set $4 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $4) - (i32.const 16) - ) - ) - (block - (local.set $x - (i32.const 1) - ) - (local.set $y - (i32.const 1) - ) - (local.set $z - (i32.const 1) - ) - (local.set $w - (i32.const 1) - ) - (block - (i32.store - (local.get $4) - (local.get $x) - ) - (i32.store offset=4 - (local.get $4) - (local.get $y) - ) - (i32.store offset=8 - (local.get $4) - (local.get $z) - ) - (i32.store offset=12 - (local.get $4) - (local.get $w) - ) - (call $nothing) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - (drop - (local.get $z) - ) - (drop - (local.get $w) - ) - ) - (global.set $stack_ptr - (local.get $4) - ) - ) - (func $spill5 - (local $x i32) - (local $y i32) - (local $z i32) - (local $w i32) - (local $a i32) - (local $5 i32) - (local.set $5 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $5) - (i32.const 32) - ) - ) - (block - (local.set $x - (i32.const 1) - ) - (local.set $y - (i32.const 1) - ) - (local.set $z - (i32.const 1) - ) - (local.set $w - (i32.const 1) - ) - (local.set $a - (i32.const 1) - ) - (block - (i32.store - (local.get $5) - (local.get $x) - ) - (i32.store offset=4 - (local.get $5) - (local.get $y) - ) - (i32.store offset=8 - (local.get $5) - (local.get $z) - ) - (i32.store offset=12 - (local.get $5) - (local.get $w) - ) - (i32.store offset=16 - (local.get $5) - (local.get $a) - ) - (call $nothing) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - (drop - (local.get $z) - ) - (drop - (local.get $w) - ) - (drop - (local.get $a) - ) - ) - (global.set $stack_ptr - (local.get $5) - ) - ) - (func $some-alive - (local $x i32) - (local $y i32) - (local $2 i32) - (local.set $2 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $2) - (i32.const 16) - ) - ) - (block - (block - (i32.store - (local.get $2) - (local.get $x) - ) - (call $nothing) - ) - (drop - (local.get $x) - ) - ) - (global.set $stack_ptr - (local.get $2) - ) - ) - (func $spill-args (param $p i32) (param $q i32) - (local $x i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local.set $3 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $3) - (i32.const 16) - ) - ) - (block - (block - (local.set $4 - (i32.const 1) - ) - (local.set $5 - (i32.const 2) - ) - (i32.store offset=8 - (local.get $3) - (local.get $x) - ) - (call $spill-args - (local.get $4) - (local.get $5) - ) - ) - (drop - (local.get $x) - ) - ) - (global.set $stack_ptr - (local.get $3) - ) - ) - (func $spill-ret (result i32) - (local $x i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local.set $1 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $1) - (i32.const 16) - ) - ) - (local.set $4 - (block (result i32) - (block - (i32.store - (local.get $1) - (local.get $x) - ) - (call $nothing) - ) - (drop - (local.get $x) - ) - (if - (i32.const 1) - (block - (local.set $2 - (i32.const 2) - ) - (global.set $stack_ptr - (local.get $1) - ) - (return - (local.get $2) - ) - ) - (block - (local.set $3 - (i32.const 3) - ) - (global.set $stack_ptr - (local.get $1) - ) - (return - (local.get $3) - ) - ) - ) - (i32.const 4) - ) - ) - (global.set $stack_ptr - (local.get $1) - ) - (local.get $4) - ) - (func $spill-unreachable (result i32) - (local $x i32) - (local $1 i32) - (local $2 i32) - (local.set $1 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $1) - (i32.const 16) - ) - ) - (local.set $2 - (block (result i32) - (block - (i32.store - (local.get $1) - (local.get $x) - ) - (call $nothing) - ) - (drop - (local.get $x) - ) - (unreachable) - ) - ) - (global.set $stack_ptr - (local.get $1) - ) - (local.get $2) - ) - (func $spill-call-call0 (param $p i32) (result i32) - (unreachable) - ) - (func $spill-call-call1 (param $p i32) (result i32) - (local $x i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local.set $2 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $2) - (i32.const 16) - ) - ) - (local.set $5 - (block (result i32) - (drop - (block (result i32) - (local.set $3 - (block (result i32) - (local.set $4 - (i32.const 1) - ) - (i32.store offset=4 - (local.get $2) - (local.get $x) - ) - (call $spill-call-call1 - (local.get $4) - ) - ) - ) - (i32.store offset=4 - (local.get $2) - (local.get $x) - ) - (call $spill-call-call0 - (local.get $3) - ) - ) - ) - (local.get $x) - ) - ) - (global.set $stack_ptr - (local.get $2) - ) - (local.get $5) - ) - (func $spill-call-ret (param $p i32) (result i32) - (local $x i32) - (drop - (call $spill-call-call0 - (return - (i32.const 1) - ) - ) - ) - (i32.const 0) - ) - (func $spill-ret-call (param $p i32) (result i32) - (local $x i32) - (drop - (return - (call $spill-call-call0 - (i32.const 1) - ) - ) - ) - (i32.const 0) - ) - (func $spill-ret-ret (result i32) - (local $x i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (local.set $1 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $1) - (i32.const 16) - ) - ) - (local.set $3 - (block (result i32) - (block - (i32.store - (local.get $1) - (local.get $x) - ) - (call $nothing) - ) - (drop - (local.get $x) - ) - (drop - (block - (global.set $stack_ptr - (local.get $1) - ) - (return - (block - (local.set $2 - (i32.const 1) - ) - (global.set $stack_ptr - (local.get $1) - ) - (return - (local.get $2) - ) - ) - ) - ) - ) - (i32.const 0) - ) - ) - (global.set $stack_ptr - (local.get $1) - ) - (local.get $3) - ) - (func $spill-call-othertype (param $y f64) - (local $x i32) - (local $2 i32) - (local $3 f64) - (local.set $2 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $2) - (i32.const 16) - ) - ) - (block - (block - (local.set $3 - (f64.const 1) - ) - (i32.store - (local.get $2) - (local.get $x) - ) - (call $spill-call-othertype - (local.get $3) - ) - ) - (drop - (local.get $x) - ) - ) - (global.set $stack_ptr - (local.get $2) - ) - ) - (func $spill-call_indirect - (local $x i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local.set $1 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $1) - (i32.const 16) - ) - ) - (block - (block - (local.set $2 - (i32.const 123) - ) - (local.set $3 - (i32.const 456) - ) - (local.set $4 - (i32.const 789) - ) - (i32.store - (local.get $1) - (local.get $x) - ) - (call_indirect (type $i32_i32_=>_none) - (local.get $2) - (local.get $3) - (local.get $4) - ) - ) - (drop - (local.get $x) - ) - ) - (global.set $stack_ptr - (local.get $1) - ) - ) - (func $spill-call_import - (local $x i32) - (local $1 i32) - (local $2 i32) - (local.set $1 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $1) - (i32.const 16) - ) - ) - (block - (block - (local.set $2 - (i32.const 200) - ) - (i32.store - (local.get $1) - (local.get $x) - ) - (call $segfault - (local.get $2) - ) - ) - (drop - (local.get $x) - ) - ) - (global.set $stack_ptr - (local.get $1) - ) - ) -) -(module - (type $none_=>_none (func)) - (type $none_=>_i32 (func (result i32))) - (type $i32_=>_i32 (func (param i32) (result i32))) - (type $i32_i32_=>_none (func (param i32 i32))) - (type $i32_=>_none (func (param i32))) - (type $f64_=>_none (func (param f64))) - (import "env" "segfault" (func $segfault (param i32))) - (memory $0 10) - (table $0 1 1 funcref) - (global $stack_ptr (mut i32) (i32.const 1716592)) - (export "stackSave" (func $stack_save)) - (func $stack_save (result i32) - (global.get $stack_ptr) - ) - (func $nothing - (nop) - ) - (func $not-alive - (local $x i32) - (local.set $x - (i32.const 1) - ) - (call $nothing) - ) - (func $spill - (local $x i32) - (local $1 i32) - (local.set $1 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $1) - (i32.const 16) - ) - ) - (block - (block - (i32.store - (local.get $1) - (local.get $x) - ) - (call $nothing) - ) - (drop - (local.get $x) - ) - ) - (global.set $stack_ptr - (local.get $1) - ) - ) - (func $ignore-non-pointers - (local $x i32) - (local $y i64) - (local $z f32) - (local $w f64) - (local $4 i32) - (local.set $4 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $4) - (i32.const 16) - ) - ) - (block - (local.set $x - (i32.const 1) - ) - (local.set $y - (i64.const 1) - ) - (local.set $z - (f32.const 1) - ) - (local.set $w - (f64.const 1) - ) - (block - (i32.store - (local.get $4) - (local.get $x) - ) - (call $nothing) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - (drop - (local.get $z) - ) - (drop - (local.get $w) - ) - ) - (global.set $stack_ptr - (local.get $4) - ) - ) - (func $spill4 - (local $x i32) - (local $y i32) - (local $z i32) - (local $w i32) - (local $4 i32) - (local.set $4 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $4) - (i32.const 16) - ) - ) - (block - (local.set $x - (i32.const 1) - ) - (local.set $y - (i32.const 1) - ) - (local.set $z - (i32.const 1) - ) - (local.set $w - (i32.const 1) - ) - (block - (i32.store - (local.get $4) - (local.get $x) - ) - (i32.store offset=4 - (local.get $4) - (local.get $y) - ) - (i32.store offset=8 - (local.get $4) - (local.get $z) - ) - (i32.store offset=12 - (local.get $4) - (local.get $w) - ) - (call $nothing) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - (drop - (local.get $z) - ) - (drop - (local.get $w) - ) - ) - (global.set $stack_ptr - (local.get $4) - ) - ) - (func $spill5 - (local $x i32) - (local $y i32) - (local $z i32) - (local $w i32) - (local $a i32) - (local $5 i32) - (local.set $5 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $5) - (i32.const 32) - ) - ) - (block - (local.set $x - (i32.const 1) - ) - (local.set $y - (i32.const 1) - ) - (local.set $z - (i32.const 1) - ) - (local.set $w - (i32.const 1) - ) - (local.set $a - (i32.const 1) - ) - (block - (i32.store - (local.get $5) - (local.get $x) - ) - (i32.store offset=4 - (local.get $5) - (local.get $y) - ) - (i32.store offset=8 - (local.get $5) - (local.get $z) - ) - (i32.store offset=12 - (local.get $5) - (local.get $w) - ) - (i32.store offset=16 - (local.get $5) - (local.get $a) - ) - (call $nothing) - ) - (drop - (local.get $x) - ) - (drop - (local.get $y) - ) - (drop - (local.get $z) - ) - (drop - (local.get $w) - ) - (drop - (local.get $a) - ) - ) - (global.set $stack_ptr - (local.get $5) - ) - ) - (func $some-alive - (local $x i32) - (local $y i32) - (local $2 i32) - (local.set $2 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $2) - (i32.const 16) - ) - ) - (block - (block - (i32.store - (local.get $2) - (local.get $x) - ) - (call $nothing) - ) - (drop - (local.get $x) - ) - ) - (global.set $stack_ptr - (local.get $2) - ) - ) - (func $spill-args (param $p i32) (param $q i32) - (local $x i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local.set $3 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $3) - (i32.const 16) - ) - ) - (block - (block - (local.set $4 - (i32.const 1) - ) - (local.set $5 - (i32.const 2) - ) - (i32.store offset=8 - (local.get $3) - (local.get $x) - ) - (call $spill-args - (local.get $4) - (local.get $5) - ) - ) - (drop - (local.get $x) - ) - ) - (global.set $stack_ptr - (local.get $3) - ) - ) - (func $spill-ret (result i32) - (local $x i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local.set $1 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $1) - (i32.const 16) - ) - ) - (local.set $4 - (block (result i32) - (block - (i32.store - (local.get $1) - (local.get $x) - ) - (call $nothing) - ) - (drop - (local.get $x) - ) - (if - (i32.const 1) - (block - (local.set $2 - (i32.const 2) - ) - (global.set $stack_ptr - (local.get $1) - ) - (return - (local.get $2) - ) - ) - (block - (local.set $3 - (i32.const 3) - ) - (global.set $stack_ptr - (local.get $1) - ) - (return - (local.get $3) - ) - ) - ) - (i32.const 4) - ) - ) - (global.set $stack_ptr - (local.get $1) - ) - (local.get $4) - ) - (func $spill-unreachable (result i32) - (local $x i32) - (local $1 i32) - (local $2 i32) - (local.set $1 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $1) - (i32.const 16) - ) - ) - (local.set $2 - (block (result i32) - (block - (i32.store - (local.get $1) - (local.get $x) - ) - (call $nothing) - ) - (drop - (local.get $x) - ) - (unreachable) - ) - ) - (global.set $stack_ptr - (local.get $1) - ) - (local.get $2) - ) - (func $spill-call-call0 (param $p i32) (result i32) - (unreachable) - ) - (func $spill-call-call1 (param $p i32) (result i32) - (local $x i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local $5 i32) - (local.set $2 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $2) - (i32.const 16) - ) - ) - (local.set $5 - (block (result i32) - (drop - (block (result i32) - (local.set $3 - (block (result i32) - (local.set $4 - (i32.const 1) - ) - (i32.store offset=4 - (local.get $2) - (local.get $x) - ) - (call $spill-call-call1 - (local.get $4) - ) - ) - ) - (i32.store offset=4 - (local.get $2) - (local.get $x) - ) - (call $spill-call-call0 - (local.get $3) - ) - ) - ) - (local.get $x) - ) - ) - (global.set $stack_ptr - (local.get $2) - ) - (local.get $5) - ) - (func $spill-call-ret (param $p i32) (result i32) - (local $x i32) - (drop - (call $spill-call-call0 - (return - (i32.const 1) - ) - ) - ) - (i32.const 0) - ) - (func $spill-ret-call (param $p i32) (result i32) - (local $x i32) - (drop - (return - (call $spill-call-call0 - (i32.const 1) - ) - ) - ) - (i32.const 0) - ) - (func $spill-ret-ret (result i32) - (local $x i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (local.set $1 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $1) - (i32.const 16) - ) - ) - (local.set $3 - (block (result i32) - (block - (i32.store - (local.get $1) - (local.get $x) - ) - (call $nothing) - ) - (drop - (local.get $x) - ) - (drop - (block - (global.set $stack_ptr - (local.get $1) - ) - (return - (block - (local.set $2 - (i32.const 1) - ) - (global.set $stack_ptr - (local.get $1) - ) - (return - (local.get $2) - ) - ) - ) - ) - ) - (i32.const 0) - ) - ) - (global.set $stack_ptr - (local.get $1) - ) - (local.get $3) - ) - (func $spill-call-othertype (param $y f64) - (local $x i32) - (local $2 i32) - (local $3 f64) - (local.set $2 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $2) - (i32.const 16) - ) - ) - (block - (block - (local.set $3 - (f64.const 1) - ) - (i32.store - (local.get $2) - (local.get $x) - ) - (call $spill-call-othertype - (local.get $3) - ) - ) - (drop - (local.get $x) - ) - ) - (global.set $stack_ptr - (local.get $2) - ) - ) - (func $spill-call_indirect - (local $x i32) - (local $1 i32) - (local $2 i32) - (local $3 i32) - (local $4 i32) - (local.set $1 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $1) - (i32.const 16) - ) - ) - (block - (block - (local.set $2 - (i32.const 123) - ) - (local.set $3 - (i32.const 456) - ) - (local.set $4 - (i32.const 789) - ) - (i32.store - (local.get $1) - (local.get $x) - ) - (call_indirect (type $i32_i32_=>_none) - (local.get $2) - (local.get $3) - (local.get $4) - ) - ) - (drop - (local.get $x) - ) - ) - (global.set $stack_ptr - (local.get $1) - ) - ) - (func $spill-call_import - (local $x i32) - (local $1 i32) - (local $2 i32) - (local.set $1 - (global.get $stack_ptr) - ) - (global.set $stack_ptr - (i32.add - (local.get $1) - (i32.const 16) - ) - ) - (block - (block - (local.set $2 - (i32.const 200) - ) - (i32.store - (local.get $1) - (local.get $x) - ) - (call $segfault - (local.get $2) - ) - ) - (drop - (local.get $x) - ) - ) - (global.set $stack_ptr - (local.get $1) - ) - ) -) diff --git a/test/passes/spill-pointers.wast b/test/passes/spill-pointers.wast deleted file mode 100644 index 4eb05a72116..00000000000 --- a/test/passes/spill-pointers.wast +++ /dev/null @@ -1,338 +0,0 @@ -(module - (memory 10) - (type $ii (func (param i32 i32))) - (table 1 1 funcref) - (elem (i32.const 0)) - (import "env" "STACKTOP" (global $STACKTOP$asm2wasm$import i32)) - (import "env" "segfault" (func $segfault (param i32))) - (global $stack_ptr (mut i32) (global.get $STACKTOP$asm2wasm$import)) - - (func $nothing - ) - (func $not-alive - (local $x i32) - (local.set $x (i32.const 1)) - (call $nothing) - ) - (func $spill - (local $x i32) - (call $nothing) - (drop (local.get $x)) - ) - (func $ignore-non-pointers - (local $x i32) - (local $y i64) - (local $z f32) - (local $w f64) - (local.set $x (i32.const 1)) - (local.set $y (i64.const 1)) - (local.set $z (f32.const 1)) - (local.set $w (f64.const 1)) - (call $nothing) - (drop (local.get $x)) - (drop (local.get $y)) - (drop (local.get $z)) - (drop (local.get $w)) - ) - (func $spill4 - (local $x i32) - (local $y i32) - (local $z i32) - (local $w i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 1)) - (local.set $z (i32.const 1)) - (local.set $w (i32.const 1)) - (call $nothing) - (drop (local.get $x)) - (drop (local.get $y)) - (drop (local.get $z)) - (drop (local.get $w)) - ) - (func $spill5 - (local $x i32) - (local $y i32) - (local $z i32) - (local $w i32) - (local $a i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 1)) - (local.set $z (i32.const 1)) - (local.set $w (i32.const 1)) - (local.set $a (i32.const 1)) - (call $nothing) - (drop (local.get $x)) - (drop (local.get $y)) - (drop (local.get $z)) - (drop (local.get $w)) - (drop (local.get $a)) - ) - (func $some-alive - (local $x i32) - (local $y i32) - (call $nothing) - (drop (local.get $x)) - ) - (func $spill-args (param $p i32) (param $q i32) - (local $x i32) - (call $spill-args (i32.const 1) (i32.const 2)) - (drop (local.get $x)) - ) - (func $spill-ret (result i32) - (local $x i32) - (call $nothing) - (drop (local.get $x)) - (if (i32.const 1) - (return (i32.const 2)) - (return (i32.const 3)) - ) - (i32.const 4) - ) - (func $spill-unreachable (result i32) - (local $x i32) - (call $nothing) - (drop (local.get $x)) - (unreachable) - ) - (func $spill-call-call0 (param $p i32) (result i32) - (unreachable) - ) - (func $spill-call-call1 (param $p i32) (result i32) - (local $x i32) - (drop - (call $spill-call-call0 - (call $spill-call-call1 - (i32.const 1) - ) - ) - ) - (local.get $x) - ) - (func $spill-call-ret (param $p i32) (result i32) - (local $x i32) - (drop - (call $spill-call-call0 - (return - (i32.const 1) - ) - ) - ) - (local.get $x) - ) - (func $spill-ret-call (param $p i32) (result i32) - (local $x i32) - (drop - (return - (call $spill-call-call0 - (i32.const 1) - ) - ) - ) - (local.get $x) - ) - (func $spill-ret-ret (result i32) - (local $x i32) - (call $nothing) - (drop (local.get $x)) - (drop - (return - (return - (i32.const 1) - ) - ) - ) - (local.get $x) - ) - (func $spill-call-othertype (param $y f64) - (local $x i32) - (call $spill-call-othertype (f64.const 1)) - (drop (local.get $x)) - ) - (func $spill-call_indirect - (local $x i32) - (call_indirect (type $ii) - (i32.const 123) - (i32.const 456) - (i32.const 789) - ) - (drop (local.get $x)) - ) - (func $spill-call_import - (local $x i32) - (call $segfault - (i32.const 200) - ) - (drop (local.get $x)) - ) -) - -(module - (memory 10) - (type $ii (func (param i32 i32))) - (table 1 1 funcref) - (elem (i32.const 0)) - (global $stack_ptr (mut i32) (i32.const 1716592)) - (export "stackSave" (func $stack_save)) - (import "env" "segfault" (func $segfault (param i32))) - (func $stack_save (result i32) - (global.get $stack_ptr) - ) - - (func $nothing - ) - (func $not-alive - (local $x i32) - (local.set $x (i32.const 1)) - (call $nothing) - ) - (func $spill - (local $x i32) - (call $nothing) - (drop (local.get $x)) - ) - (func $ignore-non-pointers - (local $x i32) - (local $y i64) - (local $z f32) - (local $w f64) - (local.set $x (i32.const 1)) - (local.set $y (i64.const 1)) - (local.set $z (f32.const 1)) - (local.set $w (f64.const 1)) - (call $nothing) - (drop (local.get $x)) - (drop (local.get $y)) - (drop (local.get $z)) - (drop (local.get $w)) - ) - (func $spill4 - (local $x i32) - (local $y i32) - (local $z i32) - (local $w i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 1)) - (local.set $z (i32.const 1)) - (local.set $w (i32.const 1)) - (call $nothing) - (drop (local.get $x)) - (drop (local.get $y)) - (drop (local.get $z)) - (drop (local.get $w)) - ) - (func $spill5 - (local $x i32) - (local $y i32) - (local $z i32) - (local $w i32) - (local $a i32) - (local.set $x (i32.const 1)) - (local.set $y (i32.const 1)) - (local.set $z (i32.const 1)) - (local.set $w (i32.const 1)) - (local.set $a (i32.const 1)) - (call $nothing) - (drop (local.get $x)) - (drop (local.get $y)) - (drop (local.get $z)) - (drop (local.get $w)) - (drop (local.get $a)) - ) - (func $some-alive - (local $x i32) - (local $y i32) - (call $nothing) - (drop (local.get $x)) - ) - (func $spill-args (param $p i32) (param $q i32) - (local $x i32) - (call $spill-args (i32.const 1) (i32.const 2)) - (drop (local.get $x)) - ) - (func $spill-ret (result i32) - (local $x i32) - (call $nothing) - (drop (local.get $x)) - (if (i32.const 1) - (return (i32.const 2)) - (return (i32.const 3)) - ) - (i32.const 4) - ) - (func $spill-unreachable (result i32) - (local $x i32) - (call $nothing) - (drop (local.get $x)) - (unreachable) - ) - (func $spill-call-call0 (param $p i32) (result i32) - (unreachable) - ) - (func $spill-call-call1 (param $p i32) (result i32) - (local $x i32) - (drop - (call $spill-call-call0 - (call $spill-call-call1 - (i32.const 1) - ) - ) - ) - (local.get $x) - ) - (func $spill-call-ret (param $p i32) (result i32) - (local $x i32) - (drop - (call $spill-call-call0 - (return - (i32.const 1) - ) - ) - ) - (local.get $x) - ) - (func $spill-ret-call (param $p i32) (result i32) - (local $x i32) - (drop - (return - (call $spill-call-call0 - (i32.const 1) - ) - ) - ) - (local.get $x) - ) - (func $spill-ret-ret (result i32) - (local $x i32) - (call $nothing) - (drop (local.get $x)) - (drop - (return - (return - (i32.const 1) - ) - ) - ) - (local.get $x) - ) - (func $spill-call-othertype (param $y f64) - (local $x i32) - (call $spill-call-othertype (f64.const 1)) - (drop (local.get $x)) - ) - (func $spill-call_indirect - (local $x i32) - (call_indirect (type $ii) - (i32.const 123) - (i32.const 456) - (i32.const 789) - ) - (drop (local.get $x)) - ) - (func $spill-call_import - (local $x i32) - (call $segfault - (i32.const 200) - ) - (drop (local.get $x)) - ) -)