mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #84180 from meg-gupta/borrowandmutatepr
Add preliminary support for borrow accessors
This commit is contained in:
@@ -254,6 +254,11 @@ private struct CollectedEffects {
|
||||
// effect, it would not give any significant benefit in any of our current optimizations.
|
||||
addEffects(.destroy, to: inst.operands[0].value, fromInitialPath: SmallProjectionPath(.anyValueFields))
|
||||
|
||||
case is ReturnInst:
|
||||
if inst.parentFunction.convention.hasGuaranteedAddressResult {
|
||||
addEffects(.read, to: inst.operands[0].value)
|
||||
}
|
||||
|
||||
default:
|
||||
if inst.mayRelease {
|
||||
globalEffects = .worstEffects
|
||||
|
||||
@@ -806,6 +806,10 @@ extension InteriorUseWalker {
|
||||
if let inst = operand.instruction as? ForwardingInstruction {
|
||||
return inst.forwardedResults.walk { walkDownUses(of: $0) }
|
||||
}
|
||||
// TODO: Represent apply of borrow accessors as ForwardingOperation and use that over ForwardingInstruction
|
||||
if let apply = operand.instruction as? FullApplySite, apply.hasGuaranteedResult {
|
||||
return walkDownUses(of: apply.singleDirectResult!)
|
||||
}
|
||||
// TODO: verify that ForwardInstruction handles all .forward operand ownership and assert that only phis can be
|
||||
// reached: assert(Phi(using: operand) != nil)
|
||||
return .continueWalk
|
||||
|
||||
@@ -299,6 +299,14 @@ extension ApplySite {
|
||||
public func calleeArgumentIndex(of operand: Operand) -> Int? {
|
||||
operandConventions.calleeArgumentIndex(of: operand)
|
||||
}
|
||||
|
||||
public var hasGuaranteedResult: Bool {
|
||||
functionConvention.hasGuaranteedResult
|
||||
}
|
||||
|
||||
public var hasGuaranteedAddressResult: Bool {
|
||||
functionConvention.hasGuaranteedAddressResult
|
||||
}
|
||||
}
|
||||
|
||||
extension ApplySite {
|
||||
|
||||
@@ -488,6 +488,8 @@ public enum ArgumentConvention : CustomStringConvertible {
|
||||
self = .directUnowned
|
||||
case .pack:
|
||||
self = .packOut
|
||||
case .guaranteed, .guaranteedAddress:
|
||||
fatalError("Result conventions @guaranteed and @guaranteed_addr are always returned directly")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -98,6 +98,20 @@ public struct FunctionConvention : CustomStringConvertible {
|
||||
return SILFunctionType_getLifetimeDependencies(functionType.bridged).count() != 0
|
||||
}
|
||||
|
||||
public var hasGuaranteedResult: Bool {
|
||||
if results.count != 1 {
|
||||
return false
|
||||
}
|
||||
return results[0].convention == .guaranteed
|
||||
}
|
||||
|
||||
public var hasGuaranteedAddressResult: Bool {
|
||||
if results.count != 1 {
|
||||
return false
|
||||
}
|
||||
return results[0].convention == .guaranteedAddress
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
var str = functionType.description
|
||||
for paramIdx in 0..<parameters.count {
|
||||
@@ -133,7 +147,7 @@ public struct ResultInfo : CustomStringConvertible {
|
||||
return hasLoweredAddresses || type.isExistentialArchetypeWithError()
|
||||
case .pack:
|
||||
return true
|
||||
case .owned, .unowned, .unownedInnerPointer, .autoreleased:
|
||||
case .owned, .unowned, .unownedInnerPointer, .autoreleased, .guaranteed, .guaranteedAddress:
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -358,6 +372,14 @@ public enum ResultConvention : CustomStringConvertible {
|
||||
/// The caller is responsible for destroying this return value. Its type is non-trivial.
|
||||
case owned
|
||||
|
||||
/// The caller is responsible for using the returned address within a valid
|
||||
/// scope. This is valid only for borrow and mutate accessors.
|
||||
case guaranteedAddress
|
||||
|
||||
/// The caller is responsible for using the returned value within a valid
|
||||
/// scope. This is valid only for borrow accessors.
|
||||
case guaranteed
|
||||
|
||||
/// The caller is not responsible for destroying this return value. Its type may be trivial, or it may simply be offered unsafely. It is valid at the instant of the return, but further operations may invalidate it.
|
||||
case unowned
|
||||
|
||||
@@ -397,6 +419,10 @@ public enum ResultConvention : CustomStringConvertible {
|
||||
return "autoreleased"
|
||||
case .pack:
|
||||
return "pack"
|
||||
case .guaranteed:
|
||||
return "guaranteed"
|
||||
case .guaranteedAddress:
|
||||
return "guaranteedAddress"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -428,6 +454,8 @@ extension ResultConvention {
|
||||
case .UnownedInnerPointer: self = .unownedInnerPointer
|
||||
case .Autoreleased: self = .autoreleased
|
||||
case .Pack: self = .pack
|
||||
case .Guaranteed: self = .guaranteed
|
||||
case .GuaranteedAddress: self = .guaranteedAddress
|
||||
default:
|
||||
fatalError("unsupported result convention")
|
||||
}
|
||||
|
||||
@@ -535,6 +535,9 @@ public final class EnclosingValueIterator : IteratorProtocol {
|
||||
// Recurse through guaranteed forwarding non-phi instructions.
|
||||
let ops = forwardingInst.forwardedOperands
|
||||
worklist.pushIfNotVisited(contentsOf: ops.lazy.map { $0.value })
|
||||
} else if value.isGuaranteedApplyResult {
|
||||
let selfArgument = (value as! ApplyInst).arguments.last!
|
||||
worklist.pushIfNotVisited(selfArgument)
|
||||
} else {
|
||||
fatalError("cannot get borrow introducers for unknown guaranteed value")
|
||||
}
|
||||
@@ -617,6 +620,19 @@ extension Value {
|
||||
}
|
||||
return self
|
||||
}
|
||||
|
||||
public var isGuaranteedApplyResult: Bool {
|
||||
guard let definingInstruction = self.definingInstruction else {
|
||||
return false
|
||||
}
|
||||
guard let apply = definingInstruction as? ApplyInst else {
|
||||
return false
|
||||
}
|
||||
guard apply.singleDirectResult != nil else {
|
||||
return false
|
||||
}
|
||||
return apply.functionConvention.results[0].convention == .guaranteed
|
||||
}
|
||||
}
|
||||
|
||||
extension Phi {
|
||||
|
||||
@@ -61,7 +61,7 @@ private extension Instruction {
|
||||
|
||||
func checkGuaranteedResults() {
|
||||
for result in results where result.ownership == .guaranteed {
|
||||
require(BeginBorrowValue(result) != nil || self is ForwardingInstruction,
|
||||
require(BeginBorrowValue(result) != nil || self is ForwardingInstruction || result.isGuaranteedApplyResult,
|
||||
"\(result) must either be a BeginBorrowValue or a ForwardingInstruction")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user