Skip to content

Commit e24bb55

Browse files
authored
Merge pull request #41449 from lorentey/custom-traps
[IRGen] Allow configuring a panic function to call instead of trapping
2 parents 1e45072 + e690d22 commit e24bb55

File tree

8 files changed

+113
-0
lines changed

8 files changed

+113
-0
lines changed

include/swift/AST/IRGenOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,10 @@ class IRGenOptions {
416416

417417
JITDebugArtifact DumpJIT = JITDebugArtifact::None;
418418

419+
/// If not an empty string, trap intrinsics are lowered to calls to this
420+
/// function instead of to trap instructions.
421+
std::string TrapFuncName = "";
422+
419423
IRGenOptions()
420424
: DWARFVersion(2),
421425
OutputKind(IRGenOutputKind::LLVMAssemblyAfterOptimization),

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,10 @@ def disable_preallocated_instantiation_caches : Flag<["-"], "disable-preallocate
594594
Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>,
595595
HelpText<"Avoid preallocating metadata instantiation caches in globals">;
596596

597+
def trap_function
598+
: Separate<["-"], "trap-function">, MetaVarName<"<name>">,
599+
HelpText<"Lower traps to calls to this function instead of trap instructions">;
600+
597601
def disable_previous_implementation_calls_in_dynamic_replacements :
598602
Flag<["-"], "disable-previous-implementation-calls-in-dynamic-replacements">,
599603
Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>,

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,6 +1929,9 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
19291929
Opts.StackPromotionSizeLimit = limit;
19301930
}
19311931

1932+
if (Args.hasArg(OPT_trap_function))
1933+
Opts.TrapFuncName = Args.getLastArgValue(OPT_trap_function).str();
1934+
19321935
Opts.FunctionSections = Args.hasArg(OPT_function_sections);
19331936

19341937
if (Args.hasArg(OPT_autolink_force_load))

lib/IRGen/IRGenFunction.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,13 @@ llvm::CallInst *IRBuilder::CreateNonMergeableTrap(IRGenModule &IGM,
496496
}
497497
auto Call = IRBuilderBase::CreateCall(trapIntrinsic, {});
498498
setCallingConvUsingCallee(Call);
499+
500+
if (!IGM.IRGen.Opts.TrapFuncName.empty()) {
501+
auto A = llvm::Attribute::get(getContext(), "trap-func-name",
502+
IGM.IRGen.Opts.TrapFuncName);
503+
Call->addFnAttr(A);
504+
}
505+
499506
return Call;
500507
}
501508

lib/IRGen/IRGenModule.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ static clang::CodeGenerator *createClangCodeGenerator(ASTContext &Context,
132132
CGO.DwarfDebugFlags = Opts.getDebugFlags(PD);
133133
break;
134134
}
135+
if (!Opts.TrapFuncName.empty()) {
136+
CGO.TrapFuncName = Opts.TrapFuncName;
137+
}
135138

136139
auto &HSI = Importer->getClangPreprocessor()
137140
.getHeaderSearchInfo()

test/IRGen/Inputs/usr/include/Gizmo.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ static inline int zeroRedeclared(void) { return innerZero(); }
7070

7171
static int staticButNotInline(void) { return innerZero(); }
7272

73+
static inline void ackbar(void) { __builtin_trap(); }
74+
7375
@interface NSView : NSObject
7476
- (struct NSRect) convertRectFromBase: (struct NSRect) r;
7577
@end

test/IRGen/trap-function-clang.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %build-irgen-test-overlays
3+
// RUN: %target-swift-frontend -sdk %S/Inputs -primary-file %s -trap-function oopsie -enable-objc-interop -emit-ir -module-name trap_function -I %t | %FileCheck %s -check-prefix=TRAPFN
4+
// RUN: %target-swift-frontend -O -sdk %S/Inputs -primary-file %s -trap-function oopsie -enable-objc-interop -emit-ir -module-name trap_function -I %t | %FileCheck %s -check-prefix=TRAPFN_OPT
5+
// RUN: %target-swift-frontend -sdk %S/Inputs -primary-file %s -enable-objc-interop -emit-ir -module-name trap_function -I %t | %FileCheck %s -check-prefix=NOTRAPFN
6+
7+
import gizmo
8+
9+
// TRAPFN-LABEL: define hidden swiftcc void @"$s13trap_function18checkClangImporteryyF"
10+
// TRAPFN: call void @llvm.trap() [[ATTR0:#[0-9]+]]
11+
12+
// TRAPFN_OPT-LABEL: define hidden swiftcc void @"$s13trap_function18checkClangImporteryyF"
13+
// TRAPFN_OPT: call void @llvm.trap() [[ATTR0:#[0-9]+]]
14+
15+
// NOTRAPFN-LABEL: define hidden swiftcc void @"$s13trap_function18checkClangImporteryyF"
16+
// NOTRAPFN: call void @llvm.trap(){{$}}
17+
func checkClangImporter() {
18+
ackbar()
19+
}
20+
21+
// TRAPFN: attributes [[ATTR0]] = { {{.*}}"trap-func-name"="oopsie" }
22+
// TRAPFN_OPT: attributes [[ATTR0]] = { {{.*}}"trap-func-name"="oopsie" }
23+
// NOTRAPFN-NOT: attributes {{.*}} = { {{.*}}"trap-func-name"="oopsie" }

test/IRGen/trap-function.swift

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %build-irgen-test-overlays
3+
// RUN: %target-swift-frontend -primary-file %s -trap-function oopsie -emit-ir -module-name trap_function -I %t | %FileCheck %s -check-prefix=TRAPFN
4+
// RUN: %target-swift-frontend -O -primary-file %s -trap-function oopsie -emit-ir -module-name trap_function -I %t | %FileCheck %s -check-prefix=TRAPFN_OPT
5+
// RUN: %target-swift-frontend -primary-file %s -emit-ir -module-name trap_function -I %t | %FileCheck %s -check-prefix=NOTRAPFN
6+
7+
// TRAPFN-LABEL: define hidden swiftcc {{.*}} @"$s13trap_function14checkOverflow1yS2i_SitF"
8+
// TRAPFN: call void @llvm.trap() [[ATTR0:#[0-9]+]]
9+
10+
// TRAPFN_OPT-LABEL: define hidden swiftcc {{.*}} @"$s13trap_function14checkOverflow1yS2i_SitF"
11+
// TRAPFN_OPT: call void @llvm.trap() [[ATTR0:#[0-9]+]]
12+
13+
// NOTRAPFN-LABEL: define hidden swiftcc {{.*}} @"$s13trap_function14checkOverflow1yS2i_SitF"
14+
// NOTRAPFN: call void @llvm.trap(){{$}}
15+
func checkOverflow1(_ a: Int, _ b: Int) -> Int {
16+
a + b
17+
}
18+
19+
// TRAPFN-LABEL: define hidden swiftcc {{.*}} @"$s13trap_function14checkOverflow2yySiz_SitF"
20+
// TRAPFN: call void @llvm.trap() [[ATTR0:#[0-9]+]]
21+
22+
// TRAPFN_OPT-LABEL: define hidden swiftcc {{.*}} @"$s13trap_function14checkOverflow2yySiz_SitF"
23+
// TRAPFN_OPT: call void @llvm.trap() [[ATTR0:#[0-9]+]]
24+
25+
// NOTRAPFN-LABEL: define hidden swiftcc {{.*}} @"$s13trap_function14checkOverflow2yySiz_SitF"
26+
// NOTRAPFN: call void @llvm.trap(){{$}}
27+
func checkOverflow2(_ a: inout Int, _ b: Int) {
28+
a *= b
29+
}
30+
31+
// TRAPFN-LABEL: define hidden swiftcc void @"$s13trap_function17checkPreconditionyySiF"
32+
// TRAPFN: call swiftcc void @"$ss17_assertionFailure__4file4line5flagss5NeverOs12StaticStringV_SSAHSus6UInt32VtF"
33+
// TRAPFN-NOT: call void @llvm.trap()
34+
35+
// TRAPFN_OPT-LABEL: define hidden swiftcc void @"$s13trap_function17checkPreconditionyySiF"
36+
// TRAPFN_OPT: call void @llvm.trap() [[ATTR0]]
37+
38+
// NOTRAPFN-LABEL: define hidden swiftcc void @"$s13trap_function17checkPreconditionyySiF"
39+
// NOTRAPFN: call swiftcc void @"$ss17_assertionFailure__4file4line5flagss5NeverOs12StaticStringV_SSAHSus6UInt32VtF"
40+
func checkPrecondition(_ a: Int) {
41+
precondition(a != 23)
42+
}
43+
44+
// TRAPFN-LABEL: define hidden swiftcc void @"$s13trap_function24checkPreconditionFailureyySiF"
45+
// TRAPFN: call swiftcc void @"$ss17_assertionFailure__4file4line5flagss5NeverOs12StaticStringV_SSAHSus6UInt32VtF"
46+
// TRAPFN-NOT: call void @llvm.trap()
47+
48+
// TRAPFN_OPT-LABEL: define hidden swiftcc void @"$s13trap_function24checkPreconditionFailureyySiF"
49+
// TRAPFN_OPT: call void @llvm.trap() [[ATTR0]]
50+
51+
// NOTRAPFN-LABEL: define hidden swiftcc void @"$s13trap_function24checkPreconditionFailureyySiF"
52+
// NOTRAPFN: call swiftcc void @"$ss17_assertionFailure__4file4line5flagss5NeverOs12StaticStringV_SSAHSus6UInt32VtF"
53+
func checkPreconditionFailure(_ a: Int) {
54+
if a == 42 {
55+
preconditionFailure()
56+
}
57+
}
58+
59+
// TRAPFN-LABEL: define hidden swiftcc void @"$s13trap_function10terminatoryyF"
60+
// TRAPFN_OPT-LABEL: define hidden swiftcc void @"$s13trap_function10terminatoryyF"
61+
// NOTRAPFN-LABEL: define hidden swiftcc void @"$s13trap_function10terminatoryyF"
62+
func terminator() {
63+
}
64+
65+
// TRAPFN: attributes [[ATTR0]] = { {{.*}}"trap-func-name"="oopsie" }
66+
// TRAPFN_OPT: attributes [[ATTR0]] = { {{.*}}"trap-func-name"="oopsie" }
67+
// NOTRAPFN-NOT: attributes {{.*}} = { {{.*}}"trap-func-name"="oopsie" }

0 commit comments

Comments
 (0)