WebAssembly / WebAssembly/tool-conventions

ABI for C functions without prototypes

Open
#16 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
WebAssembly
Stars
372
Forks
75
PR merge metrics
No merged PRs in 30d

Description

If you have a K&R-style C function declaration, such as int foo(); currently LLVM will lower calls to it with the usual fixed-arg calling convention. Binaryen's s2wasm will leave the calls untouched, and generate foo's function section entry using the type of foo's implementation. If there is a mismatch, then the linked module fails validation.

We should specify in the ABI what is supposed to happen, and LLVM and lld should implement that. The wasm ABI is somewhat unique in that the vararg calling convention is incompatible with the fixed-arg calling convention. Based on previous discussion I think we are still happy with that decision, so that means that at high level there are 2 options here:

  1. All calls to functions with no prototype use the vararg calling convention.
    • As a result the signatures of the imports of such functions in the callers' object files all just take a single i32 (the vararg buffer).
    • Of course if the implementation of the function is not vararg, then there will be a link-time/validation failure or a runtime failure (if the wasm signature happens to match).
  2. Calls to such functions use the fixed-arg calling convention.
    • The signatures in a caller's object file will have whatever arguments are used at the callsite. (If multiple callsites in the object file have different arguments, that would be a compile-time error).

In either case, the linker would check the signatures of all of the the imports for a particular function against the implementation of that function (i.e. the function signature in the object that exports it), and would issue an error if there was a mismatch. Also in either case, a mismatch at the source level could accidentally match at the wasm level, and result in a more-difficult-to-debug runtime failure.

I had thought that option 1 would be easier to specify in an ABI, but now I'm not so sure. Basically everything that needs to be specified (e.g. how does a C function signature lower to a wasm signature, what signature gets put in the import section of an object file, how the linker resolves mismatches, etc) has to be specified either way, and furthermore most of the behaviors will be the same either way. As far as I can see, the only difference is whether we use the vararg or fixed-arg convention. Given that, I'm actually more inclined just to use the fixed-arg convention on the grounds that it's almost always what people actually want.

Thoughts?

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the wasm ABI conventions and the issue's discussion of LLVM, lld, and Binaryen's s2wasm handling of K&R-style declarations. Compare the fixed-argument and vararg options, including import and implementation signatures. Done means the ABI behavior is decided, documented, and the relevant tools consistently reject mismatches.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, wasm
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.