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>
Reasonably Related Threads
- RFC: Insertion of nops for performance stability
- [LLVMdev] Passing structures as pointers, MSVC x64 style
- avx512 JIT backend generates wrong code on <4 x float>
- [LLVMdev] Unexpected spilling of vector register during lane extraction on some x86_64 targets
- clang emits calls to consexpr function.