Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 25 additions & 20 deletions AstSemantics.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,36 +294,41 @@ buffer.
In the MVP, the length of the return types sequence may only be 0 or 1. This
restriction may be lifted in the future.

Direct calls to a function specify the callee by index into a function table.
Direct calls to a function specify the callee by index into a *main function table*.

* `call`: call function directly

Calls must match the function signature exactly.
A direct call to a function with a mismatched signature is a module verification error.

Like direct calls, calls to [imports](Modules.md#imports-and-exports) specify
the callee by index into an import table (defined by the sequence of import
declarations in the module import section) and the call must match the declared
signature of the import exactly.
the callee by index into an *imported function table* defined by the sequence of import
declarations in the module import section. A direct call to an imported function with a
mismatched signature is a module verification error.

* `call_import` : call imported function directly

Indirect calls may be made to a value of function-pointer type. A
function-pointer value may be obtained for a given function as specified by its index
in the function table.
Indirect calls allow calling target functions that are unknown at compile time.
The target function is an expression of local type `i32` and is always the first
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be i64 for wasm64? I don't have a specific use case that needs more than 4 billion indirect function table entries, but since functions can appear multiple times in the table, one could imagine possibilities.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the other hand, having the a priori i32 limit would allow the C++ compiler so simply make func-ptrs 32-bit. (Is that easy to do in LLVM, or is that baked into the LLP model?)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Wed, Oct 7, 2015 at 3:06 PM, Dan Gohman notifications@github.com wrote:

In AstSemantics.md
#392 (comment):

  • call_import : call imported function directly

-Indirect calls may be made to a value of function-pointer type. A
-function-pointer value may be obtained for a given function as specified by its index
-in the function table.
+Indirect calls allow calling target functions that are unknown at compile time.
+The target function is an expression of local type i32 and is always the first

Should this be i64 for wasm64? I don't have a specific use case that
needs more than 4 billon indirect function table entries, but since
functions can appear multiple times in the table, one could imagine
possibilities.

The tables would have to be sparse somehow, otherwise, declaring 4 billion
indirect tables is going to be a pretty big wasm module :-)


Reply to this email directly or view it on GitHub
https://github.com/WebAssembly/design/pull/392/files#r41386881.

input into the indirect call.
A `call_indirect` specifies the *expected* signature of the target function with
an index into a *signature table* defined by the module.
An indirect call to a function with a mismatched signature causes a trap.

* `call_indirect`: call function indirectly
* `addressof`: obtain a function pointer value for a given function

Function-pointer values are comparable for equality and the `addressof` operator
is monomorphic. Function-pointer values can be explicitly coerced to and from
integers (which, in particular, is necessary when loading/storing to memory
since memory only provides integer types). For security and safety reasons,
the integer value of a coerced function-pointer value is an abstract index and
does not reveal the actual machine code address of the target function.

In the MVP, function pointer values are local to a single module. The
[dynamic linking](DynamicLinking.md) feature is necessary for
two modules to pass function pointers back and forth.

Functions from the main function table are made addressable by defining an
*indirect function table* that consists of a sequence of indices
into the module's main function table. A function from the main table may appear more than
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the main function table local to each module?

Why has the indirect function table been introduced?

Are the elements of the indirect function table observable to the wasm code? Can it be accessed to load the index?

No provision has been made for homogeneous function tables. These seem important for code that wants to avoid a runtime signature check.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Wed, Oct 7, 2015 at 8:55 AM, JSStats notifications@github.com wrote:

In AstSemantics.md
#392 (comment):

- * addressof: obtain a function pointer value for a given function

-Function-pointer values are comparable for equality and the addressof operator
-is monomorphic. Function-pointer values can be explicitly coerced to and from
-integers (which, in particular, is necessary when loading/storing to memory
-since memory only provides integer types). For security and safety reasons,
-the integer value of a coerced function-pointer value is an abstract index and

-does not reveal the actual machine code address of the target function.

-In the MVP, function pointer values are local to a single module. The
-dynamic linking feature is necessary for
-two modules to pass function pointers back and forth.
+
+Functions from the main function table are made addressable by defining an
+indirect function table that consists of a sequence of indices
+into the module's main function table. A function from the main table may appear more than

Is the main function table local to each module?

Yes, each module will have its own (local) main function table that
declares the functions in that module.

Why has the indirect function table been introduced?

The indirect function table allows the module to declare which functions
are addressable and arrange them into a table. Thus the assignment of
integers to functions pointers is under the control of the module. Since
the indirect function table allows functions to appear more than once, it
allows, e.g. a compiler to map vtables into the one big indirect table. So
a C++ table dispatch can be as simple as:

call_indirect(i32_add(i32_load(obj, #0), #meth_num), ... args ...)

So C++ objects store the "vtable base" in the object header, add a
method-specific offset, and then call that.

This has the advantage that vtables can be placed outside the linear memory
for safety (and performance--one less memory access).

Are the elements of the indirect function table observable to the wasm
code? Can it be accessed to load the index?

No, wasm code cannot directly read the indirect function table.

No provision has been made for homogeneous function tables. These seem
important for code that wants to avoid a runtime signature check.

That's an optimization that we can consider adding in the future, e.g. by
denoting an expected range within the single table where all the functions
have the same signature. AFAICT, that trades one branch (signature check)
for a subtract before the bounds check. Seems like it could be worthwhile,
but let's add that when we have data.


Reply to this email directly or view it on GitHub
https://github.com/WebAssembly/design/pull/392/files#r41356981.

once in the indirect function table. Functions not appearing in the indirect function
table cannot be called indirectly.

In the MVP, indices into the indirect function table are local to a single module, so wasm
modules may use `i32` constants to refer to entries in their own indirect function table. The
[dynamic linking](DynamicLinking.md) feature is necessary for two modules to pass function
pointers back and forth. This will mean concatenating indirect function tables
and adding an operation `address_of` that computes the absolute index into the concatenated
table from an index in a module's local indirect table. JITing may also mean appending more
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a nice way to put it. That addresses my only nit.

functions to the end of the indirect function table.

Multiple return value calls will be possible, though possibly not in the
MVP. The details of multiple-return-value calls needs clarification. Calling a
Expand Down