[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