Skip to content

Commit 1de2d3f

Browse files
committed
[ast] Enable the ASTVerifier behind the enable-ast-verifier flag in no-asserts builds.
This follows the design of how we handled this with sil-verify-all. Specifically, the default behavior is to run only in asserts builds, but one can use the two flags: enable-ast-verifier and disable-ast-verifier to override the default behavior. The reason why this is interesting is that this means that when compiling normally, we will not run the verifier, so we won't have a perf hit. But we can now ask the user to run with this flag (or in a future maybe a re-run in the driver would do this for them), saving us time when screening bugs by avoiding the need to build an asserts compiler to triage if the ASTVerifier would catch the bug.
1 parent f205b20 commit 1de2d3f

File tree

10 files changed

+106
-33
lines changed

10 files changed

+106
-33
lines changed

CMakeLists.txt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -336,10 +336,6 @@ set(SWIFT_DARWIN_DEPLOYMENT_VERSION_WATCHOS "2.0" CACHE STRING
336336
# User-configurable debugging options.
337337
#
338338

339-
option(SWIFT_AST_VERIFIER
340-
"Enable the AST verifier in the built compiler, and run it on every compilation"
341-
TRUE)
342-
343339
option(SWIFT_SIL_VERIFY_ALL
344340
"Run SIL verification after each transform when building Swift files in the build process"
345341
FALSE)

include/swift/Basic/LangOptions.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,20 @@ namespace swift {
367367
// FrontendOptions.
368368
bool AllowModuleWithCompilerErrors = false;
369369

370+
/// A helper enum to represent whether or not we customized the default
371+
/// ASTVerifier behavior via a frontend flag. By default, we do not
372+
/// customize.
373+
///
374+
/// NOTE: The default behavior is to run the ASTVerifier only when asserts
375+
/// are enabled. This just allows for one to customize that behavior.
376+
enum class ASTVerifierOverrideKind {
377+
NoOverride = 0,
378+
EnableVerifier = 1,
379+
DisableVerifier = 2,
380+
};
381+
ASTVerifierOverrideKind ASTVerifierOverride =
382+
ASTVerifierOverrideKind::NoOverride;
383+
370384
/// Sets the target we are building for and updates platform conditions
371385
/// to match.
372386
///

include/swift/Option/FrontendOptions.td

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,4 +767,20 @@ def bad_file_descriptor_retry_count:
767767
Separate<["-"], "bad-file-descriptor-retry-count">,
768768
HelpText<"Number of retrying opening a file if previous open returns a bad "
769769
"file descriptor error.">;
770+
771+
def enable_ast_verifier : Flag<["-"], "enable-ast-verifier">,
772+
HelpText<"Run the AST verifier during compilation. NOTE: This lets the user "
773+
"override the default behavior on whether or not the ASTVerifier "
774+
"is run. The default behavior is to run the verifier when asserts "
775+
"are enabled and not run it when asserts are disabled. NOTE: "
776+
"Can not be used if disable-ast-verifier is used as well">;
777+
778+
def disable_ast_verifier : Flag<["-"], "disable-ast-verifier">,
779+
HelpText<"Do not run the AST verifier during compilation. NOTE: This lets "
780+
"the user override the default behavior on whether or not the "
781+
"ASTVerifier is run. The default behavior is to run the verifier "
782+
"when asserts are enabled and not run it when asserts are "
783+
"disabled. NOTE: Can not be used if enable-ast-verifier is used "
784+
"as well">;
785+
770786
} // end let Flags = [FrontendOption, NoDriverOption, HelpHidden]

lib/AST/ASTVerifier.cpp

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3634,15 +3634,36 @@ class Verifier : public ASTWalker {
36343634
};
36353635
} // end anonymous namespace
36363636

3637+
static bool shouldVerifyGivenContext(const ASTContext &ctx) {
3638+
using ASTVerifierOverrideKind = LangOptions::ASTVerifierOverrideKind;
3639+
switch (ctx.LangOpts.ASTVerifierOverride) {
3640+
case ASTVerifierOverrideKind::EnableVerifier:
3641+
return true;
3642+
case ASTVerifierOverrideKind::DisableVerifier:
3643+
return false;
3644+
case ASTVerifierOverrideKind::NoOverride:
3645+
#ifndef NDEBUG
3646+
// asserts. Default behavior is to run.
3647+
return true;
3648+
#else
3649+
// no-asserts. Default behavior is not to run the verifier.
3650+
return false;
3651+
#endif
3652+
}
3653+
llvm_unreachable("Covered switch isn't covered?!");
3654+
}
3655+
36373656
void swift::verify(SourceFile &SF) {
3638-
#if !(defined(NDEBUG) || defined(SWIFT_DISABLE_AST_VERIFIER))
3657+
if (!shouldVerifyGivenContext(SF.getASTContext()))
3658+
return;
36393659
Verifier verifier(SF, &SF);
36403660
SF.walk(verifier);
3641-
#endif
36423661
}
36433662

36443663
bool swift::shouldVerify(const Decl *D, const ASTContext &Context) {
3645-
#if !(defined(NDEBUG) || defined(SWIFT_DISABLE_AST_VERIFIER))
3664+
if (!shouldVerifyGivenContext(Context))
3665+
return false;
3666+
36463667
if (const auto *ED = dyn_cast<ExtensionDecl>(D)) {
36473668
return shouldVerify(ED->getExtendedNominal(), Context);
36483669
}
@@ -3654,15 +3675,13 @@ bool swift::shouldVerify(const Decl *D, const ASTContext &Context) {
36543675
}
36553676

36563677
return true;
3657-
#else
3658-
return false;
3659-
#endif
36603678
}
36613679

36623680
void swift::verify(Decl *D) {
3663-
#if !(defined(NDEBUG) || defined(SWIFT_DISABLE_AST_VERIFIER))
3681+
if (!shouldVerifyGivenContext(D->getASTContext()))
3682+
return;
3683+
36643684
Verifier V = Verifier::forDecl(D);
36653685
D->walk(V);
3666-
#endif
36673686
}
36683687

lib/AST/CMakeLists.txt

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,3 @@ endif()
144144
# headers.
145145
# For more information see the comment at the top of lib/CMakeLists.txt.
146146
add_dependencies(swiftAST intrinsics_gen clang-tablegen-targets)
147-
148-
set(swift_ast_verifier_flag)
149-
if(SWIFT_AST_VERIFIER)
150-
set(swift_ast_verifier_flag " -USWIFT_DISABLE_AST_VERIFIER")
151-
else()
152-
set(swift_ast_verifier_flag " -DSWIFT_DISABLE_AST_VERIFIER=1")
153-
endif()
154-
155-
set_property(SOURCE ASTVerifier.cpp APPEND_STRING PROPERTY COMPILE_FLAGS
156-
"${swift_ast_verifier_flag}")
157-

lib/Frontend/CompilerInvocation.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,21 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
689689
Opts.AllowModuleWithCompilerErrors = true;
690690
}
691691

692+
if (auto A =
693+
Args.getLastArg(OPT_enable_ast_verifier, OPT_disable_ast_verifier)) {
694+
using ASTVerifierOverrideKind = LangOptions::ASTVerifierOverrideKind;
695+
if (A->getOption().matches(OPT_enable_ast_verifier)) {
696+
Opts.ASTVerifierOverride = ASTVerifierOverrideKind::EnableVerifier;
697+
} else if (A->getOption().matches(OPT_disable_ast_verifier)) {
698+
Opts.ASTVerifierOverride = ASTVerifierOverrideKind::DisableVerifier;
699+
} else {
700+
// This is an assert since getLastArg should not have let us get here if
701+
// we did not have one of enable/disable specified.
702+
llvm_unreachable(
703+
"Should have found one of enable/disable ast verifier?!");
704+
}
705+
}
706+
692707
return HadError || UnsupportedOS || UnsupportedArch;
693708
}
694709

test/lit.site.cfg.in

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,6 @@ if "@SWIFT_STDLIB_ASSERTIONS@" == "TRUE":
8383
else:
8484
config.available_features.add('swift_stdlib_no_asserts')
8585

86-
if "@SWIFT_AST_VERIFIER@" == "TRUE":
87-
config.available_features.add('swift_ast_verifier')
88-
8986
if "@SWIFT_OPTIMIZED@" == "TRUE":
9087
config.available_features.add("optimized_stdlib")
9188

tools/sil-opt/SILOpt.cpp

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,11 @@ EnableSpeculativeDevirtualization("enable-spec-devirt",
116116
llvm::cl::desc("Enable Speculative Devirtualization pass."));
117117

118118
namespace {
119-
enum EnforceExclusivityMode {
119+
enum class EnforceExclusivityMode {
120120
Unchecked, // static only
121121
Checked, // static and dynamic
122122
DynamicOnly,
123-
None
123+
None,
124124
};
125125
} // end anonymous namespace
126126

@@ -203,6 +203,16 @@ SILVerifyNone("sil-verify-none",
203203
llvm::cl::init(false),
204204
llvm::cl::desc("Completely disable SIL verification"));
205205

206+
/// Customize the default behavior
207+
static llvm::cl::opt<bool> EnableASTVerifier(
208+
"enable-ast-verifier", llvm::cl::Hidden, llvm::cl::init(false),
209+
llvm::cl::desc("Override the default behavior and Enable the ASTVerifier"));
210+
211+
static llvm::cl::opt<bool> DisableASTVerifier(
212+
"disable-ast-verifier", llvm::cl::Hidden, llvm::cl::init(false),
213+
llvm::cl::desc(
214+
"Override the default behavior and force disable the ASTVerifier"));
215+
206216
static llvm::cl::opt<bool>
207217
RemoveRuntimeAsserts("remove-runtime-asserts",
208218
llvm::cl::Hidden,
@@ -310,6 +320,22 @@ static void runCommandLineSelectedPasses(SILModule *Module,
310320
Module->verify();
311321
}
312322

323+
namespace {
324+
using ASTVerifierOverrideKind = LangOptions::ASTVerifierOverrideKind;
325+
} // end anonymous namespace
326+
327+
static Optional<ASTVerifierOverrideKind> getASTOverrideKind() {
328+
assert(!(EnableASTVerifier && DisableASTVerifier) &&
329+
"Can only set one of EnableASTVerifier/DisableASTVerifier?!");
330+
if (EnableASTVerifier)
331+
return ASTVerifierOverrideKind::EnableVerifier;
332+
333+
if (DisableASTVerifier)
334+
return ASTVerifierOverrideKind::DisableVerifier;
335+
336+
return None;
337+
}
338+
313339
// This function isn't referenced outside its translation unit, but it
314340
// can't use the "static" keyword because its address is used for
315341
// getMainExecutable (since some platforms don't support taking the
@@ -362,7 +388,9 @@ int main(int argc, char **argv) {
362388
Invocation.getLangOptions().DisableAvailabilityChecking = true;
363389
Invocation.getLangOptions().EnableAccessControl = false;
364390
Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false;
365-
391+
if (auto overrideKind = getASTOverrideKind()) {
392+
Invocation.getLangOptions().ASTVerifierOverride = *overrideKind;
393+
}
366394
Invocation.getLangOptions().EnableExperimentalConcurrency =
367395
EnableExperimentalConcurrency;
368396

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
// RUN: not %target-sil-opt %s
2-
// REQUIRES: swift_ast_verifier
1+
// RUN: not %target-sil-opt -enable-ast-verifier %s
2+
33
import Swift func g(@opened(Any

validation-test/compiler_crashers_fixed/28653-child-source-range-not-contained-within-its-parent.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
// See https://swift.org/LICENSE.txt for license information
66
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
77

8-
// RUN: not %target-swift-frontend %s -emit-ir
9-
// REQUIRES: swift_ast_verifier
8+
// RUN: not %target-swift-frontend -enable-ast-verifier %s -emit-ir
109

1110
switch{case.b(u){

0 commit comments

Comments
 (0)