Files
swift-mirror/SwiftCompilerSources/Sources/Optimizer/ModulePasses/ReadOnlyGlobalVariables.swift
Andrew Trick 2128c21106 Migrate SwiftCompilerSources to FunctionConvention.
Layers:
- FunctionConvention: AST FunctionType: results, parameters
- ArgumentConventions: SIL function arguments
- ApplyOperandConventions: applied operands

The meaning of an integer index is determined by the collection
type. All the mapping between the various indices (results,
parameters, SIL argument, applied arguments) is restricted to the
collection type that owns that mapping. Remove the concept of a
"caller argument index".
2024-01-03 12:24:50 -08:00

74 lines
2.3 KiB
Swift

//===--- ReadOnlyGlobalVariables.swift ------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import SIL
/// Marks global `var` variables as `let` if they are never written.
///
/// Note that this pass relies on the initialize-static-globals pass which converts lazily
/// initialized globals to statically initialized globals.
/// This pass does not mark lazily initialized globals as `let`, because such globals _are_
/// written: in their initializers.
///
let readOnlyGlobalVariablesPass = ModulePass(name: "read-only-global-variables") {
(moduleContext: ModulePassContext) in
var writtenGlobals = Set<GlobalVariable>()
for f in moduleContext.functions {
for inst in f.instructions {
if let gAddr = inst as? GlobalAddrInst {
if findWrites(toAddress: gAddr) {
writtenGlobals.insert(gAddr.global)
}
}
}
}
for g in moduleContext.globalVariables {
if !g.isAvailableExternally,
!g.isPossiblyUsedExternally,
!g.isLet,
!writtenGlobals.contains(g) {
g.setIsLet(to: true, moduleContext)
}
}
}
private func findWrites(toAddress: Value) -> Bool {
var walker = FindWrites()
return walker.walkDownUses(ofAddress: toAddress, path: UnusedWalkingPath()) == .abortWalk
}
private struct FindWrites : AddressDefUseWalker {
mutating func leafUse(address: Operand, path: UnusedWalkingPath) -> WalkResult {
switch address.instruction {
case is LoadInst, is LoadBorrowInst:
return .continueWalk
case let ca as CopyAddrInst:
return address == ca.sourceOperand ? .continueWalk : .abortWalk
case let apply as FullApplySite:
if let calleeArgIdx = apply.calleeArgumentIndex(of: address) {
let convention = apply.calleeArgumentConventions[calleeArgIdx]
if convention.isIndirectIn {
return .continueWalk
}
}
return .abortWalk
default:
return .abortWalk
}
}
}