| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Adds the capability to programatically split a module into a primary and
secondary module such that the primary module can be compiled and run before the
secondary module has been instantiated. All calls to secondary functions (i.e.
functions that have been split out into the secondary module) in the primary
module are rewritten to be indirect calls through the table. Initially, the
table slots of all secondary functions contain references to imported
placeholder functions. When the secondary module is instantiated, it will
automatically patch the table to insert references to the original functions.
The process of module splitting involves these steps:
1. Create the new secondary module.
2. Export globals, events, tables, and memories from the primary module and
import them in the secondary module.
3. Move the deferred functions from the primary to the secondary module.
4. For any secondary function exported from the primary module, export in
its place a trampoline function that makes an indirect call to its
placeholder function (and eventually to the original secondary function),
allocating a new table slot for the placeholder if necessary.
5. Rewrite direct calls from primary functions to secondary functions to be
indirect calls to their placeholder functions (and eventually to their
original secondary functions), allocating new table slots for the
placeholders if necessary.
6. For each primary function directly called from a secondary function, export
the primary function if it is not already exported and import it into the
secondary module.
7. Replace all references to secondary functions in the primary module's table
segments with references to imported placeholder functions.
8. Create new active table segments in the secondary module that will replace
all the placeholder function references in the table with references to
their corresponding secondary functions upon instantiation.
Functions can be used or referenced three ways in a WebAssembly module: they can
be exported, called, or placed in a table. The above procedure introduces a
layer of indirection to each of those mechanisms that removes all references to
secondary functions from the primary module but restores the original program's
semantics once the secondary module is instantiated. As more mechanisms that
reference functions are added in the future, such as ref.func instructions, they
will have to be modified to use a similar layer of indirection.
The code as currently written makes a few assumptions about the module that is
being split:
1. It assumes that mutable-globals is allowed. This could be worked around by
introducing wrapper functions for globals and rewriting secondary code that
accesses them, but now that mutable-globals is shipped on all browsers,
hopefully that extra complexity won't be necessary.
2. It assumes that all table segment offsets are constants. This simplifies the
generation of segments to actively patch in the secondary functions without
overwriting any other table slots. This assumption could be relaxed by 1)
having secondary segments re-write primary function slots as well, 2)
allowing addition in segment offsets, or 3) synthesizing a start function to
modify the table instead of using segments.
3. It assumes that each function appears in the table at most once. This isn't
necessarily true in general or even for LLVM output after function
deduplication. Relaxing this assumption would just require slightly more
complex code, so it is a good candidate for a follow up PR.
Future Binaryen work for this feature includes providing a command line tool
exposing this functionality as well as C API, JS API, and fuzzer support. We
will also want to provide a simple instrumentation pass for finding dead or
late-executing functions that would be good candidates for splitting out. It
would also be good to integrate that instrumentation with future function
outlining work so that dead or exceptional basic blocks could be split out into
a separate module.
|
|
|
| |
We can only pack memory if we know it is zero-filled before us.
|
|
|
|
|
|
|
| |
Including saturating, rounding Q15 multiplication as proposed in
https://github.com/WebAssembly/simd/pull/365 and extending multiplications as
proposed in https://github.com/WebAssembly/simd/pull/376. Since these are just
prototypes, skips adding them to the C or JS APIs and the fuzzer, as well as
implementing them in the interpreter.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Previously when we processed a block for example, we'd do this:
;; start is here
(block (result type)
;; end is here
.. contents ..
)
;; end delimiter is here
Not how this represents the block's start and end as the "header", and
uses an extra delimiter to mark the end.
I think this is wrong, and was an attempt to handle some offsets from
LLVM that otherwise made no sense, ones at the end of the "header".
But it turns out that this makes us completely incorrect on some things
where there is a low/high pc pair, and we need to understand that the
end of a block is at the end opcode at the very end, and not the end of
the header. This PR changes us to do that, i.e.
;; start is here
(block (result type)
.. contents ..
)
;; end is here
This fixes a testcase already in the test suite,
test/passes/fib_nonzero-low-pc_dwarf.bin.txt
where you can see that lexical block now has a valid value for the end, and
not a 0 (the proper scope extends all the way to the end of the big block in
that function, and is now the same in the DWARF before and after we
process it). test/passes/fannkuch3_dwarf.bin.txt is also improved by
this.
To implement this, this removes the BinaryLocations::End delimeter. After
this we just need one type of delimiter actually, but I didn't refactor that any
more to keep this PR small (see TODO).
This removes an assertion in writeDebugLocationEnd() that is no longer
valid: the assert ensures that we wrote an end only if there was a 0 for
the end, but for a control flow structure, we write the end of the "header"
automatically like for any expression, and then overwrite it later when we
finish writing the children and the end marker. We could in theory special-case
control flow structures to avoid the first write, but it would add more complexity.
This uncovered what appears to be a possible bug in our debug_line
handling, see test/passes/fannkuch3_manyopts_dwarf.bin.txt. That needs
to be looked into more, but I suspect that was invalid info from when we
looked at the end of the "header" of control flow structures. Note that there
was one definite bug uncovered here, fixed by the extra
} else if (locationUpdater.hasOldExprEnd(oldAddr)) {
that is added here, which was definitely a bug.
|
|
|
|
|
|
| |
As proposed in https://github.com/WebAssembly/simd/pull/379. Since this
instruction is still being evaluated for inclusion in the SIMD proposal, this PR
does not add support for it to the C/JS APIs or to the fuzzer. This PR also
performs a drive-by fix for unrelated instructions in c-api-kitchen-sink.c
|
|
|
|
|
|
|
|
|
| |
This change makes matchers in OptimizeInstructions more compact and readable by
removing the explicit `Abstract::` namespace from individual operations. In some
cases, this makes multi-line matcher expressions fit on a single line.
This change is only possible because it also adds an explicit "RMW" prefix to
each element of the `AtomicRMWOp` enumeration. Without that, their names
conflicted with the names of Abstract ops.
|
|
|
|
|
|
|
| |
These instructions are proposed in https://github.com/WebAssembly/simd/pull/350.
This PR implements them throughout Binaryen except in the C/JS APIs and in the
fuzzer, where it leaves TODOs instead. Right now these instructions are just
being implemented for prototyping so adding them to the APIs isn't critical and
they aren't generally available to be fuzzed in Wasm engines.
|
|
|
|
| |
Fixes: #3226
|
|
|
| |
When there are two versions of a function, one handling tuples and the other handling non-tuple values, the previous naming convention was to have "Single" in the name of the non-tuple handling function. This PR simplifies the convention and shortens function names by making the names plural for the tuple-handling version and singular for the non-tuple-handling version.
|
| |
|
|
|
| |
NFC, except adding most of the boilerplate for the remaining GC instructions. Each implementation site is marked with a respective `TODO (gc): theInstruction` in between the typical boilerplate code.
|
|
|
| |
This can unlock further instruction optimizations that do not apply to signed operations.
|
|
|
| |
Adds the `i31.new` and `i31.get_s/u` instructions for creating and working with `i31ref` typed values. Does not include fuzzer integration just yet because the fuzzer expects that trivial values it creates are suitable in global initializers, which is not the case for trivial `i31ref` expressions.
|
|
|
| |
With `eqref` now integrated, the `ref.eq` instruction can be implemented. The only valid LHS and RHS value is `(ref.null eq)` for now, but implementation and fuzzer integration is otherwise complete.
|
|
|
| |
Also includes a lot of new spec tests that eventually need to go into the spec repo
|
|
|
| |
Aligns the internal representations of `memory.size` and `memory.grow` with other more recent memory instructions by removing the legacy `Host` expression class and adding separate expression classes for `MemorySize` and `MemoryGrow`. Simplifies related APIs, but is also a breaking API change.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Adds support for the module and local subsections of the name section plus the respective C and JS APIs to populate and obtain local names.
C API:
* BinaryenFunctionGetNumLocals(func)
* BinaryenFunctionHasLocalName(func, index)
* BinaryenFunctionGetLocalName(func, index)
* BinaryenFunctionSetLocalName(func, index, name)
JS API:
* Function.getNumLocals(func)
* Function.hasLocalName(func, index)
* Function.getLocalName(func, index)
* Function.setLocalName(func, index, name)
|
|
|
|
|
| |
Adds an IR profile to each function so the validator can determine
which validation rules to apply and adds a flag to have the wast
parser set the profile to Poppy for testing purposes.
|
|
|
|
|
|
|
| |
Align with the current state of the reference types proposal:
* Remove `nullref`
* Remove `externref` and `funcref` subtyping
* A `Literal` of a nullable reference type can now represent `null` (previously was type `nullref`)
* Update the tests and temporarily comment out those tests relying on subtyping
|
|
|
|
|
|
|
|
| |
Specified in https://github.com/WebAssembly/simd/pull/237. Since these
are just prototypes necessary for benchmarking, this PR does not add
support for these instructions to the fuzzer or the C or JS APIs. This
PR also renumbers the QFMA instructions that previously used the
opcodes for these new instructions. The renumbering matches the
renumbering in V8 and LLVM.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
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.
|
|
|
| |
As specified in https://github.com/WebAssembly/simd/pull/232.
|
|
|
|
|
|
| |
Push and Pop have been superseded by tuples for their original
intended purpose of supporting multivalue. Pop is still used to
represent block arguments for exception handling, but there are no
plans to use Push for anything now or in the future.
|
|
|
|
| |
This is the only instruction in the current spec proposal that had not
yet been implemnented in the tools.
|
|
|
| |
As specified in https://github.com/WebAssembly/simd/pull/122.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Now that we update the dylink section properly, we can
do the same optimization in side modules as in main ones:
if the module provides a function, don't call an $fp method
during startup, instead add it to the table ourselves and use
the relative offset to the table base.
Fix an issue when the table has no segments initially: the
code just added an offset of 0, but that's not right. Instead,
an a __table_base import and use that as the offset. As
this is ABI-specific I did it on wasm-emscripten-finalize,
leaving TableUtils to just assert on having a singleton
segment.
Add a test of a wasm file with a dylink section to the lld tests.
|
|
|
|
| |
Update it from wasm-emscripten-finalize when we append
to the table.
|
|
|
|
|
|
| |
Adds full support for the {i8x16,i16x8,i32x4}.abs instructions merged
to the SIMD proposal in https://github.com/WebAssembly/simd/pull/128
as well as the {i8x16,i16x8,i32x4}.bitmask instructions proposed in
https://github.com/WebAssembly/simd/pull/201.
|
|
|
|
| |
Updates the interpreter to properly flow vectors of values, including
at function boundaries. Adds a small spec test for multivalue return.
|
|
|
|
|
|
|
|
|
| |
Implements parsing and emitting of tuple creation and extraction and tuple-typed control flow for both the text and binary formats.
TODO:
- Extend Precompute/interpreter to handle tuple values
- C and JS API support/testing
- Figure out how to lower in stack IR
- Fuzzing
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Fixes the testcase in #2343 (comment)
Looks like that's from Rust. Not sure why it would have an invalid
abbreviation code, but perhaps the LLVM there emits dwarf differently
than we've tested on so far. May be worth investigating further, but
for now emit a warning, skip that element, and don't crash.
Also fix valgrind warnings about Span values not being initialized,
which was invalid and bad as well (wasted memory in our maps,
and might have overlapped with real values), and interfered with
figuring this out.
|
|
|
|
| |
This will make it easier to switch to something else for
offsets in wasm binaries if we get >4GB files.
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
| |
This does something similar to #2489 for more functions, removing
boilerplate code for each module element using template functions.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
With this, we can update DWARF debug line info properly as
we write a new binary.
To do that we track binary locations as we write. Each
instruction is mapped to the location it is written to. We
must also adjust them as we move code around because
of LEB optimization (we emit a function or a section
with a 5-byte LEB placeholder, the maximal size; later
we shrink it which is almost always possible).
writeDWARFSections() now takes a second param, the new
locations of instructions. It then maps debug line info from the
original offsets in the binary to the new offsets in the binary
being written.
The core logic for updating the debug line section is in
wasm-debug.cpp. It basically tracks state machine logic
both to read the existing debug lines and to emit the new
ones. I couldn't find a way to reuse LLVM code for this, but
reading LLVM's code was very useful here.
A final tricky thing we need to do is to update the DWARF
section's internal size annotation. The LLVM YAML writing
code doesn't do that for us. Luckily it's pretty easy, in
fixEmittedSection we just update the first 4 bytes in place
to have the section size, after we've emitted it and know
the size.
This ignores debug lines with a 0 in the line, col, or addr,
see WebAssembly/debugging#9 (comment)
This ignores debug line offsets into the middle of
instructions, which LLVM sometimes emits for some
reason, see WebAssembly/debugging#9 (comment)
Handling that would likely at least double our memory
usage, which is unfortunate - we are run in an LTO manner,
where the entire app's DWARF is present, and it may be
massive. I think we should see if such odd offsets are
a bug in LLVM, and if we can fix or prevent that.
This does not emit "special" opcodes for debug lines. Those
are purely an optimization, which I wanted to leave for
later. (Even without them we decrease the size quite a lot,
btw, as many lines have 0s in them...)
This adds some testing that shows we can load and save
fib2.c and fannkuch.cpp properly. The latter includes more
than one function and has nontrivial code.
To actually emit correct offsets a few minor fixes are
done here:
* Fix the code section location tracking during reading -
the correct offset we care about is the body of the code
section, not including the section declaration and size.
* Fix wasm-stack debug line emitting. We need to update
in BinaryInstWriter::visit(), that is, right before writing
bytes for the instruction. That differs from
* BinaryenIRWriter::visit which is a recursive function
that also calls the children - so the offset there would be
of the first child. For some reason that is correct with
source maps, I don't understand why, but it's wrong for
DWARF...
* Print code section offsets in hex, to match other tools.
Remove DWARFUpdate pass, which was useful for testing
temporarily, but doesn't make sense now (it just updates without
writing a binary).
cc @yurydelendik
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Optionally track the binary format code section offsets,
that is, when loading a binary, remember where each IR
node was read from. This is necessary for DWARF
debug info, as these are the offsets DWARF refers to.
(Note that eventually we may want to do something
else, like first read the DWARF and only then add
debug info annotations into the IR in a more LLVM-like
manner, but this is more straightforward and should be
enough to update debug lines and ranges).
This tracking adds noticeable overhead - every single
IR node adds an entry in a map - so avoid it unless
actually necessary. Specifically, if the user passes in
-g and there are actually DWARF sections in the
binary, and we are not about to remove those sections,
then we need it.
Print binary format code section offsets in text, when
printing with -g. This will help debug and test dwarf
support. It looks like
;; code offset: 0x7
as an annotation right before each node.
Also add support for -g in wasm-opt tests (unlike
a pass, it has just one - as a prefix).
Helps #2400
|
|
|
| |
As specified in https://github.com/WebAssembly/simd/pull/126.
|
|
|
|
|
|
| |
Currently `ModuleUtils::clearModule` does not clear `exists` flags in
the memory and table, and running RoundTrip pass on any module that has
a memory or a table fails as a result. This creates `clear` function in
`Memory` and `Table` and makes `clearModule` call them.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
According to the current spec, `local.tee`'s return type should be the
same as its local's type. (Discussions on whether we should change this
rule is going on in WebAssembly/reference-types#55, but here I will
assume this spec does not change. If this changes, we should change many
parts of Binaryen transformation anyway...)
But currently in Binaryen `local.tee`'s type is computed from its
value's type. This didn't make any difference in the MVP, but after we
have subtype relationship in #2451, this can become a problem. For
example:
```
(func $test (result funcref) (local $0 anyref)
(local.tee $0
(ref.func $test)
)
)
```
This shouldn't validate in the spec, but this will pass Binaryen
validation with the current `local.tee` implementation.
This makes `local.tee`'s type computed from the local's type, and makes
`LocalSet::makeTee` get a type parameter, to which we should pass the
its corresponding local's type. We don't embed the local type in the
class `LocalSet` because it may increase memory size.
This also fixes the type of `local.get` to be the local type where
`local.get` and `local.set` pair is created from `local.tee`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Function signatures were previously redundantly stored on Function
objects as well as on FunctionType objects. These two signature
representations had to always be kept in sync, which was error-prone
and needlessly complex. This PR takes advantage of the new ability of
Type to represent multiple value types by consolidating function
signatures as a pair of Types (params and results) stored on the
Function object.
Since there are no longer module-global named function types,
significant changes had to be made to the printing and emitting of
function types, as well as their parsing and manipulation in various
passes.
The C and JS APIs and their tests also had to be updated to remove
named function types.
|
|
|
|
|
|
|
|
|
|
|
| |
This creates utility functions for removing module elements: removing
one element by name, and removing multiple elements using a predicate
function. And makes other parts of code use it. I think this is a
light-handed approach than calling `Module::updateMaps` after removing
only a part of module elements.
This also fixes a bug in the inlining pass: it didn't call
`Module::updateMaps` after removing functions. After this patch callers
don't need to additionally call it anyway.
|
|
|
|
|
|
|
|
|
| |
This is the start of a larger refactoring to remove FunctionType entirely and
store types and signatures directly on the entities that use them. This PR
updates BrOnExn and Events to remove their use of FunctionType and makes the
BinaryWriter traverse the module and collect types rather than using the global
FunctionType list. While we are collecting types, we also sort them by frequency
as an optimization. Remaining uses of FunctionType in Function, CallIndirect,
and parsing will be removed in a future PR.
|
|
|
|
|
| |
This experimental instruction is specified in
https://github.com/WebAssembly/simd/pull/127 and is being implemented
to enable further investigation of its performance impact.
|