Skip to content

Commit b25d443

Browse files
Merge pull request swiftlang#6403 from adrian-prantl/29481673
Represent Swift errors as DW_TAG_thrown_type in DWARF
2 parents 888894c + d50448a commit b25d443

File tree

3 files changed

+77
-30
lines changed

3 files changed

+77
-30
lines changed

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,7 @@ IRGenDebugInfo::emitFunction(const SILDebugScope *DS, llvm::Function *Fn,
697697
llvm::DITemplateParameterArray TemplateParameters = nullptr;
698698
llvm::DISubprogram *Decl = nullptr;
699699

700-
// Various flags
700+
// Various flags.
701701
bool IsLocalToUnit = Fn ? Fn->hasInternalLinkage() : true;
702702
bool IsDefinition = true;
703703
bool IsOptimized = Opts.Optimize;
@@ -722,9 +722,20 @@ IRGenDebugInfo::emitFunction(const SILDebugScope *DS, llvm::Function *Fn,
722722
== SILFunctionType::Representation::Block)
723723
Flags |= llvm::DINode::FlagAppleBlock;
724724

725+
// Get the throws information.
726+
llvm::DITypeArray Error = nullptr;
727+
if (FnTy)
728+
if (auto ErrorInfo = FnTy->getOptionalErrorResult()) {
729+
auto DTI = DebugTypeInfo::getFromTypeInfo(
730+
nullptr, nullptr, ErrorInfo->getType(),
731+
IGM.getTypeInfo(IGM.silConv.getSILType(*ErrorInfo)));
732+
Error = DBuilder.getOrCreateArray({getOrCreateType(DTI)}).get();
733+
}
734+
735+
// Construct the DISubprogram.
725736
llvm::DISubprogram *SP = DBuilder.createFunction(
726737
Scope, Name, LinkageName, File, Line, DIFnTy, IsLocalToUnit, IsDefinition,
727-
ScopeLine, Flags, IsOptimized, TemplateParameters, Decl);
738+
ScopeLine, Flags, IsOptimized, TemplateParameters, Decl, Error);
728739

729740
if (Fn && !Fn->isDeclaration())
730741
Fn->setSubprogram(SP);

test/DebugInfo/ErrorVar.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s
2+
// REQUIRES: CPU=i386
3+
class Obj {}
4+
5+
enum MyError : Error {
6+
case Simple
7+
case WithObj(Obj)
8+
}
9+
10+
// i386 does not pass swifterror in a register. To support debugging of the
11+
// thrown error we create a shadow stack location holding the address of the
12+
// location that holds the pointer to the error instead.
13+
func simple(_ placeholder: Int64) throws -> () {
14+
// CHECK: define {{.*}}void @_T06Errors6simpleys5Int64VKF(i64, %swift.refcounted* swiftself, %swift.error**)
15+
// CHECK: call void @llvm.dbg.declare
16+
// CHECK: call void @llvm.dbg.declare({{.*}}, metadata ![[ERROR:[0-9]+]], metadata ![[DEREF:[0-9]+]])
17+
// CHECK: ![[ERROR]] = !DILocalVariable(name: "$error", arg: 2,
18+
// CHECK-SAME: type: ![[ERRTY:.*]], flags: DIFlagArtificial)
19+
// CHECK: ![[ERRTY]] = !DICompositeType({{.*}}identifier: "_T0s5Error_pD"
20+
// CHECK: ![[DEREF]] = !DIExpression(DW_OP_deref)
21+
throw MyError.Simple
22+
}
23+
24+
func obj() throws -> () {
25+
throw MyError.WithObj(Obj())
26+
}
27+
28+
public func foo() {
29+
do {
30+
try simple(1)
31+
try obj()
32+
}
33+
catch {}
34+
}

test/DebugInfo/Errors.swift

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,36 @@
11
// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s
2-
// REQUIRES: CPU=i386
3-
class Obj {}
2+
public enum E : Error { case Err }
43

5-
enum MyError : Error {
6-
case Simple
7-
case WithObj(Obj)
8-
}
4+
// Function throws.
5+
public func throwError() throws { throw E.Err }
6+
// CHECK: !DISubprogram(name: "throwError", {{.*}}thrownTypes: ![[THROWN:.*]])
7+
// CHECK: ![[THROWN]] = !{![[ERROR:[0-9]+]]}
8+
// CHECK: ![[ERROR]] = !DICompositeType(tag: DW_TAG_structure_type,
9+
// CHECK-SAME: name: "Error"
910

10-
// i386 does not pass swifterror in a register. To support debugging of the
11-
// thrown error we create a shadow stack location holding the address of the
12-
// location that holds the pointer to the error instead.
13-
func simple(_ placeholder: Int64) throws -> () {
14-
// CHECK: define {{.*}}void @_T06Errors6simpleys5Int64VKF(i64, %swift.refcounted* swiftself, %swift.error**)
15-
// CHECK: call void @llvm.dbg.declare
16-
// CHECK: call void @llvm.dbg.declare({{.*}}, metadata ![[ERROR:[0-9]+]], metadata ![[DEREF:[0-9]+]])
17-
// CHECK: ![[ERROR]] = !DILocalVariable(name: "$error", arg: 2,
18-
// CHECK-SAME: type: ![[ERRTY:.*]], flags: DIFlagArtificial)
19-
// CHECK: ![[ERRTY]] = !DICompositeType({{.*}}identifier: "_T0s5Error_pD"
20-
// CHECK: ![[DEREF]] = !DIExpression(DW_OP_deref)
21-
throw MyError.Simple
22-
}
2311

24-
func obj() throws -> () {
25-
throw MyError.WithObj(Obj())
26-
}
12+
// Function rethrows.
13+
public func rethrow(fn : (() throws -> ())) rethrows { try fn() }
14+
// CHECK: !DISubprogram(name: "rethrow", {{.*}}thrownTypes: ![[THROWN:.*]])
2715

28-
public func foo() {
29-
do {
30-
try simple(1)
31-
try obj()
32-
}
33-
catch {}
16+
public class C {
17+
// Initializer throws.
18+
init() throws { throw E.Err }
19+
// CHECK: !DISubprogram(name: "init", {{.*}}line: [[@LINE-1]],
20+
// CHECK-SAME: thrownTypes: ![[THROWN:.*]])
21+
22+
// Initializer rethrows.
23+
init(fn : (() throws -> ())) rethrows {
24+
// CHECK: !DISubprogram(name: "init", {{.*}}line: [[@LINE-1]],
25+
// CHECK-SAME: thrownTypes: ![[THROWN:.*]])
26+
try fn()
27+
}
3428
}
29+
30+
// Negative tests.
31+
// CHECK: !DISubprogram(name: "returnThrowing",
32+
// CHECK-NOT: thrownTypes:
33+
public func returnThrowing() -> (() throws -> ()) { return throwError }
34+
// CHECK: !DISubprogram(name: "takesThrowing",
35+
// CHECK-NOT: thrownTypes:
36+
public func takesThrowing(fn : (() throws -> ())) {}

0 commit comments

Comments
 (0)