Why just use separate stacks for code and data if you can engineer a more complicated solution with higher overhead?
CPU architectures that have register windows [2] tend to spill shifted-out registers onto a separate stack lazily, and those registers could contain the return pointer.
Nothing precludes an architecture from having both: register windows to avoid register clobbering and register renaming to allow dozens/hundreds of micro-ops “in flight” at the same time.