Skip to content

[LangRef] Add a description of the semantics of call signatures. #136189

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

Merged
merged 2 commits into from
Apr 18, 2025
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
25 changes: 19 additions & 6 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9475,10 +9475,11 @@ This instruction requires several arguments:
from the :ref:`datalayout string<langref_datalayout>` will be used.
#. '``ty``': the type of the call instruction itself which is also the
type of the return value. Functions that return no value are marked
``void``.
``void``. The signature is computed based on the return type and argument
types.
#. '``fnty``': shall be the signature of the function being invoked. The
argument types must match the types implied by this signature. This
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
argument types must match the types implied by this signature. Thisa
argument types must match the types implied by this signature. This

type can be omitted if the function is not varargs.
is only required if the signature specifies a varargs type.
#. '``fnptrval``': An LLVM value containing a pointer to a function to
be invoked. In most cases, this is a direct function invocation, but
indirect ``invoke``'s are just as possible, calling an arbitrary pointer
Expand Down Expand Up @@ -9571,10 +9572,11 @@ This instruction requires several arguments:
from the :ref:`datalayout string<langref_datalayout>` will be used.
#. '``ty``': the type of the call instruction itself which is also the
type of the return value. Functions that return no value are marked
``void``.
``void``. The signature is computed based on the return type and argument
types.
#. '``fnty``': shall be the signature of the function being called. The
argument types must match the types implied by this signature. This
type can be omitted if the function is not varargs.
is only required if the signature specifies a varargs type.
#. '``fnptrval``': An LLVM value containing a pointer to a function to
be called. In most cases, this is a direct function call, but
other ``callbr``'s are just as possible, calling an arbitrary pointer
Expand Down Expand Up @@ -13127,10 +13129,11 @@ This instruction requires several arguments:
from the :ref:`datalayout string<langref_datalayout>` will be used.
#. '``ty``': the type of the call instruction itself which is also the
type of the return value. Functions that return no value are marked
``void``.
``void``. The signature is computed based on the return type and argument
types.
#. '``fnty``': shall be the signature of the function being called. The
argument types must match the types implied by this signature. This
type can be omitted if the function is not varargs.
is only required if the signature specifies a varargs type.
#. '``fnptrval``': An LLVM value containing a pointer to a function to
be called. In most cases, this is a direct function call, but
indirect ``call``'s are just as possible, calling an arbitrary pointer
Expand All @@ -13152,6 +13155,16 @@ values. Upon a '``ret``' instruction in the called function, control
flow continues with the instruction after the function call, and the
return value of the function is bound to the result argument.

If the callee refers to an intrinsic function, the signature of the call must
match the signature of the callee. Otherwise, if the signature of the call
does not match the signature of the called function, the behavior is
target-specific. For a significant mismatch, this likely results in undefined
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
target-specific. For a signficant mismatch, this likely results in undefined
target-specific. For a significant mismatch, this likely results in undefined

Copy link
Member

Choose a reason for hiding this comment

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

shall we say "undefined behavior"? might to more consistent with the -passes=lint diagnostics.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

There's some weirdness here because of the way ABI lowering works: we don't define one correct way to lower a high-level type to an LLVM type, so different frontends represent the "same" type as a different LLVM type. Because of this, optimizations are conservative with signature mismatches. Maybe we can revisit this at some point.

behavior. LLVM interprocedural optimizations generally only optimize calls
where the signature of the caller matches the signature of the callee.

Note that it is possible for the signatures to mismatch even if a call appears
to be a "direct" call, like ``call void @f()``.

Example:
""""""""

Expand Down
Loading