diff options
-rw-r--r-- | src/passes/Inlining.cpp | 16 | ||||
-rw-r--r-- | test/passes/inlining.txt | 75 | ||||
-rw-r--r-- | test/passes/inlining.wast | 59 | ||||
-rw-r--r-- | test/unit.fromasm | 5 | ||||
-rw-r--r-- | test/unit.fromasm.clamp | 5 | ||||
-rw-r--r-- | test/unit.fromasm.imprecise | 5 |
6 files changed, 154 insertions, 11 deletions
diff --git a/src/passes/Inlining.cpp b/src/passes/Inlining.cpp index 377aa5247..20becfe46 100644 --- a/src/passes/Inlining.cpp +++ b/src/passes/Inlining.cpp @@ -28,6 +28,7 @@ #include <pass.h> #include <wasm-builder.h> #include <ast_utils.h> +#include <ast/literal-utils.h> #include <parsing.h> namespace wasm { @@ -121,11 +122,12 @@ private: // Core inlining logic. Modifies the outside function (adding locals as // needed), and returns the inlined code. static Expression* doInlining(Module* module, Function* into, InliningAction& action) { + Function* from = action.contents; auto* call = (*action.callSite)->cast<Call>(); Builder builder(*module); auto* block = Builder(*module).makeBlock(); block->type = call->type; - block->name = Name(std::string("__inlined_func$") + action.contents->name.str); + block->name = Name(std::string("__inlined_func$") + from->name.str); *action.callSite = block; // set up a locals mapping struct Updater : public PostWalker<Updater> { @@ -145,15 +147,19 @@ static Expression* doInlining(Module* module, Function* into, InliningAction& ac } updater; updater.returnName = block->name; updater.builder = &builder; - for (Index i = 0; i < action.contents->getNumLocals(); i++) { - updater.localMapping[i] = builder.addVar(into, action.contents->getLocalType(i)); + for (Index i = 0; i < from->getNumLocals(); i++) { + updater.localMapping[i] = builder.addVar(into, from->getLocalType(i)); } // assign the operands into the params - for (Index i = 0; i < action.contents->params.size(); i++) { + for (Index i = 0; i < from->params.size(); i++) { block->list.push_back(builder.makeSetLocal(updater.localMapping[i], call->operands[i])); } + // zero out the vars (as we may be in a loop, and may depend on their zero-init value + for (Index i = 0; i < from->vars.size(); i++) { + block->list.push_back(builder.makeSetLocal(updater.localMapping[from->getVarIndexBase() + i], LiteralUtils::makeZero(from->vars[i], *module))); + } // generate and update the inlined contents - auto* contents = ExpressionManipulator::copy(action.contents->body, *module); + auto* contents = ExpressionManipulator::copy(from->body, *module); updater.walk(contents); block->list.push_back(contents); return block; diff --git a/test/passes/inlining.txt b/test/passes/inlining.txt index 99f764351..838dd1f38 100644 --- a/test/passes/inlining.txt +++ b/test/passes/inlining.txt @@ -58,6 +58,9 @@ (block (block $__inlined_func$with-local (set_local $2 + (f32.const 0) + ) + (set_local $2 (f32.const 2.1418280601501465) ) ) @@ -65,6 +68,9 @@ (block (block $__inlined_func$with-local2 (set_local $3 + (i64.const 0) + ) + (set_local $3 (i64.const 4) ) ) @@ -97,6 +103,9 @@ (set_local $5 (i64.const 890005350012) ) + (set_local $6 + (f32.const 0) + ) (block (drop (get_local $4) @@ -143,3 +152,69 @@ ) ) ) +(module + (type $0 (func (result i32))) + (type $1 (func (param f32 i32) (result i32))) + (type $2 (func)) + (global $hangLimit (mut i32) (i32.const 25)) + (memory $0 1 1) + (export "hangLimitInitializer" (func $hangLimitInitializer)) + (func $func_4 (type $1) (param $0 f32) (param $1 i32) (result i32) + (local $2 i64) + (local $3 f64) + (local $4 f32) + (local $5 i32) + (local $6 i32) + (local $7 f64) + (local $8 i32) + (loop $label$0 (result i32) + (block $block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const 54) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (i32.eqz + (if (result i32) + (i32.const 1) + (if (result i32) + (i32.eqz + (block (result i32) + (block $__inlined_func$func_3 (result i32) + (set_local $8 + (i32.const 0) + ) + (select + (get_local $8) + (tee_local $8 + (i32.const -1) + ) + (i32.const 1) + ) + ) + ) + ) + (br $label$0) + (i32.const 0) + ) + (unreachable) + ) + ) + ) + ) + (func $hangLimitInitializer (type $2) + (set_global $hangLimit + (i32.const 25) + ) + ) +) diff --git a/test/passes/inlining.wast b/test/passes/inlining.wast index ce8b1b8be..38370addf 100644 --- a/test/passes/inlining.wast +++ b/test/passes/inlining.wast @@ -86,4 +86,63 @@ ) ) ) +(module + (global $hangLimit (mut i32) (i32.const 25)) + (memory $0 1 1) + (export "hangLimitInitializer" (func $hangLimitInitializer)) + (func $func_3 (result i32) + (local $0 i32) + (select + (get_local $0) ;; we depend on the zero-init value here, so it must be set when inlining! + (tee_local $0 + (i32.const -1) + ) + (i32.const 1) + ) + ) + (func $func_4 (param $0 f32) (param $1 i32) (result i32) + (local $2 i64) + (local $3 f64) + (local $4 f32) + (local $5 i32) + (local $6 i32) + (local $7 f64) + (loop $label$0 (result i32) + (block + (if + (i32.eqz + (get_global $hangLimit) + ) + (return + (i32.const 54) + ) + ) + (set_global $hangLimit + (i32.sub + (get_global $hangLimit) + (i32.const 1) + ) + ) + ) + (i32.eqz + (if (result i32) + (i32.const 1) + (if (result i32) + (i32.eqz + (call $func_3) + ) + (br $label$0) + (i32.const 0) + ) + (unreachable) + ) + ) + ) + ) + (func $hangLimitInitializer + (set_global $hangLimit + (i32.const 25) + ) + ) +) diff --git a/test/unit.fromasm b/test/unit.fromasm index 7ac63bfcc..ec97a3320 100644 --- a/test/unit.fromasm +++ b/test/unit.fromasm @@ -1164,7 +1164,6 @@ ) (func $keepAlive (local $0 i32) - (local $1 i32) (drop (call $sqrts (f64.const 3.14159) @@ -1200,7 +1199,9 @@ (i32.const 17) ) (call_indirect $FUNCSIG$vi - (get_local $1) + (tee_local $0 + (i32.const 0) + ) (block (result i32) (set_global $Int (i32.const 1) diff --git a/test/unit.fromasm.clamp b/test/unit.fromasm.clamp index 8f3e387ae..b110204f9 100644 --- a/test/unit.fromasm.clamp +++ b/test/unit.fromasm.clamp @@ -1188,7 +1188,6 @@ ) (func $keepAlive (local $0 i32) - (local $1 i32) (drop (call $sqrts (f64.const 3.14159) @@ -1224,7 +1223,9 @@ (i32.const 17) ) (call_indirect $FUNCSIG$vi - (get_local $1) + (tee_local $0 + (i32.const 0) + ) (block (result i32) (set_global $Int (i32.const 1) diff --git a/test/unit.fromasm.imprecise b/test/unit.fromasm.imprecise index 17c9109c3..13c29f151 100644 --- a/test/unit.fromasm.imprecise +++ b/test/unit.fromasm.imprecise @@ -1126,7 +1126,6 @@ ) (func $keepAlive (local $0 i32) - (local $1 i32) (drop (call $sqrts (f64.const 3.14159) @@ -1152,7 +1151,9 @@ (i32.const 17) ) (call_indirect $FUNCSIG$vi - (get_local $1) + (tee_local $0 + (i32.const 0) + ) (block (result i32) (set_global $Int (i32.const 1) |