summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/ExtractFunction.cpp79
-rw-r--r--src/passes/pass.cpp3
-rw-r--r--src/passes/passes.h1
-rw-r--r--test/lit/passes/extract-function.wast72
-rw-r--r--test/passes/extract-function=foo.txt28
-rw-r--r--test/passes/extract-function=foo.wast36
-rw-r--r--test/passes/extract-function_pass-arg=extract-function@foo.txt28
-rw-r--r--test/passes/extract-function_pass-arg=extract-function@foo.wast36
8 files changed, 127 insertions, 156 deletions
diff --git a/src/passes/ExtractFunction.cpp b/src/passes/ExtractFunction.cpp
index ac3be9366..a219000c8 100644
--- a/src/passes/ExtractFunction.cpp
+++ b/src/passes/ExtractFunction.cpp
@@ -21,50 +21,73 @@
// order to remove as many things as possible.
#include "pass.h"
+#include "wasm-builder.h"
#include "wasm.h"
namespace wasm {
+static void extract(PassRunner* runner, Module* module, Name name) {
+ std::cerr << "extracting " << name << "\n";
+ bool found = false;
+ for (auto& func : module->functions) {
+ if (func->name != name) {
+ // Turn it into an import.
+ func->module = "env";
+ func->base = func->name;
+ func->vars.clear();
+ func->body = nullptr;
+ } else {
+ found = true;
+ }
+ }
+ if (!found) {
+ Fatal() << "could not find the function to extract\n";
+ }
+
+ // Leave just one export, for the thing we want.
+ module->exports.clear();
+ module->addExport(Builder::makeExport(name, name, ExternalKind::Function));
+
+ // Remove unneeded things.
+ PassRunner postRunner(runner);
+ postRunner.add("remove-unused-module-elements");
+ postRunner.setIsNested(true);
+ postRunner.run();
+}
+
struct ExtractFunction : public Pass {
void run(PassRunner* runner, Module* module) override {
Name name = runner->options.getArgument(
"extract-function",
"ExtractFunction usage: wasm-opt --extract-function=FUNCTION_NAME");
- std::cerr << "extracting " << name << "\n";
- bool found = false;
- for (auto& func : module->functions) {
- if (func->name != name) {
- // Turn it into an import.
- func->module = "env";
- func->base = func->name;
- func->vars.clear();
- func->body = nullptr;
- } else {
- found = true;
+ extract(runner, module, name);
+ }
+};
+
+struct ExtractFunctionIndex : public Pass {
+ void run(PassRunner* runner, Module* module) override {
+ std::string index =
+ runner->options.getArgument("extract-function-index",
+ "ExtractFunctionIndex usage: wasm-opt "
+ "--extract-function-index=FUNCTION_INDEX");
+ for (char c : index) {
+ if (!std::isdigit(c)) {
+ Fatal() << "Expected numeric function index";
}
}
- if (!found) {
- Fatal() << "could not find the function to extract\n";
+ Index i = std::stoi(index);
+ if (i >= module->functions.size()) {
+ Fatal() << "Invalid function index";
}
-
- // Leave just one export, for the thing we want.
- module->exports.clear();
- auto* export_ = new Export;
- export_->name = name;
- export_->value = name;
- export_->kind = ExternalKind::Function;
- module->addExport(export_);
-
- // Remove unneeded things.
- PassRunner postRunner(runner);
- postRunner.add("remove-unused-module-elements");
- postRunner.setIsNested(true);
- postRunner.run();
+ // Assumes imports are at the beginning
+ Name name = module->functions[std::stoi(index)]->name;
+ extract(runner, module, name);
}
};
-// declare pass
+// declare passes
Pass* createExtractFunctionPass() { return new ExtractFunction(); }
+Pass* createExtractFunctionIndexPass() { return new ExtractFunctionIndex(); }
} // namespace wasm
diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp
index 89b367272..10a688313 100644
--- a/src/passes/pass.cpp
+++ b/src/passes/pass.cpp
@@ -129,6 +129,9 @@ void PassRegistry::registerPasses() {
registerPass("extract-function",
"leaves just one function (useful for debugging)",
createExtractFunctionPass);
+ registerPass("extract-function-index",
+ "leaves just one function selected by index",
+ createExtractFunctionIndexPass);
registerPass(
"flatten", "flattens out code, removing nesting", createFlattenPass);
registerPass("fpcast-emu",
diff --git a/src/passes/passes.h b/src/passes/passes.h
index 4cc8040a4..5f265470d 100644
--- a/src/passes/passes.h
+++ b/src/passes/passes.h
@@ -42,6 +42,7 @@ Pass* createDuplicateImportEliminationPass();
Pass* createDuplicateFunctionEliminationPass();
Pass* createEmitTargetFeaturesPass();
Pass* createExtractFunctionPass();
+Pass* createExtractFunctionIndexPass();
Pass* createFlattenPass();
Pass* createFuncCastEmulationPass();
Pass* createFullPrinterPass();
diff --git a/test/lit/passes/extract-function.wast b/test/lit/passes/extract-function.wast
new file mode 100644
index 000000000..1a8970598
--- /dev/null
+++ b/test/lit/passes/extract-function.wast
@@ -0,0 +1,72 @@
+;; RUN: foreach %s %t wasm-opt --extract-function=foo -S -o - | filecheck %s
+;; RUN: foreach %s %t wasm-opt --extract-function --pass-arg=extract-function@foo -S -o - | filecheck %s
+;; RUN: foreach %s %t wasm-opt --extract-function-index=0 -S -o - | filecheck %s
+;; RUN: foreach %s %t wasm-opt --extract-function-index --pass-arg=extract-function-index@0 -S -o - | filecheck %s
+
+;; CHECK: (module
+;; CHECK-NEXT: (type $none_=>_none (func))
+;; CHECK-NEXT: (import "env" "bar" (func $bar))
+;; CHECK-NEXT: (export "foo" (func $foo))
+;; CHECK-NEXT: (func $foo
+;; CHECK-NEXT: (call $bar)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: )
+(module
+ (func $foo
+ (call $bar)
+ )
+ (func $bar
+ (call $foo)
+ )
+ (func $other
+ (drop (i32.const 1))
+ )
+)
+
+;; CHECK: (module
+;; CHECK-NEXT: (type $none_=>_none (func))
+;; CHECK-NEXT: (import "env" "other" (func $other))
+;; CHECK-NEXT: (export "foo" (func $foo))
+;; CHECK-NEXT: (func $foo
+;; CHECK-NEXT: (nop)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: )
+(module
+ ;; Use another function in the table, but the table is not used in the
+ ;; extracted function
+ (table $t 10 funcref)
+ (elem $0 (table $t) (i32.const 0) func $other)
+ (func $foo
+ (nop)
+ )
+ (func $other
+ (drop (i32.const 1))
+ )
+)
+
+;; CHECK: (module
+;; CHECK-NEXT: (type $none (func))
+;; CHECK-NEXT: (import "env" "other" (func $other))
+;; CHECK-NEXT: (table $t 10 funcref)
+;; CHECK-NEXT: (elem $0 (i32.const 0) $other)
+;; CHECK-NEXT: (export "foo" (func $foo))
+;; CHECK-NEXT: (func $foo
+;; CHECK-NEXT: (call_indirect (type $none)
+;; CHECK-NEXT: (i32.const 10)
+;; CHECK-NEXT: )
+;; CHECK-NEXT: )
+;; CHECK-NEXT: )
+(module
+ ;; Use another function in the table, and the table *is* used. As a result,
+ ;; the table and its elements will remain. The called function, $other, will
+ ;; remain as an import that is placed in the table.
+ (type $none (func))
+ (table $t 10 funcref)
+ (elem $0 (table $t) (i32.const 0) func $other)
+ (func $foo
+ (call_indirect (type $none) (i32.const 10))
+ )
+ (func $other
+ (drop (i32.const 1))
+ )
+)
diff --git a/test/passes/extract-function=foo.txt b/test/passes/extract-function=foo.txt
deleted file mode 100644
index 3caf274c3..000000000
--- a/test/passes/extract-function=foo.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-(module
- (type $none_=>_none (func))
- (import "env" "bar" (func $bar))
- (export "foo" (func $foo))
- (func $foo
- (call $bar)
- )
-)
-(module
- (type $none_=>_none (func))
- (import "env" "other" (func $other))
- (export "foo" (func $foo))
- (func $foo
- (nop)
- )
-)
-(module
- (type $none (func))
- (import "env" "other" (func $other))
- (table $t 10 funcref)
- (elem $0 (i32.const 0) $other)
- (export "foo" (func $foo))
- (func $foo
- (call_indirect (type $none)
- (i32.const 10)
- )
- )
-)
diff --git a/test/passes/extract-function=foo.wast b/test/passes/extract-function=foo.wast
deleted file mode 100644
index ab1d8b269..000000000
--- a/test/passes/extract-function=foo.wast
+++ /dev/null
@@ -1,36 +0,0 @@
-(module
- (func $foo
- (call $bar)
- )
- (func $bar
- (call $foo)
- )
- (func $other
- (drop (i32.const 1))
- )
-)
-(module
- ;; Use another function in the table, but the table is not used in the
- ;; extracted function
- (table $t 10 funcref)
- (elem $0 (table $t) (i32.const 0) func $other)
- (func $foo
- )
- (func $other
- (drop (i32.const 1))
- )
-)
-(module
- ;; Use another function in the table, and the table *is* used. As a result,
- ;; the table and its elements will remain. The called function, $other, will
- ;; remain as an import that is placed in the table.
- (type $none (func))
- (table $t 10 funcref)
- (elem $0 (table $t) (i32.const 0) func $other)
- (func $foo
- (call_indirect (type $none) (i32.const 10))
- )
- (func $other
- (drop (i32.const 1))
- )
-)
diff --git a/test/passes/extract-function_pass-arg=extract-function@foo.txt b/test/passes/extract-function_pass-arg=extract-function@foo.txt
deleted file mode 100644
index 3caf274c3..000000000
--- a/test/passes/extract-function_pass-arg=extract-function@foo.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-(module
- (type $none_=>_none (func))
- (import "env" "bar" (func $bar))
- (export "foo" (func $foo))
- (func $foo
- (call $bar)
- )
-)
-(module
- (type $none_=>_none (func))
- (import "env" "other" (func $other))
- (export "foo" (func $foo))
- (func $foo
- (nop)
- )
-)
-(module
- (type $none (func))
- (import "env" "other" (func $other))
- (table $t 10 funcref)
- (elem $0 (i32.const 0) $other)
- (export "foo" (func $foo))
- (func $foo
- (call_indirect (type $none)
- (i32.const 10)
- )
- )
-)
diff --git a/test/passes/extract-function_pass-arg=extract-function@foo.wast b/test/passes/extract-function_pass-arg=extract-function@foo.wast
deleted file mode 100644
index ab1d8b269..000000000
--- a/test/passes/extract-function_pass-arg=extract-function@foo.wast
+++ /dev/null
@@ -1,36 +0,0 @@
-(module
- (func $foo
- (call $bar)
- )
- (func $bar
- (call $foo)
- )
- (func $other
- (drop (i32.const 1))
- )
-)
-(module
- ;; Use another function in the table, but the table is not used in the
- ;; extracted function
- (table $t 10 funcref)
- (elem $0 (table $t) (i32.const 0) func $other)
- (func $foo
- )
- (func $other
- (drop (i32.const 1))
- )
-)
-(module
- ;; Use another function in the table, and the table *is* used. As a result,
- ;; the table and its elements will remain. The called function, $other, will
- ;; remain as an import that is placed in the table.
- (type $none (func))
- (table $t 10 funcref)
- (elem $0 (table $t) (i32.const 0) func $other)
- (func $foo
- (call_indirect (type $none) (i32.const 10))
- )
- (func $other
- (drop (i32.const 1))
- )
-)