mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
In #85757, part of the changes resolving #68944 is submitted. Most bridges required for #85757 were previously implemented in #84648. After #82653 got merged, we have demand for several new bridges in order to properly support optimizing derivatives of throwing functions via AutoDiff Closure Specialization pass. This patch implements: - **AST:** * `var optionalObjectType: Type` property of `Type` struct * `var optionalType: Type` property of `Type` struct - **SIL:** * `let name: StringRef` property of `EnumCase` struct * `func createOptionalSome(operand: Value, type: Type) -> EnumInst` method of `Builder` * `func createOptionalNone(type: Type) -> EnumInst` method of `Builder`
869 lines
38 KiB
Swift
869 lines
38 KiB
Swift
//===--- Builder.swift - Building and modifying SIL ----------------------===//
|
|
//
|
|
// 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 Basic
|
|
import AST
|
|
import SILBridging
|
|
|
|
/// A utility to create new instructions at a given insertion point.
|
|
public struct Builder {
|
|
|
|
public enum InsertionPoint {
|
|
case before(Instruction)
|
|
case atEndOf(BasicBlock)
|
|
case atStartOf(Function)
|
|
case staticInitializer(GlobalVariable)
|
|
}
|
|
|
|
public let insertionPoint: InsertionPoint
|
|
let location: Location
|
|
private let notificationHandler: BridgedContext
|
|
private let notifyNewInstruction: (Instruction) -> ()
|
|
|
|
/// Creates a builder which inserts _before_ `insPnt`, using a custom `location`.
|
|
public init(before insPnt: Instruction, location: Location, _ context: some MutatingContext) {
|
|
context.verifyIsTransforming(function: insPnt.parentFunction)
|
|
self.init(insertAt: .before(insPnt), location: location, context.notifyInstructionChanged, context._bridged)
|
|
}
|
|
|
|
/// Creates a builder which inserts before `insPnt`, using `insPnt`'s next
|
|
/// non-meta instruction's location.
|
|
/// This function should be used when moving code to an unknown insert point,
|
|
/// when we want to inherit the location of the closest non-meta instruction.
|
|
/// For replacing an existing meta instruction with another, use
|
|
/// ``Builder.init(replacing:_:)``.
|
|
public init(before insPnt: Instruction, _ context: some MutatingContext) {
|
|
context.verifyIsTransforming(function: insPnt.parentFunction)
|
|
self.init(insertAt: .before(insPnt), location: insPnt.location,
|
|
context.notifyInstructionChanged, context._bridged)
|
|
}
|
|
|
|
/// Creates a builder which inserts _before_ `insPnt`, using the exact location of `insPnt`,
|
|
/// for the purpose of replacing that meta instruction with an equivalent instruction.
|
|
/// This function does not delete `insPnt`.
|
|
public init(replacing insPnt: MetaInstruction, _ context: some MutatingContext) {
|
|
context.verifyIsTransforming(function: insPnt.parentFunction)
|
|
self.init(insertAt: .before(insPnt), location: insPnt.location, context.notifyInstructionChanged, context._bridged)
|
|
}
|
|
|
|
/// Creates a builder which inserts _after_ `insPnt`, using a custom `location`.
|
|
///
|
|
/// TODO: this is usually incorrect for terminator instructions. Instead use
|
|
/// `Builder.insert(after:location:_:insertFunc)` from OptUtils.swift. Rename this to afterNonTerminator.
|
|
public init(after insPnt: Instruction, location: Location, _ context: some MutatingContext) {
|
|
context.verifyIsTransforming(function: insPnt.parentFunction)
|
|
guard let nextInst = insPnt.next else {
|
|
fatalError("cannot insert an instruction after a block terminator.")
|
|
}
|
|
self.init(insertAt: .before(nextInst), location: location, context.notifyInstructionChanged, context._bridged)
|
|
}
|
|
|
|
/// Creates a builder which inserts _after_ `insPnt`, using `insPnt`'s next
|
|
/// non-meta instruction's location.
|
|
///
|
|
/// TODO: this is incorrect for terminator instructions. Instead use `Builder.insert(after:location:_:insertFunc)`
|
|
/// from OptUtils.swift. Rename this to afterNonTerminator.
|
|
public init(after insPnt: Instruction, _ context: some MutatingContext) {
|
|
self.init(after: insPnt, location: insPnt.location, context)
|
|
}
|
|
|
|
/// Creates a builder which inserts at the end of `block`, using a custom `location`.
|
|
public init(atEndOf block: BasicBlock, location: Location, _ context: some MutatingContext) {
|
|
context.verifyIsTransforming(function: block.parentFunction)
|
|
self.init(insertAt: .atEndOf(block), location: location, context.notifyInstructionChanged, context._bridged)
|
|
}
|
|
|
|
/// Creates a builder which inserts at the begin of `block`, using a custom `location`.
|
|
public init(atBeginOf block: BasicBlock, location: Location, _ context: some MutatingContext) {
|
|
context.verifyIsTransforming(function: block.parentFunction)
|
|
let firstInst = block.instructions.first!
|
|
self.init(insertAt: .before(firstInst), location: location, context.notifyInstructionChanged, context._bridged)
|
|
}
|
|
|
|
/// Creates a builder which inserts at the begin of `block`, using the location of the first
|
|
/// non-meta instruction of `block`.
|
|
public init(atBeginOf block: BasicBlock, _ context: some MutatingContext) {
|
|
context.verifyIsTransforming(function: block.parentFunction)
|
|
let firstInst = block.instructions.first!
|
|
self.init(insertAt: .before(firstInst),
|
|
location: firstInst.location, context.notifyInstructionChanged, context._bridged)
|
|
}
|
|
|
|
/// Creates a builder which inserts instructions into an empty function, using the location of the function itself.
|
|
public init(atStartOf function: Function, _ context: some MutatingContext) {
|
|
context.verifyIsTransforming(function: function)
|
|
self.init(insertAt: .atStartOf(function), location: function.location,
|
|
context.notifyInstructionChanged, context._bridged)
|
|
}
|
|
|
|
public init(staticInitializerOf global: GlobalVariable, _ context: some MutatingContext) {
|
|
self.init(insertAt: .staticInitializer(global),
|
|
location: Location.artificialUnreachableLocation, { _ in }, context._bridged)
|
|
}
|
|
|
|
/// Return 'nil' when inserting at the start of a function or in a global initializer.
|
|
public var insertionBlock: BasicBlock? {
|
|
switch insertionPoint {
|
|
case let .before(inst):
|
|
return inst.parentBlock
|
|
case let .atEndOf(block):
|
|
return block
|
|
case .atStartOf, .staticInitializer:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
public var bridged: BridgedBuilder {
|
|
switch insertionPoint {
|
|
case .before(let inst):
|
|
return BridgedBuilder(insertAt: .beforeInst, insertionObj: inst.bridged.obj,
|
|
loc: location.bridged)
|
|
case .atEndOf(let block):
|
|
return BridgedBuilder(insertAt: .endOfBlock, insertionObj: block.bridged.obj,
|
|
loc: location.bridged)
|
|
case .atStartOf(let function):
|
|
return BridgedBuilder(insertAt: .startOfFunction, insertionObj: function.bridged.obj,
|
|
loc: location.bridged)
|
|
case .staticInitializer(let global):
|
|
return BridgedBuilder(insertAt: .intoGlobal, insertionObj: global.bridged.obj,
|
|
loc: location.bridged)
|
|
}
|
|
}
|
|
|
|
private func notifyNew<I: Instruction>(_ instruction: I) -> I {
|
|
notificationHandler.notifyChanges(.Instructions)
|
|
if instruction is FullApplySite {
|
|
notificationHandler.notifyChanges(.Calls)
|
|
}
|
|
if instruction is TermInst {
|
|
notificationHandler.notifyChanges(.Branches)
|
|
}
|
|
notifyNewInstruction(instruction)
|
|
return instruction
|
|
}
|
|
|
|
private init(insertAt: InsertionPoint, location: Location,
|
|
_ notifyNewInstruction: @escaping (Instruction) -> (),
|
|
_ notificationHandler: BridgedContext) {
|
|
self.insertionPoint = insertAt
|
|
self.location = location;
|
|
self.notifyNewInstruction = notifyNewInstruction
|
|
self.notificationHandler = notificationHandler
|
|
}
|
|
|
|
public func createBuiltin(name: StringRef,
|
|
type: Type,
|
|
substitutions: SubstitutionMap = SubstitutionMap(),
|
|
arguments: [Value]) -> BuiltinInst {
|
|
return arguments.withBridgedValues { valuesRef in
|
|
let bi = bridged.createBuiltin(
|
|
name._bridged, type.bridged, substitutions.bridged, valuesRef)
|
|
return notifyNew(bi.getAs(BuiltinInst.self))
|
|
}
|
|
}
|
|
|
|
public func createBuiltinBinaryFunction(name: String,
|
|
operandType: Type, resultType: Type, arguments: [Value]) -> BuiltinInst {
|
|
return arguments.withBridgedValues { valuesRef in
|
|
return name._withBridgedStringRef { nameStr in
|
|
let bi = bridged.createBuiltinBinaryFunction(
|
|
nameStr, operandType.bridged, resultType.bridged, valuesRef)
|
|
return notifyNew(bi.getAs(BuiltinInst.self))
|
|
}
|
|
}
|
|
}
|
|
|
|
@discardableResult
|
|
public func createCondFail(condition: Value, message: String) -> CondFailInst {
|
|
return message._withBridgedStringRef { messageStr in
|
|
let cf = bridged.createCondFail(condition.bridged, messageStr)
|
|
return notifyNew(cf.getAs(CondFailInst.self))
|
|
}
|
|
}
|
|
|
|
/// Creates a integer literal instruction with the given integer value and
|
|
/// type. If an extension is necessary, the value is extended in accordance
|
|
/// with the signedness of `Value`.
|
|
public func createIntegerLiteral<Value: FixedWidthInteger>(
|
|
_ value: Value,
|
|
type: Type
|
|
) -> IntegerLiteralInst {
|
|
precondition(
|
|
Value.bitWidth <= Int.bitWidth,
|
|
"Cannot fit \(Value.bitWidth)-bit integer into \(Int.bitWidth)-bit 'Swift.Int'"
|
|
)
|
|
// Extend the value based on its signedness to the bit width of `Int` and
|
|
// reinterpret it as an `Int`.
|
|
let extendedValue: Int =
|
|
if Value.isSigned {
|
|
Int(value)
|
|
} else {
|
|
// NB: This initializer is effectively a generic equivalent
|
|
// of `Int(bitPattern:)`
|
|
Int(truncatingIfNeeded: value)
|
|
}
|
|
|
|
let literal = bridged.createIntegerLiteral(type.bridged, extendedValue, Value.isSigned)
|
|
return notifyNew(literal.getAs(IntegerLiteralInst.self))
|
|
}
|
|
|
|
/// Creates a `Builtin.Int1` integer literal instruction with a value
|
|
/// corresponding to the given Boolean.
|
|
public func createBoolLiteral(_ value: Bool) -> IntegerLiteralInst {
|
|
let boolType = notificationHandler.getBuiltinIntegerType(1).type
|
|
let integerValue: UInt = value ? 1 : 0
|
|
return createIntegerLiteral(integerValue, type: boolType)
|
|
}
|
|
|
|
public func createAllocRef(_ type: Type, isObjC: Bool = false, canAllocOnStack: Bool = false, isBare: Bool = false,
|
|
tailAllocatedTypes: TypeArray, tailAllocatedCounts: [Value]) -> AllocRefInst {
|
|
return tailAllocatedCounts.withBridgedValues { countsRef in
|
|
let dr = bridged.createAllocRef(type.bridged, isObjC, canAllocOnStack, isBare, tailAllocatedTypes.bridged, countsRef)
|
|
return notifyNew(dr.getAs(AllocRefInst.self))
|
|
}
|
|
}
|
|
|
|
public func createAllocStack(_ type: Type,
|
|
debugVariable: DebugVariableInstruction.DebugVariable? = nil,
|
|
hasDynamicLifetime: Bool = false,
|
|
isLexical: Bool = false, isFromVarDecl: Bool = false,
|
|
usesMoveableValueDebugInfo: Bool = false) -> AllocStackInst {
|
|
let allocStack: BridgedInstruction
|
|
if let debugVariable = debugVariable {
|
|
allocStack = bridged.createAllocStack(type.bridged, debugVariable, hasDynamicLifetime, isLexical,
|
|
isFromVarDecl, usesMoveableValueDebugInfo)
|
|
} else {
|
|
allocStack = bridged.createAllocStack(type.bridged, hasDynamicLifetime, isLexical,
|
|
isFromVarDecl, usesMoveableValueDebugInfo)
|
|
}
|
|
return notifyNew(allocStack.getAs(AllocStackInst.self))
|
|
}
|
|
|
|
public func createAllocPack(_ packType: Type) -> AllocPackInst {
|
|
let allocPack = bridged.createAllocPack(packType.bridged)
|
|
return notifyNew(allocPack.getAs(AllocPackInst.self))
|
|
}
|
|
|
|
public func createAllocPackMetadata() -> AllocPackMetadataInst {
|
|
let allocPackMetadata = bridged.createAllocPackMetadata()
|
|
return notifyNew(allocPackMetadata.getAs(AllocPackMetadataInst.self))
|
|
}
|
|
|
|
public func createAllocPackMetadata(_ packType: Type) -> AllocPackMetadataInst {
|
|
let allocPackMetadata = bridged.createAllocPackMetadata(packType.bridged)
|
|
return notifyNew(allocPackMetadata.getAs(AllocPackMetadataInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createDeallocStack(_ operand: Value) -> DeallocStackInst {
|
|
let dr = bridged.createDeallocStack(operand.bridged)
|
|
return notifyNew(dr.getAs(DeallocStackInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createDeallocPack(_ operand: Value) -> DeallocPackInst {
|
|
let dr = bridged.createDeallocPack(operand.bridged)
|
|
return notifyNew(dr.getAs(DeallocPackInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createDeallocStackRef(_ operand: Value) -> DeallocStackRefInst {
|
|
let dr = bridged.createDeallocStackRef(operand.bridged)
|
|
return notifyNew(dr.getAs(DeallocStackRefInst.self))
|
|
}
|
|
|
|
public func createAddressToPointer(address: Value, pointerType: Type,
|
|
needStackProtection: Bool) -> AddressToPointerInst {
|
|
let dr = bridged.createAddressToPointer(address.bridged, pointerType.bridged, needStackProtection)
|
|
return notifyNew(dr.getAs(AddressToPointerInst.self))
|
|
}
|
|
|
|
public func createPointerToAddress(pointer: Value, addressType: Type,
|
|
isStrict: Bool, isInvariant: Bool,
|
|
alignment: Int? = nil) -> PointerToAddressInst {
|
|
let dr = bridged.createPointerToAddress(pointer.bridged, addressType.bridged, isStrict, isInvariant,
|
|
UInt64(alignment ?? 0))
|
|
return notifyNew(dr.getAs(PointerToAddressInst.self))
|
|
}
|
|
|
|
public func createIndexAddr(base: Value, index: Value, needStackProtection: Bool) -> IndexAddrInst {
|
|
let dr = bridged.createIndexAddr(base.bridged, index.bridged, needStackProtection)
|
|
return notifyNew(dr.getAs(IndexAddrInst.self))
|
|
}
|
|
|
|
public func createUncheckedRefCast(from value: Value, to type: Type) -> UncheckedRefCastInst {
|
|
let cast = bridged.createUncheckedRefCast(value.bridged, type.bridged)
|
|
return notifyNew(cast.getAs(UncheckedRefCastInst.self))
|
|
}
|
|
|
|
public func createUncheckedAddrCast(from value: Value, to type: Type) -> UncheckedAddrCastInst {
|
|
let cast = bridged.createUncheckedAddrCast(value.bridged, type.bridged)
|
|
return notifyNew(cast.getAs(UncheckedAddrCastInst.self))
|
|
}
|
|
|
|
public func createUncheckedValueCast(from value: Value, to type: Type) -> UncheckedValueCastInst {
|
|
let cast = bridged.createUncheckedValueCast(value.bridged, type.bridged)
|
|
return notifyNew(cast.getAs(UncheckedValueCastInst.self))
|
|
}
|
|
|
|
public func createUpcast(from value: Value, to type: Type) -> UpcastInst {
|
|
let cast = bridged.createUpcast(value.bridged, type.bridged)
|
|
return notifyNew(cast.getAs(UpcastInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createCheckedCastAddrBranch(
|
|
source: Value, sourceFormalType: CanonicalType,
|
|
destination: Value, targetFormalType: CanonicalType,
|
|
options: CheckedCastInstOptions,
|
|
consumptionKind: CheckedCastAddrBranchInst.CastConsumptionKind,
|
|
successBlock: BasicBlock,
|
|
failureBlock: BasicBlock
|
|
) -> CheckedCastAddrBranchInst {
|
|
|
|
let bridgedConsumption: BridgedInstruction.CastConsumptionKind
|
|
switch consumptionKind {
|
|
case .TakeAlways: bridgedConsumption = .TakeAlways
|
|
case .TakeOnSuccess: bridgedConsumption = .TakeOnSuccess
|
|
case .CopyOnSuccess: bridgedConsumption = .CopyOnSuccess
|
|
}
|
|
|
|
let cast = bridged.createCheckedCastAddrBranch(source.bridged, sourceFormalType.bridged,
|
|
destination.bridged, targetFormalType.bridged,
|
|
options.bridged,
|
|
bridgedConsumption,
|
|
successBlock.bridged, failureBlock.bridged)
|
|
return notifyNew(cast.getAs(CheckedCastAddrBranchInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createUnconditionalCheckedCastAddr(
|
|
options: CheckedCastInstOptions,
|
|
source: Value, sourceFormalType: CanonicalType,
|
|
destination: Value, targetFormalType: CanonicalType
|
|
) -> UnconditionalCheckedCastAddrInst {
|
|
let cast = bridged.createUnconditionalCheckedCastAddr(
|
|
options.bridged, source.bridged, sourceFormalType.bridged,
|
|
destination.bridged, targetFormalType.bridged
|
|
)
|
|
return notifyNew(cast.getAs(UnconditionalCheckedCastAddrInst.self))
|
|
}
|
|
|
|
public func createUncheckedOwnershipConversion(
|
|
operand: Value, resultOwnership: Ownership
|
|
) -> UncheckedOwnershipConversionInst {
|
|
let uoc = bridged.createUncheckedOwnershipConversion(operand.bridged, resultOwnership._bridged)
|
|
return notifyNew(uoc.getAs(UncheckedOwnershipConversionInst.self))
|
|
}
|
|
|
|
public func createLoad(fromAddress: Value, ownership: LoadInst.LoadOwnership) -> LoadInst {
|
|
let load = bridged.createLoad(fromAddress.bridged, ownership.rawValue)
|
|
return notifyNew(load.getAs(LoadInst.self))
|
|
}
|
|
|
|
public func createLoadBorrow(fromAddress: Value) -> LoadBorrowInst {
|
|
let load = bridged.createLoadBorrow(fromAddress.bridged)
|
|
return notifyNew(load.getAs(LoadBorrowInst.self))
|
|
}
|
|
|
|
public func createBeginDeallocRef(reference: Value, allocation: AllocRefInstBase) -> BeginDeallocRefInst {
|
|
let beginDealloc = bridged.createBeginDeallocRef(reference.bridged, allocation.bridged)
|
|
return notifyNew(beginDealloc.getAs(BeginDeallocRefInst.self))
|
|
}
|
|
|
|
public func createEndInitLetRef(operand: Value) -> EndInitLetRefInst {
|
|
let endInit = bridged.createEndInitLetRef(operand.bridged)
|
|
return notifyNew(endInit.getAs(EndInitLetRefInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createRetainValue(operand: Value) -> RetainValueInst {
|
|
let retain = bridged.createRetainValue(operand.bridged)
|
|
return notifyNew(retain.getAs(RetainValueInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createReleaseValue(operand: Value) -> ReleaseValueInst {
|
|
let release = bridged.createReleaseValue(operand.bridged)
|
|
return notifyNew(release.getAs(ReleaseValueInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createStrongRetain(operand: Value) -> StrongRetainInst {
|
|
let retain = bridged.createStrongRetain(operand.bridged)
|
|
return notifyNew(retain.getAs(StrongRetainInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createStrongRelease(operand: Value) -> StrongReleaseInst {
|
|
let release = bridged.createStrongRelease(operand.bridged)
|
|
return notifyNew(release.getAs(StrongReleaseInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createUnownedRetain(operand: Value) -> UnownedRetainInst {
|
|
let retain = bridged.createUnownedRetain(operand.bridged)
|
|
return notifyNew(retain.getAs(UnownedRetainInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createUnownedRelease(operand: Value) -> UnownedReleaseInst {
|
|
let release = bridged.createUnownedRelease(operand.bridged)
|
|
return notifyNew(release.getAs(UnownedReleaseInst.self))
|
|
}
|
|
|
|
public func createFunctionRef(_ function: Function) -> FunctionRefInst {
|
|
let functionRef = bridged.createFunctionRef(function.bridged)
|
|
return notifyNew(functionRef.getAs(FunctionRefInst.self))
|
|
}
|
|
|
|
public func createCopyValue(operand: Value) -> CopyValueInst {
|
|
return notifyNew(bridged.createCopyValue(operand.bridged).getAs(CopyValueInst.self))
|
|
}
|
|
|
|
public func createBeginBorrow(
|
|
of value: Value,
|
|
isLexical: Bool = false,
|
|
hasPointerEscape: Bool = false,
|
|
isFromVarDecl: Bool = false
|
|
) -> BeginBorrowInst {
|
|
return notifyNew(bridged.createBeginBorrow(value.bridged,
|
|
isLexical, hasPointerEscape, isFromVarDecl).getAs(BeginBorrowInst.self))
|
|
}
|
|
|
|
public func createBorrowedFrom(borrowedValue: Value, enclosingValues: [Value]) -> BorrowedFromInst {
|
|
let bfi = enclosingValues.withBridgedValues { valuesRef in
|
|
return bridged.createBorrowedFrom(borrowedValue.bridged, valuesRef)
|
|
}
|
|
return notifyNew(bfi.getAs(BorrowedFromInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createEndBorrow(of beginBorrow: Value) -> EndBorrowInst {
|
|
return notifyNew(bridged.createEndBorrow(beginBorrow.bridged).getAs(EndBorrowInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createCopyAddr(from fromAddr: Value, to toAddr: Value,
|
|
takeSource: Bool = false, initializeDest: Bool = false) -> CopyAddrInst {
|
|
return notifyNew(bridged.createCopyAddr(fromAddr.bridged, toAddr.bridged,
|
|
takeSource, initializeDest).getAs(CopyAddrInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createDestroyValue(operand: Value) -> DestroyValueInst {
|
|
return notifyNew(bridged.createDestroyValue(operand.bridged).getAs(DestroyValueInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createDestroyAddr(address: Value) -> DestroyAddrInst {
|
|
return notifyNew(bridged.createDestroyAddr(address.bridged).getAs(DestroyAddrInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createEndLifetime(of value: Value) -> EndLifetimeInst {
|
|
return notifyNew(bridged.createEndLifetime(value.bridged).getAs(EndLifetimeInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createDebugValue(value: Value, debugVariable: DebugVariableInstruction.DebugVariable) -> DebugValueInst {
|
|
return notifyNew(bridged.createDebugValue(value.bridged, debugVariable).getAs(DebugValueInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createDebugStep() -> DebugStepInst {
|
|
return notifyNew(bridged.createDebugStep().getAs(DebugStepInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createApply(
|
|
function: Value,
|
|
_ substitutionMap: SubstitutionMap,
|
|
arguments: [Value],
|
|
isNonThrowing: Bool = false,
|
|
isNonAsync: Bool = false,
|
|
specializationInfo: ApplyInst.SpecializationInfo = ApplyInst.SpecializationInfo()
|
|
) -> ApplyInst {
|
|
let apply = arguments.withBridgedValues { valuesRef in
|
|
bridged.createApply(function.bridged, substitutionMap.bridged, valuesRef,
|
|
isNonThrowing, isNonAsync, specializationInfo)
|
|
}
|
|
return notifyNew(apply.getAs(ApplyInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createTryApply(
|
|
function: Value,
|
|
_ substitutionMap: SubstitutionMap,
|
|
arguments: [Value],
|
|
normalBlock: BasicBlock,
|
|
errorBlock: BasicBlock,
|
|
isNonAsync: Bool = false,
|
|
specializationInfo: ApplyInst.SpecializationInfo = ApplyInst.SpecializationInfo()
|
|
) -> TryApplyInst {
|
|
let apply = arguments.withBridgedValues { valuesRef in
|
|
bridged.createTryApply(function.bridged, substitutionMap.bridged, valuesRef,
|
|
normalBlock.bridged, errorBlock.bridged,
|
|
isNonAsync, specializationInfo)
|
|
}
|
|
return notifyNew(apply.getAs(TryApplyInst.self))
|
|
}
|
|
|
|
public func createBeginApply(function: Value,
|
|
_ substitutionMap: SubstitutionMap,
|
|
arguments: [Value],
|
|
isNonThrowing: Bool = false,
|
|
isNonAsync: Bool = false,
|
|
specializationInfo: ApplyInst.SpecializationInfo = ApplyInst.SpecializationInfo()
|
|
) -> BeginApplyInst {
|
|
let apply = arguments.withBridgedValues { valuesRef in
|
|
bridged.createBeginApply(function.bridged, substitutionMap.bridged, valuesRef,
|
|
isNonThrowing, isNonAsync, specializationInfo)
|
|
}
|
|
return notifyNew(apply.getAs(BeginApplyInst.self))
|
|
}
|
|
|
|
public func createWitnessMethod(lookupType: CanonicalType,
|
|
conformance: Conformance,
|
|
member: DeclRef,
|
|
methodType: Type) -> WitnessMethodInst {
|
|
return notifyNew(bridged.createWitnessMethod(lookupType.bridged, conformance.bridged,
|
|
member.bridged, methodType.bridged).getAs(WitnessMethodInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createReturn(of value: Value) -> ReturnInst {
|
|
return notifyNew(bridged.createReturn(value.bridged).getAs(ReturnInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createThrow(of value: Value) -> ThrowInst {
|
|
return notifyNew(bridged.createThrow(value.bridged).getAs(ThrowInst.self))
|
|
}
|
|
|
|
public func createUncheckedEnumData(enum enumVal: Value,
|
|
caseIndex: Int,
|
|
resultType: Type) -> UncheckedEnumDataInst {
|
|
let ued = bridged.createUncheckedEnumData(enumVal.bridged, caseIndex, resultType.bridged)
|
|
return notifyNew(ued.getAs(UncheckedEnumDataInst.self))
|
|
}
|
|
|
|
public func createUncheckedTakeEnumDataAddr(enumAddress: Value,
|
|
caseIndex: Int) -> UncheckedTakeEnumDataAddrInst {
|
|
let uteda = bridged.createUncheckedTakeEnumDataAddr(enumAddress.bridged, caseIndex)
|
|
return notifyNew(uteda.getAs(UncheckedTakeEnumDataAddrInst.self))
|
|
}
|
|
|
|
public func createInitEnumDataAddr(enumAddress: Value, caseIndex: Int, type: Type) -> InitEnumDataAddrInst {
|
|
let uteda = bridged.createInitEnumDataAddr(enumAddress.bridged, caseIndex, type.bridged)
|
|
return notifyNew(uteda.getAs(InitEnumDataAddrInst.self))
|
|
}
|
|
|
|
public func createEnum(caseIndex: Int, payload: Value?, enumType: Type) -> EnumInst {
|
|
let enumInst = bridged.createEnum(caseIndex, payload.bridged, enumType.bridged)
|
|
return notifyNew(enumInst.getAs(EnumInst.self))
|
|
}
|
|
|
|
static let optionalNoneCaseIndex = 0
|
|
static let optionalSomeCaseIndex = 1
|
|
|
|
public func createOptionalNone(type: Type) -> EnumInst {
|
|
return createEnum(caseIndex: Self.optionalNoneCaseIndex, payload: nil, enumType: type)
|
|
}
|
|
|
|
public func createOptionalSome(operand: Value, type: Type) -> EnumInst {
|
|
return createEnum(caseIndex: Self.optionalSomeCaseIndex, payload: operand, enumType: type)
|
|
}
|
|
|
|
public func createThinToThickFunction(thinFunction: Value, resultType: Type) -> ThinToThickFunctionInst {
|
|
let tttf = bridged.createThinToThickFunction(thinFunction.bridged, resultType.bridged)
|
|
return notifyNew(tttf.getAs(ThinToThickFunctionInst.self))
|
|
}
|
|
|
|
public func createPartialApply(
|
|
function: Value,
|
|
substitutionMap: SubstitutionMap,
|
|
capturedArguments: [Value],
|
|
calleeConvention: ArgumentConvention,
|
|
hasUnknownResultIsolation: Bool,
|
|
isOnStack: Bool
|
|
) -> PartialApplyInst {
|
|
return capturedArguments.withBridgedValues { capturedArgsRef in
|
|
let pai = bridged.createPartialApply(function.bridged, capturedArgsRef, calleeConvention.bridged, substitutionMap.bridged, hasUnknownResultIsolation, isOnStack)
|
|
return notifyNew(pai.getAs(PartialApplyInst.self))
|
|
}
|
|
}
|
|
|
|
@discardableResult
|
|
public func createSwitchEnum(enum enumVal: Value,
|
|
cases: [(Int, BasicBlock)],
|
|
defaultBlock: BasicBlock? = nil) -> SwitchEnumInst {
|
|
let se = cases.withUnsafeBufferPointer { caseBuffer in
|
|
bridged.createSwitchEnumInst(enumVal.bridged, defaultBlock.bridged,
|
|
caseBuffer.baseAddress, caseBuffer.count)
|
|
}
|
|
return notifyNew(se.getAs(SwitchEnumInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createSwitchEnumAddr(enumAddress: Value,
|
|
cases: [(Int, BasicBlock)],
|
|
defaultBlock: BasicBlock? = nil) -> SwitchEnumAddrInst {
|
|
let se = cases.withUnsafeBufferPointer { caseBuffer in
|
|
bridged.createSwitchEnumAddrInst(enumAddress.bridged, defaultBlock.bridged,
|
|
caseBuffer.baseAddress, caseBuffer.count)
|
|
}
|
|
return notifyNew(se.getAs(SwitchEnumAddrInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createBranch(to destBlock: BasicBlock, arguments: [Value] = []) -> BranchInst {
|
|
return arguments.withBridgedValues { valuesRef in
|
|
let bi = bridged.createBranch(destBlock.bridged, valuesRef)
|
|
return notifyNew(bi.getAs(BranchInst.self))
|
|
}
|
|
}
|
|
|
|
@discardableResult
|
|
public func createCondBranch(condition: Value, trueBlock: BasicBlock, falseBlock: BasicBlock) -> CondBranchInst {
|
|
let condBr = bridged.createCondBranch(condition.bridged, trueBlock.bridged, falseBlock.bridged)
|
|
return notifyNew(condBr.getAs(CondBranchInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createUnreachable() -> UnreachableInst {
|
|
let ui = bridged.createUnreachable()
|
|
return notifyNew(ui.getAs(UnreachableInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createObject(type: Type, arguments: [Value], numBaseElements: Int) -> ObjectInst {
|
|
let objectInst = arguments.withBridgedValues { valuesRef in
|
|
return bridged.createObject(type.bridged, valuesRef, numBaseElements)
|
|
}
|
|
return notifyNew(objectInst.getAs(ObjectInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createVector(type: Type, arguments: [Value]) -> VectorInst {
|
|
let vectorInst = arguments.withBridgedValues { valuesRef in
|
|
return bridged.createVector(valuesRef)
|
|
}
|
|
return notifyNew(vectorInst.getAs(VectorInst.self))
|
|
}
|
|
|
|
public func createVectorBaseAddr(vector: Value) -> VectorBaseAddrInst {
|
|
return notifyNew(bridged.createVectorBaseAddr(vector.bridged).getAs(VectorBaseAddrInst.self))
|
|
}
|
|
|
|
public func createGlobalAddr(global: GlobalVariable, dependencyToken: Value?) -> GlobalAddrInst {
|
|
return notifyNew(bridged.createGlobalAddr(global.bridged, dependencyToken.bridged).getAs(GlobalAddrInst.self))
|
|
}
|
|
|
|
public func createGlobalValue(global: GlobalVariable, isBare: Bool) -> GlobalValueInst {
|
|
return notifyNew(bridged.createGlobalValue(global.bridged, isBare).getAs(GlobalValueInst.self))
|
|
}
|
|
|
|
public func createStruct(type: Type, elements: [Value]) -> StructInst {
|
|
let structInst = elements.withBridgedValues { valuesRef in
|
|
return bridged.createStruct(type.bridged, valuesRef)
|
|
}
|
|
return notifyNew(structInst.getAs(StructInst.self))
|
|
}
|
|
|
|
public func createStructExtract(struct: Value, fieldIndex: Int) -> StructExtractInst {
|
|
return notifyNew(bridged.createStructExtract(`struct`.bridged, fieldIndex).getAs(StructExtractInst.self))
|
|
}
|
|
|
|
public func createStructElementAddr(structAddress: Value, fieldIndex: Int) -> StructElementAddrInst {
|
|
return notifyNew(bridged.createStructElementAddr(structAddress.bridged, fieldIndex).getAs(StructElementAddrInst.self))
|
|
}
|
|
|
|
public func createDestructureStruct(struct: Value) -> DestructureStructInst {
|
|
return notifyNew(bridged.createDestructureStruct(`struct`.bridged).getAs(DestructureStructInst.self))
|
|
}
|
|
|
|
public func createTuple(type: Type, elements: [Value]) -> TupleInst {
|
|
let tuple = elements.withBridgedValues { valuesRef in
|
|
return bridged.createTuple(type.bridged, valuesRef)
|
|
}
|
|
return notifyNew(tuple.getAs(TupleInst.self))
|
|
}
|
|
|
|
public func createTupleExtract(tuple: Value, elementIndex: Int) -> TupleExtractInst {
|
|
return notifyNew(bridged.createTupleExtract(tuple.bridged, elementIndex).getAs(TupleExtractInst.self))
|
|
}
|
|
|
|
public func createTupleElementAddr(tupleAddress: Value, elementIndex: Int) -> TupleElementAddrInst {
|
|
return notifyNew(bridged.createTupleElementAddr(tupleAddress.bridged, elementIndex).getAs(TupleElementAddrInst.self))
|
|
}
|
|
|
|
public func createDestructureTuple(tuple: Value) -> DestructureTupleInst {
|
|
return notifyNew(bridged.createDestructureTuple(tuple.bridged).getAs(DestructureTupleInst.self))
|
|
}
|
|
|
|
public func createProjectBox(box: Value, fieldIndex: Int) -> ProjectBoxInst {
|
|
return notifyNew(bridged.createProjectBox(box.bridged, fieldIndex).getAs(ProjectBoxInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createStore(source: Value, destination: Value, ownership: StoreInst.StoreOwnership) -> StoreInst {
|
|
let store = bridged.createStore(source.bridged, destination.bridged, ownership.rawValue)
|
|
return notifyNew(store.getAs(StoreInst.self))
|
|
}
|
|
|
|
public func createStoreBorrow(source: Value, destination: Value) -> StoreBorrowInst {
|
|
let storeBorrow = bridged.createStoreBorrow(source.bridged, destination.bridged)
|
|
return notifyNew(storeBorrow.getAs(StoreBorrowInst.self))
|
|
}
|
|
|
|
public func createInitExistentialRef(instance: Value,
|
|
existentialType: Type,
|
|
formalConcreteType: CanonicalType,
|
|
conformances: ConformanceArray) -> InitExistentialRefInst {
|
|
let initExistential = bridged.createInitExistentialRef(instance.bridged,
|
|
existentialType.bridged,
|
|
formalConcreteType.bridged,
|
|
conformances.bridged)
|
|
return notifyNew(initExistential.getAs(InitExistentialRefInst.self))
|
|
}
|
|
|
|
public func createInitExistentialMetatype(
|
|
metatype: Value,
|
|
existentialType: Type,
|
|
conformances: [Conformance]
|
|
) -> InitExistentialMetatypeInst {
|
|
let initExistential = conformances.map{ $0.bridged }.withBridgedArrayRef {
|
|
return bridged.createInitExistentialMetatype(metatype.bridged,
|
|
existentialType.bridged,
|
|
BridgedConformanceArray(pcArray: $0))
|
|
}
|
|
return notifyNew(initExistential.getAs(InitExistentialMetatypeInst.self))
|
|
}
|
|
|
|
public func createScalarPackIndex(componentIndex: Int, indexedPackType: CanonicalType) -> ScalarPackIndexInst {
|
|
let scalarPackIndex = bridged.createScalarPackIndex(SwiftInt(componentIndex), indexedPackType.bridged)
|
|
return notifyNew(scalarPackIndex.getAs(ScalarPackIndexInst.self))
|
|
}
|
|
|
|
public func createPackElementGet(packIndex: Value, pack: Value, elementType: Type) -> PackElementGetInst {
|
|
let packElementGet = bridged.createPackElementGet(packIndex.bridged, pack.bridged, elementType.bridged)
|
|
return notifyNew(packElementGet.getAs(PackElementGetInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createPackElementSet(elementValue: Value, packIndex: Value, pack: Value) -> PackElementSetInst {
|
|
let packElementSet = bridged.createPackElementSet(elementValue.bridged, packIndex.bridged, pack.bridged)
|
|
return notifyNew(packElementSet.getAs(PackElementSetInst.self))
|
|
}
|
|
|
|
public func createMetatype(
|
|
ofInstanceType instanceType: CanonicalType,
|
|
representation: AST.`Type`.MetatypeRepresentation
|
|
) -> MetatypeInst {
|
|
let bridgedRep: BridgedASTType.MetatypeRepresentation
|
|
switch representation {
|
|
case .thin: bridgedRep = .Thin
|
|
case .thick: bridgedRep = .Thick
|
|
case .objC: bridgedRep = .ObjC
|
|
}
|
|
let metatype = bridged.createMetatype(instanceType.bridged, bridgedRep)
|
|
return notifyNew(metatype.getAs(MetatypeInst.self))
|
|
}
|
|
|
|
public func createEndCOWMutation(instance: Value, keepUnique: Bool) -> EndCOWMutationInst {
|
|
let endMutation = bridged.createEndCOWMutation(instance.bridged, keepUnique)
|
|
return notifyNew(endMutation.getAs(EndCOWMutationInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createEndCOWMutationAddr(address: Value) -> EndCOWMutationAddrInst {
|
|
let endMutation = bridged.createEndCOWMutationAddr(address.bridged)
|
|
return notifyNew(endMutation.getAs(EndCOWMutationAddrInst.self))
|
|
}
|
|
|
|
public func createMarkDependence(value: Value, base: Value, kind: MarkDependenceKind) -> MarkDependenceInst {
|
|
let markDependence = bridged.createMarkDependence(value.bridged, base.bridged,
|
|
BridgedInstruction.MarkDependenceKind(rawValue: kind.rawValue)!)
|
|
return notifyNew(markDependence.getAs(MarkDependenceInst.self))
|
|
}
|
|
|
|
public func createMarkDependenceAddr(value: Value, base: Value, kind: MarkDependenceKind) -> MarkDependenceAddrInst {
|
|
let markDependence = bridged.createMarkDependenceAddr(
|
|
value.bridged, base.bridged, BridgedInstruction.MarkDependenceKind(rawValue: kind.rawValue)!)
|
|
return notifyNew(markDependence.getAs(MarkDependenceAddrInst.self))
|
|
}
|
|
|
|
public func createMarkUninitialized(value: Value, kind: MarkUninitializedInst.Kind) -> MarkUninitializedInst {
|
|
let mu = bridged.createMarkUninitialized(value.bridged, kind.rawValue)
|
|
return notifyNew(mu.getAs(MarkUninitializedInst.self))
|
|
}
|
|
|
|
public func createMarkUnresolvedNonCopyableValue(value: Value,
|
|
checkKind: MarkUnresolvedNonCopyableValueInst.CheckKind,
|
|
isStrict: Bool) -> MarkUnresolvedNonCopyableValueInst {
|
|
let mu = bridged.createMarkUnresolvedNonCopyableValue(value.bridged, checkKind.rawValue, isStrict)
|
|
return notifyNew(mu.getAs(MarkUnresolvedNonCopyableValueInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createEndAccess(beginAccess: BeginAccessInst) -> EndAccessInst {
|
|
let endAccess = bridged.createEndAccess(beginAccess.bridged)
|
|
return notifyNew(endAccess.getAs(EndAccessInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createEndApply(beginApply: BeginApplyInst) -> EndApplyInst {
|
|
let endApply = bridged.createEndApply(beginApply.token.bridged)
|
|
return notifyNew(endApply.getAs(EndApplyInst.self))
|
|
}
|
|
|
|
@discardableResult
|
|
public func createAbortApply(beginApply: BeginApplyInst) -> AbortApplyInst {
|
|
let endApply = bridged.createAbortApply(beginApply.token.bridged)
|
|
return notifyNew(endApply.getAs(AbortApplyInst.self))
|
|
}
|
|
|
|
public func createConvertFunction(originalFunction: Value, resultType: Type, withoutActuallyEscaping: Bool) -> ConvertFunctionInst {
|
|
let convertFunction = bridged.createConvertFunction(originalFunction.bridged, resultType.bridged, withoutActuallyEscaping)
|
|
return notifyNew(convertFunction.getAs(ConvertFunctionInst.self))
|
|
}
|
|
|
|
public func createConvertEscapeToNoEscape(originalFunction: Value, resultType: Type, isLifetimeGuaranteed: Bool) -> ConvertEscapeToNoEscapeInst {
|
|
let convertFunction = bridged.createConvertEscapeToNoEscape(originalFunction.bridged, resultType.bridged, isLifetimeGuaranteed)
|
|
return notifyNew(convertFunction.getAs(ConvertEscapeToNoEscapeInst.self))
|
|
}
|
|
}
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Utilities
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
extension Builder {
|
|
public func emitDestroy(of value: Value) {
|
|
if value.type.isTrivial(in: value.parentFunction) {
|
|
return
|
|
}
|
|
if value.type.isAddress {
|
|
return
|
|
}
|
|
if value.parentFunction.hasOwnership {
|
|
createDestroyValue(operand: value)
|
|
} else if value.type.isClass {
|
|
createStrongRelease(operand: value)
|
|
} else {
|
|
createReleaseValue(operand: value)
|
|
}
|
|
}
|
|
}
|