<div dir="ltr"><div dir="auto"><div>Yes, indeed!</div><div dir="auto"><br></div><div dir="auto">The SBCL lisp compiler (not llvm based) used to emit functions which would return either via ret to the usual instruction after the call, or else load the return-address from the stack, then jump 2 bytes later (which would skip over either a nop or a short jmp at original target location). Which one it used depended upon whether the function was doing a multi-valued return (in which case it used ret) or a single-valued return (in which case it did the jmp retpc+2).</div><div dir="auto"><br></div><div dir="auto"><div dir="auto">While this seems like a clever and efficient hack, it actually has an absolutely awful effect on performance, due to the unpaired call vs return, and the unexpected return address.</div><div dir="auto"></div></div><div dir="auto"><div dir="auto"><br></div><div dir="auto">SBCL stopped doing this in 2006, a decade later than it should've -- the Pentium1 MMX from 1997 already had a hardware return stack which made this a really bad idea! </div><div dir="auto"><br></div><div dir="auto">What it does now is have the called function set or clear the carry flag (using STC and CLC) immediately before the return. If the caller cares, then the caller emits JNC as the first instruction after the call. (but callers typically do not care -- most calls only consume a single value, and any extra return-values are silently ignored).</div><br><br><div class="gmail_quote" dir="auto"><div dir="ltr" class="gmail_attr">On Sun, Jul 21, 2019, 6:18 AM Jacob Lifshay via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">one (non-LLVM) problem you will run into is that almost all processors<br>
are optimized to have functions return to the instruction right after<br>
the instruction that called them.<br>
<br>
The most common method is to predict where the return instruction will<br>
jump to by using a processor-internal stack of return addresses, which<br>
is separate from the in-memory call stack. This enables the processor<br>
to fetch, decode, and execute instructions following (in program<br>
order) the return instruction before the processor knows for sure what<br>
address the return instruction will branch to. If the return address<br>
turns out to be different than the processor predicted, it has to<br>
throw out all the instructions it started executing that it thought<br>
came after the return, causing massive slow-downs.<br>
<br>
For an interesting application of changing the return address, lookup<br>
retpolines.<br>
<br>
On Sun, Jul 21, 2019 at 2:07 AM Tsur Herman via llvm-dev<br>
<<a href="mailto:llvm-dev@lists.llvm.org" rel="noreferrer" target="_blank">llvm-dev@lists.llvm.org</a>> wrote:<br>
><br>
> Playing around with calling conventions naked functions and epilogue/prologue...<br>
> Is it possible/expressible/feasible to alter the return address the function will return to?<br>
><br>
> For example, when a function may return an Int8 or a Float64, depending on some external state<br>
> (user, or random variable), instead of checking the returned type in the calling function, is it possible<br>
> to pass 2 potential return addresses one suitable for Int8 and one suitable for Float64 and let the function return to the right place?<br>
><br>
> if it is possible, what are the implications? do these inhibit the optimization opportunities somehow?<br>
> _______________________________________________<br>
> LLVM Developers mailing list<br>
> <a href="mailto:llvm-dev@lists.llvm.org" rel="noreferrer" target="_blank">llvm-dev@lists.llvm.org</a><br>
> <a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" rel="noreferrer" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div></div></div>
</div>