← board

cdecl indirect call with more than 6 integer args is rejected

Repro

program Cd7;
type
  TFn7 = function(a, b, c, d, e, f, g: PtrInt): PtrInt; cdecl;
var p: TFn7; r: PtrInt;
begin
  p := nil;
  if p <> nil then r := p(1, 2, 3, 4, 5, 6, 7);
  writeln('compiled');
end.
pascal26:11: error: cdecl indirect call: more than 6 integer args not supported yet

The same program with six parameters compiles and links fine. So the boundary is exactly the six System V integer argument registers — anything that has to spill to the stack is refused.

Why this matters now

It is the remaining blocker for the last open item of the dynlib-loader ticket. external/synapse/ssl_openssl3_lib.pas binds OpenSSL 3 through dlopen + function pointers, and OpenSSL has plenty of 7+ argument entry points, so the unit cannot be compiled at all — which means the Synapse-SSL end-to-end test that would actually exercise the loader cannot be written.

At least it fails loudly: a compile error naming the limitation, not silent mis-marshalling. That is the right behaviour for an unimplemented case and worth keeping until the real thing lands.

Note on [[feature-cdecl-indirect-cross-targets]] (marked done)

That ticket's acceptance list includes:

A cdecl proc-type indirect call with float and >6/>4 args marshals correctly

which is not true today on x86-64 — the case is rejected outright. Either the acceptance was written for the direct-call path and the indirect one was never covered, or a later change narrowed it. Worth reconciling while fixing this: if that ticket's tests do cover >6 args, they are not exercising the indirect path, and the gap that let this through is itself worth closing.

Scope

Acceptance

[[feature-real-dynlib-loader]] (item d, blocked on this) · [[feature-cdecl-indirect-cross-targets]] (marked done; acceptance overlaps).

Log