Skip to content

Commit 89f22f0

Browse files
committed
SwiftCompilerSources: add the ability to implement SIL verification in swift
1 parent f445f4f commit 89f22f0

File tree

9 files changed

+124
-1
lines changed

9 files changed

+124
-1
lines changed

SwiftCompilerSources/Sources/Optimizer/PassManager/PassRegistration.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import OptimizerBridging
1717
public func initializeSwiftModules() {
1818
registerSILClasses()
1919
registerSwiftAnalyses()
20+
registerUtilities()
2021
registerSwiftPasses()
2122
registerOptimizerTests()
2223
}
@@ -119,3 +120,7 @@ private func registerSwiftAnalyses() {
119120
AliasAnalysis.register()
120121
CalleeAnalysis.register()
121122
}
123+
124+
private func registerUtilities() {
125+
registerVerifier()
126+
}

SwiftCompilerSources/Sources/Optimizer/Utilities/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@ swift_compiler_sources(Optimizer
2020
SSAUpdater.swift
2121
StaticInitCloner.swift
2222
Test.swift
23+
Verifier.swift
2324
)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//===--- Verifier.swift ---------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2024 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+
import SIL
14+
import OptimizerBridging
15+
16+
private protocol VerifyableInstruction : Instruction {
17+
func verify(_ context: FunctionPassContext)
18+
}
19+
20+
extension Function {
21+
func verify(_ context: FunctionPassContext) {
22+
for block in blocks {
23+
for inst in block.instructions {
24+
if let verifyableInst = inst as? VerifyableInstruction {
25+
verifyableInst.verify(context)
26+
}
27+
}
28+
}
29+
}
30+
}
31+
32+
func registerVerifier() {
33+
BridgedUtilities.registerVerifier(
34+
{ (bridgedCtxt: BridgedPassContext, bridgedFunction: BridgedFunction) in
35+
let context = FunctionPassContext(_bridged: bridgedCtxt)
36+
bridgedFunction.function.verify(context)
37+
}
38+
)
39+
}

include/swift/SILOptimizer/OptimizerBridging.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,12 @@ struct BridgedPostDomTree {
128128
BRIDGED_INLINE bool postDominates(BridgedBasicBlock dominating, BridgedBasicBlock dominated) const;
129129
};
130130

131+
struct BridgedUtilities {
132+
typedef void (* _Nonnull VerifyFunctionFn)(BridgedPassContext, BridgedFunction);
133+
134+
static void registerVerifier(VerifyFunctionFn verifyFunctionFn);
135+
};
136+
131137
struct BridgedBasicBlockSet {
132138
swift::BasicBlockSet * _Nonnull set;
133139

include/swift/SILOptimizer/PassManager/PassManager.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ class SwiftPassInvocation {
151151

152152
void endTransformFunction();
153153

154+
void beginVerifyFunction(SILFunction *function);
155+
void endVerifyFunction();
156+
154157
void notifyNewCloner() { numClonersAllocated++; }
155158
void notifyClonerDestroyed() { numClonersAllocated--; }
156159

@@ -417,6 +420,12 @@ class SILPassManager {
417420
static bool isInstructionPassDisabled(StringRef instName);
418421
static bool disablePassesForFunction(SILFunction *function);
419422

423+
/// Runs the SIL verifier which is implemented in the SwiftCompilerSources.
424+
void runSwiftFunctionVerification(SILFunction *f);
425+
426+
/// Runs the SIL verifier which is implemented in the SwiftCompilerSources.
427+
void runSwiftModuleVerification();
428+
420429
private:
421430
void parsePassCount(StringRef countsStr);
422431

lib/DriverTool/sil_opt_main.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,8 +566,11 @@ static void runCommandLineSelectedPasses(SILModule *Module,
566566
Module, SILPassPipelinePlan::getPassPipelineForKinds(opts, options.Passes),
567567
isMandatory, IRGenMod);
568568

569-
if (Module->getOptions().VerifyAll)
569+
if (Module->getOptions().VerifyAll) {
570570
Module->verify();
571+
SILPassManager pm(Module, isMandatory, IRGenMod);
572+
pm.runSwiftModuleVerification();
573+
}
571574
}
572575

573576
namespace {

lib/SILOptimizer/Mandatory/OwnershipModelEliminator.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,7 @@ struct OwnershipModelEliminator : SILFunctionTransform {
840840
"ownership. Please re-run with -sil-verify-all to identify the "
841841
"actual pass that introduced the verification error.");
842842
f->verify(getAnalysis<BasicCalleeAnalysis>()->getCalleeCache());
843+
getPassManager()->runSwiftFunctionVerification(f);
843844
}
844845

845846
if (stripOwnership(*f)) {

lib/SILOptimizer/PassManager/PassManager.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,11 @@ llvm::cl::opt<bool> SILForceVerifyAll(
161161
llvm::cl::desc("For all passes, precompute analyses before the pass and "
162162
"verify analyses after the pass"));
163163

164+
llvm::cl::opt<bool> DisableSwiftVerification(
165+
"disable-swift-verification", llvm::cl::init(false),
166+
llvm::cl::desc("Disable verification which is implemented in the SwiftCompilerSources"));
167+
168+
164169
static llvm::ManagedStatic<std::vector<unsigned>> DebugPassNumbers;
165170

166171
namespace {
@@ -611,6 +616,7 @@ void SILPassManager::runPassOnFunction(unsigned TransIdx, SILFunction *F) {
611616
MatchFun))) {
612617
F->verify(getAnalysis<BasicCalleeAnalysis>()->getCalleeCache());
613618
verifyAnalyses();
619+
runSwiftFunctionVerification(F);
614620
}
615621

616622
if (SILPrintPassName)
@@ -706,6 +712,7 @@ void SILPassManager::runPassOnFunction(unsigned TransIdx, SILFunction *F) {
706712
(CurrentPassHasInvalidated || SILVerifyWithoutInvalidation)) {
707713
F->verify(getAnalysis<BasicCalleeAnalysis>()->getCalleeCache());
708714
verifyAnalyses(F);
715+
runSwiftFunctionVerification(F);
709716
} else {
710717
if ((SILVerifyAfterPass.end() != std::find_if(SILVerifyAfterPass.begin(),
711718
SILVerifyAfterPass.end(),
@@ -715,6 +722,7 @@ void SILPassManager::runPassOnFunction(unsigned TransIdx, SILFunction *F) {
715722
MatchFun))) {
716723
F->verify(getAnalysis<BasicCalleeAnalysis>()->getCalleeCache());
717724
verifyAnalyses();
725+
runSwiftFunctionVerification(F);
718726
}
719727
}
720728

@@ -821,6 +829,7 @@ void SILPassManager::runModulePass(unsigned TransIdx) {
821829
MatchFun))) {
822830
Mod->verify(getAnalysis<BasicCalleeAnalysis>()->getCalleeCache());
823831
verifyAnalyses();
832+
runSwiftModuleVerification();
824833
}
825834

826835
swiftPassInvocation.startModulePassRun(SMT);
@@ -855,6 +864,7 @@ void SILPassManager::runModulePass(unsigned TransIdx) {
855864
(CurrentPassHasInvalidated || !SILVerifyWithoutInvalidation)) {
856865
Mod->verify(getAnalysis<BasicCalleeAnalysis>()->getCalleeCache());
857866
verifyAnalyses();
867+
runSwiftModuleVerification();
858868
} else {
859869
if ((SILVerifyAfterPass.end() != std::find_if(SILVerifyAfterPass.begin(),
860870
SILVerifyAfterPass.end(),
@@ -864,6 +874,7 @@ void SILPassManager::runModulePass(unsigned TransIdx) {
864874
MatchFun))) {
865875
Mod->verify(getAnalysis<BasicCalleeAnalysis>()->getCalleeCache());
866876
verifyAnalyses();
877+
runSwiftModuleVerification();
867878
}
868879
}
869880
}
@@ -1483,6 +1494,26 @@ void SwiftPassInvocation::endTransformFunction() {
14831494
assert(numNodeSetsAllocated == 0 && "Not all NodeSets deallocated");
14841495
}
14851496

1497+
void SwiftPassInvocation::beginVerifyFunction(SILFunction *function) {
1498+
if (transform) {
1499+
assert(this->function == function);
1500+
} else {
1501+
assert(!this->function);
1502+
this->function = function;
1503+
}
1504+
}
1505+
1506+
void SwiftPassInvocation::endVerifyFunction() {
1507+
assert(function);
1508+
if (!transform) {
1509+
assert(changeNotifications == SILAnalysis::InvalidationKind::Nothing &&
1510+
"verifyication must not change the SIL of a function");
1511+
assert(numBlockSetsAllocated == 0 && "Not all BasicBlockSets deallocated");
1512+
assert(numNodeSetsAllocated == 0 && "Not all NodeSets deallocated");
1513+
function = nullptr;
1514+
}
1515+
}
1516+
14861517
SwiftPassInvocation::~SwiftPassInvocation() {}
14871518

14881519
//===----------------------------------------------------------------------===//
@@ -1864,3 +1895,29 @@ void BridgedCloner::clone(BridgedInstruction inst) {
18641895
cloner->cloneInst(inst.unbridged());
18651896
}
18661897

1898+
static BridgedUtilities::VerifyFunctionFn verifyFunctionFunction;
1899+
1900+
void BridgedUtilities::registerVerifier(VerifyFunctionFn verifyFunctionFn) {
1901+
verifyFunctionFunction = verifyFunctionFn;
1902+
}
1903+
1904+
void SILPassManager::runSwiftFunctionVerification(SILFunction *f) {
1905+
if (!verifyFunctionFunction)
1906+
return;
1907+
1908+
if (f->getModule().getOptions().VerifyNone)
1909+
return;
1910+
1911+
if (DisableSwiftVerification)
1912+
return;
1913+
1914+
getSwiftPassInvocation()->beginVerifyFunction(f);
1915+
verifyFunctionFunction({getSwiftPassInvocation()}, {f});
1916+
getSwiftPassInvocation()->endVerifyFunction();
1917+
}
1918+
1919+
void SILPassManager::runSwiftModuleVerification() {
1920+
for (SILFunction &f : *Mod) {
1921+
runSwiftFunctionVerification(&f);
1922+
}
1923+
}

lib/SILOptimizer/Transforms/PerformanceInliner.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,6 +1196,7 @@ bool SILPerformanceInliner::inlineCallsIntoFunction(SILFunction *Caller) {
11961196
}
11971197

11981198
Caller->verify();
1199+
pm->runSwiftFunctionVerification(Caller);
11991200
}
12001201
}
12011202
deleter.cleanupDeadInstructions();
@@ -1214,6 +1215,7 @@ bool SILPerformanceInliner::inlineCallsIntoFunction(SILFunction *Caller) {
12141215
// the inliner without running the entire inliner.
12151216
if (EnableVerifyAfterInlining) {
12161217
Caller->verify();
1218+
pm->runSwiftFunctionVerification(Caller);
12171219
}
12181220

12191221
return true;

0 commit comments

Comments
 (0)