[llvm-dev] Expected behavior of __builtin_return_address() with inlining?

Gao, Yunzhong via llvm-dev llvm-dev at lists.llvm.org
Tue Dec 1 11:37:33 PST 2015

Hey Sean,
Thanks for the explanation. The LLVM IR doc does clarify things for me. The part
that I got confused is not really about what is "the function that is returned to":
the GCC doc explicitly mentions it should be the address of "the function that is
returned to", i.e., &bar in my example; whereas the observed behavior from the
compiler is more like the return address as if the builtin was placed inside "the
function that is returned to", i.e.,
  long bar() { return __builtin_return_address(0); }
Reading the old thread from https://gcc.gnu.org/ml/gcc/2002-06/msg00335.html seems
to indicate that the GCC doc is intended as an after-the-fact description of what the
compiler does, rather than a description of behavior which the compiler should be
changed to conform to. I am therefore inclined to believe that the GCC doc is inaccurate
in capturing the behavior of the compiler. The clang LangRef.html says,
  "Note that calling this intrinsic does not prevent function inlining or other
   aggressive transformations, so the value returned may not be that of the obvious
   source-language caller."
And I believe it is consistent with the observed behavior from the compiler.
- Gao

From: Sean Silva [mailto:chisophugis at gmail.com]
Sent: Monday, November 30, 2015 10:23 PM
To: Gao, Yunzhong
Cc: llvm-dev at lists.llvm.org
Subject: Re: [llvm-dev] Expected behavior of __builtin_return_address() with inlining?

On Mon, Nov 30, 2015 at 7:13 PM, Gao, Yunzhong via llvm-dev <llvm-dev at lists.llvm.org<mailto:llvm-dev at lists.llvm.org>> wrote:
I am trying to understand what should be the expected behavior of __builtin_return_address(0)
when inlining has happened.

So, the GCC doc from https://gcc.gnu.org/onlinedocs/gcc/Return-Address.html says:
(I used GCC doc because I could not find equivalent Clang/LLVM builtin doc)
  When inlining the expected behavior is that the function returns the address of the function
  that is returned to. To work around this behavior use the noinline function attribute.

I wrote the following test case to verify this behavior:
  /* test.c */
  long foo() {
    return (long)__builtin_return_address(0);
  inline long bar() {
    return foo();
  long foobar() {
    return bar();
  /* end test.c */

My interpretation of the GCC doc is that, if foo() is inlined into bar(), then __builtin_return_address(0)
will return &bar, instead of the instruction address of the call to foo().

I think the wording "the function that is returned to" is referring to the function that is dynamically returned to, not anything at source level. It's more like "if you were to say `asm("ret")`, where would you return to"

Also see: See http://llvm.org/docs/LangRef.html#llvm-returnaddress-intrinsic

The "current function" is pretty much "whatever the backend sees". That seems like the only reasonable way to define it.

-- Sean Silva

I compiled with GCC 4.8.2 and Clang 3.8.0, and I got the following result:

  # clang 3.8.0 trunk 253253
  # clang -S -O2 test.c
    movq    (%rsp), %rax
    movq    (%rsp), %rax
  # end assembly

  # GCC 4.8.2-19ubuntu1
  # gcc -S -O2 test.c
    movq    (%rsp), %rax
    movq    (%rsp), %rax
    movq    (%rsp), %rax
  # end assembly

So with both compilers, an inlined __builtin_return_address(0) seems to produce the return address of the
function containing the callsite where the inlined function is expanded.

Maybe I misunderstood the documentation regarding the inlined __builtin_return_address()? Please help,

- Gao
LLVM Developers mailing list
llvm-dev at lists.llvm.org<mailto:llvm-dev at lists.llvm.org>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20151201/6301036a/attachment-0001.html>

More information about the llvm-dev mailing list