BasicCABI.md: mention how function pointers look like#200
BasicCABI.md: mention how function pointers look like#200yamt wants to merge 2 commits intoWebAssembly:mainfrom
Conversation
BasicCABI.md
Outdated
|
|
||
| **Function pointers** | ||
|
|
||
| A pointer to a function is an index into the table 0 of the module. |
There was a problem hiding this comment.
| A pointer to a function is an index into the table 0 of the module. | |
| A pointer to a function is an index into table 0 of the module. |
There was a problem hiding this comment.
I think __indirect_function_table might not be table 0. For example, if the module happens to import a table, since import always come first in the index space there is no way for the linker to arrange for __indirect_function_table to be at index 0.
In other words, any documentation like this should probably refer to the table by name on only.
There was a problem hiding this comment.
on runtime (eg. when calling a host function which takes a function pointer), the name is not available, is it?
There was a problem hiding this comment.
i was confused with linker symbol and export name.
i dropped table 0 assumption.
There was a problem hiding this comment.
There can be multiple tables, but will clang/LLVM ever emit more than one? To my eye, it looks like there's an undocumented assumption that we'll only ever handle a single table. For example, Linking.md discusses indices in tables but not indices of tables. For tools wishing to be compatible with clang/LLVM it seems to me that they must reserve table 0 for function pointers
There was a problem hiding this comment.
Some links from trawling through LLVM itself:
- WebAssembly::getOrCreateFunctionTableSymbol
__indirect_function_tableseems to have been hard-coded since a refactor 5 years ago requiring that table be present even when not referenced
- The
wasm-llddocs imply a singular table and that's been there for 8 years
There was a problem hiding this comment.
The things is that the Basic C API, up until this point has not needed to refer to symbols, or the linking metatdata, or the object file format. That has been specified in Linking.md.
Note that there is also no mention of the other magic symbols __stack_pointer here, although perhaps there should be?
I think perhaps its enough to to say something like:
Function pointers are represented as i32 (or i64 under wasm64) values which are indexes into a single Wasm table named `__indirect_function_table` (See Linking.md for more of how symbols work). The are invoked using the `call_indirect` instruction.
There was a problem hiding this comment.
How about:
Function pointers are represented as i32 (or i64 under wasm64) values which are indexes into a single Wasm table,
which must be the table 0. If it is exported or imported then its name is__indirect_function_table
(See Linking.md for more of how symbols work). The are invoked using thecall_indirectinstruction.
There was a problem hiding this comment.
But its not true anymore that it must be table zero. Its just the table with the name __indirect_function_table which gets identified via a relocation. Same as how stack pointer is identified via its symbols name __stack_pointer.
I don't think we need to mention the importing or exporting because in the final binary you can export as whatever name you like. Its only things like emscripten and WASI that care about the exported name, not the C API or the Linking specification.
There was a problem hiding this comment.
For example I could create a runtime where the table has to be exported as __table, and that would not effect the C ABI using withing the module.
|
|
||
| A pointer to a function is an index into the table 0 of the module. | ||
| The type of the table is funcref. | ||
| The table needs to be exported with the name `__indirect_function_table` |
There was a problem hiding this comment.
I'm not sure if this should be a requirement of the base C ABI. IIRC it is what emscripten does, but emscripten is also focused on the JS embedding (and has other conventions such as other exports that are also beyond the scope of this doc). There are also other ways to accomplish the same objective (for example, a module could export a function that takes the function pointer as an argument, and then calls it itself).
Probably it makes sense for conventions used by particular embeddings or particular SDKs/runtimes to be either left out of this doc or put in a separate section. Is this requirement particularly important to the environment that you are using?
There was a problem hiding this comment.
There are also other ways to accomplish the same objective (for example, a module could export a function that takes the function pointer as an argument, and then calls it itself).
yes. but sometimes it isn't desirable to tweak the api that way. eg. when it's from a standard. or when it's a port from non-wasm platform.
Probably it makes sense for conventions used by particular embeddings or particular SDKs/runtimes to be either left out of this doc or put in a separate section. Is this requirement particularly important to the environment that you are using?
i'm not familiar with emscripten.
my concern is more about wasi: https://github.com/WebAssembly/WASI/blob/main/legacy/application-abi.md#current-unstable-abi
There was a problem hiding this comment.
@dschuff i'm not sure what exactly your concern is. after all, as the first section of this document is saying, this is just about "the ABI that the clang/LLVM WebAssembly backend is currently using".
There was a problem hiding this comment.
Everything in this document is about inter-linking between object files (and the interface between object files and the linker), and is therefore independent of the embedding. Its says nothing about what must be exported from the linked binary, or about what the linked binary may import from the environment (i.e. what APIs would be available to the program, or what API the program must implement). Those would depend on the embedding, whether WASI or emscripten is being used, and indeed even which WASI APIs were available vs. not.
I think those concerns should at the very least be in a separate section, and maybe a separate document entirely.
There was a problem hiding this comment.
The import name env.__indirect_function_table is documented in DynamicLinking.md. It's not required that the table be exported from WASM at all; each module might import a table initialized by the host, for example.
daf2f35 to
bece839
Compare
|
the last push was just a rebase |
|
Collecting the discussion from the 2 different comment locations to here: But the indirect function table and stack pointer are a little bit in between. Modules have to agree on which global is the stack pointer. In hardware, the modules have to agree on which register to use but the register is always there. In Wasm we could have said "global 0 is always the stack pointer" but we made it a little more flexible than that and IIRC we have a linking scheme where stack pointer references are relocatable. And in fact it is not covered either here (there are TODOs) or in Linking.md. Likewise an indirect function table required: for function pointers to even exist and be callable (even where no symbol resolution or linking are required) modules have to agree on which table to use. We could have specified which table it was (indeed in MVP there was only one) but we decided not to. Maybe in this document we could say something like what Sam is suggesting above, Particular environments may want to impose additional constraints. Maybe Emscripten wants the memory exported, or some environment wants the stack pointer exported. But I think that goes beyond this convention. WDYT? |
No description provided.