-
Notifications
You must be signed in to change notification settings - Fork 701
Update discussion of indirect calls and function pointers #392
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 | ||
| 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 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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:
call_indirect(i32_add(i32_load(obj, #0), #meth_num), ... args ...) So C++ objects store the "vtable base" in the object header, add a This has the advantage that vtables can be placed outside the linear memory
|
||
| 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 | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be
i64for 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.There was a problem hiding this comment.
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
i32limit 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?)There was a problem hiding this comment.
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: