[llvm-bugs] [Bug 39901] New: clobbered return value from this-adjustment thunk returning a member pointer
via llvm-bugs
llvm-bugs at lists.llvm.org
Thu Dec 6 04:58:55 PST 2018
https://bugs.llvm.org/show_bug.cgi?id=39901
Bug ID: 39901
Summary: clobbered return value from this-adjustment thunk
returning a member pointer
Product: clang
Version: trunk
Hardware: PC
OS: Linux
Status: NEW
Severity: enhancement
Priority: P
Component: LLVM Codegen
Assignee: unassignedclangbugs at nondot.org
Reporter: hans at chromium.org
CC: llvm-bugs at lists.llvm.org, neeilans at live.com,
richard-llvm at metafoo.co.uk
Consider the following example, targeting 32-bit x86:
struct X;
typedef void (X::*memptr)();
struct A {
virtual memptr f();
};
struct B {
virtual memptr f();
};
struct C : A, B {
C();
memptr f() override __attribute__((noinline)) { return nullptr; };
};
C::C() {}
$ clang -cc1 -triple i686 -emit-llvm -o - a.cc -O3
[...]
define linkonce_odr void @_ZThn4_N1C1fEv({ i32, i32 }* noalias sret
%agg.result, %struct.C* %this) unnamed_addr #1 comdat align 2 {
entry:
%tmp = alloca { i32, i32 }, align 4
%0 = getelementptr inbounds %struct.C, %struct.C* %this, i32 -1, i32 1
%1 = bitcast %struct.B* %0 to %struct.C*
tail call void @_ZN1C1fEv({ i32, i32 }* nonnull sret %tmp, %struct.C* nonnull
%1)
ret void
}
Note that the sret value from @_ZN1C1fEv gets dropped!
The -O0 IR looks like this:
define linkonce_odr void @_ZThn4_N1C1fEv({ i32, i32 }* noalias sret
%agg.result, %struct.C* %this) unnamed_addr #0 comdat align 2 {
entry:
%retval = alloca { i32, i32 }, align 4
%this.addr = alloca %struct.C*, align 4
%tmp = alloca { i32, i32 }, align 4
store %struct.C* %this, %struct.C** %this.addr, align 4
%this1 = load %struct.C*, %struct.C** %this.addr, align 4
%0 = bitcast %struct.C* %this1 to i8*
%1 = getelementptr inbounds i8, i8* %0, i32 -4
%2 = bitcast i8* %1 to %struct.C*
tail call void @_ZN1C1fEv({ i32, i32 }* sret %tmp, %struct.C* %2)
%3 = load { i32, i32 }, { i32, i32 }* %tmp, align 4
store { i32, i32 } %3, { i32, i32 }* %retval, align 4
%4 = load { i32, i32 }, { i32, i32 }* %retval, align 4
store { i32, i32 } %4, { i32, i32 }* %agg.result, align 4
ret void
}
Note that the thunk is passing its %tmp alloca into the tail-called function.
That's not allowed: a tail-call function is not supposed to access alloca's
from the caller. Because of that, the subsequent copy from %tmp to %agg.result
gets optimized away.
Interestingly, this doesn't happen for all sret values, such as a regular
struct. I could only reproduce with a member pointer.
--
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20181206/b2a9986c/attachment.html>
More information about the llvm-bugs
mailing list