I am reading this docs to study wasm binary format. I am finding it very tough to understand the composition of element section. Can someone please give me an example / explanation about it ? Maybe similar to one given here
The idea of this section is to fill the WebAssembly.Table
objects with content. Initially there was only one table, and its only possible content were indexes/ids of functions. You could write:
(elem 0 (offset (i32.const 1)) 2)
It means: during the instantiation of the instance fill index 1
of table 0
with a value of 2
, like tables[0][1] = 2;
. Here 2
is the index of the function the table will store.
The type of element segment above is called active
nowadays, and after the instantiation it will no longer be accessible by the application (they are "dropped"). From the specs:
An active element segment copies its elements into a table during instantiation, as specified by a table index and a constant expression defining an offset into that table
So far so good. But it was recognized that there is a need for a more powerful element segment section. Introduced were the passive and the declarative element segments.
The passive segment is not used during the instantiation and it is always available at runtime (until is not dropped, by the application itself, with elem.drop
). There are instructions (from the Bulk memory and table instructions
proposal, already integrated into the standard) that can be used to do operations with tables and element segments.
A declarative element segment is not available at runtime but merely serves to forward-declare references that are formed in code with instructions like ref.func.
Here is the test suite, where you can see many examples of element segments (in a text format).
Assuming that you parser the code, you read one u32
, and based on its value you expect the format from specification:
0
means an active segment, as the one above, for an implicit table index of 0
, and a vector of func.refs
.1
means a passive segment, the elemkind
(0x00
for func.ref
at this time), followed by a vector of the respective items (func.refs
).2
is an active segment.3
means a declarative segment.4
is an active segment where the values in the vector are expressions, not just plain indexes (so you could have (i32.const 2)
in the above example, instead of 2
).5
passive with expressions6
active with table index and expressions7
declarative with expressionsFor this reason the specs says that from this u32
[0..7] you can use its three lower bits to detect what is the format that you have to parse. For example, the 3th bit signifies "is the vector made of expressions?".
Now, all that said, it seems that the reference types proposal is not (yet) fully integrated into the specification's binary format (but seems to be in the text one). When it is you will be able to have other then 0x00
(func.ref
) for an elemkind
.
It is visible that some of this formats overlap, but the specification evolves, and for backward compatibility reasons with the earliest versions the format is like this today.