Skip to content

Commit 2966dce

Browse files
committed
[IRGen] Allow configuring a panic function to call instead of trapping
Add a new frontend option (called `-trap-function <name>`, similar to Clang’s existing `-ftrap-function`) that specifies a function to call instead of trapping. When the option is used, the compiler will emit a call to the specified function every time it would have otherwise emitted a trap instruction. The function must have no parameters and it must never return. rdar://89125883
1 parent 0011b07 commit 2966dce

File tree

7 files changed

+107
-0
lines changed

7 files changed

+107
-0
lines changed

include/swift/AST/IRGenOptions.h

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

414414
JITDebugArtifact DumpJIT = JITDebugArtifact::None;
415415

416+
/// If not an empty string, trap intrinsics are lowered to calls to this
417+
/// function instead of to trap instructions.
418+
std::string TrapFuncName = "";
419+
416420
IRGenOptions()
417421
: DWARFVersion(2),
418422
OutputKind(IRGenOutputKind::LLVMAssemblyAfterOptimization),

include/swift/Option/FrontendOptions.td

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

590+
def trap_function
591+
: Separate<["-"], "trap-function">, MetaVarName<"<name>">,
592+
HelpText<"Lower traps to calls to this function instead of trap instructions">;
593+
590594
def disable_previous_implementation_calls_in_dynamic_replacements :
591595
Flag<["-"], "disable-previous-implementation-calls-in-dynamic-replacements">,
592596
Flags<[FrontendOption, NoInteractiveOption, HelpHidden]>,

lib/Frontend/CompilerInvocation.cpp

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

1926+
if (Args.hasArg(OPT_trap_function))
1927+
Opts.TrapFuncName = Args.getLastArgValue(OPT_trap_function).str();
1928+
19261929
Opts.FunctionSections = Args.hasArg(OPT_function_sections);
19271930

19281931
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.swift

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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 {{.*}} @"$s13trap_function14checkOverflow1yS2i_SitF"
10+
// TRAPFN: call void @llvm.trap() [[ATTR0:#[0-9]+]]
11+
12+
// TRAPFN_OPT-LABEL: define hidden swiftcc {{.*}} @"$s13trap_function14checkOverflow1yS2i_SitF"
13+
// TRAPFN_OPT: call void @llvm.trap() [[ATTR0:#[0-9]+]]
14+
15+
// NOTRAPFN-LABEL: define hidden swiftcc {{.*}} @"$s13trap_function14checkOverflow1yS2i_SitF"
16+
// NOTRAPFN: call void @llvm.trap(){{$}}
17+
func checkOverflow1(_ a: Int, _ b: Int) -> Int {
18+
a + b
19+
}
20+
21+
// TRAPFN-LABEL: define hidden swiftcc {{.*}} @"$s13trap_function14checkOverflow2yySiz_SitF"
22+
// TRAPFN: call void @llvm.trap() [[ATTR0:#[0-9]+]]
23+
24+
// TRAPFN_OPT-LABEL: define hidden swiftcc {{.*}} @"$s13trap_function14checkOverflow2yySiz_SitF"
25+
// TRAPFN_OPT: call void @llvm.trap() [[ATTR0:#[0-9]+]]
26+
27+
// NOTRAPFN-LABEL: define hidden swiftcc {{.*}} @"$s13trap_function14checkOverflow2yySiz_SitF"
28+
// NOTRAPFN: call void @llvm.trap(){{$}}
29+
func checkOverflow2(_ a: inout Int, _ b: Int) {
30+
a *= b
31+
}
32+
33+
// TRAPFN-LABEL: define hidden swiftcc void @"$s13trap_function17checkPreconditionyySiF"
34+
// TRAPFN: call swiftcc void @"$ss17_assertionFailure__4file4line5flagss5NeverOs12StaticStringV_SSAHSus6UInt32VtF"
35+
// TRAPFN-NOT: call void @llvm.trap()
36+
37+
// TRAPFN_OPT-LABEL: define hidden swiftcc void @"$s13trap_function17checkPreconditionyySiF"
38+
// TRAPFN_OPT: call void @llvm.trap() [[ATTR0]]
39+
40+
// NOTRAPFN-LABEL: define hidden swiftcc void @"$s13trap_function17checkPreconditionyySiF"
41+
// NOTRAPFN: call swiftcc void @"$ss17_assertionFailure__4file4line5flagss5NeverOs12StaticStringV_SSAHSus6UInt32VtF"
42+
func checkPrecondition(_ a: Int) {
43+
precondition(a != 23)
44+
}
45+
46+
// TRAPFN-LABEL: define hidden swiftcc void @"$s13trap_function24checkPreconditionFailureyySiF"
47+
// TRAPFN: call swiftcc void @"$ss17_assertionFailure__4file4line5flagss5NeverOs12StaticStringV_SSAHSus6UInt32VtF"
48+
// TRAPFN-NOT: call void @llvm.trap()
49+
50+
// TRAPFN_OPT-LABEL: define hidden swiftcc void @"$s13trap_function24checkPreconditionFailureyySiF"
51+
// TRAPFN_OPT: call void @llvm.trap() [[ATTR0]]
52+
53+
// NOTRAPFN-LABEL: define hidden swiftcc void @"$s13trap_function24checkPreconditionFailureyySiF"
54+
// NOTRAPFN: call swiftcc void @"$ss17_assertionFailure__4file4line5flagss5NeverOs12StaticStringV_SSAHSus6UInt32VtF"
55+
func checkPreconditionFailure(_ a: Int) {
56+
if a == 42 {
57+
preconditionFailure()
58+
}
59+
}
60+
61+
// TRAPFN-LABEL: define hidden swiftcc void @"$s13trap_function18checkClangImporteryyF"
62+
// TRAPFN: call {{.*}} @ackbar()
63+
64+
// TRAPFN_OPT-LABEL: define hidden swiftcc void @"$s13trap_function18checkClangImporteryyF"
65+
// TRAPFN_OPT: call {{.*}} @ackbar()
66+
67+
// NOTRAPFN-LABEL: define hidden swiftcc void @"$s13trap_function18checkClangImporteryyF"
68+
// NOTRAPFN: call {{.*}} @ackbar()
69+
func checkClangImporter() {
70+
ackbar()
71+
}
72+
73+
// TRAPFN-LABEL: define internal {{.*}} @ackbar()
74+
// TRAPFN: call void @llvm.trap() [[ATTR0]]
75+
76+
// TRAPFN_OPT-LABEL: define internal {{.*}} @ackbar()
77+
// TRAPFN_OPT: call void @llvm.trap() [[ATTR0]]
78+
79+
// NOTRAPFN-LABEL: define internal {{.*}} @ackbar()
80+
// NOTRAPFN: call void @llvm.trap(){{$}}
81+
82+
83+
// TRAPFN: attributes [[ATTR0]] = { {{.*}}"trap-func-name"="oopsie" }
84+
// NOTRAPFN-NOT: attributes {{.*}} = { {{.*}}"trap-func-name"="oopsie" }

0 commit comments

Comments
 (0)