Gao, Yunzhong via llvm-dev
2015-Dec-01 03:13 UTC
[llvm-dev] Expected behavior of __builtin_return_address() with inlining?
Hi, 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 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 foo: movq (%rsp), %rax retq foobar: movq (%rsp), %rax retq # end assembly # GCC 4.8.2-19ubuntu1 # gcc -S -O2 test.c foo: movq (%rsp), %rax ret bar: movq (%rsp), %rax ret foobar: movq (%rsp), %rax ret # 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
Sean Silva via llvm-dev
2015-Dec-01 06:23 UTC
[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> wrote:> Hi, > 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 > foo: > movq (%rsp), %rax > retq > foobar: > movq (%rsp), %rax > retq > # end assembly > > # GCC 4.8.2-19ubuntu1 > # gcc -S -O2 test.c > foo: > movq (%rsp), %rax > ret > bar: > movq (%rsp), %rax > ret > foobar: > movq (%rsp), %rax > ret > # 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 > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20151130/dbf6198f/attachment.html>
Gao, Yunzhong via llvm-dev
2015-Dec-01 19:37 UTC
[llvm-dev] Expected behavior of __builtin_return_address() with inlining?
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. Thanks! - 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: Hi, 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 foo: movq (%rsp), %rax retq foobar: movq (%rsp), %rax retq # end assembly # GCC 4.8.2-19ubuntu1 # gcc -S -O2 test.c foo: movq (%rsp), %rax ret bar: movq (%rsp), %rax ret foobar: movq (%rsp), %rax ret # 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> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20151201/6301036a/attachment-0001.html>