Skip to content

Commit

Permalink
Use FinishThunk to finish musttail thunks
Browse files Browse the repository at this point in the history
FinishThunk, and the invariant of setting and then unsetting
CurCodeDecl, was added in 7f416cc (2015). The invariant didn't
exist when I added this musttail codepath in ab2090d (2014).
Recently in 28328c3, I started using this codepath on non-Windows
platforms, and users reported problems during release testing (PR44987).

The issue was already present for users of EH on i686-windows-msvc, so I
added a test for that case as well.

Reviewed By: hans

Differential Revision: https://reviews.llvm.org/D76444

(cherry picked from commit ce5173c)
  • Loading branch information
rnk authored and Bigcheese committed May 21, 2020
1 parent 5044021 commit 6ffd432
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 2 deletions.
5 changes: 3 additions & 2 deletions clang/lib/CodeGen/CGVTables.cpp
Expand Up @@ -438,7 +438,8 @@ void CodeGenFunction::EmitMustTailThunk(GlobalDecl GD,
// Finish the function to maintain CodeGenFunction invariants.
// FIXME: Don't emit unreachable code.
EmitBlock(createBasicBlock());
FinishFunction();

FinishThunk();
}

void CodeGenFunction::generateThunk(llvm::Function *Fn,
Expand Down Expand Up @@ -565,7 +566,7 @@ llvm::Constant *CodeGenVTables::maybeEmitThunk(GlobalDecl GD,
CGM.SetLLVMFunctionAttributesForDefinition(GD.getDecl(), ThunkFn);

// Thunks for variadic methods are special because in general variadic
// arguments cannot be perferctly forwarded. In the general case, clang
// arguments cannot be perfectly forwarded. In the general case, clang
// implements such thunks by cloning the original function body. However, for
// thunks with no return adjustment on targets that support musttail, we can
// use musttail to perfectly forward the variadic arguments.
Expand Down
27 changes: 27 additions & 0 deletions clang/test/CodeGenCXX/ms-thunks-ehspec.cpp
@@ -0,0 +1,27 @@
// RUN: %clang_cc1 -fexceptions -fcxx-exceptions %s -triple=i686-windows-msvc -emit-llvm -o - | FileCheck %s

// When generating thunks using musttail due to inalloca parameters, don't push
// and pop terminate scopes. PR44987

struct NonTrivial {
NonTrivial();
NonTrivial(const NonTrivial &o);
~NonTrivial();
int x;
};
struct A {
virtual void f(NonTrivial o) noexcept;
};
struct B {
virtual void f(NonTrivial o) noexcept;
};
class C : A, B {
virtual void f(NonTrivial o) noexcept;
};
C c;

// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?f@C@@G3AEXUNonTrivial@@@Z"(%class.C* %this, <{ %struct.NonTrivial }>* inalloca %0)
// CHECK-NOT: invoke
// CHECK: musttail call x86_thiscallcc void @"?f@C@@EAEXUNonTrivial@@@Z"(%class.C* %{{.*}}, <{ %struct.NonTrivial }>* inalloca %0)
// CHECK-NEXT ret void

29 changes: 29 additions & 0 deletions clang/test/CodeGenCXX/thunks-ehspec.cpp
@@ -0,0 +1,29 @@
// RUN: %clang_cc1 -fexceptions -fcxx-exceptions %s -triple=x86_64-pc-linux-gnu -munwind-tables -emit-llvm -o - -O1 -disable-llvm-passes | FileCheck %s

// When generating the thunk for secondary, do not push terminate scopes for
// either the varargs or non-varargs case. Related to PR44987.

struct A {
virtual void primary_key();
};
struct B {
virtual void secondary();
virtual void secondary_vararg(int, ...);
};
class C : A, B {
virtual void primary_key();
void secondary() noexcept;
void secondary_vararg(int, ...) noexcept;
};
void C::primary_key() {}

// CHECK-LABEL: define available_externally void @_ZThn8_N1C9secondaryEv(%class.C* %this)
// CHECK-NOT: invoke
// CHECK: tail call void @_ZN1C9secondaryEv(%class.C* %{{.*}})
// CHECK-NOT: invoke
// CHECK: ret void

// CHECK-LABEL: define available_externally void @_ZThn8_N1C16secondary_varargEiz(%class.C* %this, i32 %0, ...)
// CHECK-NOT: invoke
// CHECK: musttail call void (%class.C*, i32, ...) @_ZN1C16secondary_varargEiz(%class.C* %{{.*}}, i32 %{{.*}}, ...) #2
// CHECK-NEXT: ret void

0 comments on commit 6ffd432

Please sign in to comment.