Files
swift-mirror/SwiftCompilerSources/Sources/SIL/ApplySite.swift
Erik Eckstein 5325a4fe21 Swift SIL: add some instruction classes and APIs
* add `UnownedRetainInst` and `UnownedReleaseInst`
* add `var value` to `RetainValueInst` and `ReleaseValueInst`
* make the protocol `UnaryInstruction` be an `Instruction`
* add `var Type.isValueTypeWithDeinit`
* add `var Type.isUnownedStorageType`
* add `var OperandArray.values`
2023-06-07 12:55:56 +02:00

151 lines
4.9 KiB
Swift

//===--- ApplySite.swift - Defines the ApplySite protocols ----------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2021 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 SILBridging
public struct ApplyOperands {
public static let calleeOperandIndex: Int = 0
public static let firstArgumentIndex = 1
}
public protocol ApplySite : Instruction {
var operands: OperandArray { get }
var numArguments: Int { get }
var substitutionMap: SubstitutionMap { get }
/// Converts an argument index of the apply to the corresponding argument index of the callee.
///
/// For a FullApplySite this is always a 1-to-1 mapping.
/// For a `partial_apply` the callee index can be higher than the caller's argument index
/// because the arguments to `partial_apply` are a suffix of the callee.
///
/// Example:
/// ```
/// func callee(a, b, c, d, e) { }
///
/// %pa = partial_apply @callee(c, d, e)
/// // caller indices: 0, 1, 2
/// // callee indices: 2, 3, 4
///
/// %a = apply %pa (a, b)
/// // caller indices: 0, 1
/// // callee indices: 0, 1
/// ```
func calleeArgIndex(callerArgIndex: Int) -> Int
/// Converts an argument index of a callee to the corresponding argument index of the apply.
///
/// If the apply does not actually apply that argument, it returns nil.
/// Otherwise, for a FullApplySite this is always a 1-to-1 mapping.
/// For a `partial_apply` the caller index can be lower than the callee's argument index
/// because the arguments to `partial_apply` are a suffix of the callee.
///
/// Example:
/// ```
/// func callee(a, b, c, d, e) { }
/// // callee indices: 0, 1, 2, 3, 4
/// // caller indices in %pa: -, -, 0, 1, 2 ("-" == nil)
/// // caller indices in %a: 0, 1, -, -, -
///
/// %pa = partial_apply @callee(c, d, e)
/// %a = apply %pa (a, b)
/// ```
func callerArgIndex(calleeArgIndex: Int) -> Int?
func getArgumentConvention(calleeArgIndex: Int) -> ArgumentConvention
}
extension ApplySite {
public var callee: Value { operands[ApplyOperands.calleeOperandIndex].value }
/// Returns the subset of operands which are argument operands.
///
/// This does not include the callee function operand.
public var argumentOperands: OperandArray {
let numArgs = bridged.ApplySite_getNumArguments()
let offset = ApplyOperands.firstArgumentIndex
return operands[offset..<(numArgs + offset)]
}
/// Returns the subset of operand values which are arguments.
///
/// This does not include the callee function operand.
public var arguments: LazyMapSequence<OperandArray, Value> {
argumentOperands.values
}
public var substitutionMap: SubstitutionMap {
SubstitutionMap(bridged.ApplySite_getSubstitutionMap())
}
/// Returns the argument index of an operand.
///
/// Returns nil if 'operand' is not an argument operand. This is the case if
/// it's the callee function operand.
public func argumentIndex(of operand: Operand) -> Int? {
let opIdx = operand.index
if opIdx >= ApplyOperands.firstArgumentIndex &&
opIdx <= ApplyOperands.firstArgumentIndex + numArguments {
return opIdx - ApplyOperands.firstArgumentIndex
}
return nil
}
/// Returns true if `operand` is the callee function operand and not am argument operand.
public func isCalleeOperand(_ operand: Operand) -> Bool {
return operand.index < ApplyOperands.firstArgumentIndex
}
public func getArgumentConvention(calleeArgIndex: Int) -> ArgumentConvention {
return bridged.ApplySite_getArgumentConvention(calleeArgIndex).convention
}
public var referencedFunction: Function? {
if let fri = callee as? FunctionRefInst {
return fri.referencedFunction
}
return nil
}
public func hasSemanticsAttribute(_ attr: StaticString) -> Bool {
if let callee = referencedFunction {
return callee.hasSemanticsAttribute(attr)
}
return false
}
}
public protocol FullApplySite : ApplySite {
var singleDirectResult: Value? { get }
}
extension FullApplySite {
public func calleeArgIndex(callerArgIndex: Int) -> Int {
assert(callerArgIndex >= 0 && callerArgIndex < numArguments)
return callerArgIndex
}
public func callerArgIndex(calleeArgIndex: Int) -> Int? {
if calleeArgIndex < numArguments {
return calleeArgIndex
}
return nil
}
/// The number of indirect out arguments.
///
/// 0 if the callee has a direct or no return value and 1, if it has an indirect return value.
public var numIndirectResultArguments: Int {
return bridged.FullApplySite_numIndirectResultArguments()
}
}