[llvm] [SystemZ][z/OS] Use a function descriptor for external functions in initializers (PR #226682)
MMS IT GmbH via llvm-commits
llvm-commits at lists.llvm.org
Sun Sep 27 08:34:23 PDT 2026
mms-it-ch wrote:
A problem with this approach that showed up since: with a function descriptor of its own in the
ADA, a pointer to an **external** function from a static initializer is callable, but it does not
compare equal to the address of the same function taken in code.
```c
#include <stdio.h>
void f(void) {}
static void g(void) {}
void (*pf)(void) = f;
void (*pg)(void) = g;
int main(void) {
void (*volatile lf)(void) = f;
void (*volatile lg)(void) = g;
printf("f: %s\n", lf == pf ? "equal" : "DIFFERENT");
printf("g: %s\n", lg == pg ? "equal" : "DIFFERENT");
return !(lf == pf && lg == pg);
}
```
With this patch, on z/OS 3.1: `f: DIFFERENT`, `g: equal`.
Code takes the address of a non-internal function from an ADA slot `MO_ADA_INDIRECT_FUNC_DESC`
(`DC VD(f at indirect)`), which the binder resolves to the function descriptor of `f`. The initializer
gets `DC AD(AD(<name>#S)+XL8'56')`, i.e. the separate descriptor `DC RD(f)` / `DC VD(f)` in the ADA.
Using the indirect symbol in the initializer as well fixes it (both lines `equal` on z/OS):
```cpp
if (IsFunc) {
OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
const GlobalValue *FGV = GA ? static_cast<const GlobalValue *>(GA)
: static_cast<const GlobalValue *>(FV);
if (!FGV->hasInternalLinkage() && !FGV->hasPrivateLinkage()) {
// Same descriptor as code taking the address; the slot is inserted only
// to have the indirect symbol defined.
ADATable.insert(Sym, SystemZII::MO_ADA_INDIRECT_FUNC_DESC);
MCSymbol *Alias = OutContext.getOrCreateSymbol(
Twine(Sym->getName()).concat("@indirect"));
return MCSpecifierExpr::create(MCSymbolRefExpr::create(Alias, OutContext),
SystemZ::S_VCon, OutContext);
}
// internal functions: function descriptor in the ADA, as before
```
The initializer then becomes `DC VD(f at indirect)`. `zos-lower-constant.ll` would check
`DC VD(bar at indirect)` for `@func_e` and the ADA slot `pointer to function descriptor bar`.
This PR should be updated accordingly before it is merged. (Found with method pointers in typed constants in Free Pascal,
which compared unequal to `@Method`.)
---
*Drafted with the help of Claude Code (Anthropic), in line with the LLVM AI Tool Use Policy. The
test was run on z/OS 3.1 with the results given above.*
https://github.com/llvm/llvm-project/pull/226682
More information about the llvm-commits
mailing list