A call inside a loop whose copy precedes the loop is linked when its link
register is another pair, and left unlinked when s_swappc_b64 writes its return
address over the pointer it calls through.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
FindUserDataCalls required the s_mov copy of the user-data callee pointer to
sit in the call's basic block, so a compute shader that copies s[0:1] at entry
and calls after an execz guard was left with an unresolvable s_swappc_b64.
Fall back to reachingWriter, as FindTableCalls already does.
The UserDataCallAfterBranch execution test dispatches such a shader with two
callees and checks every lane's result.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
reachingWriter followed only fall-through and direct branches, so a V#
load on a path that reaches the loop through an s_setpc_b64 jump the
control flow analysis resolves was not seen, and another load could be
taken as the only writer. The walk now follows those jumps. It also
fails at s_call_b64 targets, whose callers it does not follow, instead
of walking from a function entry into the code above it.
Co-Authored-By: Claude <[email protected]>
An s_swappc_b64 whose target is not resolved compiles to a faulting call
only at the fallback the table-call linker emits; the linker lists those
calls in the request (GuestContext::linkedCallFallbacks), and every other
computed call is refused at compile time again, as on main. The new
agc_driver_compute_table_calls test runs a linked two-record table on
Vulkan in wave32 and wave64, with SCC 0 and 1 reaching the callee, and a
record past the table reporting the UnlinkedCall fault.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
An s_swappc_b64 whose target pair comes from an s_buffer_load of a buffer
whose descriptor is loaded from user data now calls the targets that buffer
holds: at dispatch the driver reads the buffer, links one copy of each
distinct callee after the caller and rewrites the call into a compare chain
that s_call_b64s the matching copy. A target that matches no copy, and any
other computed call, records an UnlinkedCall fault that the driver reports,
instead of failing the shader at compile time.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Reject tuple and descriptor overlap, wrong-pair returns, relative SGPR reads, reversed regions and ordinary or conditional fall-through into a callee. Preserve the existing scalar write analysis and require exact return-pair matching.
Seven targeted regressions fail before these guards and pass afterward. Seven focused CMake tests and 15 SPIR-V validations pass; the execution matrix passes 3,200 comparisons and detects a one-bit expected-output mutation.
Reuse the prerequisite call-region analysis for signed relative calls, including callees after s_endpgm. Lower the saved link as shader base plus PC+4 and reject unsupported targets and call shapes.
Add decoder, IR, CFG and Vulkan execution regressions. Seven focused CMake tests pass; five layouts cover 15 dispatches and 3,200 output comparisons on lavapipe. Record ISA sources and native RDNA2/PS5 limits in TechnicalDebt.