Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect destructor parameter alignment on windows #60465

Closed
jacobly0 opened this issue Feb 2, 2023 · 3 comments
Closed

Incorrect destructor parameter alignment on windows #60465

jacobly0 opened this issue Feb 2, 2023 · 3 comments

Comments

@jacobly0
Copy link
Contributor

jacobly0 commented Feb 2, 2023

struct SE {
    virtual ~SE() = default;

    virtual void oE() {}
};

struct WE : virtual SE {
    ~WE() override = default;

    void oE() override;
};

struct FT : virtual WE {
    ~FT() override;

    int m_b alignas(2 * sizeof(void*));
};

FT::~FT() {
    m_b = 0;
}
$ clang --version
clang version 15.0.7
Target: x86_64-w64-windows-gnu
Thread model: posix
InstalledDir: D:/dep/msys64/ucrt64/bin

$ clang -O1 -target x86_64-windows repro.cpp -S -emit-llvm -o -
<snip>
define dso_local void @"??1FT@@UEAA@XZ"(ptr nocapture noundef nonnull align 16 dereferenceable(32) %0) unnamed_addr #
0 align 2 {
  <snip>
  %15 = getelementptr inbounds i8, ptr %0, i64 -24
  store i32 0, ptr %15, align 16, !tbaa !7
  ret void
}
<snip>

Note that both %0 and %15 are marked with align 16 even though the offset between them is 24 bytes.


This is much reduced with shortened identifiers so that I can still associate it with the original code. This bug manifested as optimized builds crashing at runtime on a movaps instruction which was storing to a pointer that was not, in fact, 16 byte aligned, but which was derived from an 8-byte aligned pointer with an incorrectly marked alignment of 16 bytes and an offset that happened to be a multiple of 16 bytes.

@llvmbot
Copy link
Collaborator

llvmbot commented Feb 2, 2023

@llvm/issue-subscribers-clang-codegen

@jacobly0
Copy link
Contributor Author

jacobly0 commented Feb 2, 2023

Reduced reproducer after some investigation into the bug:

struct A { virtual ~A(); };

struct alignas(2 * sizeof(void *)) B : virtual A {
    ~B();

    void *x, *y;
};
B::~B() { y = nullptr; }
$ clang --version
clang version 17.0.0
Target: x86_64-w64-windows-gnu
Thread model: posix
InstalledDir: D:/dep/msys64/home/Admin/prg/llvm/build-Debug/bin

$ clang -O1 -target x86_64-windows repro.cpp -S -emit-llvm -o -
<snip>
; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read, argmem: readwrite, inaccessiblemem: none) uwtable
define dso_local void @"??1B@@UEAA@XZ"(ptr nocapture noundef nonnull align 16 dereferenceable(24) %this) unnamed_addr #0 align 2 {
entry:
  %0 = getelementptr inbounds i8, ptr %this, i64 -24
  %vbtable = load ptr, ptr %0, align 16
  %1 = getelementptr inbounds i32, ptr %vbtable, i64 1
  %vbase_offs = load i32, ptr %1, align 4
  %2 = sext i32 %vbase_offs to i64
  %add.ptr = getelementptr inbounds i8, ptr %0, i64 %2
  store ptr @"??_7B@@6B@", ptr %add.ptr, align 8, !tbaa !4
  %y = getelementptr inbounds i8, ptr %this, i64 -8
  store ptr null, ptr %y, align 16, !tbaa !7
  ret void
}
<snip>

Note that both %this and %y are marked with align 16 even though the offset between them is 8 bytes.

@jacobly0
Copy link
Contributor Author

jacobly0 commented Feb 3, 2023

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants