| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
|
|
|
| |
Like `br_if`, `br_on_exn` is a conditional branch and across which code
can be pushed past when conditions are satisfied.
Also adds a few lines of comments and NFC changes in a couple places.
Changes in Vacuum are NFC because they were being handled in `default:`
in the same way anyway, but I added them to be more explicit and
consistent with existing code.
|
|
|
|
|
|
|
|
|
|
|
| |
Don't print the entire module on an error. Instead, just print
the validation errors.
However, if the user passed --print, then do print it, as otherwise
nothing would get printed - the error would be before the pass
to print happens. And in general a user passing in a request
to print would expect a printed module anyhow.
fixes #2634
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
If an invalid entry appears - either it began as such, or became
invalid after optimization - we should not emit (0, 0) which is
an end marker. Instead, emit an invalid entry marker, something
with (0, x) for x != 0.
As a bonus, if a test/passes case has "noprint" in the name,
don't print the wasm, which we do by default. In the testcase
here for example we just care about the dwarf, and the
printed module would be quite large.
Thank you to @paolosevMSFT for identifying and suggesting
the fix.
|
|
|
|
|
|
|
|
|
|
| |
Allows a user to modify the inlining limits using the C- and JS-APIs.
* binaryen.**getAlwaysInlineMaxSize**(): `number`
* binaryen.**setAlwaysInlineMaxSize**(size: `number`): `void`
* binaryen.**getFlexibleInlineMaxSize**(): `number`
* binaryen.**setFlexibleInlineMaxSize**(size: `number`): `void`
* binaryen.**getOneCallerInlineMaxSize**(): `number`
* binaryen.**setOneCallerInlineMaxSize**(size: `number`): `void`
|
| |
|
|
|
|
|
|
|
|
|
|
| |
EMSCRIPTEN_END_FUNCS markers. (#2626)
* Fix missing newline after // EMSCRIPTEN_START_FUNCS and // EMSCRIPTEN_END_FUNCS markers.
* Flake
* Update tests
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Optimize base64 decoding (about 7x-10x faster and temporary garbage-free compared to the original version)
* new Uint8Array
* Reuse Uint8Array view
* Fix end handling
* Code format
* Update tests
|
|
|
|
| |
If try's body does not throw, the whole try-catch can be replaced with
the try body.
|
|
|
|
|
|
|
|
|
| |
Allows a user to enable/disable the `lowMemoryUnused` option and to get/set/clear arbitrary pass arguments when using the C- or JS-APIs.
* binaryen.**getLowMemoryUnused**(): `boolean`
* binaryen.**setLowMemoryUnused**(on: `boolean`): `void`
* binaryen.**getPassArgument**(key: `string`): `string | null`
* binaryen.**setPassArgument**(key: `string`, value: `string | null`): `void`
* binaryen.**clearPassArguments**(): `void`
|
|
|
|
|
|
|
|
|
|
|
| |
Anything that merges/swaps/etc. locals, or inlines, or merges functions,
must be disabled for now. However, that does still leave almost all
passes, so this should not affect output sizes much (and the full LLVM
optimizer can be run before too).
Over time we can resolve each of those FIXMEs.
The test output here shows how disabling those allows over twice as
much debug_line info to be preserved.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Now that we have subtypes, we cannot reuse any local that contains the
same expression, because that local's type can be a supertype. For
example:
```
(local $0 anyref)
(local $1 nullref)
...
(local.set $0 (ref.null))
(local.set $1 (ref.null)) ;; cannot be replaced with (local.get $0)
```
This extends `usables` map's key to contain both `HashedExpression` and
the local's type, so we can get the right usable local in presence of
subtypes.
|
|
|
|
|
|
| |
- Adds support for `Try` in `optimizeBoolean` function
- Adds support for `Try` in `getFallThrough` function
- Adds approximate cost values for instructions in EH and reference
types proposals.
|
|
|
|
|
|
|
|
|
|
|
| |
This makes the interpreter trap when the signature in `call_indirect`
instruction and that of the actual function in the table mismatch. This
also makes the `wasm-ctor-eval` not evaluate `call_indirect` in case the
signatures mismatch.
Before we only compared the arguments' signature and the function
signature, which was sufficient before we had subtypes, but now the
signature in `call_indirect` and that of the actual function can be
different even if the argument's signature is OK.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This adds EH support to `EffectAnalyzer`. Before `throw` and `rethrow`
conservatively set property. Now `EffectAnalyzer` has a new property
`throws` to represent an expression that can throw, and expression that
can throw sets `throws` correctly.
When EH is enabled, any calls can throw too, so we cannot reorder them
with another expression with any side effects, meaning all calls should
be treated in the same way as branches when evaluating `invalidate`.
This prevents many reorderings, so this patch sets `throws` for calls
only when the exception handling features is enabled. This is also why I
passed `--disable-exception-handling` to `wasm2js` tests. Most of code
changes outside of `EffectAnalyzer` class was made in order to pass
`FeatureSet` to it.
`throws` isn't always set whenever an expression contains a throwable
instruction. When an throwable instruction is within an inner try, it
will be caught by the corresponding inner catch, so it does not set
`throws`.
|
|
|
|
|
|
|
|
|
| |
Each compilation unit's abbreviations must be terminated by
a zero, so that we use the right abbreviations. This adds that
support to the YAML layer, both adding the zeros and parsing
them to look in the right abbreviation section at the right time.
Also add two large testcases, zlib and cubescript, which
crash without this and the last PR.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This replaces imports like env.foo with a.foo, which can
save a bunch of bytes when there are many imported
functions.
Note that by changing all the import names to a it ends
up requiring a single merged import module.
Note also that when doing this we modify all the imports,
minifying their modules and names (since it makes no
sense to be careful about minifying only modules known
to us - env/wasi - if we are minifyin the names of all
modules).
This will require an emscripten PR to benefit from it.
|
|
|
|
|
|
|
|
|
| |
The LLVM SData field is 64-bit (to support 64-bit
addresses I suppose) so when we assigned to it we
actually led it to emit an LEB for a signed 64-bit value
that is an unsigned 32-bit one. This worked in LLVM
(where I guess it forces the value to 32-bit anyhow?)
but failed in gimli (where I guess it doesn't?).
|
|
|
|
|
| |
This reverts commit 132daae1e9154782bb1afa5df80dfe7ea35f0369.
This change is the same as before but the fix in #2619 should now make it safe.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We ignored them, which is a bad default, as typically they imply
we can call anything in the table (and the table might change).
Instead, notice indirect calls during traversal, and force the user
to decide whether to ignore them or not.
This was only an issue in PostEmscripten because the other
user, Asyncify, already had indirect call analysis because it
needed it for other things.
Fixes a bug uncovered by #2619 and fixes the current binaryen
roll.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Add support for that section to the YAML layer, and add
code to update it.
The updating is slightly tricky - unlike .debug_ranges, the
size of entries is not fixed. So we can't just skip entries,
as the end marker is smaller than a normal entry. Instead,
replace now-invalid segments with (1, 1) which is of size
0 and so should be ignored by the debugger (we can't use
(0, 0) as that would be an end marker, and (-1, *) is
the special base marker).
In the future we probably do want to do this in a more
sophisticated manner, completely rewriting the indexes
into the section as well. For now though this should be
enough for when binaryen does not optimize (as we
don't move/reorder anything).
Note that this doesn't update the location description
(like where on the wasm expression stack the value is).
Again, that is correct for when binaryen doesn't
optimize, but for fully optimized builds we would need
to track things (which would be hard!).
Also clean up some code that uses "Extra" instead of
"Delimiter" that was missed before, and shorten some
unnecessarily long names.
|
|
|
|
|
|
| |
Chrome is currently decoding the segment indices as signed numbers, so
some ranges of indices greater than 63 do not work. As a temporary
workaround, limit the number of segments produced by MemoryPacking to
63 when bulk-memory is enabled.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Pretty straightforward given all we have so far.
Note that fannkuch3_manyopts has an example of
a sequence of ranges of which some must be skipped
while others must not, showing we handle that by
skipping the bad ones and updating the remaining. That
is, if that we have a sequence of two (begin, end) spans
[(10, 20),
(30, 40)]
It's possible (10, 20) maps in the new binary to (110, 120)
while (30, 40) was eliminated by the optimizer and we have
nothing valid to map it to. In that case we emit
[(110, 120)]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Just some trivial fixes:
* Properly reset prologue after each line (unlike others, this
flag should be reset immediately).
* Test for a function's end address first, as LLVM output appears to
use 1-past-the-end-of-the-function as a location in that function,
and not the next (note the first byte of the next function, which is
ambiguously identical to that value, is used at least in low_pc;
I'm not sure if it's used in debug lines too).
* Ignore the same address if LLVM emitted it more than once, which
it does sometimes.
|
|
|
|
|
|
|
| |
We need to track end_sequence directly, and use either
end_sequence or copy (copy emits a line without marking
it as ending a sequence).
After this, fib2 debug line output looks perfect.
|
|
|
|
| |
While line and address values of 0 should be skipped, it
seems like column 0 are valid lines emitted by LLVM.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
DWARF from LLVM can refer to the first byte belonging to the function,
where the size LEB is, or to the first byte after that, where the local
declarations are, or the end opcode, or to one byte past that which is
one byte past the bytes that belong to the function. We aren't sure why
LLVM does this, but track it all for now.
After this all debug line positions are identified. However,
in some cases a debug line refers to one past the end of the
function, which may be an LLVM bug. That location is ambiguous
as it could also be the first byte of the next function (what
made this discovery possible was when this happened to the
last function, after which there is another section).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Control flow structures have those in addition to the normal span of
(start, end), and we need to track them too.
Tracking them during reading requires us to track control flow
structures while parsing, so that we can know to which structure
an end/else/catch refers to.
We track these locations using a map on the side of instruction
to its "extra" locations. That avoids increasing the size of the
tracking info for the much more common non-control flow
instructions.
Note that there is one more 'end' location, that of the function
(not referring to any instruction). I left that to a later PR to
not increase this one too much.
|
|
|
|
|
|
|
|
|
|
| |
Binaryen.js now uses offset instead of byteOffset when inspecting
a memory segment, matching the arguments on memory segment
creation. Also adds inspection of the passive property.
Previously, one would specify { offset, data, passive } on creation
and get back { byteOffset, data } upon inspection. This PR unifies
both to the keys on creation while also adding the respective C-API
to retrieve passive status, which was missing.
|
|
|
|
|
|
| |
LLVM points to the start of the function in some debug line
entries - right after the size LEB of the function, which is
where the locals are declared, and before any instructions.
|
|
|
|
|
|
|
| |
Instead of reinventing the wheel on our side, this adds ExpressionAnalyzer
bindings to the C- and JS-APIs, which can be useful for generators. For
example, a generator may decide to simplify a compilation step if a
subexpression doesn't have any side effects, or simply skip emitting
something that is likely to compile to a drop or an empty block right away.
|
|
|
|
|
|
|
| |
Update high_pc values. These are interesting as they
may be a relative offset compared to the low_pc.
For functions we already had both a start and an end. Add
such tracking for instructions as well.
|
|
|
|
|
|
|
|
| |
This adds EH instruction support for `CFGWalker`. This also implements
`call` instruction handling within a try-catch; every call can possibly
throw and unwind to the innermost catch block.
This adds tests for RedundantSetElimination pass, which uses
`CFGWalker`.
|
|
|
|
|
| |
This only touches test code. The files are compiled with
latest LLVM + https://reviews.llvm.org/D71681 in order
to get more realistic DWARF content.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Track the beginning and end of each function, both when reading
and writing.
We track expressions and functions separately, instead of having a single
big map of (oldAddr) => (newAddr) because of the potentially ambiguous case
of the final expression in a function: it's end might be identical in offset
to the end of the function. So we have two different things that map to the
same offset. However, if the context is "the end of the function" then the
updated address is the new end of the function, even if the function ends
with a different instruction now, as the old last instruction might have
moved or been optimized out. Concretely, we have getNewExprAddr
and getNewFuncAddr, so we can ask to update the location of either
an expression or a function, and use that contextual information.
This checks for the DIE tag in order to know what we are looking for.
To be safe, if we hit an unknown tag, we halt, so that we don't silently
miss things.
As the test updates show, the new things we can do thanks to this
PR are to update compile unit and subprogram low_pc locations.
Note btw that in the first test (dwarfdump_roundtrip_dwarfdump.bin.txt)
we change 5 to 0: that is correct since that test does not write out
DWARF (it intentionally has no -g), so we do not track binary
locations while writing, and so we have nothing to update to (the
other tests show actual updating).
Also fix the order in the python test runner code to show a diff
of expected to encountered, and not the reverse, which confused
me.
|
|
|
|
|
|
|
|
|
| |
When memory is packed and there are passive segments, bulk memory
operations that reference those segments by index need to be updated to
reflect the new indices and possibly split into multiple instructions
that reference multiple split segments. For some bulk-memory operations,
it is necessary to introduce new globals to explicitly track the drop
state of the original segments, but this PR is careful to only add
globals where necessary.
|
|
|
|
|
| |
Binaryen.js now uses binaryen (was Binaryen) as its global
name to align with the npm package. Also fixes issues with
emitting and testing both the JS and Wasm builds.
|
|
|
|
|
|
|
| |
Mostly straightforward: go over the dwarf entries, find the
low_pc ones, and update their positions. A slight oddity is
that we must traverse both the dwarf context - which has
the rich APIs for analsis - and the YAML data structure -
which is minimal but is used for writing out.
|
|
|
|
|
|
|
|
|
|
|
| |
Check if an entry starts a new range of addresses. Each range is a set of
related addresses, where in particular, if the first has been zeroed out
by the linker, we must omit the entire range. If we do not, then the
initial range is 0 and the others are offsets relative to it, which will
look like random addresses, perhaps into the middle of instructions, and
perhaps that happen to collide with real ones (a debugger would ignore
those, so we must too; it's easier and better to simply omit them).
See https://bugs.llvm.org/show_bug.cgi?id=44516#c2
|
|
|
|
|
| |
gimli-rs and perhaps also the spec require a final 0
to terminate the list. LLVM itself is fine without that.
|
|
|
|
|
|
|
|
|
|
|
|
| |
isBinary was used where we should only accept
a signed binary, as removing the | 0 from an unsigned
value may be incorrect.
This does regress a few small things (as can be seen
in the diff). If it's important we can add more sophisticated
optimizations here, perhaps like an assumption that the
signedness of a local never matters.
Fixes emscripten-core/emscripten#10173
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Multiple tables appear to be emitted when linking files
together. This fixes our support for that, which did not
update their size properly. This required patching the
YAML emitting code from LLVM in order to measure
the size and then emit it, as that code is apparently
not designed to handle changes in line table
contents.
Other minor fixes:
* Set the flags for our dwarfdump command to emit
the same as llvm-dwarfdump does with -v -all.
* Add support for a few more opcodes,
set_discriminator, set_basic_block, fixed_advance_pc,
set_isa.
* Handle a compile unit without abbreviations in the
YAML code (again, apparently not something this
LLVM code was intended to do).
* Handle a compile unit with zero entries in the
YAML code (ditto).
* Properly set the AddressSize - we use the
DWARFContext in a different way than LLVM expects,
apparently.
With this the emscripten test suite passes with
-gforce_dwarf without crashing.
My overall impression so from the the YAML code is
that it probably isn't a long-term solution for us. Perhaps
it may end up being scaffolding, that is, we can
replace it with our own code eventually that is based
on it, and remove most of the LLVM code. Before
deciding that we should get everything working first,
and this seems like the quickest path there.
|
|
|
|
|
| |
(#2542)" (#2576)
This reverts commit f62e171c38bea14302f9b79f7941a248ea704425.
|
|
|
|
|
|
| |
By doing so we ensure that our calls to convert wasm
types to JS types never try to convert an unreachable.
Fixes #2558
|
|
|
|
|
| |
This makes push and pop instructions not printed in the stack IR format
to make it valid wat form. Push and pop are still generated in the stack
IR in memory but not printed in the text format.
|
|
|
|
|
| |
This allows subtype for arguments of `throw`. This also renames
`shouldBeSubTypeOrUnreachable` to `shouldBeSubTypeOrFirstIsUnreachable`,
to be consistent with `shouldBeEqualOrFirstIsUnreachable`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The analysis currently uses a dense matrix. If there are >65535
locals then the indexes don't fit in a 32-bit type like a wasm32
index, which led to overflows and incorrect behavior. To avoid
that, don't run passes with liveness analysis for now if they have
that many locals.
Note that skipping coalesce-locals (the main liveness-using
pass) is not that bad, as we run it more than once, and it's
likely that even if the first must be skipped, we can still run
the second (which is after simplify- and reorder-locals, which
can greatly reduce the local count).
Fixes #2559
|
|
|
|
|
|
| |
- Allow `atomic.notify` and `atomic.wait` instructions to parse memory
arguments (`align` and `offset`) and print the offset in these
instruction when writing binary, rather than assuming it to be 0
- Change arguments of `parseMemAttributes` to be references
|
|
|
|
|
|
|
|
|
|
|
| |
We have not been generating push and pop instructions in the stack IR.
Even though they are not written in binary, they have to be in the stack
IR to match the number of inputs and outputs of instructions.
Currently `BinaryenIRWriter` is used both for stack IR generation and
binary generation, so we should emit those instructions in
`BinaryenIRWriter`. `BinaryenIRToBinaryWriter`, which inherits
`BinaryenIRWriter`, does not do anything for push and pop instructions,
so they are still not emitted in binary.
|
|
|
|
|
|
|
|
|
|
|
|
| |
This adds support for the reference type proposal. This includes support
for all reference types (`anyref`, `funcref`(=`anyfunc`), and `nullref`)
and four new instructions: `ref.null`, `ref.is_null`, `ref.func`, and
new typed `select`. This also adds subtype relationship support between
reference types.
This does not include table instructions yet. This also does not include
wasm2js support.
Fixes #2444 and fixes #2447.
|
|
|
|
| |
movements (#2552)
|