Skip to content

Commit 2aba85f

Browse files
authored
Merge pull request swiftlang#71056 from al45tair/eng/PR-120952971
[Runtime][IRGen] Trap C++ exceptions on *throw*, not catch.
2 parents a679bbc + 76f2389 commit 2aba85f

File tree

10 files changed

+155
-7
lines changed

10 files changed

+155
-7
lines changed

include/swift/AST/FeatureAvailability.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ FEATURE(SignedDescriptor, (5, 9))
5959
FEATURE(ObjCSymbolicReferences, (5, 11))
6060
FEATURE(TypedThrows, (5, 11))
6161
FEATURE(StaticReadOnlyArrays, (5, 11))
62+
FEATURE(SwiftExceptionPersonality, (5, 11))
6263

6364
FEATURE(TaskExecutor, FUTURE)
6465
FEATURE(Differentiation, FUTURE)

include/swift/Runtime/Exception.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//===--- Exception.h - Exception support ------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// Swift doesn't support exception handlers, but might call code that uses
14+
// exceptions, and when they leak out into Swift code, we want to trap them.
15+
//
16+
// To that end, we have our own exception personality routine, which we use
17+
// to trap exceptions and terminate.
18+
//
19+
//===----------------------------------------------------------------------===//
20+
21+
#ifndef SWIFT_RUNTIME_EXCEPTION_H
22+
#define SWIFT_RUNTIME_EXCEPTION_H
23+
24+
#include "swift/Runtime/Config.h"
25+
26+
#if defined(__ELF__) || defined(__APPLE__)
27+
#include <unwind.h>
28+
29+
namespace swift {
30+
31+
SWIFT_RUNTIME_STDLIB_API _Unwind_Reason_Code
32+
swift_exceptionPersonality(int version,
33+
_Unwind_Action actions,
34+
uint64_t exceptionClass,
35+
struct _Unwind_Exception *exceptionObject,
36+
struct _Unwind_Context *context);
37+
38+
} // end namespace swift
39+
40+
#endif // defined(__ELF__) || defined(__APPLE__)
41+
42+
#endif // SWIFT_RUNTIME_EXCEPTION_H

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2807,6 +2807,24 @@ FUNCTION(InitRawStructMetadata,
28072807
EFFECT(MetaData),
28082808
UNKNOWN_MEMEFFECTS)
28092809

2810+
// _Unwind_Reason_Code _swift_exceptionPersonality(int version,
2811+
// _Unwind_Action actions,
2812+
// uint64 exceptionClass,
2813+
// struct _Unwind_Exception *exceptionObject,
2814+
// struct _Unwind_Context *context);
2815+
FUNCTION(ExceptionPersonality,
2816+
_swift_exceptionPersonality,
2817+
C_CC, AlwaysAvailable,
2818+
RETURNS(Int32Ty),
2819+
ARGS(Int32Ty,
2820+
Int32Ty,
2821+
Int64Ty,
2822+
Int8PtrTy,
2823+
Int8PtrTy),
2824+
ATTRS(NoUnwind),
2825+
EFFECT(NoEffect),
2826+
UNKNOWN_MEMEFFECTS)
2827+
28102828
#undef RETURNS
28112829
#undef ARGS
28122830
#undef ATTRS

lib/IRGen/GenCall.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4994,7 +4994,20 @@ void IRGenFunction::emitEpilogue() {
49944994
// The function should have an unwind table when catching exceptions.
49954995
CurFn->addFnAttr(llvm::Attribute::getWithUWTableKind(
49964996
*IGM.LLVMContext, llvm::UWTableKind::Default));
4997-
CurFn->setPersonalityFn(IGM.getForeignExceptionHandlingPersonalityFunc());
4997+
4998+
auto deploymentAvailability =
4999+
AvailabilityContext::forDeploymentTarget(IGM.Context);
5000+
llvm::Constant *personality;
5001+
5002+
if (IGM.isSwiftExceptionPersonalityFeatureAvailable()) {
5003+
// The function should use our personality routine
5004+
auto swiftPersonality = IGM.getExceptionPersonalityFunctionPointer();
5005+
personality = swiftPersonality.getDirectPointer();
5006+
} else {
5007+
personality = IGM.getForeignExceptionHandlingPersonalityFunc();
5008+
}
5009+
5010+
CurFn->setPersonalityFn(personality);
49985011
}
49995012
for (auto *bb : ExceptionUnwindBlocks)
50005013
CurFn->insert(CurFn->end(), bb);

stdlib/public/runtime/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ set(swift_runtime_sources
4747
ErrorObjectNative.cpp
4848
Errors.cpp
4949
ErrorDefaultImpls.cpp
50+
Exception.cpp
5051
Exclusivity.cpp
5152
ExistentialContainer.cpp
5253
Float16Support.cpp

stdlib/public/runtime/Exception.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
//===--- Exception.cpp - Exception support --------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// Swift doesn't support exception handlers, but might call code that uses
14+
// exceptions, and when they leak out into Swift code, we want to trap them.
15+
//
16+
// To that end, we have our own exception personality routine, which we use
17+
// to trap exceptions and terminate.
18+
//
19+
//===----------------------------------------------------------------------===//
20+
21+
#if defined(__ELF__) || defined(__APPLE__)
22+
23+
#include <exception>
24+
25+
#include <cstdio>
26+
27+
#include <unwind.h>
28+
29+
#include "swift/Runtime/Exception.h"
30+
31+
using namespace swift;
32+
33+
extern "C" void __cxa_begin_catch(void *);
34+
35+
SWIFT_RUNTIME_STDLIB_API _Unwind_Reason_Code
36+
_swift_exceptionPersonality(int version,
37+
_Unwind_Action actions,
38+
uint64_t exceptionClass,
39+
struct _Unwind_Exception *exceptionObject,
40+
struct _Unwind_Context *context)
41+
{
42+
// Handle exceptions by catching them and calling std::terminate().
43+
// This, in turn, will trigger the unhandled exception routine in the
44+
// C++ runtime.
45+
__cxa_begin_catch(exceptionObject);
46+
std::terminate();
47+
48+
return _URC_FATAL_PHASE1_ERROR;
49+
}
50+
51+
#endif /* defined(__ELF__) || defined(__APPLE__) */

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

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
// RUN: %empty-directory(%t)
22
// RUN: split-file %s %t
33

4-
// RUN: %target-swift-emit-ir %t/test.swift -I %t/Inputs -enable-experimental-cxx-interop | %FileCheck %s
4+
// RUN: %target-swift-emit-ir -target %target-future-triple -min-runtime-version 5.11 %t/test.swift -I %t/Inputs -enable-experimental-cxx-interop | %FileCheck %s
5+
// RUN: %target-swift-emit-ir -target %target-triple -min-runtime-version 5.9 %t/test.swift -I %t/Inputs -enable-experimental-cxx-interop | %FileCheck %s --check-prefix=GXX
56

67
// REQUIRES: objc_interop
78
// UNSUPPORTED: OS=windows-msvc
@@ -32,7 +33,7 @@ func testObjCMethodCall() {
3233

3334
testObjCMethodCall()
3435

35-
// CHECK: define {{.*}} @"$s4test0A14ObjCMethodCallyyF"() #[[#UWATTR:]] personality
36+
// CHECK: define {{.*}} @"$s4test0A14ObjCMethodCallyyF"() #[[#UWATTR:]] personality ptr @_swift_exceptionPersonality
3637
// CHECK: invoke void {{.*}}@objc_msgSend
3738
// CHECK-NEXT: to label %[[CONT1:.*]] unwind label %[[UNWIND1:.*]]
3839
// CHECK-EMPTY:
@@ -45,3 +46,17 @@ testObjCMethodCall()
4546
// CHECK-NEXT: call void @llvm.trap()
4647
// CHECK-NEXT: unreachable
4748
// CHECK-NEXT: }
49+
50+
// GXX: define {{.*}} @"$s4test0A14ObjCMethodCallyyF"() #[[#UWATTR:]] personality ptr @__gxx_personality_v0
51+
// GXX: invoke void {{.*}}@objc_msgSend
52+
// GXX-NEXT: to label %[[CONT1:.*]] unwind label %[[UNWIND1:.*]]
53+
// GXX-EMPTY:
54+
// GXX-NEXT: [[CONT1]]:
55+
// GXX: ret
56+
// GXX-EMPTY:
57+
// GXX-NEXT: [[UNWIND1]]:
58+
// GXX-NEXT: landingpad { ptr, i32 }
59+
// GXX-NEXT: catch ptr null
60+
// GXX-NEXT: call void @llvm.trap()
61+
// GXX-NEXT: unreachable
62+
// GXX-NEXT: }

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
// RUN: %empty-directory(%t)
22
// RUN: split-file %s %t
33

4-
// RUN: %target-swift-emit-ir %t/test.swift -I %t/Inputs -enable-experimental-cxx-interop | %FileCheck %s
5-
// RUN: %target-swift-emit-ir %t/test.swift -I %t/Inputs -enable-experimental-cxx-interop -g | %FileCheck --check-prefix=DEBUG %s
4+
// RUN: %target-swift-emit-ir -target %target-future-triple -min-runtime-version 5.11 %t/test.swift -I %t/Inputs -enable-experimental-cxx-interop | %FileCheck %s
5+
// RUN: %target-swift-emit-ir -target %target-future-triple -min-runtime-version 5.11 %t/test.swift -I %t/Inputs -enable-experimental-cxx-interop -g | %FileCheck --check-prefix=DEBUG %s
6+
// RUN: %target-swift-emit-ir -target %target-triple -min-runtime-version 5.9 %t/test.swift -I %t/Inputs -enable-experimental-cxx-interop | %FileCheck --check-prefix=GXX %s
7+
// RUN: %target-swift-emit-ir -target %target-triple -min-runtime-version 5.9 %t/test.swift -I %t/Inputs -enable-experimental-cxx-interop -g | %FileCheck --check-prefix=GXX %s
68

79
// UNSUPPORTED: OS=windows-msvc
810

@@ -309,7 +311,7 @@ public func test() {
309311
// CHECK-NEXT: ret i32
310312
// CHECK-NEXT: }
311313

312-
// CHECK: define {{.*}} @"$s4test0A17FreeFunctionCallss5Int32VyF"() #[[#SWIFTUWMETA:]] personality ptr @__gxx_personality_v0
314+
// CHECK: define {{.*}} @"$s4test0A17FreeFunctionCallss5Int32VyF"() #[[#SWIFTUWMETA:]] personality ptr @_swift_exceptionPersonality
313315
// CHECK: invoke i32 @_Z18freeFunctionThrowsi(i32 0)
314316
// CHECK-NEXT: to label %[[CONT1:.*]] unwind label %[[UNWIND1:.*]]
315317
// CHECK-EMPTY:
@@ -335,7 +337,7 @@ public func test() {
335337
// CHECK-NEXT: unreachable
336338
// CHECK-NEXT: }
337339

338-
// CHECK: i32 @__gxx_personality_v0(...)
340+
// CHECK: i32 @_swift_exceptionPersonality(i32, i32, i64, ptr, ptr)
339341

340342
// CHECK: define {{.*}} @"$s4test0A11MethodCallss5Int32VyF"() #[[#SWIFTUWMETA]] personality
341343
// CHECK: call swiftcc i32 @"$s4test8makeCInts5Int32VyF"()
@@ -502,3 +504,6 @@ public func test() {
502504
// DEBUG: ![[#DEBUGLOC_TRAP1]] = !DILocation(line: 0, scope: ![[#TRAPSCOPE:]], inlinedAt: ![[#DEBUGLOC_FREEFUNCTIONTHROWS1]])
503505
// DEBUG: ![[#TRAPSCOPE]] = distinct !DISubprogram(name: "Swift runtime failure: unhandled C++{{ / Objective-C | }}exception"
504506
// DEBUG: ![[#DEBUGLOC_TRAP2]] = !DILocation(line: 0, scope: ![[#TRAPSCOPE]], inlinedAt: ![[#DEBUGLOC_FREEFUNCTIONTHROWS2]])
507+
508+
// GXX: __gxx_personality_v0
509+
// GXX-NOT: _swift_exceptionPersonality

test/abi/macOS/arm64/stdlib.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,4 +254,5 @@ Added: __swift_pod_destroy
254254
Added: __swift_pod_direct_initializeBufferWithCopyOfBuffer
255255
Added: __swift_pod_indirect_initializeBufferWithCopyOfBuffer
256256
Added: __swift_validatePrespecializedMetadata
257+
Added: __swift_exceptionPersonality
257258
Added: _swift_willThrowTypedImpl

test/abi/macOS/x86_64/stdlib.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,4 +254,5 @@ Added: __swift_pod_destroy
254254
Added: __swift_pod_direct_initializeBufferWithCopyOfBuffer
255255
Added: __swift_pod_indirect_initializeBufferWithCopyOfBuffer
256256
Added: __swift_validatePrespecializedMetadata
257+
Added: __swift_exceptionPersonality
257258
Added: _swift_willThrowTypedImpl

0 commit comments

Comments
 (0)