Skip to content

Commit ee60173

Browse files
committed
[interop] ensure we correctly handle copy constructor invokes
1 parent 9feb764 commit ee60173

File tree

4 files changed

+47
-22
lines changed

4 files changed

+47
-22
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3252,26 +3252,35 @@ llvm::Constant *swift::irgen::emitCXXConstructorThunkIfNeeded(
32523252
Args.push_back(arg);
32533253
}
32543254

3255-
bool canThrow = IGM.isForeignExceptionHandlingEnabled();
3256-
if (auto *fpt = ctor->getType()->getAs<clang::FunctionProtoType>()) {
3257-
if (fpt->isNothrow())
3258-
canThrow = false;
3259-
}
3260-
if (canThrow) {
3255+
auto *call =
3256+
emitCXXConstructorCall(subIGF, ctor, ctorFnType, ctorAddress, Args);
3257+
if (isa<llvm::InvokeInst>(call))
32613258
IGM.emittedForeignFunctionThunksWithExceptionTraps.insert(thunk);
3262-
subIGF.createExceptionTrapScope([&](llvm::BasicBlock *invokeNormalDest,
3263-
llvm::BasicBlock *invokeUnwindDest) {
3264-
subIGF.Builder.createInvoke(ctorFnType, ctorAddress, Args,
3265-
invokeNormalDest, invokeUnwindDest);
3266-
});
3267-
} else
3268-
subIGF.Builder.CreateCall(ctorFnType, ctorAddress, Args);
3269-
32703259
subIGF.Builder.CreateRetVoid();
32713260

32723261
return thunk;
32733262
}
32743263

3264+
llvm::CallBase *swift::irgen::emitCXXConstructorCall(
3265+
IRGenFunction &IGF, const clang::CXXConstructorDecl *ctor,
3266+
llvm::FunctionType *ctorFnType, llvm::Constant *ctorAddress,
3267+
llvm::ArrayRef<llvm::Value *> args) {
3268+
bool canThrow = IGF.IGM.isForeignExceptionHandlingEnabled();
3269+
if (auto *fpt = ctor->getType()->getAs<clang::FunctionProtoType>()) {
3270+
if (fpt->isNothrow())
3271+
canThrow = false;
3272+
}
3273+
if (!canThrow)
3274+
return IGF.Builder.CreateCall(ctorFnType, ctorAddress, args);
3275+
llvm::CallBase *result;
3276+
IGF.createExceptionTrapScope([&](llvm::BasicBlock *invokeNormalDest,
3277+
llvm::BasicBlock *invokeUnwindDest) {
3278+
result = IGF.Builder.createInvoke(ctorFnType, ctorAddress, args,
3279+
invokeNormalDest, invokeUnwindDest);
3280+
});
3281+
return result;
3282+
}
3283+
32753284
StackProtectorMode IRGenModule::shouldEmitStackProtector(SILFunction *f) {
32763285
const SILOptions &opts = IRGen.SIL.getOptions();
32773286
return (opts.EnableStackProtection && f->needsStackProtection()) ?

lib/IRGen/GenDecl.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ namespace llvm {
2929
class AttributeList;
3030
class Function;
3131
class FunctionType;
32+
class CallBase;
3233
}
3334
namespace swift {
3435
namespace irgen {
@@ -69,6 +70,12 @@ namespace irgen {
6970
emitCXXConstructorThunkIfNeeded(IRGenModule &IGM, Signature signature,
7071
const clang::CXXConstructorDecl *ctor,
7172
StringRef name, llvm::Constant *ctorAddress);
73+
74+
llvm::CallBase *emitCXXConstructorCall(IRGenFunction &IGF,
75+
const clang::CXXConstructorDecl *ctor,
76+
llvm::FunctionType *ctorFnType,
77+
llvm::Constant *ctorAddress,
78+
llvm::ArrayRef<llvm::Value *> args);
7279
}
7380
}
7481

lib/IRGen/GenStruct.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,7 @@ namespace {
567567
auto callee = cast<llvm::Function>(clangFnAddr->stripPointerCasts());
568568
Signature signature = IGF.IGM.getSignature(fnType);
569569
std::string name = "__swift_cxx_copy_ctor" + callee->getName().str();
570+
auto *origClangFnAddr = clangFnAddr;
570571
clangFnAddr = emitCXXConstructorThunkIfNeeded(
571572
IGF.IGM, signature, copyConstructor, name, clangFnAddr);
572573
callee = cast<llvm::Function>(clangFnAddr);
@@ -576,7 +577,19 @@ namespace {
576577
src = IGF.coerceValue(src, callee->getFunctionType()->getParamType(1),
577578
IGF.IGM.DataLayout);
578579
}
579-
IGF.Builder.CreateCall(callee->getFunctionType(), callee, {dest, src});
580+
llvm::Value *args[] = {dest, src};
581+
if (clangFnAddr == origClangFnAddr) {
582+
// Ensure we can use 'invoke' to trap on uncaught exceptions when
583+
// calling original copy constructor without going through the thunk.
584+
emitCXXConstructorCall(IGF, copyConstructor, callee->getFunctionType(),
585+
callee, args);
586+
return;
587+
}
588+
// Check if we're calling a thunk that traps on exception thrown from copy
589+
// constructor.
590+
if (IGF.IGM.emittedForeignFunctionThunksWithExceptionTraps.count(callee))
591+
IGF.setCallsThunksWithForeignExceptionTraps();
592+
IGF.Builder.CreateCall(callee->getFunctionType(), callee, args);
580593
}
581594

582595
public:

test/Interop/Cxx/exceptions/trap-on-exception-irgen-itanium.swift

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -369,19 +369,15 @@ let _ = testClassWithNoThrowingConstructor()
369369
// CHECK-NOT: invoke
370370
// CHECK: }
371371

372-
// CHECK: define {{.*}} @"$s4test0A32ClassWithThrowingCopyConstructors5Int32VyF"() #[[#SWIFTMETA]] personality
372+
// CHECK: define {{.*}} @"$s4test0A32ClassWithThrowingCopyConstructors5Int32VyF"() #[[#SWIFTUWMETA]] personality
373373
// CHECK: invoke {{.*}} @_ZN32ClassWithThrowingCopyConstructorC1ERKS_(
374374
// CHECK-NEXT: to label %[[CONT41:.*]] unwind label %[[UNWIND41:.*]]
375-
// CHECK-EMPTY:
376-
// CHECK-NEXT: [[UNWIND41]]:
375+
376+
// CHECK: [[UNWIND41]]:
377377
// CHECK-NEXT: landingpad { i8*, i32 }
378378
// CHECK-NEXT: catch i8* null
379379
// CHECK-NEXT: call void @llvm.trap()
380380
// CHECK-NEXT: unreachable
381-
// CHECK-EMPTY:
382-
// CHECK: [[CONT41]]:
383-
// CHECK: ret i32
384-
// CHECK-NEXT: }
385381

386382
// CHECK: define {{.*}} @"$s4test0A28ClassWithThrowingConstructors5Int32VyF"() #[[#SWIFTUWMETA]] personality
387383
// CHECK: invoke {{.*}} @_ZN28ClassWithThrowingConstructorC{{.*}}(

0 commit comments

Comments
 (0)