-
Notifications
You must be signed in to change notification settings - Fork 787
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
Reintroduce wasm-merge #5709
Changes from all commits
82e796d
6f20502
2e891a3
c7d397c
5957325
a444694
f9a8209
c2c0015
35b97b2
bb0ab00
4ba764b
9a71da9
062c9d1
3d93ac9
579bda8
02d1c5a
13fbd79
6293f52
7bf2cd9
7250203
281b9f4
ec225f4
1117f19
ebfa4fe
98a42fb
901173a
d5c3fc3
a19961c
09f9b3e
797e395
c13d73f
7ee0eeb
717b802
9a70762
441082a
072960e
35e1849
afd0093
8c59f48
bceb0e3
73124d1
1cdd884
2d54c7d
4867c42
cda9b86
42d9386
7900001
f755d3e
a559825
e922a5c
e92cf0b
eecc45b
f34dab2
7cf3ded
2c19914
5e445c7
b5bd608
c2abdd3
80ed932
127af53
d9ccfec
bd02e14
019d87d
ca23503
2a2995b
322dac2
ff728d7
daf4e41
476a995
60c8b28
8a4835f
d7ea5e2
fd69258
a910d79
8c0dea2
a0ed235
82abf9d
7f713f2
b4402ad
0bd3582
a566d80
3edfc7e
b6a1c29
3b536d5
6ff6a44
fc57035
915ccd9
a0b498c
9f749ab
ccef54f
2e977df
a366ee8
43c02b8
713bade
ab26e32
31d2c16
7b35437
d9ad817
d65d259
2a106af
20505cc
c3a15c8
c2efc06
a857a8a
300a952
6b7e57d
dcced41
2b4ed13
5c33e04
3ea77e5
3f927ae
c011720
1354d84
ef4e3dd
5ca2537
c5628ff
5aabcce
6b19d78
a5d90f7
f06dfde
0db94ed
9e965fc
958c751
8e49cb2
591d79b
c8dfb45
ffa30ad
08117a7
a40ef1f
c07c8d1
13f010a
49e49c1
e535613
a42a8e6
d2b5e05
c6ef992
01cc5a5
0174f9e
90fc377
2944efa
c6d868a
e8b2ac5
280fb12
5978aff
27e9407
6ac0f50
0d7fd4c
ede30ee
83ef25c
b78ffa4
b8961fe
ad49e7d
7e5d899
d1b46f4
deaa8be
aa74668
c1ccafd
9aa26a3
823899c
c7c8d94
87adf39
56d39c0
dbbebe9
638ffcc
e73fa57
774da27
18ea6b2
6cda810
2a43a31
98dab03
064667c
280a125
b64c74b
9fe14a3
db917cc
931831b
5c2121f
ae2c47b
8577a24
46f4679
83d4f77
0feeb5e
68492c7
e985310
f6e6e88
8085db6
1872952
1e341a2
b21c058
b9679e0
802a9ab
3f12412
78daf59
bee6401
8c771b4
dea1b3c
240071d
b610d75
85131ca
8781a54
cc674a4
2a91a3e
8a2fab5
1211352
9a32c34
d7f54e0
27f51c8
b0ae1c7
185f7d4
97320ec
e794707
1e1e7bd
4b4619f
2c2b132
fbc1419
d1eb2be
169140d
7d47af0
1a0661d
15e7be7
ce77013
730310c
96c5d6a
296e5be
c326d69
acb55eb
a539250
fc06d9a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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)) | ||
|
@@ -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
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 So maybe we want some modes like this:
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
|
@@ -1306,6 +1367,7 @@ def handle(self, wasm): | |
Asyncify(), | ||
TrapsNeverHappen(), | ||
CtorEval(), | ||
Merge(), | ||
# FIXME: Re-enable after https://github.com/WebAssembly/binaryen/issues/3989 | ||
# RoundtripText() | ||
] | ||
|
@@ -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() | ||
|
||
|
@@ -1503,7 +1565,7 @@ def write_commands(commands, filename): | |
("--type-merging",)} | ||
|
||
|
||
def randomize_opt_flags(): | ||
def get_random_opts(): | ||
flag_groups = [] | ||
has_flatten = False | ||
|
||
|
@@ -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 | ||
|
Uh oh!
There was an error while loading. Please reload this page.