Skip to content

Reintroduce wasm-merge #5709

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 228 commits into from
May 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
228 commits
Select commit Hold shift + click to select a range
82e796d
start.somewhere
kripken Apr 25, 2023
6f20502
framework
kripken Apr 25, 2023
2e891a3
framework
kripken Apr 25, 2023
c7d397c
builds
kripken Apr 25, 2023
5957325
yolo
kripken Apr 26, 2023
a444694
refactor
kripken Apr 26, 2023
f9a8209
comment
kripken Apr 26, 2023
c2c0015
one file builds
kripken Apr 26, 2023
35b97b2
another
kripken Apr 26, 2023
bb0ab00
work
kripken Apr 26, 2023
4ba764b
work
kripken Apr 26, 2023
9a71da9
mre
kripken Apr 26, 2023
062c9d1
more
kripken Apr 26, 2023
3d93ac9
more
kripken Apr 26, 2023
579bda8
more
kripken Apr 26, 2023
02d1c5a
more
kripken Apr 26, 2023
13fbd79
more
kripken Apr 26, 2023
6293f52
more
kripken Apr 26, 2023
7bf2cd9
more
kripken Apr 26, 2023
7250203
more
kripken Apr 26, 2023
281b9f4
more
kripken Apr 26, 2023
ec225f4
more
kripken Apr 26, 2023
1117f19
more
kripken Apr 26, 2023
ebfa4fe
more
kripken Apr 26, 2023
98a42fb
more
kripken Apr 26, 2023
901173a
more
kripken Apr 26, 2023
d5c3fc3
more
kripken Apr 26, 2023
a19961c
more
kripken Apr 26, 2023
09f9b3e
more
kripken Apr 26, 2023
797e395
more
kripken Apr 26, 2023
c13d73f
more
kripken Apr 26, 2023
7ee0eeb
more
kripken Apr 26, 2023
717b802
more
kripken Apr 26, 2023
9a70762
more
kripken Apr 26, 2023
441082a
more
kripken Apr 26, 2023
072960e
more
kripken Apr 26, 2023
35e1849
more
kripken Apr 26, 2023
afd0093
more
kripken Apr 26, 2023
8c59f48
more
kripken Apr 26, 2023
bceb0e3
more
kripken Apr 26, 2023
73124d1
format
kripken Apr 26, 2023
1cdd884
Merge branch 'delegate.kind' into wasm-merge-comeback
kripken Apr 26, 2023
2d54c7d
start
kripken Apr 26, 2023
4867c42
work
kripken Apr 26, 2023
cda9b86
work
kripken Apr 26, 2023
42d9386
work
kripken Apr 26, 2023
7900001
work
kripken Apr 26, 2023
f755d3e
work
kripken Apr 26, 2023
a559825
work
kripken Apr 26, 2023
e922a5c
work
kripken Apr 26, 2023
e92cf0b
work
kripken Apr 26, 2023
eecc45b
work
kripken Apr 26, 2023
f34dab2
work
kripken Apr 27, 2023
7cf3ded
work
kripken Apr 27, 2023
2c19914
work
kripken Apr 27, 2023
5e445c7
work
kripken Apr 27, 2023
b5bd608
work
kripken Apr 27, 2023
c2abdd3
work
kripken Apr 27, 2023
80ed932
format
kripken Apr 27, 2023
127af53
work
kripken Apr 27, 2023
d9ccfec
work
kripken Apr 27, 2023
bd02e14
work
kripken Apr 27, 2023
019d87d
work
kripken Apr 27, 2023
ca23503
builds
kripken Apr 27, 2023
2a2995b
builds
kripken Apr 27, 2023
322dac2
fix
kripken Apr 27, 2023
ff728d7
work
kripken Apr 27, 2023
daf4e41
work
kripken Apr 27, 2023
476a995
work
kripken Apr 27, 2023
60c8b28
test
kripken Apr 27, 2023
8a4835f
test
kripken Apr 27, 2023
d7ea5e2
test
kripken Apr 27, 2023
fd69258
test
kripken Apr 27, 2023
a910d79
test
kripken Apr 27, 2023
8c0dea2
globals
kripken Apr 27, 2023
a0ed235
Merge remote-tracking branch 'origin/delegate.kind' into wasm-merge-c…
kripken Apr 27, 2023
82abf9d
fix
kripken Apr 27, 2023
7f713f2
Merge remote-tracking branch 'origin/delegate.kind' into wasm-merge-c…
kripken Apr 27, 2023
b4402ad
test
kripken Apr 27, 2023
0bd3582
work
kripken Apr 27, 2023
a566d80
work
kripken Apr 27, 2023
3edfc7e
work
kripken Apr 27, 2023
b6a1c29
work
kripken Apr 27, 2023
3b536d5
work
kripken Apr 27, 2023
6ff6a44
work
kripken Apr 27, 2023
fc57035
work
kripken Apr 27, 2023
915ccd9
work
kripken Apr 27, 2023
a0b498c
halfworking
kripken Apr 27, 2023
9f749ab
work
kripken Apr 27, 2023
ccef54f
halfworking
kripken Apr 27, 2023
2e977df
fix
kripken Apr 27, 2023
a366ee8
fix
kripken Apr 27, 2023
43c02b8
fatal
kripken Apr 27, 2023
713bade
comments
kripken Apr 27, 2023
ab26e32
nicer
kripken Apr 27, 2023
31d2c16
comment
kripken Apr 27, 2023
7b35437
start
kripken Apr 28, 2023
d9ad817
work
kripken Apr 28, 2023
d65d259
test
kripken Apr 28, 2023
2a106af
test
kripken Apr 28, 2023
20505cc
test
kripken Apr 28, 2023
c3a15c8
test
kripken Apr 28, 2023
c2efc06
test
kripken Apr 28, 2023
a857a8a
broken
kripken Apr 28, 2023
300a952
test
kripken Apr 28, 2023
6b7e57d
format
kripken Apr 28, 2023
dcced41
Merge remote-tracking branch 'origin/main' into wasm-merge-comeback
kripken Apr 28, 2023
2b4ed13
yolo
kripken Apr 28, 2023
5c33e04
format
kripken Apr 28, 2023
3ea77e5
fix
kripken Apr 28, 2023
3f927ae
format
kripken Apr 28, 2023
c011720
work
kripken Apr 28, 2023
1354d84
IMPORT
kripken Apr 28, 2023
ef4e3dd
work
kripken Apr 28, 2023
5ca2537
work
kripken Apr 28, 2023
c5628ff
work
kripken Apr 28, 2023
5aabcce
work
kripken Apr 28, 2023
6b19d78
work
kripken Apr 28, 2023
a5d90f7
work
kripken Apr 28, 2023
f06dfde
work
kripken Apr 28, 2023
0db94ed
work
kripken Apr 28, 2023
9e965fc
work
kripken Apr 28, 2023
958c751
work
kripken Apr 28, 2023
8e49cb2
work
kripken Apr 28, 2023
591d79b
work
kripken Apr 28, 2023
c8dfb45
work
kripken Apr 28, 2023
ffa30ad
work
kripken Apr 28, 2023
08117a7
work
kripken Apr 28, 2023
a40ef1f
format
kripken Apr 28, 2023
c07c8d1
work
kripken Apr 28, 2023
13f010a
work
kripken Apr 28, 2023
49e49c1
work
kripken Apr 28, 2023
e535613
Merge remote-tracking branch 'origin/main' into delegate.kind
kripken Apr 28, 2023
a42a8e6
Merge remote-tracking branch 'origin/seg.data.elem' into delegate.kind
kripken Apr 28, 2023
d2b5e05
fix
kripken Apr 28, 2023
c6ef992
fix
kripken Apr 28, 2023
01cc5a5
Merge remote-tracking branch 'origin/main' into delegate.kind
kripken Apr 28, 2023
0174f9e
test update
kripken Apr 28, 2023
90fc377
Merge branch 'seg.data.elem' into delegate.kind
kripken Apr 28, 2023
2944efa
simplify
kripken May 1, 2023
c6d868a
remove Seg from name
kripken May 1, 2023
e8b2ac5
format
kripken May 1, 2023
280fb12
fix
kripken May 1, 2023
5978aff
fix
kripken May 1, 2023
27e9407
fix
kripken May 1, 2023
6ac0f50
formt
kripken May 1, 2023
0d7fd4c
format
kripken May 1, 2023
ede30ee
Merge branch 'seg.data.elem' into delegate.kind
kripken May 1, 2023
83ef25c
Merge remote-tracking branch 'origin/main' into seg.data.elem
kripken May 1, 2023
b78ffa4
Merge branch 'seg.data.elem' into delegate.kind
kripken May 1, 2023
b8961fe
Merge remote-tracking branch 'origin/delegate.kind' into wasm-merge-c…
kripken May 2, 2023
ad49e7d
Merge remote-tracking branch 'origin/main' into wasm-merge-comeback
kripken May 2, 2023
7e5d899
comments
kripken May 2, 2023
d1b46f4
comments
kripken May 2, 2023
deaa8be
comments
kripken May 2, 2023
aa74668
comment
kripken May 2, 2023
c1ccafd
format
kripken May 2, 2023
9aa26a3
rename
kripken May 2, 2023
823899c
docs
kripken May 2, 2023
c7c8d94
work
kripken May 2, 2023
87adf39
fix
kripken May 2, 2023
56d39c0
fix
kripken May 2, 2023
dbbebe9
format
kripken May 2, 2023
638ffcc
xplain
kripken May 2, 2023
e73fa57
xplain
kripken May 2, 2023
774da27
start.fuzz
kripken May 2, 2023
18ea6b2
work
kripken May 2, 2023
6cda810
todo
kripken May 2, 2023
2a43a31
anbs
kripken May 2, 2023
98dab03
fix
kripken May 2, 2023
064667c
test
kripken May 2, 2023
280a125
test
kripken May 2, 2023
b64c74b
work
kripken May 3, 2023
9fe14a3
todo
kripken May 3, 2023
db917cc
comment
kripken May 3, 2023
931831b
docs
kripken May 3, 2023
5c2121f
note
kripken May 3, 2023
ae2c47b
Merge remote-tracking branch 'origin/main' into wasm-merge-comeback
kripken May 4, 2023
8577a24
fix
kripken May 4, 2023
46f4679
Merge remote-tracking branch 'origin/main' into delegate.kind
kripken May 4, 2023
83d4f77
Merge branch 'delegate.kind' into wasm-merge-comeback
kripken May 4, 2023
0feeb5e
update
kripken May 5, 2023
68492c7
quadratic => linear
kripken May 5, 2023
e985310
note
kripken May 5, 2023
f6e6e88
Merge remote-tracking branch 'origin/main' into wasm-merge-comeback
kripken May 5, 2023
8085db6
Merge remote-tracking branch 'origin/main' into wasm-merge-comeback
kripken May 5, 2023
1872952
fic
kripken May 5, 2023
1e341a2
better
kripken May 5, 2023
b21c058
work
kripken May 5, 2023
b9679e0
fix
kripken May 5, 2023
802a9ab
simpler
kripken May 5, 2023
3f12412
fix
kripken May 5, 2023
78daf59
fix
kripken May 5, 2023
bee6401
bettr
kripken May 5, 2023
8c771b4
bettr
kripken May 5, 2023
dea1b3c
bettr
kripken May 5, 2023
240071d
remove obsolete comment
kripken May 5, 2023
b610d75
the worst typo
kripken May 5, 2023
85131ca
fix comment
kripken May 5, 2023
8781a54
Merge remote-tracking branch 'origin/main' into wasm-merge-comeback
kripken May 9, 2023
cc674a4
add help test
kripken May 9, 2023
2a91a3e
feedback: use std::unique_ptr
kripken May 9, 2023
8a2fab5
Merge remote-tracking branch 'origin/main' into wasm-merge-comeback
kripken May 10, 2023
1211352
feedback: name modules in examples
kripken May 10, 2023
9a32c34
feedback: remove unused things
kripken May 10, 2023
d7f54e0
feedback: check for a namemap for each kind to avoid UB
kripken May 10, 2023
27f51c8
meedback: rename NameMap=>NameUpdates
kripken May 10, 2023
b0ae1c7
feedback: remove first
kripken May 10, 2023
185f7d4
feedback: note on es6 cycles
kripken May 10, 2023
97320ec
feedback: test fusing of a memory
kripken May 10, 2023
e794707
feedback on test
kripken May 10, 2023
1e1e7bd
fix english
kripken May 10, 2023
4b4619f
text fixes
kripken May 10, 2023
2c2b132
reorder to try to match CHECK lines
kripken May 11, 2023
fbc1419
apply auto-updater output
kripken May 11, 2023
d1eb2be
Merge remote-tracking branch 'origin/main' into wasm-merge-comeback
kripken May 12, 2023
169140d
work
kripken May 12, 2023
7d47af0
forat
kripken May 12, 2023
1a0661d
work
kripken May 12, 2023
15e7be7
rename
kripken May 12, 2023
ce77013
fix
kripken May 12, 2023
730310c
sad
kripken May 12, 2023
96c5d6a
test
kripken May 12, 2023
296e5be
simplify fuzzer
kripken May 12, 2023
c326d69
update help
kripken May 12, 2023
acb55eb
Switch 3rd option to skip conflicts
kripken May 15, 2023
a539250
fix.fuzzer
kripken May 15, 2023
fc06d9a
Update test/lit/merge/export_options.wat
kripken May 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ full changeset diff at the end of each section.
Current Trunk
-------------

- Add a `wasm-merge` tool. This is a full rewrite of the previous `wasm-merge`
tool that was removed from the tree in the past. The new version is much
simpler after recent improvements to multi-memory and multi-table. The
rewrite was motivated by new use cases for merging modules in the context of
WasmGC.
- Some C and JS API functions now refer to data and element segments by name
instead of index.
- The --nominal and --hybrid command line options and related API functions have
Expand Down
147 changes: 147 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,9 @@ This repository contains code that builds the following tools in `bin/`:
performs emscripten-specific passes over it.
* **wasm-ctor-eval**: A tool that can execute functions (or parts of functions)
at compile time.
* **wasm-merge**: Merges multiple wasm files into a single file, connecting
corresponding imports to exports as it does so. Like a bundler for JS, but
for wasm.
* **binaryen.js**: A standalone JavaScript library that exposes Binaryen methods for [creating and optimizing Wasm modules](https://github.com/WebAssembly/binaryen/blob/main/test/binaryen.js/hello-world.js). For builds, see [binaryen.js on npm](https://www.npmjs.com/package/binaryen) (or download it directly from [github](https://github.com/raw/AssemblyScript/binaryen.js/master/index.js), [rawgit](https://cdn.rawgit.com/AssemblyScript/binaryen.js/master/index.js), or [unpkg](https://unpkg.com/binaryen@latest/index.js)). Minimal requirements: Node.js v15.8 or Chrome v75 or Firefox v78.

Usage instructions for each are below.
Expand Down Expand Up @@ -562,6 +565,150 @@ as mentioned earlier, but there is no limitation on what you can execute here.
Any export from the wasm can be executed, if its contents are suitable. For
example, in Emscripten `wasm-ctor-eval` is even run on `main()` when possible.

### wasm-merge

`wasm-merge` combines wasm files together. For example, imagine you have a
project that uses wasm files from multiple toolchains. Then it can be helpful to
merge them all into a single wasm file before shipping, since in a single wasm
file the calls between the modules become just normal calls inside a module,
which allows them to be inlined, dead code eliminated, and so forth, potentially
improving speed and size.

For example, imagine we have these two wasm files:

```wat
;; a.wasm
(module
(import "second" "bar" (func $second.bar))

(export "main" (func $func))

(func $func
(call $second.bar)
)
)
```

```wat
;; b.wasm
(module
(import "outside" "log" (func $log (param i32)))

(export "bar" (func $func))

(func $func
(call $log
(i32.const 42)
)
)
)
```

The filenames on your local drive are `a.wasm` and `b.wasm`, but for merging /
bundling purposes let's say that the first is known as `"first"` and the second
as `"second"`. That is, we want the first module's import of `"second.bar"` to
call the function `$func` in the second module. Here is a wasm-merge command for
that:

```
wasm-merge a.wasm first b.wasm second -o output.wasm
```

We give it the first wasm file, then its name, and then the second wasm file
and then its name. The merged output is this:

```wat
(module
(import "second" "bar" (func $second.bar))
(import "outside" "log" (func $log (param i32)))

(export "main" (func $func))
(export "bar" (func $func_2))

(func $func
(call $func_2)
)

(func $func_2
(call $log
(i32.const 42)
)
)
)
```

`wasm-merge` combined the two files into one, merging their functions, imports,
etc., all while fixing up name conflicts and connecting corresponding imports to
exports. In particular, note how `$func` calls `$func_2`, which is exactly what
we wanted: `$func_2` is the function from the second module (renamed to avoid a
name collision).

Note that the wasm output in this example could benefit from additional
optimization. First, the call to `$func_2` can now be easily inlined, so we can
run `wasm-opt -O3` to do that for us. Also, we may not need all the imports and
exports, for which we can run
[wasm-metadce](https://github.com/WebAssembly/binaryen/wiki/Pruning-unneeded-code-in-wasm-files-with-wasm-metadce#example-pruning-exports).
A good workflow could be to run `wasm-merge`, then `wasm-metadce`, then finish
with `wasm-opt`.

`wasm-merge` is kind of like a bundler for wasm files, in the sense of a "JS
bundler" but for wasm. That is, with the wasm files above, imagine that we had
this JS code to instantiate and connect them at runtime:

```js
// Compile the first module.
var first = await fetch("a.wasm");
first = new WebAssembly.Module(first);

// Compile the first module.
var second = await fetch("b.wasm");
second = new WebAssembly.Module(second);

// Instantiate the second, with a JS import.
second = new WebAssembly.Instance(second, {
outside: {
log: (value) => {
console.log('value:', value);
}
}
});

// Instantiate the first, importing from the second.
first = new WebAssembly.Instance(first, {
second: second.exports
});

// Call the main function.
first.exports.main();
```

What `wasm-merge` does is basically what that JS does: it hooks up imports to
exports, resolving names using the module names you provided. That is, by
running `wasm-merge` we are moving the work of connecting the modules from
runtime to compile time. As a result, after running `wasm-merge` we need a lot
less JS to get the same result:

```js
// Compile the single module.
var merged = await fetch("merged.wasm");
merged = new WebAssembly.Module(merged);

// Instantiate it with a JS import.
merged = new WebAssembly.Instance(merged, {
outside: {
log: (value) => {
console.log('value:', value);
}
}
});

// Call the main function.
merged.exports.main();
```

We still need to fetch and compile the merged wasm, and to provide it the JS
import, but the work to connect two wasm modules is not needed any more.

## Testing

```
Expand Down
69 changes: 65 additions & 4 deletions scripts/fuzz_opt.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ def random_size():
return random.randint(INPUT_SIZE_MIN, 2 * INPUT_SIZE_MEAN - INPUT_SIZE_MIN)


def make_random_input(input_size, raw_input_data):
with open(raw_input_data, 'wb') as f:
f.write(bytes([random.randint(0, 255) for x in range(input_size)]))


def run(cmd, stderr=None, silent=False):
if not silent:
print(' '.join(cmd))
Expand Down Expand Up @@ -1284,6 +1289,62 @@ def handle(self, wasm):
compare_between_vms(fix_output(wasm_exec), fix_output(evalled_wasm_exec), 'CtorEval')


# Tests wasm-merge
class Merge(TestCaseHandler):
frequency = 0.15

def handle(self, wasm):
# generate a second wasm file to merge. note that we intentionally pick
# a smaller size than the main wasm file, so that reduction is
# effective (i.e., as we reduce the main wasm to small sizes, we also
# end up with small secondary wasms)
# TODO: add imports and exports that connect between the two
wasm_size = os.stat(wasm).st_size
second_size = min(wasm_size, random_size())
second_input = abspath('second_input.dat')
make_random_input(second_size, second_input)
second_wasm = abspath('second.wasm')
run([in_bin('wasm-opt'), second_input, '-ttf', '-o', second_wasm] + FUZZ_OPTS + FEATURE_OPTS)

# sometimes also optimize the second module
if random.random() < 0.5:
opts = get_random_opts()
run([in_bin('wasm-opt'), second_wasm, '-o', second_wasm, '-all'] + FEATURE_OPTS + opts)

# merge the wasm files. note that we must pass -all, as even if the two
# inputs are MVP, the output may have multiple tables and multiple
# memories (and we must also do that in the commands later down).
#
# Use --skip-export-conflicts as we only look at the first module's
# exports for now - we don't care about the second module's.
# TODO: compare the second module's exports as well, but we'd need
# to handle renaming of conflicting exports.
merged = abspath('merged.wasm')
run([in_bin('wasm-merge'), wasm, 'first',
abspath('second.wasm'), 'second', '-o', merged,
'--skip-export-conflicts'] + FEATURE_OPTS + ['-all'])

# sometimes also optimize the merged module
if random.random() < 0.5:
opts = get_random_opts()
run([in_bin('wasm-opt'), merged, '-o', merged, '-all'] + FEATURE_OPTS + opts)

# verify that merging in the second module did not alter the output.
output = run_bynterp(wasm, ['--fuzz-exec-before', '-all'])
output = fix_output(output)
merged_output = run_bynterp(merged, ['--fuzz-exec-before', '-all'])
merged_output = fix_output(merged_output)

# a complication is that the second module's exports are appended, so we
# have extra output. to handle that, just prune the tail, so that we
# only compare the original exports from the first module.
# TODO: compare the second module's exports to themselves as well, but
# they may have been renamed due to overlaps...
Comment on lines +1341 to +1342
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Silently renaming exports seems bad! Should this be an error by default instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this should error, since there are use cases like e.g. two modules export "main" and so after renaming we end up with "main" and "main_1". The user of wasm-merge knows that the first is the first module's and so forth, so they can call them at the appropriate times. (The renamings are deterministic, which makes that possible.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general I wouldn't expect a user to have a detailed enough global understanding of their system to anticipate name conflicts. In particular for the example of main, I expect that merges with two exported mains are more likely to be accidental than intentional. I agree that it should be possible to let wasm-merge handle resolve conflicts automatically, but I think that should be opt-in and that erroring out would be a safer default.

Also, WDYT about resolving conflicts or even handling all exports by renaming each export from an original module to module.export in the combined module? That would make conflicts impossible by construction.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want multiple modes here, yeah. I'm not sure what the default should be, though. Renaming all exports to module.export would mean we don't handle well the simple use case of a main module being merged with side modules, and the side modules have no final exports to the outside - in that case we just want the main module's exports to be kept as they are, and the side module's exports to be "dropped."

So maybe we want some modes like this:

  • Rename conflicting export names.
  • Error on conflicting export names.
  • Keep exports from one module, drop all the rest. (Or, perhaps a set of modules could keep their exports, with either renaming or erroring.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, those modes make sense to me. For the mode where we drop duplicated exports, it would make sense if the first module to supply an export won. I do think the error mode is the safest default.

merged_output = merged_output[:len(output)]

compare_between_vms(output, merged_output, 'Merge')


# Check that the text format round-trips without error.
class RoundtripText(TestCaseHandler):
frequency = 0.05
Expand All @@ -1306,6 +1367,7 @@ def handle(self, wasm):
Asyncify(),
TrapsNeverHappen(),
CtorEval(),
Merge(),
# FIXME: Re-enable after https://github.com/WebAssembly/binaryen/issues/3989
# RoundtripText()
]
Expand All @@ -1329,7 +1391,7 @@ def test_one(random_input, given_wasm):
randomize_fuzz_settings()
pick_initial_contents()

opts = randomize_opt_flags()
opts = get_random_opts()
print('randomized opts:', '\n ' + '\n '.join(opts))
print()

Expand Down Expand Up @@ -1503,7 +1565,7 @@ def write_commands(commands, filename):
("--type-merging",)}


def randomize_opt_flags():
def get_random_opts():
flag_groups = []
has_flatten = False

Expand Down Expand Up @@ -1643,8 +1705,7 @@ def randomize_opt_flags():
'iters/sec, ', total_wasm_size / elapsed,
'wasm_bytes/sec, ', ignored_vm_runs,
'ignored\n')
with open(raw_input_data, 'wb') as f:
f.write(bytes([random.randint(0, 255) for x in range(input_size)]))
make_random_input(input_size, raw_input_data)
assert os.path.getsize(raw_input_data) == input_size
# remove the generated wasm file, so that we can tell if the fuzzer
# fails to create one
Expand Down
2 changes: 1 addition & 1 deletion scripts/update_help_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

TOOLS = ['wasm-opt', 'wasm-as', 'wasm-dis', 'wasm2js', 'wasm-ctor-eval',
'wasm-shell', 'wasm-reduce', 'wasm-metadce', 'wasm-split',
'wasm-fuzz-types', 'wasm-emscripten-finalize']
'wasm-fuzz-types', 'wasm-emscripten-finalize', 'wasm-merge']


def main():
Expand Down
48 changes: 42 additions & 6 deletions src/ir/module-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,9 @@ inline DataSegment* copyDataSegment(const DataSegment* segment, Module& out) {
return out.addDataSegment(std::move(ret));
}

inline void copyModule(const Module& in, Module& out) {
// we use names throughout, not raw pointers, so simple copying is fine
// for everything *but* expressions
for (auto& curr : in.exports) {
out.addExport(new Export(*curr));
}
// Copies named toplevel module items (things of kind ModuleItemKind). See
// copyModule() for something that also copies exports, the start function, etc.
inline void copyModuleItems(const Module& in, Module& out) {
for (auto& curr : in.functions) {
copyFunction(curr.get(), out);
}
Expand All @@ -159,6 +156,15 @@ inline void copyModule(const Module& in, Module& out) {
for (auto& curr : in.dataSegments) {
copyDataSegment(curr.get(), out);
}
}

inline void copyModule(const Module& in, Module& out) {
// we use names throughout, not raw pointers, so simple copying is fine
// for everything *but* expressions
for (auto& curr : in.exports) {
out.addExport(std::make_unique<Export>(*curr));
}
copyModuleItems(in, out);
out.start = in.start;
out.customSections = in.customSections;
out.debugInfoFileNames = in.debugInfoFileNames;
Expand Down Expand Up @@ -354,6 +360,36 @@ template<typename T> inline void iterImports(Module& wasm, T visitor) {
iterImportedTags(wasm, visitor);
}

// Iterates over all importable module items. The visitor provided should have
// signature void(ExternalKind, Importable*).
template<typename T> inline void iterImportable(Module& wasm, T visitor) {
for (auto& curr : wasm.functions) {
if (curr->imported()) {
visitor(ExternalKind::Function, curr.get());
}
}
for (auto& curr : wasm.tables) {
if (curr->imported()) {
visitor(ExternalKind::Table, curr.get());
}
}
for (auto& curr : wasm.memories) {
if (curr->imported()) {
visitor(ExternalKind::Memory, curr.get());
}
}
for (auto& curr : wasm.globals) {
if (curr->imported()) {
visitor(ExternalKind::Global, curr.get());
}
}
for (auto& curr : wasm.tags) {
if (curr->imported()) {
visitor(ExternalKind::Tag, curr.get());
}
}
}

// Helper class for performing an operation on all the functions in the module,
// in parallel, with an Info object for each one that can contain results of
// some computation that the operation performs.
Expand Down
1 change: 1 addition & 0 deletions src/tools/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ binaryen_add_executable(wasm-ctor-eval wasm-ctor-eval.cpp)
if(NOT BUILD_EMSCRIPTEN_TOOLS_ONLY)
binaryen_add_executable(wasm-shell wasm-shell.cpp)
binaryen_add_executable(wasm-reduce wasm-reduce.cpp)
binaryen_add_executable(wasm-merge wasm-merge.cpp)
binaryen_add_executable(wasm-fuzz-types "${fuzzing_SOURCES};wasm-fuzz-types.cpp")
endif()

Expand Down
Loading