[llvm] [IR] Define empty and malformed !callees semantics (PR #221550)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 8 00:59:08 PDT 2026
================
@@ -7778,12 +7778,24 @@ Example (assuming 64-bit pointers):
#### '`callees`' Metadata
-`callees` metadata may be attached to indirect call sites. If `callees`
-metadata is attached to a call site, and any callee is not among the set of
-functions provided by the metadata, the behavior is undefined. The intent of
-this metadata is to facilitate optimizations such as indirect-call promotion.
-For example, in the code below, the call instruction may only target the
-`add` or `sub` functions:
+`callees` metadata may be attached to call sites.
+Its operands provide an exhaustive list of possible callees.
+The list may be conservative: a listed function need not be dynamically feasible, but on every defined execution of the call the callee must be one of the listed functions.
+The order and duplication of operands are semantically irrelevant.
+The intent of this metadata is to facilitate optimizations such as indirect-call promotion.
+
+The constraint applies whether the called operand is a constant or not.
+Executing a direct call whose target is not in the list has undefined behavior.
+If the direct target is in the list, the attachment is redundant and may be dropped.
+
+An empty node is an exhaustive empty set, so executing the call has undefined behavior.
+If the metadata is absent, no exhaustive callee information is provided.
+
+Each operand must refer to a `Function`.
+If any operand does not, the entire attachment provides no information and must be ignored.
----------------
mmiftahx wrote:
@arsenm
> This doesn't make sense. A direct call to a list of the single function shouldn't be structurally disallowed
Agree here, a direct call to `@known_target` with `!callees !{ptr @known_target}` is **allowed** by the patch. It also remains valid with `!callees !{ptr @known_target, null}`: ignoring that attachment means it supplies no exhaustive callee information, **not** that the call is rejected.
My response to @nikic concerns whether that damaged list can be treated as an exhaustive singleton. In the example, the raw metadata `null` is left by deleting `@external_target`'s declaration; another module can still pass that function's address to the indirect call. Treating the surviving entry as exhaustive would exclude that possibility without justification. This supports discarding the damaged list's exhaustive information, but does not settle every other operand kind or make that the only possible fix.
Could you clarify which case you mean by "structurally disallowed" ?
https://github.com/llvm/llvm-project/pull/221550
More information about the llvm-commits
mailing list