| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
| |
optimizeBoolean does not receive a boolean, it is done when the
output flows into a boolean context.
|
|
|
|
|
|
|
|
| |
This is precursor to moving dynCall generation into a pass of its own.
It seems to be up to the caller if they want to run dynCall generation
either before or after fpcast-emu.
Verified that this change does not effect emscripten's wasm2 other other
test suite.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
fallthrough (#2989)
We can turn a reinterpret of a load into a different load, and so forth, but if
the reinterpret has a non-load child with a load fallthrough, that's not good
enough - we can't remove the extra code:
(reinterpret
(block
..extra code..
(load)
)
)
That can't be turned into a load of the flipped type.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We marked it as readsMemory so that it could be reordered with various
things, except for memory.init. However, the fuzzer found that's not quite
right, as it has a global side effect - memory.inits that run later can notice
that. So it can't be reordered with anything that might affect global side
effects from happening, as in the testcase added here (an instruction that
may trap cannot be reordered with a data.drop, as it may prevent the
data.drop from happening and changing global state).
There may be a way to optimize this more carefully that would allow more
optimizations, but as this is a rare instruction I'm not sure it's worth more
work.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
It is usually fine to do if (x | 0) => if (x) since it just cares if the
value is 0 or not. However, if the cast turns it into 0, then that is
incorrect, which the fuzzer found as
-2147483648 + -2147483648 | 0
(the sum is 2^32, which | 0 is 0).
We can maybe look into doing this in a safe way, but for now
just remove it. It doesn't have a big impact on code size as this
is pretty rare (e.g. the minimal runtime code size test is not
broken by this).
|
|
|
|
|
| |
This new pass takes an optional stack-check-handler argument
which is the name of the function to call on stack overflow.
If no argument is passed then it just traps.
|
|
|
| |
Simplify stack allocation and array generation logic.
|
|
|
|
| |
This should not be needed since in emscripten standalone mode we
always include a crt1.o that includes _start.
|
|
|
|
| |
Doing it this way happens to re-order the __assign_got_entries
function in the module, but its otherwise NFC.
|
|
|
| |
First step in making wasm-emscripten-finalize use more passes.
|
|
|
|
|
| |
(#2977)
It may not be present while reducing a testcase, if the reducer removed it.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The binary writer reorders locals unconditionally. I forgot about this, and so
when I made DWARF disable optimization passes that reorder, this was
left active.
Optimally the writer would not do this, and the ReorderLocals pass would.
But it looks like we need special logic for tuple locals anyhow, as they
expand into multiple locals, so some amount of local order changes seems
unavoidable atm.
Test changes are mostly just lots of offsets, and can be ignored, but
the new test test/passes/dwarf-local-order.* shows the issue. It
prints $foo once, then after a roundtrip (showing no reordering), then
it strips the DWARF section and prints after another roundtrip (which
does show reordering).
This also makes us avoid the Stack IR writer if DWARF is present, which
matches what we do with source maps. This doesn't prevent any known
bugs, but it's simpler this way and debugging + Stack IR opts is not an
important combination.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We emit FUNCTION_TABLE[ptr], where FUNCTION_TABLE is a JS
array. That is a rare case where true is handled differently than 1
(a typed array or an add would cast, etc.), so we must explicitly cast
there.
Fixes an issue that existed before, but became a problem due to
#2869 which optimized some selects into a form that emitted a true
or a false, and if that was a function pointer, it could be bad, see
https://app.circleci.com/pipelines/github/emscripten-core/emscripten/6699/workflows/0c4da49c-75d0-4b0a-8fac-686a8330a3fe/jobs/336520
The new test/wasm2js/indirect-select.2asm.js.opt output shows
what happened there.
Verified as passing emscripten's wasm2js1 wasm2js2 test suites.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Renames the following C-API functions
BinaryenBlockGetChild to BinaryenBlockGetChildAt
BinaryenSwitchGetName to BinaryenSwitchGetNameAt
BinaryenCallGetOperand to BinaryenCallGetOperandAt
BinaryenCallIndirectGetOperand to BinaryenCallIndirectGetOperandAt
BinaryenHostGetOperand to BinaryenHostGetOperandAt
BinaryenThrowGetOperand to BinaryenThrowGetOperandAt
BinaryenTupleMakeGetOperand to BinaryenTupleMakeGetOperandAt
Adds the following C-API functions
BinaryenExpressionSetType
BinaryenExpressionFinalize
BinaryenBlockSetName
BinaryenBlockSetChildAt
BinaryenBlockAppendChild
BinaryenBlockInsertChildAt
BinaryenBlockRemoveChildAt
BinaryenIfSetCondition
BinaryenIfSetIfTrue
BinaryenIfSetIfFalse
BinaryenLoopSetName
BinaryenLoopSetBody
BinaryenBreakSetName
BinaryenBreakSetCondition
BinaryenBreakSetValue
BinaryenSwitchSetNameAt
BinaryenSwitchAppendName
BinaryenSwitchInsertNameAt
BinaryenSwitchRemoveNameAt
BinaryenSwitchSetDefaultName
BinaryenSwitchSetCondition
BinaryenSwitchSetValue
BinaryenCallSetTarget
BinaryenCallSetOperandAt
BinaryenCallAppendOperand
BinaryenCallInsertOperandAt
BinaryenCallRemoveOperandAt
BinaryenCallSetReturn
BinaryenCallIndirectSetTarget
BinaryenCallIndirectSetOperandAt
BinaryenCallIndirectAppendOperand
BinaryenCallIndirectInsertOperandAt
BinaryenCallIndirectRemoveOperandAt
BinaryenCallIndirectSetReturn
BinaryenCallIndirectGetParams
BinaryenCallIndirectSetParams
BinaryenCallIndirectGetResults
BinaryenCallIndirectSetResults
BinaryenLocalGetSetIndex
BinaryenLocalSetSetIndex
BinaryenLocalSetSetValue
BinaryenGlobalGetSetName
BinaryenGlobalSetSetName
BinaryenGlobalSetSetValue
BinaryenHostSetOp
BinaryenHostSetNameOperand
BinaryenHostSetOperandAt
BinaryenHostAppendOperand
BinaryenHostInsertOperandAt
BinaryenHostRemoveOperandAt
BinaryenLoadSetAtomic
BinaryenLoadSetSigned
BinaryenLoadSetOffset
BinaryenLoadSetBytes
BinaryenLoadSetAlign
BinaryenLoadSetPtr
BinaryenStoreSetAtomic
BinaryenStoreSetBytes
BinaryenStoreSetOffset
BinaryenStoreSetAlign
BinaryenStoreSetPtr
BinaryenStoreSetValue
BinaryenStoreGetValueType
BinaryenStoreSetValueType
BinaryenConstSetValueI32
BinaryenConstSetValueI64
BinaryenConstSetValueI64Low
BinaryenConstSetValueI64High
BinaryenConstSetValueF32
BinaryenConstSetValueF64
BinaryenConstSetValueV128
BinaryenUnarySetOp
BinaryenUnarySetValue
BinaryenBinarySetOp
BinaryenBinarySetLeft
BinaryenBinarySetRight
BinaryenSelectSetIfTrue
BinaryenSelectSetIfFalse
BinaryenSelectSetCondition
BinaryenDropSetValue
BinaryenReturnSetValue
BinaryenAtomicRMWSetOp
BinaryenAtomicRMWSetBytes
BinaryenAtomicRMWSetOffset
BinaryenAtomicRMWSetPtr
BinaryenAtomicRMWSetValue
BinaryenAtomicCmpxchgSetBytes
BinaryenAtomicCmpxchgSetOffset
BinaryenAtomicCmpxchgSetPtr
BinaryenAtomicCmpxchgSetExpected
BinaryenAtomicCmpxchgSetReplacement
BinaryenAtomicWaitSetPtr
BinaryenAtomicWaitSetExpected
BinaryenAtomicWaitSetTimeout
BinaryenAtomicWaitSetExpectedType
BinaryenAtomicNotifySetPtr
BinaryenAtomicNotifySetNotifyCount
BinaryenAtomicFenceSetOrder
BinaryenSIMDExtractSetOp
BinaryenSIMDExtractSetVec
BinaryenSIMDExtractSetIndex
BinaryenSIMDReplaceSetOp
BinaryenSIMDReplaceSetVec
BinaryenSIMDReplaceSetIndex
BinaryenSIMDReplaceSetValue
BinaryenSIMDShuffleSetLeft
BinaryenSIMDShuffleSetRight
BinaryenSIMDShuffleSetMask
BinaryenSIMDTernarySetOp
BinaryenSIMDTernarySetA
BinaryenSIMDTernarySetB
BinaryenSIMDTernarySetC
BinaryenSIMDShiftSetOp
BinaryenSIMDShiftSetVec
BinaryenSIMDShiftSetShift
BinaryenSIMDLoadSetOp
BinaryenSIMDLoadSetOffset
BinaryenSIMDLoadSetAlign
BinaryenSIMDLoadSetPtr
BinaryenMemoryInitSetSegment
BinaryenMemoryInitSetDest
BinaryenMemoryInitSetOffset
BinaryenMemoryInitSetSize
BinaryenDataDropSetSegment
BinaryenMemoryCopySetDest
BinaryenMemoryCopySetSource
BinaryenMemoryCopySetSize
BinaryenMemoryFillSetDest
BinaryenMemoryFillSetValue
BinaryenMemoryFillSetSize
BinaryenRefIsNullSetValue
BinaryenRefFuncSetFunc
BinaryenTrySetBody
BinaryenTrySetCatchBody
BinaryenThrowSetEvent
BinaryenThrowSetOperandAt
BinaryenThrowAppendOperand
BinaryenThrowInsertOperandAt
BinaryenThrowRemoveOperandAt
BinaryenRethrowSetExnref
BinaryenBrOnExnSetEvent
BinaryenBrOnExnSetName
BinaryenBrOnExnSetExnref
BinaryenTupleMakeSetOperandAt
BinaryenTupleMakeAppendOperand
BinaryenTupleMakeInsertOperandAt
BinaryenTupleMakeRemoveOperandAt
BinaryenTupleExtractSetTuple
BinaryenTupleExtractSetIndex
BinaryenFunctionSetBody
Also introduces wrappers to the JS-API resembling the classes in C++
to perform the above operations on an expression. For example:
var unary = binaryen.Unary(module.i32.eqz(1));
unary.getOp(...) / .op
unary.setOp(...) / .op = ...
unary.getValue(...) / .value
unary.setValue(...) / .value = ...
unary.getType(...) / .type
unary.finalize()
...
Usage of wrappers is optional, and one can also use plain functions:
var unary = module.i32.eqz(1);
binaryen.Unary.getOp(unary, ...)
...
Also adds comments to all affected functions in case we'd like to generate
API documentation at some point.
|
|
|
|
|
| |
x ? 1 : 0 => !!x
and so forth.
|
|
|
| |
See WebAssembly/spec#1224
|
| |
|
|
|
| |
See WebAssembly/spec#1223
|
|
|
|
|
|
|
|
|
|
|
| |
i64 reinterprets were lowered in the i64 pass, and i32s at the very end, in
wasm2js itself. This could break since in between the i64 pass and wasm2js
we run optimizations, and the optimizer was not aware of what we lower
the i32 reinterprets to - calls to use scratch memory. Those calls have a
side effect of altering scratch memory. The optimizer just saw an i32
reinterpret, and moved it across the i64 reinterpret's scratch memory calls.
This makes 32-bit reinterprets use separate scratch memory from 64-bit ones,
which means they can never interfere with each other.
|
|
|
|
|
|
| |
In instrument-locals_all-features.wast I added the tests to the end of
the file so that the diff of expected output is smaller and easier to
read. Otherwise the constants will have to all change since they are
order dependent.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
It's valid to change NaN bits in that case per the wasm spec, but
if we do so then fuzz testcases will fail on the optimization of
nan:foo / 1 => nan:foo
That is, it is ok to leave the bits as they are, and if we do that then
we are consistent with the simple and valid optimization of removing
a divide by 1.
Found by the fuzzer - looks like on x64 on some float32 NaNs,
the bits will actually change (see the testcase). I've seen this on
two machines consistently, so it's normal apparently.
Disable an old wasm spectest that has been updated in upstream
anyhow, but the new test here is even more strict and verifies
the interpreter literally changes no bits.
|
|
|
|
|
|
| |
Use WASM_RT_SETJMP so we use sigsetjmp when we need to.
Also disable signals in emcc+wasm2c in the fuzzer. emcc looks like
unix, so it enters the ifdef to use signals, but wasm has no signals...
|
|
|
|
|
|
|
|
|
|
| |
This bug was present from the very first version of this pass from 2018,
but it went unnoticed until now when a large project broke on it, for
some reason after
emscripten-core/emscripten#11403
Nothing wrong in that PR, probably just luck that it started to happen
there...
|
|
|
|
|
|
| |
The usual "trick" to extend: shift left so the sign bit in the small
integer is now the sign bit in a 32-bit integer, then shift right to
spread that sign bit out and return the lower bits to their
proper place, (x << 24) >> 24.
|
|
|
| |
bool(-x) ==> bool(x)
|
|
|
|
| |
We may need to check the CPU ID or something else before using
those special things on MSVC. To be safe, avoid them for now.
|
| |
|
|
|
|
|
|
|
|
| |
An (x, y) span is updated to some (q, r) in the new binary. If q > r then the
span is no longer valid - the optimizer has reordered things too much.
It's possible this could be flipped, but I'm not certain. It seems safer to
just omit these, which are very rare (I only see this on some larger
testcases in the emscripten test suite).
|
|
|
|
|
|
|
|
|
| |
After mapping to the new positions, and after relativizing to the
base, if we end up with (0, 0) then we must emit something else, as
that would be interpreted as the end of a list. As it is an empty
span, the actual value doesn't matter, it just has to be != 0.
This can happen if the very first span in a compile unit is an
empty span, in which case relative to the base of the compile unit
we would have (0, 0).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
.debug_loc entries can have bases: a value that all values after
it in the list are relative to. Previously we used to keep the base
value as it was, to keep things as similar to the original DWARF as
possible. However, if optimizations move code around so that the
values after the base are before the base, then the values could
no longer be emitted, and we skipped them in effect.
This PR makes us always pick a new base for each list. This
allows the base to always work for the values after it, but does
mean we change the lists quite a lot more. If there is any extra
meaning to the original bases here we may lose that, but the
DWARF spec doesn't seem to indicate anything like that
(however, it isn't clear to me why LLVM then doesn't always
choose the maximal base as the code here does - LLVM's values
seem oddly arbitrary).
Also properly note the base of each compile unit, which
previously we just noted the old value, but didn't look at the
new one in the new binary being written.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Previously we tracked sequence ends, so if an instruction was marked
as the end, we'd keep marking it that way in the output. However, if
X, Y, Z form a sequence that is then reordered into Z, Y, X then we need
to emit the end on X now.
To do that, give a "sequence number" to each debug line. Then when
emitting, we can tell if two adjacent lines are in a sequence or not, and
emit the end properly.
This fixes a large partner testcase, allowing
llvm-dwarfdump --verify --debug-line to pass on it.
With this change it is easier to remove the hackish handling of
prologueEnd that we had before, where we reset it. Instead, just
emit it when it is set, and that's all. In particular we can get rid
of the // Reset the state and resetAfterLine() calls in emitDiff.
That function now just emits a diff, with no side effects, and is
marked const.
This refactoring moves the needToEmit() check to an earlier
place. Instead of noting lines we'll never emit, don't even note them
at all.
The test diff seems large, but it is all due to one small change that
then changes all the later offsets:
- 0x00000831: 01 DW_LNS_copy
- 0x000000000000086e 43 4 1 0 0 is_stmt
+ 0x00000831: 00 DW_LNE_end_sequence
+ 0x000000000000086e 43 4 1 0 0 is_stmt end_sequence
Note how we add end_sequence there. We used to have an entry
right after it with line 0 that was marked as the end of the sequence.
In the new code, we don't emit that unnecessary line (which was
previously only emitted for the end sequence!) and instead emit
the end sequence on the last valid line.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We must emit those, even if otherwise it looks like a line we can
omit, as the ends of sequences have important meaning and
dwarfdump will warn without them.
Looks like fannkuch0 in the test suite already had an example
of an incorrectly-omitted sequence_end, so no need for a new
testcase.
Verified that without this e.g. wasm2.test_exceptions with -g
added will lead to a wasm that warns, but with this PR the debug_line
section is reported as valid by dwarfdump.
|
|
|
|
|
| |
Atomic loads, stores, RMW, cmpXchg, wait, and notify. This is enough
to get the asm.js atomics tests in the emscripten test suite to pass, at least
(but they are a subset of the entire pthreads suite).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
That code originally used memory location 1024 to save 64 bits of
data (as that is what rust does apparently). We refactored it
manually to instead use a scratch memory helper, which is safer.
However, that 64-bit function ends up legalized, which actually
changes the interface between the module and the outside,
which is confusing and causes problems with optimizations
that can remove the getTempRet0 imports, see
emscripten-core/emscripten#11456
Instead, just use a global i64 to stash those bits. This requires
adding support for copying globals from the intrinsics module,
but otherwise seems simpler overall.
|
|
|
|
|
|
|
|
|
| |
This finds out which locals are live at call sites that might pause/resume,
which is the set of locals we need to actually save/load. That is, if a local
is not alive at any call site in the function, then it's value doesn't need to
stay alive while sleeping.
This saves about 10% of locals that are saved/loaded, and about 1.5%
in final code size.
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Adds a special helper functions for data.drop etc., as unlike most
wasm instructions these are too big to emit inline.
Track passive segments at runtime in var memorySegments
whose indexes are the segment indexes.
Emit var bufferView even if the memory exists even without
memory segments, as we do still need the view in order to
operate on it.
Also adds a few constants for atomics that will be useful in future
PRs (as this PR updates the constant lists anyhow).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Necessary preparations for a later PR that adds bulk memory
support to wasm2js (splitting this out so the next PR is less big):
* Fix logging of print functions in wasm2js spec tests, there
was an extra space in the output (which console.log adds
automatically between items).
* Don't assume the output is always empty, as some tests
(like bulk memory) do have expected output.
* Rename test/bulk-memory.wast as it "conflicts" with
test/spec/bulk-memory.wast - the problem is that we scan
both places, and emit files in test/wasm2js/*, so those
would collide if the names overlap.
* Extend the parsing and emitting of JS for (assert.. ) lines such as
(assert_return (invoke "foo" (i32.const 1)) (i32.const 2))
to also handle
(invoke "foo" (i32.const 1)) (i32.const 2))
Without this, we skip (invoke ..) lines in spec tests, which normally is
fine, but in bulk memory at least they have side effects we need - we
must run them before the later assertions.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
(#2913)
When doing manual tuning of calls using asyncify lists, we want it to
be possible to write out all the functions that can be on the stack when
pausing, and for that to work. This did not quite work right with the
ignore-indirect option: that would ignore all indirect calls all the
time, so that if foo() calls bar() indirectly, that indirect call was
not instrumented (we didn't check for a pause around it), even if
both foo() and bar() were listed. There was no way to make that
work (except for not ignoring indirect calls at all).
This PR makes the add-list and only-lists fully instrument the functions
mentioned in them: both themselves, and indirect calls from them.
(Note that direct calls need no special handling - we can just add
the direct call target to the add-list or only-list.)
This may add some overhead to existing users, but only in a function
that is instrumented anyhow, and also indirect calls are slow anyhow,
so it's probably fine. And it is simpler to do it this way instead of
adding another list for indirect call handling.
|
|
|
|
|
| |
I have found that similar dump functions have been extremely helpful
while debugging LLVM. Rather than re-implement this locally whenever I
need it, it would be better have this utility upstream.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Asyncify does a whole-program analysis to figure out the list of functions
to instrument. In
emscripten-core/emscripten#10746 (comment)
we realized that we need another type of list there, an "add list" which is a
list of functions to add to the instrumented functions list, that is, that we
should definitely instrument.
The use case in that link is that we disable indirect calls, but there is
one special indirect call that we do need to instrument. Being able to add
just that one can be much more efficient than assuming all indirect calls in
a big codebase need instrumentation. Similar issues can come up if we
add a profile-guided option to asyncify, which we've discussed.
The existing lists were not good enough to allow that, so a new option
is needed. I took the opportunity to rename the old ones to something
better and more consistent, so after this PR we have 3 lists as follows:
* The old "remove list" (previously "blacklist") which removes functions
from the list of functions to be instrumented.
* The new "add list" which adds to that list (note how add/remove are
clearly parallel).
* The old "only list" (previously "whitelist") which simply replaces the
entire list, and so only those functions are instrumented and no other.
This PR temporarily still supports the old names in the commandline
arguments, to avoid immediate breakage for our CI.
|
|
|
|
| |
To avoid the conditional trailing comma.
|
|
|
|
|
|
|
| |
The process of DCE'ing the argument handling is already handled in
a different way in standalone more. In standalone mode the entry
point is `_start` which takes no args, and argv code is included
on-demand via the presence or absence the wasi syscalls for argument
processing (__wasi_args_get/__wasi_args_sizes_get).
|
|
|
|
|
|
|
|
|
| |
The plan is that for standlone mode we can function just like wasi-sdk
and call the correct main from crt1.c.
For non-standalone mode we still want to export can call main directly
so we rename __main_argc_argv back to main as part of finalize.
See https://reviews.llvm.org/D70700
|
|
|
|
|
|
|
| |
anyref future semantics were changed to only represent opaque host values, and thus renamed to externref.
[Chromium](https://bugs.chromium.org/p/v8/issues/detail?id=7748#c360) was just updated to today (not yet released). I couldn't find a Mozilla bugzilla ticket mentioning externref so I don't immediately know if they've updated yet.
https://github.com/WebAssembly/reference-types/pull/87
|
|
|
|
| |
Expressions that may throw cannot be sinked into 'try'. At the start of
'try', we drop all sinkables that may throw.
|
|
|
|
|
| |
* Micro-optimize base64Decode
* Update test expectations
|