forked from OSchip/llvm-project
Use FinishThunk to finish musttail thunks
FinishThunk, and the invariant of setting and then unsetting CurCodeDecl, was added in7f416cc426
(2015). The invariant didn't exist when I added this musttail codepath inab2090d107
(2014). Recently in28328c3771
, 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
This commit is contained in:
parent
ffcc076a2b
commit
ce5173c0e1
|
@ -437,7 +437,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,
|
||||
|
@ -564,7 +565,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.
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
Loading…
Reference in New Issue