| //===--- SILGenBuilder.cpp ------------------------------------------------===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "SILGenBuilder.h" |
| #include "ArgumentSource.h" |
| #include "RValue.h" |
| #include "SILGenFunction.h" |
| #include "Scope.h" |
| #include "SwitchCaseFullExpr.h" |
| #include "swift/AST/SubstitutionMap.h" |
| |
| using namespace swift; |
| using namespace Lowering; |
| |
| //===----------------------------------------------------------------------===// |
| // Utility Methods |
| //===----------------------------------------------------------------------===// |
| |
| SILGenModule &SILGenBuilder::getSILGenModule() const { return SGF.SGM; } |
| |
| //===----------------------------------------------------------------------===// |
| // Constructors |
| //===----------------------------------------------------------------------===// |
| |
| SILGenBuilder::SILGenBuilder(SILGenFunction &SGF) |
| : SILBuilder(SGF.F), SGF(SGF) {} |
| |
| SILGenBuilder::SILGenBuilder(SILGenFunction &SGF, SILBasicBlock *insertBB) |
| : SILBuilder(insertBB), SGF(SGF) {} |
| |
| SILGenBuilder::SILGenBuilder(SILGenFunction &SGF, SILBasicBlock *insertBB, |
| SmallVectorImpl<SILInstruction *> *insertedInsts) |
| : SILBuilder(insertBB, insertedInsts), SGF(SGF) {} |
| |
| SILGenBuilder::SILGenBuilder(SILGenFunction &SGF, SILBasicBlock *insertBB, |
| SILBasicBlock::iterator insertInst) |
| : SILBuilder(insertBB, insertInst), SGF(SGF) {} |
| |
| //===----------------------------------------------------------------------===// |
| // Instruction Emission |
| //===----------------------------------------------------------------------===// |
| |
| MetatypeInst *SILGenBuilder::createMetatype(SILLocation loc, SILType metatype) { |
| auto theMetatype = metatype.castTo<MetatypeType>(); |
| // Getting a nontrivial metatype requires forcing any conformances necessary |
| // to instantiate the type. |
| switch (theMetatype->getRepresentation()) { |
| case MetatypeRepresentation::Thin: |
| break; |
| case MetatypeRepresentation::Thick: |
| case MetatypeRepresentation::ObjC: { |
| // Walk the type recursively to look for substitutions we may need. |
| theMetatype.getInstanceType().findIf([&](Type t) -> bool { |
| auto *decl = t->getAnyNominal(); |
| if (!decl) |
| return false; |
| |
| auto *genericSig = decl->getGenericSignature(); |
| if (!genericSig) |
| return false; |
| |
| auto subMap = t->getContextSubstitutionMap(getSILGenModule().SwiftModule, |
| decl); |
| SmallVector<Substitution, 4> subs; |
| genericSig->getSubstitutions(subMap, subs); |
| getSILGenModule().useConformancesFromSubstitutions(subs); |
| return false; |
| }); |
| |
| break; |
| } |
| } |
| |
| return SILBuilder::createMetatype(loc, metatype); |
| } |
| |
| ApplyInst *SILGenBuilder::createApply(SILLocation loc, SILValue fn, |
| SILType substFnTy, SILType result, |
| SubstitutionList subs, |
| ArrayRef<SILValue> args) { |
| getSILGenModule().useConformancesFromSubstitutions(subs); |
| return SILBuilder::createApply(loc, fn, subs, args, false); |
| } |
| |
| TryApplyInst * |
| SILGenBuilder::createTryApply(SILLocation loc, SILValue fn, SILType substFnTy, |
| SubstitutionList subs, ArrayRef<SILValue> args, |
| SILBasicBlock *normalBB, SILBasicBlock *errorBB) { |
| getSILGenModule().useConformancesFromSubstitutions(subs); |
| return SILBuilder::createTryApply(loc, fn, subs, args, normalBB, errorBB); |
| } |
| |
| PartialApplyInst * |
| SILGenBuilder::createPartialApply(SILLocation loc, SILValue fn, |
| SILType substFnTy, SubstitutionList subs, |
| ArrayRef<SILValue> args, SILType closureTy) { |
| getSILGenModule().useConformancesFromSubstitutions(subs); |
| return SILBuilder::createPartialApply( |
| loc, fn, subs, args, |
| closureTy.getAs<SILFunctionType>()->getCalleeConvention()); |
| } |
| |
| BuiltinInst *SILGenBuilder::createBuiltin(SILLocation loc, Identifier name, |
| SILType resultTy, |
| SubstitutionList subs, |
| ArrayRef<SILValue> args) { |
| getSILGenModule().useConformancesFromSubstitutions(subs); |
| return SILBuilder::createBuiltin(loc, name, resultTy, subs, args); |
| } |
| |
| InitExistentialAddrInst *SILGenBuilder::createInitExistentialAddr( |
| SILLocation loc, SILValue existential, CanType formalConcreteType, |
| SILType loweredConcreteType, |
| ArrayRef<ProtocolConformanceRef> conformances) { |
| for (auto conformance : conformances) |
| getSILGenModule().useConformance(conformance); |
| |
| return SILBuilder::createInitExistentialAddr( |
| loc, existential, formalConcreteType, loweredConcreteType, conformances); |
| } |
| |
| InitExistentialValueInst *SILGenBuilder::createInitExistentialValue( |
| SILLocation Loc, SILType ExistentialType, CanType FormalConcreteType, |
| SILValue Concrete, ArrayRef<ProtocolConformanceRef> Conformances) { |
| for (auto conformance : Conformances) |
| getSILGenModule().useConformance(conformance); |
| |
| return SILBuilder::createInitExistentialValue( |
| Loc, ExistentialType, FormalConcreteType, Concrete, Conformances); |
| } |
| |
| ManagedValue SILGenBuilder::createInitExistentialValue( |
| SILLocation loc, SILType existentialType, CanType formalConcreteType, |
| ManagedValue concrete, ArrayRef<ProtocolConformanceRef> conformances) { |
| // *NOTE* we purposely do not use a cleanup cloner here. The reason why is no |
| // matter whether we have a trivial or non-trivial input, |
| // init_existential_value returns a +1 value (the COW box). |
| SILValue v = createInitExistentialValue( |
| loc, existentialType, formalConcreteType, concrete.forward(SGF), conformances); |
| return SGF.emitManagedRValueWithCleanup(v); |
| } |
| |
| InitExistentialMetatypeInst *SILGenBuilder::createInitExistentialMetatype( |
| SILLocation loc, SILValue metatype, SILType existentialType, |
| ArrayRef<ProtocolConformanceRef> conformances) { |
| for (auto conformance : conformances) |
| getSILGenModule().useConformance(conformance); |
| |
| return SILBuilder::createInitExistentialMetatype( |
| loc, metatype, existentialType, conformances); |
| } |
| |
| InitExistentialRefInst *SILGenBuilder::createInitExistentialRef( |
| SILLocation loc, SILType existentialType, CanType formalConcreteType, |
| SILValue concreteValue, ArrayRef<ProtocolConformanceRef> conformances) { |
| for (auto conformance : conformances) |
| getSILGenModule().useConformance(conformance); |
| |
| return SILBuilder::createInitExistentialRef( |
| loc, existentialType, formalConcreteType, concreteValue, conformances); |
| } |
| |
| ManagedValue SILGenBuilder::createInitExistentialRef( |
| SILLocation Loc, SILType ExistentialType, CanType FormalConcreteType, |
| ManagedValue Concrete, ArrayRef<ProtocolConformanceRef> Conformances) { |
| CleanupCloner Cloner(*this, Concrete); |
| InitExistentialRefInst *IERI = |
| createInitExistentialRef(Loc, ExistentialType, FormalConcreteType, |
| Concrete.forward(SGF), Conformances); |
| return Cloner.clone(IERI); |
| } |
| |
| AllocExistentialBoxInst *SILGenBuilder::createAllocExistentialBox( |
| SILLocation loc, SILType existentialType, CanType concreteType, |
| ArrayRef<ProtocolConformanceRef> conformances) { |
| for (auto conformance : conformances) |
| getSILGenModule().useConformance(conformance); |
| |
| return SILBuilder::createAllocExistentialBox(loc, existentialType, |
| concreteType, conformances); |
| } |
| |
| ManagedValue SILGenBuilder::createStructExtract(SILLocation loc, |
| ManagedValue base, |
| VarDecl *decl) { |
| ManagedValue borrowedBase = base.borrow(SGF, loc); |
| SILValue extract = |
| SILBuilder::createStructExtract(loc, borrowedBase.getValue(), decl); |
| return ManagedValue::forUnmanaged(extract); |
| } |
| |
| ManagedValue SILGenBuilder::createRefElementAddr(SILLocation loc, |
| ManagedValue operand, |
| VarDecl *field, |
| SILType resultTy) { |
| operand = operand.borrow(SGF, loc); |
| SILValue result = createRefElementAddr(loc, operand.getValue(), field); |
| return ManagedValue::forUnmanaged(result); |
| } |
| |
| ManagedValue SILGenBuilder::createCopyValue(SILLocation loc, |
| ManagedValue originalValue) { |
| auto &lowering = SGF.getTypeLowering(originalValue.getType()); |
| return createCopyValue(loc, originalValue, lowering); |
| } |
| |
| ManagedValue SILGenBuilder::createCopyValue(SILLocation loc, |
| ManagedValue originalValue, |
| const TypeLowering &lowering) { |
| if (lowering.isTrivial()) |
| return originalValue; |
| |
| SILType ty = originalValue.getType(); |
| assert(!ty.isAddress() && "Can not perform a copy value of an address typed " |
| "value"); |
| |
| if (ty.isObject() && |
| originalValue.getOwnershipKind() == ValueOwnershipKind::Trivial) { |
| return originalValue; |
| } |
| |
| SILValue result = |
| lowering.emitCopyValue(*this, loc, originalValue.getValue()); |
| return SGF.emitManagedRValueWithCleanup(result, lowering); |
| } |
| |
| ManagedValue SILGenBuilder::createCopyUnownedValue(SILLocation loc, |
| ManagedValue originalValue) { |
| auto unownedType = originalValue.getType().castTo<UnownedStorageType>(); |
| assert(unownedType->isLoadable(ResilienceExpansion::Maximal)); |
| (void)unownedType; |
| |
| SILValue result = |
| SILBuilder::createCopyUnownedValue(loc, originalValue.getValue()); |
| return SGF.emitManagedRValueWithCleanup(result); |
| } |
| |
| ManagedValue |
| SILGenBuilder::createUnsafeCopyUnownedValue(SILLocation loc, |
| ManagedValue originalValue) { |
| // *NOTE* The reason why this is unsafe is that we are converting and |
| // unconditionally retaining, rather than before converting from |
| // unmanaged->ref checking that our value is not yet uninitialized. |
| auto unmanagedType = originalValue.getType().getAs<UnmanagedStorageType>(); |
| SILValue result = SILBuilder::createUnmanagedToRef( |
| loc, originalValue.getValue(), |
| SILType::getPrimitiveObjectType(unmanagedType.getReferentType())); |
| result = SILBuilder::createCopyValue(loc, result); |
| return SGF.emitManagedRValueWithCleanup(result); |
| } |
| |
| ManagedValue SILGenBuilder::createOwnedPHIArgument(SILType type) { |
| SILPHIArgument *arg = |
| getInsertionBB()->createPHIArgument(type, ValueOwnershipKind::Owned); |
| return SGF.emitManagedRValueWithCleanup(arg); |
| } |
| |
| ManagedValue SILGenBuilder::createGuaranteedPHIArgument(SILType type) { |
| SILPHIArgument *arg = |
| getInsertionBB()->createPHIArgument(type, ValueOwnershipKind::Guaranteed); |
| return SGF.emitManagedBorrowedArgumentWithCleanup(arg); |
| } |
| |
| ManagedValue SILGenBuilder::createAllocRef( |
| SILLocation loc, SILType refType, bool objc, bool canAllocOnStack, |
| ArrayRef<SILType> inputElementTypes, |
| ArrayRef<ManagedValue> inputElementCountOperands) { |
| llvm::SmallVector<SILType, 8> elementTypes(inputElementTypes.begin(), |
| inputElementTypes.end()); |
| llvm::SmallVector<SILValue, 8> elementCountOperands; |
| std::transform(std::begin(inputElementCountOperands), |
| std::end(inputElementCountOperands), |
| std::back_inserter(elementCountOperands), |
| [](ManagedValue mv) -> SILValue { return mv.getValue(); }); |
| |
| AllocRefInst *i = SILBuilder::createAllocRef( |
| loc, refType, objc, canAllocOnStack, elementTypes, elementCountOperands); |
| return SGF.emitManagedRValueWithCleanup(i); |
| } |
| |
| ManagedValue SILGenBuilder::createAllocRefDynamic( |
| SILLocation loc, ManagedValue operand, SILType refType, bool objc, |
| ArrayRef<SILType> inputElementTypes, |
| ArrayRef<ManagedValue> inputElementCountOperands) { |
| llvm::SmallVector<SILType, 8> elementTypes(inputElementTypes.begin(), |
| inputElementTypes.end()); |
| llvm::SmallVector<SILValue, 8> elementCountOperands; |
| std::transform(std::begin(inputElementCountOperands), |
| std::end(inputElementCountOperands), |
| std::back_inserter(elementCountOperands), |
| [](ManagedValue mv) -> SILValue { return mv.getValue(); }); |
| |
| AllocRefDynamicInst *i = |
| SILBuilder::createAllocRefDynamic(loc, operand.getValue(), refType, objc, |
| elementTypes, elementCountOperands); |
| return SGF.emitManagedRValueWithCleanup(i); |
| } |
| |
| ManagedValue SILGenBuilder::createTupleExtract(SILLocation loc, |
| ManagedValue base, |
| unsigned index, SILType type) { |
| ManagedValue borrowedBase = SGF.emitManagedBeginBorrow(loc, base.getValue()); |
| SILValue extract = |
| SILBuilder::createTupleExtract(loc, borrowedBase.getValue(), index, type); |
| return ManagedValue::forUnmanaged(extract); |
| } |
| |
| ManagedValue SILGenBuilder::createTupleExtract(SILLocation loc, |
| ManagedValue value, |
| unsigned index) { |
| SILType type = value.getType().getTupleElementType(index); |
| return createTupleExtract(loc, value, index, type); |
| } |
| |
| ManagedValue SILGenBuilder::createLoadBorrow(SILLocation loc, |
| ManagedValue base) { |
| if (SGF.getTypeLowering(base.getType()).isTrivial()) { |
| auto *i = SILBuilder::createLoad(loc, base.getValue(), |
| LoadOwnershipQualifier::Trivial); |
| return ManagedValue::forUnmanaged(i); |
| } |
| |
| auto *i = SILBuilder::createLoadBorrow(loc, base.getValue()); |
| return SGF.emitManagedBorrowedRValueWithCleanup(base.getValue(), i); |
| } |
| |
| ManagedValue SILGenBuilder::createFormalAccessLoadBorrow(SILLocation loc, |
| ManagedValue base) { |
| if (SGF.getTypeLowering(base.getType()).isTrivial()) { |
| auto *i = SILBuilder::createLoad(loc, base.getValue(), |
| LoadOwnershipQualifier::Trivial); |
| return ManagedValue::forUnmanaged(i); |
| } |
| |
| SILValue baseValue = base.getValue(); |
| auto *i = SILBuilder::createLoadBorrow(loc, baseValue); |
| return SGF.emitFormalEvaluationManagedBorrowedRValueWithCleanup(loc, |
| baseValue, i); |
| } |
| |
| ManagedValue |
| SILGenBuilder::createFormalAccessCopyValue(SILLocation loc, |
| ManagedValue originalValue) { |
| SILType ty = originalValue.getType(); |
| const auto &lowering = SGF.getTypeLowering(ty); |
| if (lowering.isTrivial()) |
| return originalValue; |
| |
| assert(!lowering.isAddressOnly() && "cannot perform a copy value of an " |
| "address only type"); |
| |
| if (ty.isObject() && |
| originalValue.getOwnershipKind() == ValueOwnershipKind::Trivial) { |
| return originalValue; |
| } |
| |
| SILValue result = |
| lowering.emitCopyValue(*this, loc, originalValue.getValue()); |
| return SGF.emitFormalAccessManagedRValueWithCleanup(loc, result); |
| } |
| |
| ManagedValue SILGenBuilder::createFormalAccessCopyAddr( |
| SILLocation loc, ManagedValue originalAddr, SILValue newAddr, |
| IsTake_t isTake, IsInitialization_t isInit) { |
| SILBuilder::createCopyAddr(loc, originalAddr.getValue(), newAddr, isTake, |
| isInit); |
| return SGF.emitFormalAccessManagedBufferWithCleanup(loc, newAddr); |
| } |
| |
| ManagedValue SILGenBuilder::bufferForExpr( |
| SILLocation loc, SILType ty, const TypeLowering &lowering, |
| SGFContext context, std::function<void (SILValue)> rvalueEmitter) { |
| // If we have a single-buffer "emit into" initialization, use that for the |
| // result. |
| SILValue address = context.getAddressForInPlaceInitialization(SGF, loc); |
| |
| // If we couldn't emit into the Initialization, emit into a temporary |
| // allocation. |
| if (!address) { |
| address = SGF.emitTemporaryAllocation(loc, ty.getObjectType()); |
| } |
| |
| rvalueEmitter(address); |
| |
| // If we have a single-buffer "emit into" initialization, use that for the |
| // result. |
| if (context.finishInPlaceInitialization(SGF)) { |
| return ManagedValue::forInContext(); |
| } |
| |
| // Add a cleanup for the temporary we allocated. |
| if (lowering.isTrivial()) |
| return ManagedValue::forUnmanaged(address); |
| |
| return SGF.emitManagedBufferWithCleanup(address); |
| } |
| |
| |
| ManagedValue SILGenBuilder::formalAccessBufferForExpr( |
| SILLocation loc, SILType ty, const TypeLowering &lowering, |
| SGFContext context, std::function<void(SILValue)> rvalueEmitter) { |
| // If we have a single-buffer "emit into" initialization, use that for the |
| // result. |
| SILValue address = context.getAddressForInPlaceInitialization(SGF, loc); |
| |
| // If we couldn't emit into the Initialization, emit into a temporary |
| // allocation. |
| if (!address) { |
| address = SGF.emitTemporaryAllocation(loc, ty.getObjectType()); |
| } |
| |
| rvalueEmitter(address); |
| |
| // If we have a single-buffer "emit into" initialization, use that for the |
| // result. |
| if (context.finishInPlaceInitialization(SGF)) { |
| return ManagedValue::forInContext(); |
| } |
| |
| // Add a cleanup for the temporary we allocated. |
| if (lowering.isTrivial()) |
| return ManagedValue::forUnmanaged(address); |
| |
| return SGF.emitFormalAccessManagedBufferWithCleanup(loc, address); |
| } |
| |
| ManagedValue SILGenBuilder::createUncheckedEnumData(SILLocation loc, |
| ManagedValue operand, |
| EnumElementDecl *element) { |
| if (operand.hasCleanup()) { |
| SILValue newValue = |
| SILBuilder::createUncheckedEnumData(loc, operand.forward(SGF), element); |
| return SGF.emitManagedRValueWithCleanup(newValue); |
| } |
| |
| ManagedValue borrowedBase = operand.borrow(SGF, loc); |
| SILValue newValue = SILBuilder::createUncheckedEnumData( |
| loc, borrowedBase.getValue(), element); |
| return ManagedValue::forUnmanaged(newValue); |
| } |
| |
| ManagedValue SILGenBuilder::createUncheckedTakeEnumDataAddr( |
| SILLocation loc, ManagedValue operand, EnumElementDecl *element, |
| SILType ty) { |
| // First see if we have a cleanup. If we do, we are going to forward and emit |
| // a managed buffer with cleanup. |
| if (operand.hasCleanup()) { |
| return SGF.emitManagedBufferWithCleanup( |
| SILBuilder::createUncheckedTakeEnumDataAddr(loc, operand.forward(SGF), |
| element, ty)); |
| } |
| |
| SILValue result = SILBuilder::createUncheckedTakeEnumDataAddr( |
| loc, operand.getUnmanagedValue(), element, ty); |
| if (operand.isLValue()) |
| return ManagedValue::forLValue(result); |
| return ManagedValue::forUnmanaged(result); |
| } |
| |
| ManagedValue SILGenBuilder::createLoadTake(SILLocation loc, ManagedValue v) { |
| auto &lowering = SGF.getTypeLowering(v.getType()); |
| return createLoadTake(loc, v, lowering); |
| } |
| |
| ManagedValue SILGenBuilder::createLoadTake(SILLocation loc, ManagedValue v, |
| const TypeLowering &lowering) { |
| assert(lowering.getLoweredType().getAddressType() == v.getType()); |
| SILValue result = |
| lowering.emitLoadOfCopy(*this, loc, v.forward(SGF), IsTake); |
| if (lowering.isTrivial()) |
| return ManagedValue::forUnmanaged(result); |
| assert(!lowering.isAddressOnly() && "cannot retain an unloadable type"); |
| return SGF.emitManagedRValueWithCleanup(result, lowering); |
| } |
| |
| ManagedValue SILGenBuilder::createLoadCopy(SILLocation loc, ManagedValue v) { |
| auto &lowering = SGF.getTypeLowering(v.getType()); |
| return createLoadCopy(loc, v, lowering); |
| } |
| |
| ManagedValue SILGenBuilder::createLoadCopy(SILLocation loc, ManagedValue v, |
| const TypeLowering &lowering) { |
| assert(lowering.getLoweredType().getAddressType() == v.getType()); |
| SILValue result = |
| lowering.emitLoadOfCopy(*this, loc, v.getValue(), IsNotTake); |
| if (lowering.isTrivial()) |
| return ManagedValue::forUnmanaged(result); |
| assert((!lowering.isAddressOnly() |
| || !SGF.silConv.useLoweredAddresses()) && |
| "cannot retain an unloadable type"); |
| return SGF.emitManagedRValueWithCleanup(result, lowering); |
| } |
| |
| ManagedValue SILGenBuilder::createFunctionArgument(SILType type, |
| ValueDecl *decl) { |
| SILFunction &F = getFunction(); |
| |
| SILFunctionArgument *arg = F.begin()->createFunctionArgument(type, decl); |
| if (arg->getType().isObject()) { |
| if (arg->getOwnershipKind().isTrivialOr(ValueOwnershipKind::Owned)) |
| return SGF.emitManagedRValueWithCleanup(arg); |
| return ManagedValue::forBorrowedRValue(arg); |
| } |
| |
| return SGF.emitManagedBufferWithCleanup(arg); |
| } |
| |
| ManagedValue |
| SILGenBuilder::createMarkUninitialized(ValueDecl *decl, ManagedValue operand, |
| MarkUninitializedInst::Kind muKind) { |
| // We either have an owned or trivial value. |
| SILValue value = |
| SILBuilder::createMarkUninitialized(decl, operand.forward(SGF), muKind); |
| assert(value->getType().isObject() && "Expected only objects here"); |
| |
| // If we have a trivial value, just return without a cleanup. |
| if (operand.getOwnershipKind() != ValueOwnershipKind::Owned) { |
| return ManagedValue::forUnmanaged(value); |
| } |
| |
| // Otherwise, recreate the cleanup. |
| return SGF.emitManagedRValueWithCleanup(value); |
| } |
| |
| ManagedValue SILGenBuilder::createEnum(SILLocation loc, ManagedValue payload, |
| EnumElementDecl *decl, SILType type) { |
| SILValue result = |
| SILBuilder::createEnum(loc, payload.forward(SGF), decl, type); |
| if (result.getOwnershipKind() != ValueOwnershipKind::Owned) |
| return ManagedValue::forUnmanaged(result); |
| return SGF.emitManagedRValueWithCleanup(result); |
| } |
| |
| ManagedValue SILGenBuilder::createUnconditionalCheckedCastValue( |
| SILLocation loc, ManagedValue operand, SILType type) { |
| SILValue result = SILBuilder::createUnconditionalCheckedCastValue( |
| loc, operand.forward(SGF), type); |
| return SGF.emitManagedRValueWithCleanup(result); |
| } |
| |
| ManagedValue SILGenBuilder::createUnconditionalCheckedCast(SILLocation loc, |
| ManagedValue operand, |
| SILType type) { |
| SILValue result = SILBuilder::createUnconditionalCheckedCast( |
| loc, operand.forward(SGF), type); |
| return SGF.emitManagedRValueWithCleanup(result); |
| } |
| |
| void SILGenBuilder::createCheckedCastBranch(SILLocation loc, bool isExact, |
| ManagedValue operand, SILType type, |
| SILBasicBlock *trueBlock, |
| SILBasicBlock *falseBlock) { |
| SILBuilder::createCheckedCastBranch(loc, isExact, operand.forward(SGF), type, |
| trueBlock, falseBlock); |
| } |
| |
| void SILGenBuilder::createCheckedCastValueBranch(SILLocation loc, |
| ManagedValue operand, |
| SILType type, |
| SILBasicBlock *trueBlock, |
| SILBasicBlock *falseBlock) { |
| SILBuilder::createCheckedCastValueBranch(loc, operand.forward(SGF), type, |
| trueBlock, falseBlock); |
| } |
| |
| ManagedValue SILGenBuilder::createUpcast(SILLocation loc, ManagedValue original, |
| SILType type) { |
| CleanupCloner cloner(*this, original); |
| SILValue convertedValue = |
| SILBuilder::createUpcast(loc, original.forward(SGF), type); |
| return cloner.clone(convertedValue); |
| } |
| |
| ManagedValue SILGenBuilder::createOptionalSome(SILLocation loc, |
| ManagedValue arg) { |
| CleanupCloner cloner(*this, arg); |
| auto &argTL = SGF.getTypeLowering(arg.getType()); |
| SILType optionalType = arg.getType().wrapAnyOptionalType(getFunction()); |
| if (argTL.isLoadable() || !SGF.silConv.useLoweredAddresses()) { |
| SILValue someValue = |
| SILBuilder::createOptionalSome(loc, arg.forward(SGF), optionalType); |
| return cloner.clone(someValue); |
| } |
| |
| SILValue tempResult = SGF.emitTemporaryAllocation(loc, optionalType); |
| RValue rvalue(SGF, loc, arg.getType().getSwiftRValueType(), arg); |
| ArgumentSource argValue(loc, std::move(rvalue)); |
| SGF.emitInjectOptionalValueInto( |
| loc, std::move(argValue), tempResult, |
| SGF.getTypeLowering(tempResult->getType())); |
| return ManagedValue::forUnmanaged(tempResult); |
| } |
| |
| ManagedValue SILGenBuilder::createManagedOptionalNone(SILLocation loc, |
| SILType type) { |
| if (!type.isAddressOnly(getModule()) || !SGF.silConv.useLoweredAddresses()) { |
| SILValue noneValue = SILBuilder::createOptionalNone(loc, type); |
| return ManagedValue::forUnmanaged(noneValue); |
| } |
| |
| SILValue tempResult = SGF.emitTemporaryAllocation(loc, type); |
| SGF.emitInjectOptionalNothingInto(loc, tempResult, |
| SGF.getTypeLowering(type)); |
| return ManagedValue::forUnmanaged(tempResult); |
| } |
| |
| ManagedValue SILGenBuilder::createTupleElementAddr(SILLocation Loc, |
| ManagedValue Base, |
| unsigned Index, |
| SILType Type) { |
| SILValue TupleEltAddr = |
| SILBuilder::createTupleElementAddr(Loc, Base.getValue(), Index, Type); |
| return ManagedValue::forUnmanaged(TupleEltAddr); |
| } |
| |
| ManagedValue SILGenBuilder::createTupleElementAddr(SILLocation Loc, |
| ManagedValue Value, |
| unsigned Index) { |
| SILType Type = Value.getType().getTupleElementType(Index); |
| return createTupleElementAddr(Loc, Value, Index, Type); |
| } |
| |
| ManagedValue SILGenBuilder::createUncheckedRefCast(SILLocation loc, |
| ManagedValue value, |
| SILType type) { |
| CleanupCloner cloner(*this, value); |
| SILValue cast = |
| SILBuilder::createUncheckedRefCast(loc, value.forward(SGF), type); |
| return cloner.clone(cast); |
| } |
| |
| ManagedValue SILGenBuilder::createUncheckedBitCast(SILLocation loc, |
| ManagedValue value, |
| SILType type) { |
| CleanupCloner cloner(*this, value); |
| SILValue cast = |
| SILBuilder::createUncheckedBitCast(loc, value.forward(SGF), type); |
| return cloner.clone(cast); |
| } |
| |
| ManagedValue SILGenBuilder::createOpenExistentialRef(SILLocation loc, |
| ManagedValue original, |
| SILType type) { |
| CleanupCloner cloner(*this, original); |
| SILValue openedExistential = |
| SILBuilder::createOpenExistentialRef(loc, original.forward(SGF), type); |
| return cloner.clone(openedExistential); |
| } |
| |
| ManagedValue SILGenBuilder::createOpenExistentialValue(SILLocation loc, |
| ManagedValue original, |
| SILType type) { |
| ManagedValue borrowedExistential = original.borrow(SGF, loc); |
| SILValue openedExistential = SILBuilder::createOpenExistentialValue( |
| loc, borrowedExistential.getValue(), type); |
| return ManagedValue::forUnmanaged(openedExistential); |
| } |
| |
| ManagedValue SILGenBuilder::createOpenExistentialBoxValue(SILLocation loc, |
| ManagedValue original, |
| SILType type) { |
| ManagedValue borrowedExistential = original.borrow(SGF, loc); |
| SILValue openedExistential = SILBuilder::createOpenExistentialBoxValue( |
| loc, borrowedExistential.getValue(), type); |
| return ManagedValue::forUnmanaged(openedExistential); |
| } |
| |
| ManagedValue SILGenBuilder::createStore(SILLocation loc, ManagedValue value, |
| SILValue address, |
| StoreOwnershipQualifier qualifier) { |
| SILModule &M = SGF.F.getModule(); |
| CleanupCloner cloner(*this, value); |
| if (value.getType().isTrivial(M) || value.getOwnershipKind() == ValueOwnershipKind::Trivial) |
| qualifier = StoreOwnershipQualifier::Trivial; |
| SILBuilder::createStore(loc, value.forward(SGF), address, qualifier); |
| return cloner.clone(address); |
| } |
| |
| ManagedValue SILGenBuilder::createSuperMethod(SILLocation loc, |
| ManagedValue operand, |
| SILDeclRef member, |
| SILType methodTy, |
| bool isVolatile) { |
| SILValue v = SILBuilder::createSuperMethod(loc, operand.getValue(), member, |
| methodTy, isVolatile); |
| return ManagedValue::forUnmanaged(v); |
| } |
| |
| ManagedValue SILGenBuilder:: |
| createValueMetatype(SILLocation loc, SILType metatype, |
| ManagedValue base) { |
| SILValue v = createValueMetatype(loc, metatype, base.getValue()); |
| return ManagedValue::forUnmanaged(v); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Switch Enum Builder |
| //===----------------------------------------------------------------------===// |
| |
| void SwitchEnumBuilder::emit() && { |
| bool isAddressOnly = optional.getType().isAddressOnly(builder.getModule()) && |
| getSGF().silConv.useLoweredAddresses(); |
| using DeclBlockPair = std::pair<EnumElementDecl *, SILBasicBlock *>; |
| { |
| // TODO: We could store the data in CaseBB form and not have to do this. |
| llvm::SmallVector<DeclBlockPair, 8> caseBlocks; |
| std::transform(caseDataArray.begin(), caseDataArray.end(), |
| std::back_inserter(caseBlocks), |
| [](NormalCaseData &caseData) -> DeclBlockPair { |
| return {caseData.decl, caseData.block}; |
| }); |
| SILBasicBlock *defaultBlock = |
| defaultBlockData ? defaultBlockData->block : nullptr; |
| if (isAddressOnly) { |
| builder.createSwitchEnumAddr(loc, optional.getValue(), defaultBlock, |
| caseBlocks); |
| } else { |
| if (optional.getType().isAddress()) { |
| // TODO: Refactor this into a maybe load. |
| if (optional.hasCleanup()) { |
| optional = builder.createLoadTake(loc, optional); |
| } else { |
| optional = builder.createLoadCopy(loc, optional); |
| } |
| } |
| builder.createSwitchEnum(loc, optional.forward(getSGF()), defaultBlock, |
| caseBlocks); |
| } |
| } |
| |
| // If we are asked to create a default block and it is specified that the |
| // default block should be emitted before normal cases, emit it now. |
| if (defaultBlockData && |
| defaultBlockData->dispatchTime == |
| DefaultDispatchTime::BeforeNormalCases) { |
| SILBasicBlock *defaultBlock = defaultBlockData->block; |
| NullablePtr<SILBasicBlock> contBB = defaultBlockData->contBlock; |
| DefaultCaseHandler handler = defaultBlockData->handler; |
| |
| // Don't allow cleanups to escape the conditional block. |
| SwitchCaseFullExpr presentScope(builder.getSILGenFunction(), |
| CleanupLocation::get(loc), |
| contBB.getPtrOrNull()); |
| builder.emitBlock(defaultBlock); |
| ManagedValue input = optional; |
| if (!isAddressOnly) { |
| input = builder.createOwnedPHIArgument(optional.getType()); |
| } |
| handler(input, presentScope); |
| assert(!builder.hasValidInsertionPoint()); |
| } |
| |
| for (NormalCaseData &caseData : caseDataArray) { |
| EnumElementDecl *decl = caseData.decl; |
| SILBasicBlock *caseBlock = caseData.block; |
| NullablePtr<SILBasicBlock> contBlock = caseData.contBlock; |
| NormalCaseHandler handler = caseData.handler; |
| |
| // Don't allow cleanups to escape the conditional block. |
| SwitchCaseFullExpr presentScope(builder.getSILGenFunction(), |
| CleanupLocation::get(loc), |
| contBlock.getPtrOrNull()); |
| |
| builder.emitBlock(caseBlock); |
| |
| ManagedValue input; |
| if (decl->hasAssociatedValues()) { |
| // Pull the payload out if we have one. |
| SILType inputType = |
| optional.getType().getEnumElementType(decl, builder.getModule()); |
| input = optional; |
| if (!isAddressOnly) { |
| input = builder.createOwnedPHIArgument(inputType); |
| } |
| } |
| handler(input, presentScope); |
| assert(!builder.hasValidInsertionPoint()); |
| } |
| |
| // If we are asked to create a default block and it is specified that the |
| // default block should be emitted after normal cases, emit it now. |
| if (defaultBlockData && |
| defaultBlockData->dispatchTime == DefaultDispatchTime::AfterNormalCases) { |
| SILBasicBlock *defaultBlock = defaultBlockData->block; |
| NullablePtr<SILBasicBlock> contBB = defaultBlockData->contBlock; |
| DefaultCaseHandler handler = defaultBlockData->handler; |
| |
| // Don't allow cleanups to escape the conditional block. |
| SwitchCaseFullExpr presentScope(builder.getSILGenFunction(), |
| CleanupLocation::get(loc), |
| contBB.getPtrOrNull()); |
| builder.emitBlock(defaultBlock); |
| ManagedValue input = optional; |
| if (!isAddressOnly) { |
| input = builder.createOwnedPHIArgument(optional.getType()); |
| } |
| handler(input, presentScope); |
| assert(!builder.hasValidInsertionPoint()); |
| } |
| } |