MS ABI: Don't push destructor cleanups for aggregate parameters in thunks
The target method of the thunk will perform the cleanup. This can't be tested in 32-bit x86 yet because passing something by value would create an inalloca, and we refuse to generate broken code for that. llvm-svn: 213976
This commit is contained in:
parent
a822d94f57
commit
19819446eb
|
@ -1656,7 +1656,9 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg,
|
|||
DeclPtr = Arg->getType() == IRTy ? Arg : Builder.CreateBitCast(Arg, IRTy,
|
||||
D.getName());
|
||||
// Push a destructor cleanup for this parameter if the ABI requires it.
|
||||
if (!IsScalar &&
|
||||
// Don't push a cleanup in a thunk for a method that will also emit a
|
||||
// cleanup.
|
||||
if (!IsScalar && !CurFuncIsThunk &&
|
||||
getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) {
|
||||
const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
|
||||
if (RD && RD->hasNonTrivialDestructor())
|
||||
|
|
|
@ -194,6 +194,7 @@ void CodeGenFunction::StartThunk(llvm::Function *Fn, GlobalDecl GD,
|
|||
const CGFunctionInfo &FnInfo) {
|
||||
assert(!CurGD.getDecl() && "CurGD was already set!");
|
||||
CurGD = GD;
|
||||
CurFuncIsThunk = true;
|
||||
|
||||
// Build FunctionArgs.
|
||||
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
|
||||
|
|
|
@ -38,16 +38,16 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
|
|||
Builder(cgm.getModule().getContext(), llvm::ConstantFolder(),
|
||||
CGBuilderInserterTy(this)),
|
||||
CapturedStmtInfo(nullptr), SanOpts(&CGM.getLangOpts().Sanitize),
|
||||
IsSanitizerScope(false), AutoreleaseResult(false), BlockInfo(nullptr),
|
||||
BlockPointer(nullptr), LambdaThisCaptureField(nullptr),
|
||||
NormalCleanupDest(nullptr), NextCleanupDestIndex(1),
|
||||
FirstBlockInfo(nullptr), EHResumeBlock(nullptr), ExceptionSlot(nullptr),
|
||||
EHSelectorSlot(nullptr), DebugInfo(CGM.getModuleDebugInfo()),
|
||||
DisableDebugInfo(false), DidCallStackSave(false), IndirectBranch(nullptr),
|
||||
PGO(cgm), SwitchInsn(nullptr), SwitchWeights(nullptr),
|
||||
CaseRangeBlock(nullptr), UnreachableBlock(nullptr), NumReturnExprs(0),
|
||||
NumSimpleReturnExprs(0), CXXABIThisDecl(nullptr),
|
||||
CXXABIThisValue(nullptr), CXXThisValue(nullptr),
|
||||
IsSanitizerScope(false), CurFuncIsThunk(false), AutoreleaseResult(false),
|
||||
BlockInfo(nullptr), BlockPointer(nullptr),
|
||||
LambdaThisCaptureField(nullptr), NormalCleanupDest(nullptr),
|
||||
NextCleanupDestIndex(1), FirstBlockInfo(nullptr), EHResumeBlock(nullptr),
|
||||
ExceptionSlot(nullptr), EHSelectorSlot(nullptr),
|
||||
DebugInfo(CGM.getModuleDebugInfo()), DisableDebugInfo(false),
|
||||
DidCallStackSave(false), IndirectBranch(nullptr), PGO(cgm),
|
||||
SwitchInsn(nullptr), SwitchWeights(nullptr), CaseRangeBlock(nullptr),
|
||||
UnreachableBlock(nullptr), NumReturnExprs(0), NumSimpleReturnExprs(0),
|
||||
CXXABIThisDecl(nullptr), CXXABIThisValue(nullptr), CXXThisValue(nullptr),
|
||||
CXXDefaultInitExprThis(nullptr), CXXStructorImplicitParamDecl(nullptr),
|
||||
CXXStructorImplicitParamValue(nullptr), OutermostConditional(nullptr),
|
||||
CurLexicalScope(nullptr), TerminateLandingPad(nullptr),
|
||||
|
|
|
@ -258,6 +258,10 @@ public:
|
|||
~SanitizerScope();
|
||||
};
|
||||
|
||||
/// In C++, whether we are code generating a thunk. This controls whether we
|
||||
/// should emit cleanups.
|
||||
bool CurFuncIsThunk;
|
||||
|
||||
/// In ARC, whether we should autorelease the return value.
|
||||
bool AutoreleaseResult;
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
// RUN: not %clang_cc1 %s -fno-rtti -triple=i686-pc-win32 -emit-llvm -o /dev/null 2>&1 | FileCheck --check-prefix=CHECK32
|
||||
// RUN: %clang_cc1 %s -fno-rtti -triple=x86_64-pc-win32 -emit-llvm -o - | FileCheck --check-prefix=CHECK64
|
||||
|
||||
namespace byval_thunk {
|
||||
struct Agg {
|
||||
Agg();
|
||||
Agg(const Agg &);
|
||||
~Agg();
|
||||
int x;
|
||||
};
|
||||
|
||||
struct A { virtual void foo(Agg x); };
|
||||
struct B { virtual void foo(Agg x); };
|
||||
struct C : A, B { virtual void foo(Agg x); };
|
||||
C c;
|
||||
|
||||
// CHECK32: cannot compile this non-trivial argument copy for thunk yet
|
||||
|
||||
// CHECK64-LABEL: define linkonce_odr void @"\01?foo@C@byval_thunk@@W7EAAXUAgg@2@@Z"
|
||||
// CHECK64: (%"struct.byval_thunk::C"* %this, %"struct.byval_thunk::Agg"* %x)
|
||||
// CHECK64: getelementptr i8* %{{.*}}, i32 -8
|
||||
// CHECK64: call void @"\01?foo@C@byval_thunk@@UEAAXUAgg@2@@Z"(%"struct.byval_thunk::C"* %2, %"struct.byval_thunk::Agg"* %x)
|
||||
// CHECK64-NOT: call
|
||||
// CHECK64: ret void
|
||||
}
|
Loading…
Reference in New Issue