SwiftCompilerSources: move the Verifier to the SIL module

This commit is contained in:
Erik Eckstein
2025-07-26 07:16:16 +02:00
parent 1eb49ec186
commit 319f49ad9f
9 changed files with 69 additions and 42 deletions

View File

@@ -17,7 +17,7 @@ import OptimizerBridging
@_cdecl("initializeSwiftModules")
public func initializeSwiftModules() {
registerAST()
registerSILClasses()
registerSIL()
registerSwiftAnalyses()
registerUtilities()
registerSwiftPasses()
@@ -160,6 +160,5 @@ private func registerSwiftAnalyses() {
}
private func registerUtilities() {
registerVerifier()
registerPhiUpdater()
}

View File

@@ -20,5 +20,4 @@ swift_compiler_sources(Optimizer
OwnershipLiveness.swift
PhiUpdater.swift
StaticInitCloner.swift
Verifier.swift
)

View File

@@ -13,6 +13,11 @@
import Basic
import SILBridging
public func registerSIL() {
registerSILClasses()
registerUtilities()
}
private func register<T: AnyObject>(_ cl: T.Type) {
"\(cl)"._withBridgedStringRef { nameStr in
let metatype = unsafeBitCast(cl, to: SwiftMetatype.self)
@@ -20,7 +25,7 @@ private func register<T: AnyObject>(_ cl: T.Type) {
}
}
public func registerSILClasses() {
private func registerSILClasses() {
Function.register()
register(BasicBlock.self)
register(GlobalVariable.self)
@@ -262,3 +267,7 @@ public func registerSILClasses() {
register(MergeIsolationRegionInst.self)
register(IgnoredUseInst.self)
}
private func registerUtilities() {
registerVerifier()
}

View File

@@ -15,5 +15,6 @@ swift_compiler_sources(SIL
SSAUpdater.swift
Test.swift
WalkUtils.swift
Verifier.swift
)

View File

@@ -10,24 +10,29 @@
//
//===----------------------------------------------------------------------===//
import SIL
import OptimizerBridging
import SILBridging
/// To add verification for a specific instruction, let the instruction class conform to
/// this protocol and implement the `verify` method.
private protocol VerifiableInstruction : Instruction {
func verify(_ context: FunctionPassContext)
func verify(_ context: VerifierContext)
}
private func require(_ condition: Bool, _ message: @autoclosure () -> String, atInstruction: Instruction? = nil) {
if !condition {
let msg = message()
msg._withBridgedStringRef { stringRef in
verifierError(stringRef, atInstruction.bridged, Optional<Argument>.none.bridged)
BridgedVerifier.verifierError(stringRef, atInstruction.bridged, Optional<Argument>.none.bridged)
}
}
}
struct VerifierContext: Context {
let _bridged: BridgedContext
}
extension Function {
func verify(_ context: FunctionPassContext) {
func verify(_ context: VerifierContext) {
for block in blocks {
for arg in block.arguments {
arg.verify(context)
@@ -63,16 +68,17 @@ private extension Instruction {
}
private extension Argument {
func verify(_ context: FunctionPassContext) {
func verify(_ context: VerifierContext) {
if let phi = Phi(self), phi.value.ownership == .guaranteed {
phi.verifyBorrowedFromUse()
require(phi.isReborrow == phi.hasBorrowEndingUse ||
// In a dead-end block an end_borrow might have been deleted.
// TODO: this check is not needed anymore once we have complete OSSA lifetimes.
(isReborrow && context.deadEndBlocks.isDeadEnd(parentBlock)),
// TODO: enable this check once we have complete OSSA lifetimes.
// In a dead-end block an end_borrow might have been deleted.
/*
require(phi.isReborrow == phi.hasBorrowEndingUse,
"\(self) has stale reborrow flag");
*/
}
}
@@ -95,7 +101,7 @@ private extension Phi {
}
extension BorrowedFromInst : VerifiableInstruction {
func verify(_ context: FunctionPassContext) {
func verify(_ context: VerifierContext) {
for ev in enclosingValues {
require(ev.isValidEnclosingValueInBorrowedFrom, "invalid enclosing value in borrowed-from: \(ev)")
@@ -135,7 +141,7 @@ private extension Value {
}
extension LoadBorrowInst : VerifiableInstruction {
func verify(_ context: FunctionPassContext) {
func verify(_ context: VerifierContext) {
if isUnchecked {
return
}
@@ -149,7 +155,7 @@ extension LoadBorrowInst : VerifiableInstruction {
}
extension VectorBaseAddrInst : VerifiableInstruction {
func verify(_ context: FunctionPassContext) {
func verify(_ context: VerifierContext) {
require(vector.type.isBuiltinFixedArray,
"vector operand of vector_element_addr must be a Builtin.FixedArray")
require(type == vector.type.builtinFixedArrayElementType(in: parentFunction,
@@ -164,10 +170,10 @@ extension VectorBaseAddrInst : VerifiableInstruction {
// Otherwise the risk would be too big for false alarms. It also means that this verification is not perfect and
// might miss some subtle violations.
private struct MutatingUsesWalker : AddressDefUseWalker {
let context: FunctionPassContext
let context: VerifierContext
var mutatingInstructions: InstructionSet
init(_ context: FunctionPassContext) {
init(_ context: VerifierContext) {
self.context = context
self.mutatingInstructions = InstructionSet(context)
}
@@ -268,9 +274,9 @@ private extension Operand {
}
func registerVerifier() {
BridgedUtilities.registerVerifier(
BridgedVerifier.registerVerifier(
{ (bridgedCtxt: BridgedContext, bridgedFunction: BridgedFunction) in
let context = FunctionPassContext(_bridged: bridgedCtxt)
let context = VerifierContext(_bridged: bridgedCtxt)
bridgedFunction.function.verify(context)
}
)

View File

@@ -1494,6 +1494,16 @@ struct BridgedContext {
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE Slab freeSlab(Slab slab) const;
};
struct BridgedVerifier {
typedef void (* _Nonnull VerifyFunctionFn)(BridgedContext, BridgedFunction);
static void runSwiftFunctionVerification(swift::SILFunction * _Nonnull f, swift::SILContext * _Nonnull context);
static void registerVerifier(VerifyFunctionFn verifyFunctionFn);
static void verifierError(BridgedStringRef message, OptionalBridgedInstruction atInstruction,
OptionalBridgedArgument atArgument);
};
namespace swift::test {
struct Arguments;
class FunctionTest;

View File

@@ -120,11 +120,9 @@ struct BridgedPostDomTree {
};
struct BridgedUtilities {
typedef void (* _Nonnull VerifyFunctionFn)(BridgedContext, BridgedFunction);
typedef void (* _Nonnull UpdateFunctionFn)(BridgedContext, BridgedFunction);
typedef void (* _Nonnull UpdatePhisFn)(BridgedContext, BridgedArrayRef);
static void registerVerifier(VerifyFunctionFn verifyFunctionFn);
static void registerPhiUpdater(UpdateFunctionFn updateBorrowedFromFn,
UpdatePhisFn updateBorrowedFromPhisFn,
UpdatePhisFn replacePhisWithIncomingValuesFn);
@@ -279,8 +277,6 @@ BridgedDynamicCastResult classifyDynamicCastBridged(BridgedCanType sourceTy, Bri
BridgedDynamicCastResult classifyDynamicCastBridged(BridgedInstruction inst);
void verifierError(BridgedStringRef message, OptionalBridgedInstruction atInstruction, OptionalBridgedArgument atArgument);
//===----------------------------------------------------------------------===//
// Pass registration
//===----------------------------------------------------------------------===//

View File

@@ -775,3 +775,26 @@ void SILContext::freeOperandSet(OperandSet *set) {
}
}
//===----------------------------------------------------------------------===//
// BridgedVerifier
//===----------------------------------------------------------------------===//
static BridgedVerifier::VerifyFunctionFn verifyFunctionFunction = nullptr;
void BridgedVerifier::registerVerifier(VerifyFunctionFn verifyFunctionFn) {
verifyFunctionFunction = verifyFunctionFn;
}
void BridgedVerifier::runSwiftFunctionVerification(SILFunction * _Nonnull f, SILContext * _Nonnull context) {
if (!verifyFunctionFunction)
return;
verifyFunctionFunction({context}, {f});
}
void BridgedVerifier::verifierError(BridgedStringRef message,
OptionalBridgedInstruction atInstruction,
OptionalBridgedArgument atArgument) {
Twine msg(message.unbridged());
verificationFailure(msg, atInstruction.unbridged(), atArgument.unbridged(), /*extraContext=*/nullptr);
}

View File

@@ -49,16 +49,7 @@ llvm::cl::opt<bool> DisableSwiftVerification(
// PassManager
//===----------------------------------------------------------------------===//
static BridgedUtilities::VerifyFunctionFn verifyFunctionFunction;
void BridgedUtilities::registerVerifier(VerifyFunctionFn verifyFunctionFn) {
verifyFunctionFunction = verifyFunctionFn;
}
void SILPassManager::runSwiftFunctionVerification(SILFunction *f) {
if (!verifyFunctionFunction)
return;
if (f->getModule().getOptions().VerifyNone)
return;
@@ -70,7 +61,7 @@ void SILPassManager::runSwiftFunctionVerification(SILFunction *f) {
}
getSwiftPassInvocation()->beginVerifyFunction(f);
verifyFunctionFunction({getSwiftPassInvocation()}, {f});
BridgedVerifier::runSwiftFunctionVerification(f, getSwiftPassInvocation());
getSwiftPassInvocation()->endVerifyFunction();
}
@@ -507,13 +498,6 @@ void BridgedBuilder::destroyCapturedArgs(BridgedInstruction partialApply) const
}
}
void verifierError(BridgedStringRef message,
OptionalBridgedInstruction atInstruction,
OptionalBridgedArgument atArgument) {
Twine msg(message.unbridged());
verificationFailure(msg, atInstruction.unbridged(), atArgument.unbridged(), /*extraContext=*/nullptr);
}
//===----------------------------------------------------------------------===//
// Test
//===----------------------------------------------------------------------===//