| //===--- SILGenExpr.cpp - Implements Lowering of ASTs -> SIL for Exprs ----===// |
| // |
| // 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 "ArgumentScope.h" |
| #include "ArgumentSource.h" |
| #include "Callee.h" |
| #include "Condition.h" |
| #include "Conversion.h" |
| #include "ExitableFullExpr.h" |
| #include "Initialization.h" |
| #include "LValue.h" |
| #include "RValue.h" |
| #include "ResultPlan.h" |
| #include "SILGen.h" |
| #include "SILGenDynamicCast.h" |
| #include "SILGenFunctionBuilder.h" |
| #include "Scope.h" |
| #include "SwitchEnumBuilder.h" |
| #include "Varargs.h" |
| #include "swift/AST/ASTContext.h" |
| #include "swift/AST/ASTMangler.h" |
| #include "swift/AST/CanTypeVisitor.h" |
| #include "swift/AST/Decl.h" |
| #include "swift/AST/DiagnosticsCommon.h" |
| #include "swift/AST/Expr.h" |
| #include "swift/AST/ForeignErrorConvention.h" |
| #include "swift/AST/GenericEnvironment.h" |
| #include "swift/AST/ParameterList.h" |
| #include "swift/AST/ProtocolConformance.h" |
| #include "swift/AST/SubstitutionMap.h" |
| #include "swift/AST/Types.h" |
| #include "swift/Basic/SourceManager.h" |
| #include "swift/Basic/type_traits.h" |
| #include "swift/SIL/DynamicCasts.h" |
| #include "swift/SIL/SILArgument.h" |
| #include "swift/SIL/SILUndef.h" |
| #include "swift/SIL/TypeLowering.h" |
| #include "llvm/ADT/STLExtras.h" |
| #include "llvm/Support/Compiler.h" |
| #include "llvm/Support/ConvertUTF.h" |
| #include "llvm/Support/MemoryBuffer.h" |
| #include "llvm/Support/SaveAndRestore.h" |
| #include "llvm/Support/raw_ostream.h" |
| |
| #include "swift/AST/DiagnosticsSIL.h" |
| |
| using namespace swift; |
| using namespace Lowering; |
| |
| ManagedValue SILGenFunction::emitManagedRetain(SILLocation loc, |
| SILValue v) { |
| auto &lowering = getTypeLowering(v->getType()); |
| return emitManagedRetain(loc, v, lowering); |
| } |
| |
| ManagedValue SILGenFunction::emitManagedRetain(SILLocation loc, |
| SILValue v, |
| const TypeLowering &lowering) { |
| assert(lowering.getLoweredType() == v->getType()); |
| if (lowering.isTrivial()) |
| return ManagedValue::forUnmanaged(v); |
| if (v->getType().isObject() && v.getOwnershipKind() == OwnershipKind::None) |
| return ManagedValue::forUnmanaged(v); |
| assert((!lowering.isAddressOnly() || !silConv.useLoweredAddresses()) && |
| "cannot retain an unloadable type"); |
| |
| v = lowering.emitCopyValue(B, loc, v); |
| return emitManagedRValueWithCleanup(v, lowering); |
| } |
| |
| ManagedValue SILGenFunction::emitManagedLoadCopy(SILLocation loc, SILValue v) { |
| auto &lowering = getTypeLowering(v->getType()); |
| return emitManagedLoadCopy(loc, v, lowering); |
| } |
| |
| ManagedValue SILGenFunction::emitManagedLoadCopy(SILLocation loc, SILValue v, |
| const TypeLowering &lowering) { |
| assert(lowering.getLoweredType().getAddressType() == v->getType()); |
| v = lowering.emitLoadOfCopy(B, loc, v, IsNotTake); |
| if (lowering.isTrivial()) |
| return ManagedValue::forUnmanaged(v); |
| if (v.getOwnershipKind() == OwnershipKind::None) |
| return ManagedValue::forUnmanaged(v); |
| assert((!lowering.isAddressOnly() || !silConv.useLoweredAddresses()) && |
| "cannot retain an unloadable type"); |
| return emitManagedRValueWithCleanup(v, lowering); |
| } |
| |
| ManagedValue SILGenFunction::emitManagedLoadBorrow(SILLocation loc, |
| SILValue v) { |
| auto &lowering = getTypeLowering(v->getType()); |
| return emitManagedLoadBorrow(loc, v, lowering); |
| } |
| |
| ManagedValue |
| SILGenFunction::emitManagedLoadBorrow(SILLocation loc, SILValue v, |
| const TypeLowering &lowering) { |
| assert(lowering.getLoweredType().getAddressType() == v->getType()); |
| if (lowering.isTrivial()) { |
| v = lowering.emitLoadOfCopy(B, loc, v, IsNotTake); |
| return ManagedValue::forUnmanaged(v); |
| } |
| |
| assert((!lowering.isAddressOnly() || !silConv.useLoweredAddresses()) && |
| "cannot retain an unloadable type"); |
| auto *lbi = B.createLoadBorrow(loc, v); |
| return emitManagedBorrowedRValueWithCleanup(v, lbi, lowering); |
| } |
| |
| ManagedValue SILGenFunction::emitManagedStoreBorrow(SILLocation loc, SILValue v, |
| SILValue addr) { |
| auto &lowering = getTypeLowering(v->getType()); |
| return emitManagedStoreBorrow(loc, v, addr, lowering); |
| } |
| |
| ManagedValue SILGenFunction::emitManagedStoreBorrow( |
| SILLocation loc, SILValue v, SILValue addr, const TypeLowering &lowering) { |
| assert(lowering.getLoweredType().getObjectType() == v->getType()); |
| if (lowering.isTrivial() || v.getOwnershipKind() == OwnershipKind::None) { |
| lowering.emitStore(B, loc, v, addr, StoreOwnershipQualifier::Trivial); |
| return ManagedValue::forUnmanaged(v); |
| } |
| assert((!lowering.isAddressOnly() || !silConv.useLoweredAddresses()) && |
| "cannot retain an unloadable type"); |
| auto *sbi = B.createStoreBorrow(loc, v, addr); |
| return emitManagedBorrowedRValueWithCleanup(sbi->getSrc(), sbi, lowering); |
| } |
| |
| ManagedValue SILGenFunction::emitManagedBeginBorrow(SILLocation loc, |
| SILValue v) { |
| auto &lowering = getTypeLowering(v->getType()); |
| return emitManagedBeginBorrow(loc, v, lowering); |
| } |
| |
| ManagedValue |
| SILGenFunction::emitManagedBeginBorrow(SILLocation loc, SILValue v, |
| const TypeLowering &lowering) { |
| assert(lowering.getLoweredType().getObjectType() == |
| v->getType().getObjectType()); |
| if (lowering.isTrivial()) |
| return ManagedValue::forUnmanaged(v); |
| |
| if (v.getOwnershipKind() == OwnershipKind::None) |
| return ManagedValue::forUnmanaged(v); |
| |
| if (v.getOwnershipKind() == OwnershipKind::Guaranteed) |
| return ManagedValue::forUnmanaged(v); |
| |
| auto *bbi = B.createBeginBorrow(loc, v); |
| return emitManagedBorrowedRValueWithCleanup(v, bbi, lowering); |
| } |
| |
| namespace { |
| |
| struct EndBorrowCleanup : Cleanup { |
| SILValue borrowedValue; |
| |
| EndBorrowCleanup(SILValue borrowedValue) : borrowedValue(borrowedValue) { |
| if (auto *arg = dyn_cast<SILPhiArgument>(borrowedValue)) { |
| if (auto *ti = arg->getSingleTerminator()) { |
| assert(!ti->isTransformationTerminator() && |
| "Transforming terminators do not have end_borrow"); |
| } |
| } |
| } |
| |
| void emit(SILGenFunction &SGF, CleanupLocation l, |
| ForUnwind_t forUnwind) override { |
| SGF.B.createEndBorrow(l, borrowedValue); |
| } |
| |
| void dump(SILGenFunction &) const override { |
| #ifndef NDEBUG |
| llvm::errs() << "EndBorrowCleanup " |
| << "State:" << getState() << "\n" |
| << "borrowed:" << borrowedValue |
| << "\n"; |
| #endif |
| } |
| }; |
| |
| struct FormalEvaluationEndBorrowCleanup : Cleanup { |
| FormalEvaluationContext::stable_iterator Depth; |
| |
| FormalEvaluationEndBorrowCleanup() : Depth() {} |
| |
| void emit(SILGenFunction &SGF, CleanupLocation l, ForUnwind_t forUnwind) override { |
| getEvaluation(SGF).finish(SGF); |
| } |
| |
| void dump(SILGenFunction &SGF) const override { |
| #ifndef NDEBUG |
| llvm::errs() << "FormalEvaluationEndBorrowCleanup " |
| << "State:" << getState() << "\n" |
| << "original:" << getOriginalValue(SGF) << "\n" |
| << "borrowed:" << getBorrowedValue(SGF) << "\n"; |
| #endif |
| } |
| |
| SharedBorrowFormalAccess &getEvaluation(SILGenFunction &SGF) const { |
| auto &evaluation = *SGF.FormalEvalContext.find(Depth); |
| assert(evaluation.getKind() == FormalAccess::Shared); |
| return static_cast<SharedBorrowFormalAccess &>(evaluation); |
| } |
| |
| SILValue getOriginalValue(SILGenFunction &SGF) const { |
| return getEvaluation(SGF).getOriginalValue(); |
| } |
| |
| SILValue getBorrowedValue(SILGenFunction &SGF) const { |
| return getEvaluation(SGF).getBorrowedValue(); |
| } |
| }; |
| |
| } // end anonymous namespace |
| |
| ManagedValue |
| SILGenFunction::emitFormalEvaluationManagedBeginBorrow(SILLocation loc, |
| SILValue v) { |
| if (v.getOwnershipKind() == OwnershipKind::Guaranteed) |
| return ManagedValue::forUnmanaged(v); |
| auto &lowering = getTypeLowering(v->getType()); |
| return emitFormalEvaluationManagedBeginBorrow(loc, v, lowering); |
| } |
| |
| ManagedValue SILGenFunction::emitFormalEvaluationManagedBeginBorrow( |
| SILLocation loc, SILValue v, const TypeLowering &lowering) { |
| assert(lowering.getLoweredType().getObjectType() == |
| v->getType().getObjectType()); |
| if (lowering.isTrivial()) |
| return ManagedValue::forUnmanaged(v); |
| if (v.getOwnershipKind() == OwnershipKind::Guaranteed) |
| return ManagedValue::forUnmanaged(v); |
| auto *bbi = B.createBeginBorrow(loc, v); |
| return emitFormalEvaluationManagedBorrowedRValueWithCleanup(loc, v, bbi, |
| lowering); |
| } |
| |
| ManagedValue |
| SILGenFunction::emitFormalEvaluationManagedBorrowedRValueWithCleanup( |
| SILLocation loc, SILValue original, SILValue borrowed) { |
| auto &lowering = getTypeLowering(original->getType()); |
| return emitFormalEvaluationManagedBorrowedRValueWithCleanup( |
| loc, original, borrowed, lowering); |
| } |
| |
| ManagedValue |
| SILGenFunction::emitFormalEvaluationManagedBorrowedRValueWithCleanup( |
| SILLocation loc, SILValue original, SILValue borrowed, |
| const TypeLowering &lowering) { |
| assert(lowering.getLoweredType().getObjectType() == |
| original->getType().getObjectType()); |
| if (lowering.isTrivial()) |
| return ManagedValue::forUnmanaged(borrowed); |
| |
| if (!borrowed->getType().isObject()) { |
| return ManagedValue(borrowed, CleanupHandle::invalid()); |
| } |
| |
| assert(isInFormalEvaluationScope() && "Must be in formal evaluation scope"); |
| auto &cleanup = Cleanups.pushCleanup<FormalEvaluationEndBorrowCleanup>(); |
| CleanupHandle handle = Cleanups.getTopCleanup(); |
| FormalEvalContext.push<SharedBorrowFormalAccess>(loc, handle, original, |
| borrowed); |
| cleanup.Depth = FormalEvalContext.stable_begin(); |
| return ManagedValue(borrowed, CleanupHandle::invalid()); |
| } |
| |
| ManagedValue |
| SILGenFunction::emitManagedBorrowedArgumentWithCleanup(SILPhiArgument *arg) { |
| if (arg->getOwnershipKind() == OwnershipKind::None || |
| arg->getType().isTrivial(F)) { |
| return ManagedValue::forUnmanaged(arg); |
| } |
| |
| assert(arg->getOwnershipKind() == OwnershipKind::Guaranteed); |
| Cleanups.pushCleanup<EndBorrowCleanup>(arg); |
| return ManagedValue(arg, CleanupHandle::invalid()); |
| } |
| |
| ManagedValue |
| SILGenFunction::emitManagedBorrowedRValueWithCleanup(SILValue original, |
| SILValue borrowed) { |
| assert(original->getType().getObjectType() == |
| borrowed->getType().getObjectType()); |
| auto &lowering = getTypeLowering(original->getType()); |
| return emitManagedBorrowedRValueWithCleanup(original, borrowed, lowering); |
| } |
| |
| ManagedValue |
| SILGenFunction::emitManagedBorrowedRValueWithCleanup(SILValue borrowed) { |
| auto &lowering = getTypeLowering(borrowed->getType()); |
| return emitManagedBorrowedRValueWithCleanup(borrowed, lowering); |
| } |
| |
| ManagedValue SILGenFunction::emitManagedBorrowedRValueWithCleanup( |
| SILValue borrowed, const TypeLowering &lowering) { |
| assert(lowering.getLoweredType().getObjectType() == |
| borrowed->getType().getObjectType()); |
| if (lowering.isTrivial()) |
| return ManagedValue::forUnmanaged(borrowed); |
| |
| if (borrowed->getType().isObject() && |
| borrowed.getOwnershipKind() == OwnershipKind::None) |
| return ManagedValue::forUnmanaged(borrowed); |
| |
| if (borrowed->getType().isObject()) { |
| Cleanups.pushCleanup<EndBorrowCleanup>(borrowed); |
| } |
| |
| return ManagedValue(borrowed, CleanupHandle::invalid()); |
| } |
| |
| ManagedValue SILGenFunction::emitManagedBorrowedRValueWithCleanup( |
| SILValue original, SILValue borrowed, const TypeLowering &lowering) { |
| assert(lowering.getLoweredType().getObjectType() == |
| original->getType().getObjectType()); |
| if (lowering.isTrivial()) |
| return ManagedValue::forUnmanaged(borrowed); |
| |
| if (original->getType().isObject() && |
| original.getOwnershipKind() == OwnershipKind::None) |
| return ManagedValue::forUnmanaged(borrowed); |
| |
| if (borrowed->getType().isObject()) { |
| Cleanups.pushCleanup<EndBorrowCleanup>(borrowed); |
| } |
| |
| return ManagedValue(borrowed, CleanupHandle::invalid()); |
| } |
| |
| ManagedValue SILGenFunction::emitManagedRValueWithCleanup(SILValue v) { |
| auto &lowering = getTypeLowering(v->getType()); |
| return emitManagedRValueWithCleanup(v, lowering); |
| } |
| |
| ManagedValue SILGenFunction::emitManagedRValueWithCleanup(SILValue v, |
| const TypeLowering &lowering) { |
| assert(lowering.getLoweredType().getObjectType() == |
| v->getType().getObjectType()); |
| if (lowering.isTrivial()) |
| return ManagedValue::forUnmanaged(v); |
| if (v->getType().isObject() && v.getOwnershipKind() == OwnershipKind::None) { |
| return ManagedValue::forUnmanaged(v); |
| } |
| return ManagedValue(v, enterDestroyCleanup(v)); |
| } |
| |
| ManagedValue SILGenFunction::emitManagedBufferWithCleanup(SILValue v) { |
| auto &lowering = getTypeLowering(v->getType()); |
| return emitManagedBufferWithCleanup(v, lowering); |
| } |
| |
| ManagedValue SILGenFunction::emitManagedBufferWithCleanup(SILValue v, |
| const TypeLowering &lowering) { |
| assert(lowering.getLoweredType().getAddressType() == v->getType() || |
| !silConv.useLoweredAddresses()); |
| if (lowering.isTrivial()) |
| return ManagedValue::forUnmanaged(v); |
| |
| return ManagedValue(v, enterDestroyCleanup(v)); |
| } |
| |
| void SILGenFunction::emitExprInto(Expr *E, Initialization *I, |
| Optional<SILLocation> L) { |
| // Handle the special case of copying an lvalue. |
| if (auto load = dyn_cast<LoadExpr>(E)) { |
| FormalEvaluationScope writeback(*this); |
| auto lv = emitLValue(load->getSubExpr(), |
| SGFAccessKind::BorrowedAddressRead); |
| emitCopyLValueInto(E, std::move(lv), I); |
| return; |
| } |
| |
| RValue result = emitRValue(E, SGFContext(I)); |
| if (result.isInContext()) |
| return; |
| std::move(result).ensurePlusOne(*this, E).forwardInto(*this, L ? *L : E, I); |
| } |
| |
| namespace { |
| class RValueEmitter |
| : public Lowering::ExprVisitor<RValueEmitter, RValue, SGFContext> |
| { |
| typedef Lowering::ExprVisitor<RValueEmitter,RValue,SGFContext> super; |
| public: |
| SILGenFunction &SGF; |
| |
| RValueEmitter(SILGenFunction &SGF) : SGF(SGF) {} |
| |
| using super::visit; |
| RValue visit(Expr *E) { |
| assert(!E->getType()->is<LValueType>() && |
| !E->getType()->is<InOutType>() && |
| "RValueEmitter shouldn't be called on lvalues"); |
| return visit(E, SGFContext()); |
| } |
| |
| // These always produce lvalues. |
| RValue visitInOutExpr(InOutExpr *E, SGFContext C) { |
| LValue lv = SGF.emitLValue(E->getSubExpr(), SGFAccessKind::ReadWrite); |
| return RValue(SGF, E, SGF.emitAddressOfLValue(E->getSubExpr(), |
| std::move(lv))); |
| } |
| |
| RValue visitApplyExpr(ApplyExpr *E, SGFContext C); |
| |
| RValue visitDiscardAssignmentExpr(DiscardAssignmentExpr *E, SGFContext C) { |
| llvm_unreachable("cannot appear in rvalue"); |
| } |
| RValue visitDeclRefExpr(DeclRefExpr *E, SGFContext C); |
| RValue visitTypeExpr(TypeExpr *E, SGFContext C); |
| RValue visitSuperRefExpr(SuperRefExpr *E, SGFContext C); |
| RValue visitOtherConstructorDeclRefExpr(OtherConstructorDeclRefExpr *E, |
| SGFContext C); |
| |
| RValue visitForceTryExpr(ForceTryExpr *E, SGFContext C); |
| RValue visitOptionalTryExpr(OptionalTryExpr *E, SGFContext C); |
| |
| RValue visitNilLiteralExpr(NilLiteralExpr *E, SGFContext C); |
| RValue visitIntegerLiteralExpr(IntegerLiteralExpr *E, SGFContext C); |
| RValue visitFloatLiteralExpr(FloatLiteralExpr *E, SGFContext C); |
| RValue visitBooleanLiteralExpr(BooleanLiteralExpr *E, SGFContext C); |
| |
| RValue emitStringLiteral(Expr *E, StringRef Str, SGFContext C, |
| StringLiteralExpr::Encoding encoding); |
| |
| RValue visitStringLiteralExpr(StringLiteralExpr *E, SGFContext C); |
| RValue visitLoadExpr(LoadExpr *E, SGFContext C); |
| RValue visitDerivedToBaseExpr(DerivedToBaseExpr *E, SGFContext C); |
| RValue visitMetatypeConversionExpr(MetatypeConversionExpr *E, |
| SGFContext C); |
| RValue visitCollectionUpcastConversionExpr( |
| CollectionUpcastConversionExpr *E, |
| SGFContext C); |
| RValue visitBridgeToObjCExpr(BridgeToObjCExpr *E, SGFContext C); |
| RValue visitBridgeFromObjCExpr(BridgeFromObjCExpr *E, SGFContext C); |
| RValue visitConditionalBridgeFromObjCExpr(ConditionalBridgeFromObjCExpr *E, |
| SGFContext C); |
| RValue visitArchetypeToSuperExpr(ArchetypeToSuperExpr *E, SGFContext C); |
| RValue visitUnresolvedTypeConversionExpr(UnresolvedTypeConversionExpr *E, |
| SGFContext C); |
| RValue visitFunctionConversionExpr(FunctionConversionExpr *E, |
| SGFContext C); |
| RValue visitCovariantFunctionConversionExpr( |
| CovariantFunctionConversionExpr *E, |
| SGFContext C); |
| RValue visitCovariantReturnConversionExpr( |
| CovariantReturnConversionExpr *E, |
| SGFContext C); |
| RValue visitImplicitlyUnwrappedFunctionConversionExpr( |
| ImplicitlyUnwrappedFunctionConversionExpr *E, SGFContext C); |
| RValue visitErasureExpr(ErasureExpr *E, SGFContext C); |
| RValue visitAnyHashableErasureExpr(AnyHashableErasureExpr *E, SGFContext C); |
| RValue visitForcedCheckedCastExpr(ForcedCheckedCastExpr *E, |
| SGFContext C); |
| RValue visitConditionalCheckedCastExpr(ConditionalCheckedCastExpr *E, |
| SGFContext C); |
| RValue visitIsExpr(IsExpr *E, SGFContext C); |
| RValue visitCoerceExpr(CoerceExpr *E, SGFContext C); |
| RValue visitUnderlyingToOpaqueExpr(UnderlyingToOpaqueExpr *E, SGFContext C); |
| RValue visitTupleExpr(TupleExpr *E, SGFContext C); |
| RValue visitMemberRefExpr(MemberRefExpr *E, SGFContext C); |
| RValue visitDynamicMemberRefExpr(DynamicMemberRefExpr *E, SGFContext C); |
| RValue visitDotSyntaxBaseIgnoredExpr(DotSyntaxBaseIgnoredExpr *E, |
| SGFContext C); |
| RValue visitTupleElementExpr(TupleElementExpr *E, SGFContext C); |
| RValue visitSubscriptExpr(SubscriptExpr *E, SGFContext C); |
| RValue visitKeyPathApplicationExpr(KeyPathApplicationExpr *E, SGFContext C); |
| RValue visitDynamicSubscriptExpr(DynamicSubscriptExpr *E, |
| SGFContext C); |
| RValue visitDestructureTupleExpr(DestructureTupleExpr *E, SGFContext C); |
| RValue visitDynamicTypeExpr(DynamicTypeExpr *E, SGFContext C); |
| RValue visitCaptureListExpr(CaptureListExpr *E, SGFContext C); |
| RValue visitAbstractClosureExpr(AbstractClosureExpr *E, SGFContext C); |
| RValue visitInterpolatedStringLiteralExpr(InterpolatedStringLiteralExpr *E, |
| SGFContext C); |
| RValue visitObjectLiteralExpr(ObjectLiteralExpr *E, SGFContext C); |
| RValue visitEditorPlaceholderExpr(EditorPlaceholderExpr *E, SGFContext C); |
| RValue visitObjCSelectorExpr(ObjCSelectorExpr *E, SGFContext C); |
| RValue visitKeyPathExpr(KeyPathExpr *E, SGFContext C); |
| RValue visitMagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr *E, |
| SGFContext C); |
| RValue visitCollectionExpr(CollectionExpr *E, SGFContext C); |
| RValue visitRebindSelfInConstructorExpr(RebindSelfInConstructorExpr *E, |
| SGFContext C); |
| RValue visitInjectIntoOptionalExpr(InjectIntoOptionalExpr *E, SGFContext C); |
| RValue visitClassMetatypeToObjectExpr(ClassMetatypeToObjectExpr *E, |
| SGFContext C); |
| RValue visitExistentialMetatypeToObjectExpr(ExistentialMetatypeToObjectExpr *E, |
| SGFContext C); |
| RValue visitProtocolMetatypeToObjectExpr(ProtocolMetatypeToObjectExpr *E, |
| SGFContext C); |
| RValue visitIfExpr(IfExpr *E, SGFContext C); |
| |
| RValue visitAssignExpr(AssignExpr *E, SGFContext C); |
| RValue visitEnumIsCaseExpr(EnumIsCaseExpr *E, SGFContext C); |
| |
| RValue visitBindOptionalExpr(BindOptionalExpr *E, SGFContext C); |
| RValue visitOptionalEvaluationExpr(OptionalEvaluationExpr *E, |
| SGFContext C); |
| RValue visitForceValueExpr(ForceValueExpr *E, SGFContext C); |
| RValue emitForceValue(ForceValueExpr *loc, Expr *E, |
| unsigned numOptionalEvaluations, |
| SGFContext C); |
| RValue visitOpenExistentialExpr(OpenExistentialExpr *E, SGFContext C); |
| RValue visitMakeTemporarilyEscapableExpr( |
| MakeTemporarilyEscapableExpr *E, SGFContext C); |
| |
| RValue visitOpaqueValueExpr(OpaqueValueExpr *E, SGFContext C); |
| RValue visitPropertyWrapperValuePlaceholderExpr( |
| PropertyWrapperValuePlaceholderExpr *E, SGFContext C); |
| |
| RValue visitInOutToPointerExpr(InOutToPointerExpr *E, SGFContext C); |
| RValue visitArrayToPointerExpr(ArrayToPointerExpr *E, SGFContext C); |
| RValue visitStringToPointerExpr(StringToPointerExpr *E, SGFContext C); |
| RValue visitPointerToPointerExpr(PointerToPointerExpr *E, SGFContext C); |
| RValue visitForeignObjectConversionExpr(ForeignObjectConversionExpr *E, |
| SGFContext C); |
| RValue visitUnevaluatedInstanceExpr(UnevaluatedInstanceExpr *E, |
| SGFContext C); |
| RValue visitTapExpr(TapExpr *E, SGFContext C); |
| RValue visitDefaultArgumentExpr(DefaultArgumentExpr *E, SGFContext C); |
| RValue visitErrorExpr(ErrorExpr *E, SGFContext C); |
| |
| RValue visitDifferentiableFunctionExpr(DifferentiableFunctionExpr *E, |
| SGFContext C); |
| RValue visitLinearFunctionExpr(LinearFunctionExpr *E, SGFContext C); |
| RValue visitDifferentiableFunctionExtractOriginalExpr( |
| DifferentiableFunctionExtractOriginalExpr *E, SGFContext C); |
| RValue visitLinearFunctionExtractOriginalExpr( |
| LinearFunctionExtractOriginalExpr *E, SGFContext C); |
| RValue visitLinearToDifferentiableFunctionExpr( |
| LinearToDifferentiableFunctionExpr *E, SGFContext C); |
| }; |
| } // end anonymous namespace |
| |
| namespace { |
| struct BridgingConversion { |
| Expr *SubExpr; |
| Optional<Conversion::KindTy> Kind; |
| unsigned MaxOptionalDepth; |
| |
| BridgingConversion() : SubExpr(nullptr) {} |
| BridgingConversion(Expr *sub, Optional<Conversion::KindTy> kind, |
| unsigned depth) |
| : SubExpr(sub), Kind(kind), MaxOptionalDepth(depth) { |
| assert(!kind || Conversion::isBridgingKind(*kind)); |
| } |
| |
| explicit operator bool() const { return SubExpr != nullptr; } |
| }; |
| } |
| |
| static BridgingConversion getBridgingConversion(Expr *E) { |
| E = E->getSemanticsProvidingExpr(); |
| |
| // Detect bridging conversions. |
| if (auto bridge = dyn_cast<BridgeToObjCExpr>(E)) { |
| return { bridge->getSubExpr(), Conversion::BridgeToObjC, 0 }; |
| } |
| if (auto bridge = dyn_cast<BridgeFromObjCExpr>(E)) { |
| return { bridge->getSubExpr(), Conversion::BridgeFromObjC, 0 }; |
| } |
| |
| // We can handle optional injections. |
| if (auto inject = dyn_cast<InjectIntoOptionalExpr>(E)) { |
| return getBridgingConversion(inject->getSubExpr()); |
| } |
| |
| // Look through optional-to-optional conversions. |
| if (auto optEval = dyn_cast<OptionalEvaluationExpr>(E)) { |
| auto sub = optEval->getSubExpr()->getSemanticsProvidingExpr(); |
| if (auto subResult = getBridgingConversion(sub)) { |
| sub = subResult.SubExpr->getSemanticsProvidingExpr(); |
| if (auto bind = dyn_cast<BindOptionalExpr>(sub)) { |
| if (bind->getDepth() == subResult.MaxOptionalDepth) { |
| return { bind->getSubExpr(), |
| subResult.Kind, |
| subResult.MaxOptionalDepth + 1 }; |
| } |
| } |
| } |
| } |
| |
| // Open-existentials can be part of bridging conversions in very |
| // specific patterns. |
| auto open = dyn_cast<OpenExistentialExpr>(E); |
| if (open) E = open->getSubExpr(); |
| |
| // Existential erasure. |
| if (auto erasure = dyn_cast<ErasureExpr>(E)) { |
| Conversion::KindTy kind; |
| |
| // Converting to Any is sometimes part of bridging and definitely |
| // needs special peepholing behavior. |
| if (erasure->getType()->isAny()) { |
| kind = Conversion::AnyErasure; |
| |
| // Otherwise, nope. |
| } else { |
| return {}; |
| } |
| |
| // Tentatively look through the erasure. |
| E = erasure->getSubExpr(); |
| |
| // If we have an opening, we can only peephole if the value being |
| // used is exactly the original value. |
| if (open) { |
| if (E == open->getOpaqueValue()) { |
| return { open->getExistentialValue(), kind, 0 }; |
| } |
| return {}; |
| } |
| |
| // Otherwise we can always peephole. |
| return { E, kind, 0 }; |
| } |
| |
| // If we peeked through an opening, and we didn't recognize a specific |
| // pattern above involving the opaque value, make sure we use the opening |
| // as the final expression instead of accidentally look through it. |
| if (open) return { open, None, 0 }; |
| |
| return { E, None, 0 }; |
| } |
| |
| /// If the given expression represents a bridging conversion, emit it with |
| /// the special reabstracting context. |
| static Optional<ManagedValue> |
| tryEmitAsBridgingConversion(SILGenFunction &SGF, Expr *E, bool isExplicit, |
| SGFContext C) { |
| // Try to pattern-match a conversion. This can find bridging |
| // conversions, but it can also find simple optional conversions: |
| // injections and opt-to-opt conversions. |
| auto result = getBridgingConversion(E); |
| |
| // If we didn't find a conversion at all, there's nothing special to do. |
| if (!result || |
| result.SubExpr == E || |
| result.SubExpr->getType()->isEqual(E->getType())) |
| return None; |
| |
| // Even if the conversion doesn't involve bridging, we might still |
| // expose more peephole opportunities by combining it with a contextual |
| // conversion. |
| if (!result.Kind) { |
| // Only do this if the conversion is implicit. |
| if (isExplicit) |
| return None; |
| |
| // Look for a contextual conversion. |
| auto conversion = C.getAsConversion(); |
| if (!conversion) |
| return None; |
| |
| // Adjust the contextual conversion. |
| auto sub = result.SubExpr; |
| auto sourceType = sub->getType()->getCanonicalType(); |
| if (auto adjusted = conversion->getConversion() |
| .adjustForInitialOptionalConversions(sourceType)) { |
| // Emit into the applied conversion. |
| return conversion->emitWithAdjustedConversion(SGF, E, *adjusted, |
| [sub](SILGenFunction &SGF, SILLocation loc, SGFContext C) { |
| return SGF.emitRValueAsSingleValue(sub, C); |
| }); |
| } |
| |
| // If that didn't work, there's nothing special to do. |
| return None; |
| } |
| |
| auto kind = *result.Kind; |
| auto subExpr = result.SubExpr; |
| |
| CanType resultType = E->getType()->getCanonicalType(); |
| Conversion conversion = |
| Conversion::getBridging(kind, subExpr->getType()->getCanonicalType(), |
| resultType, SGF.getLoweredType(resultType), |
| isExplicit); |
| |
| // Only use this special pattern for AnyErasure conversions when we're |
| // emitting into a peephole. |
| if (kind == Conversion::AnyErasure) { |
| auto outerConversion = C.getAsConversion(); |
| if (!outerConversion || |
| !canPeepholeConversions(SGF, outerConversion->getConversion(), |
| conversion)) { |
| return None; |
| } |
| } |
| |
| return SGF.emitConvertedRValue(subExpr, conversion, C); |
| } |
| |
| RValue RValueEmitter::visitApplyExpr(ApplyExpr *E, SGFContext C) { |
| return SGF.emitApplyExpr(E, C); |
| } |
| |
| SILValue SILGenFunction::emitEmptyTuple(SILLocation loc) { |
| return B.createTuple( |
| loc, getLoweredType(TupleType::getEmpty(SGM.M.getASTContext())), |
| ArrayRef<SILValue>()); |
| } |
| |
| namespace { |
| |
| /// This is a simple cleanup class that at the end of a lexical scope consumes |
| /// an owned value by writing it back to memory. The user can forward this |
| /// cleanup to take ownership of the value and thus prevent it form being |
| /// written back. |
| struct OwnedValueWritebackCleanup final : Cleanup { |
| using Flags = Cleanup::Flags; |
| |
| /// We store our own loc so that we can ensure that DI ignores our writeback. |
| SILLocation loc; |
| |
| SILValue lvalueAddress; |
| SILValue value; |
| |
| OwnedValueWritebackCleanup(SILLocation loc, SILValue lvalueAddress, |
| SILValue value) |
| : loc(loc), lvalueAddress(lvalueAddress), value(value) {} |
| |
| bool getWritebackBuffer(function_ref<void(SILValue)> func) override { |
| func(lvalueAddress); |
| return true; |
| } |
| |
| void emit(SILGenFunction &SGF, CleanupLocation l, ForUnwind_t forUnwind) override { |
| SILValue valueToStore = value; |
| SILType lvalueObjTy = lvalueAddress->getType().getObjectType(); |
| |
| // If we calling a super.init and thus upcasted self, when we store self |
| // back into the self slot, we need to perform a downcast from the upcasted |
| // store value to the derived type of our lvalueAddress. |
| if (valueToStore->getType() != lvalueObjTy) { |
| if (!valueToStore->getType().isExactSuperclassOf(lvalueObjTy)) { |
| llvm_unreachable("Invalid usage of delegate init self writeback"); |
| } |
| |
| valueToStore = SGF.B.createUncheckedRefCast(loc, valueToStore, |
| lvalueObjTy); |
| } |
| |
| SGF.B.emitStoreValueOperation(loc, valueToStore, lvalueAddress, |
| StoreOwnershipQualifier::Init); |
| } |
| |
| void dump(SILGenFunction &) const override { |
| #ifndef NDEBUG |
| llvm::errs() << "OwnedValueWritebackCleanup " |
| << "State:" << getState() << "\n" |
| << "lvalueAddress:" << lvalueAddress << "value:" << value |
| << "\n"; |
| #endif |
| } |
| }; |
| |
| } // end anonymous namespace |
| |
| CleanupHandle SILGenFunction::enterOwnedValueWritebackCleanup( |
| SILLocation loc, SILValue address, SILValue newValue) { |
| Cleanups.pushCleanup<OwnedValueWritebackCleanup>(loc, address, newValue); |
| return Cleanups.getTopCleanup(); |
| } |
| |
| RValue SILGenFunction::emitRValueForSelfInDelegationInit(SILLocation loc, |
| CanType refType, |
| SILValue addr, |
| SGFContext C) { |
| assert(SelfInitDelegationState != SILGenFunction::NormalSelf && |
| "This should never be called unless we are in a delegation sequence"); |
| assert(getTypeLowering(addr->getType()).isLoadable() && |
| "Make sure that we are not dealing with semantic rvalues"); |
| |
| // If we are currently in the WillSharedBorrowSelf state, then we know that |
| // old self is not the self to our delegating initializer. Self in this case |
| // to the delegating initializer is a metatype. Thus, we perform a |
| // load_borrow. And move from WillSharedBorrowSelf -> DidSharedBorrowSelf. |
| if (SelfInitDelegationState == SILGenFunction::WillSharedBorrowSelf) { |
| assert(C.isGuaranteedPlusZeroOk() && |
| "This should only be called if guaranteed plus zero is ok"); |
| SelfInitDelegationState = SILGenFunction::DidSharedBorrowSelf; |
| ManagedValue result = |
| B.createLoadBorrow(loc, ManagedValue::forUnmanaged(addr)); |
| return RValue(*this, loc, refType, result); |
| } |
| |
| // If we are already in the did shared borrow self state, just return the |
| // shared borrow value. |
| if (SelfInitDelegationState == SILGenFunction::DidSharedBorrowSelf) { |
| assert(C.isGuaranteedPlusZeroOk() && |
| "This should only be called if guaranteed plus zero is ok"); |
| ManagedValue result = |
| B.createLoadBorrow(loc, ManagedValue::forUnmanaged(addr)); |
| return RValue(*this, loc, refType, result); |
| } |
| |
| // If we are in WillExclusiveBorrowSelf, then we need to perform an exclusive |
| // borrow (i.e. a load take) and then move to DidExclusiveBorrowSelf. |
| if (SelfInitDelegationState == SILGenFunction::WillExclusiveBorrowSelf) { |
| const auto &typeLowering = getTypeLowering(addr->getType()); |
| SelfInitDelegationState = SILGenFunction::DidExclusiveBorrowSelf; |
| SILValue self = |
| emitLoad(loc, addr, typeLowering, C, IsTake, false).forward(*this); |
| // Forward our initial value for init delegation self and create a new |
| // cleanup that performs a writeback at the end of lexical scope if our |
| // value is not consumed. |
| InitDelegationSelf = ManagedValue::forExclusivelyBorrowedOwnedObjectRValue( |
| self, enterOwnedValueWritebackCleanup(*InitDelegationLoc, addr, self)); |
| InitDelegationSelfBox = addr; |
| return RValue(*this, loc, refType, InitDelegationSelf); |
| } |
| |
| // If we hit this point, we must have DidExclusiveBorrowSelf. We should have |
| // gone through the formal evaluation variant but did not. The only way that |
| // this can happen is if during argument evaluation, we are accessing self in |
| // a way that is illegal before we call super. Return a copy of self in this |
| // case so that DI will flag on this issue. We do not care where the destroy |
| // occurs, so we can use a normal scoped copy. |
| ManagedValue Result; |
| if (!SuperInitDelegationSelf) { |
| Result = InitDelegationSelf.copy(*this, loc); |
| } else { |
| Result = |
| B.createUncheckedRefCast(loc, SuperInitDelegationSelf.copy(*this, loc), |
| InitDelegationSelf.getType()); |
| } |
| |
| return RValue(*this, loc, refType, Result); |
| } |
| |
| RValue SILGenFunction::emitFormalEvaluationRValueForSelfInDelegationInit( |
| SILLocation loc, CanType refType, SILValue addr, SGFContext C) { |
| assert(SelfInitDelegationState != SILGenFunction::NormalSelf && |
| "This should never be called unless we are in a delegation sequence"); |
| assert(getTypeLowering(addr->getType()).isLoadable() && |
| "Make sure that we are not dealing with semantic rvalues"); |
| |
| // If we are currently in the WillSharedBorrowSelf state, then we know that |
| // old self is not the self to our delegating initializer. Self in this case |
| // to the delegating initializer is a metatype. Thus, we perform a |
| // load_borrow. And move from WillSharedBorrowSelf -> DidSharedBorrowSelf. |
| if (SelfInitDelegationState == SILGenFunction::WillSharedBorrowSelf) { |
| assert(C.isGuaranteedPlusZeroOk() && |
| "This should only be called if guaranteed plus zero is ok"); |
| SelfInitDelegationState = SILGenFunction::DidSharedBorrowSelf; |
| ManagedValue result = |
| B.createFormalAccessLoadBorrow(loc, ManagedValue::forUnmanaged(addr)); |
| return RValue(*this, loc, refType, result); |
| } |
| |
| // If we are already in the did shared borrow self state, just return the |
| // shared borrow value. |
| if (SelfInitDelegationState == SILGenFunction::DidSharedBorrowSelf) { |
| assert(C.isGuaranteedPlusZeroOk() && |
| "This should only be called if guaranteed plus zero is ok"); |
| ManagedValue result = |
| B.createFormalAccessLoadBorrow(loc, ManagedValue::forUnmanaged(addr)); |
| return RValue(*this, loc, refType, result); |
| } |
| |
| // If we hit this point, we must have DidExclusiveBorrowSelf. Thus borrow |
| // self. |
| // |
| // *NOTE* This routine should /never/ begin an exclusive borrow of self. It is |
| // only called when emitting self as a base in lvalue emission. |
| assert(SelfInitDelegationState == SILGenFunction::DidExclusiveBorrowSelf); |
| |
| // If we do not have a super init delegation self, just perform a formal |
| // access borrow and return. This occurs with delegating initializers. |
| if (!SuperInitDelegationSelf) { |
| return RValue(*this, loc, refType, |
| InitDelegationSelf.formalAccessBorrow(*this, loc)); |
| } |
| |
| // Otherwise, we had an upcast of some sort due to a chaining |
| // initializer. This means that we need to perform a borrow from |
| // SuperInitDelegationSelf and then downcast that borrow. |
| ManagedValue borrowedUpcast = |
| SuperInitDelegationSelf.formalAccessBorrow(*this, loc); |
| ManagedValue castedBorrowedType = B.createUncheckedRefCast( |
| loc, borrowedUpcast, InitDelegationSelf.getType()); |
| return RValue(*this, loc, refType, castedBorrowedType); |
| } |
| |
| RValue SILGenFunction:: |
| emitRValueForDecl(SILLocation loc, ConcreteDeclRef declRef, Type ncRefType, |
| AccessSemantics semantics, SGFContext C) { |
| assert(!ncRefType->is<LValueType>() && |
| "RValueEmitter shouldn't be called on lvalues"); |
| |
| // If this is a decl that we have an lvalue for, produce and return it. |
| ValueDecl *decl = declRef.getDecl(); |
| |
| CanType refType = ncRefType->getCanonicalType(); |
| |
| // If this is a reference to a module, produce an undef value. The |
| // module value should never actually be used. |
| if (isa<ModuleDecl>(decl)) { |
| return emitUndefRValue(loc, refType); |
| } |
| |
| // If this is a reference to a var, emit it as an l-value and then load. |
| if (auto *var = dyn_cast<VarDecl>(decl)) |
| return emitRValueForNonMemberVarDecl(loc, declRef, refType, semantics, C); |
| |
| assert(!isa<TypeDecl>(decl)); |
| |
| // If the referenced decl isn't a VarDecl, it should be a constant of some |
| // sort. |
| SILDeclRef silDeclRef(decl); |
| assert(silDeclRef.getParameterListCount() == 1); |
| ManagedValue result = emitClosureValue(loc, silDeclRef, refType, |
| declRef.getSubstitutions()); |
| return RValue(*this, loc, refType, result); |
| } |
| |
| RValue RValueEmitter::visitDeclRefExpr(DeclRefExpr *E, SGFContext C) { |
| return SGF.emitRValueForDecl(E, E->getDeclRef(), E->getType(), |
| E->getAccessSemantics(), C); |
| } |
| |
| RValue RValueEmitter::visitTypeExpr(TypeExpr *E, SGFContext C) { |
| assert(E->getType()->is<AnyMetatypeType>() && |
| "TypeExpr must have metatype type"); |
| auto Val = SGF.B.createMetatype(E, SGF.getLoweredType(E->getType())); |
| return RValue(SGF, E, ManagedValue::forUnmanaged(Val)); |
| } |
| |
| |
| RValue RValueEmitter::visitSuperRefExpr(SuperRefExpr *E, SGFContext C) { |
| assert(!E->getType()->is<LValueType>() && |
| "RValueEmitter shouldn't be called on lvalues"); |
| |
| // If we have a normal self call, then use the emitRValueForDecl call. This |
| // will emit self at +0 since it is guaranteed. |
| ManagedValue Self = |
| SGF.emitRValueForDecl(E, E->getSelf(), E->getSelf()->getType(), |
| AccessSemantics::Ordinary) |
| .getScalarValue(); |
| |
| // Perform an upcast to convert self to the indicated super type. |
| auto result = SGF.B.createUpcast(E, Self, SGF.getLoweredType(E->getType())); |
| |
| return RValue(SGF, E, result); |
| } |
| |
| RValue RValueEmitter:: |
| visitUnresolvedTypeConversionExpr(UnresolvedTypeConversionExpr *E, |
| SGFContext C) { |
| llvm_unreachable("invalid code made its way into SILGen"); |
| } |
| |
| RValue RValueEmitter::visitOtherConstructorDeclRefExpr( |
| OtherConstructorDeclRefExpr *E, SGFContext C) { |
| // This should always be a child of an ApplyExpr and so will be emitted by |
| // SILGenApply. |
| llvm_unreachable("unapplied reference to constructor?!"); |
| } |
| |
| RValue RValueEmitter::visitNilLiteralExpr(NilLiteralExpr *E, SGFContext C) { |
| // Peephole away the call to Optional<T>(nilLiteral: ()). |
| if (E->getType()->getOptionalObjectType()) { |
| auto *noneDecl = SGF.getASTContext().getOptionalNoneDecl(); |
| auto enumTy = SGF.getLoweredType(E->getType()); |
| |
| ManagedValue noneValue; |
| if (enumTy.isLoadable(SGF.F) || !SGF.silConv.useLoweredAddresses()) { |
| noneValue = ManagedValue::forUnmanaged( |
| SGF.B.createEnum(E, SILValue(), noneDecl, enumTy)); |
| } else { |
| noneValue = |
| SGF.B.bufferForExpr(E, enumTy, SGF.getTypeLowering(enumTy), C, |
| [&](SILValue newAddr) { |
| SGF.B.createInjectEnumAddr(E, newAddr, noneDecl); |
| }); |
| } |
| return RValue(SGF, E, noneValue); |
| } |
| |
| return SGF.emitLiteral(E, C); |
| } |
| |
| RValue RValueEmitter::visitIntegerLiteralExpr(IntegerLiteralExpr *E, |
| SGFContext C) { |
| if (E->getType()->is<AnyBuiltinIntegerType>()) |
| return RValue(SGF, E, |
| ManagedValue::forUnmanaged(SGF.B.createIntegerLiteral(E))); |
| return SGF.emitLiteral(E, C); |
| } |
| RValue RValueEmitter::visitFloatLiteralExpr(FloatLiteralExpr *E, |
| SGFContext C) { |
| if (E->getType()->is<BuiltinFloatType>()) |
| return RValue(SGF, E, |
| ManagedValue::forUnmanaged(SGF.B.createFloatLiteral(E))); |
| |
| return SGF.emitLiteral(E, C); |
| } |
| |
| RValue RValueEmitter::visitBooleanLiteralExpr(BooleanLiteralExpr *E, |
| SGFContext C) { |
| return SGF.emitLiteral(E, C); |
| } |
| |
| RValue RValueEmitter::visitStringLiteralExpr(StringLiteralExpr *E, |
| SGFContext C) { |
| return SGF.emitLiteral(E, C); |
| } |
| |
| RValue RValueEmitter::visitLoadExpr(LoadExpr *E, SGFContext C) { |
| // Any writebacks here are tightly scoped. |
| FormalEvaluationScope writeback(SGF); |
| LValue lv = SGF.emitLValue(E->getSubExpr(), SGFAccessKind::OwnedObjectRead); |
| // We can't load at immediate +0 from the lvalue without deeper analysis, |
| // since the access will be immediately ended and might invalidate the value |
| // we loaded. |
| return SGF.emitLoadOfLValue(E, std::move(lv), C.withFollowingSideEffects()); |
| } |
| |
| SILValue SILGenFunction::emitTemporaryAllocation(SILLocation loc, |
| SILType ty) { |
| ty = ty.getObjectType(); |
| Optional<SILDebugVariable> DbgVar; |
| if (auto *VD = loc.getAsASTNode<VarDecl>()) |
| DbgVar = SILDebugVariable(VD->isLet(), 0); |
| auto alloc = B.createAllocStack(loc, ty, DbgVar); |
| enterDeallocStackCleanup(alloc); |
| return alloc; |
| } |
| |
| SILValue SILGenFunction:: |
| getBufferForExprResult(SILLocation loc, SILType ty, SGFContext C) { |
| // If you change this, change manageBufferForExprResult below as well. |
| |
| // If we have a single-buffer "emit into" initialization, use that for the |
| // result. |
| if (SILValue address = C.getAddressForInPlaceInitialization(*this, loc)) |
| return address; |
| |
| // If we couldn't emit into the Initialization, emit into a temporary |
| // allocation. |
| return emitTemporaryAllocation(loc, ty.getObjectType()); |
| } |
| |
| ManagedValue SILGenFunction:: |
| manageBufferForExprResult(SILValue buffer, const TypeLowering &bufferTL, |
| SGFContext C) { |
| // If we have a single-buffer "emit into" initialization, use that for the |
| // result. |
| if (C.finishInPlaceInitialization(*this)) |
| return ManagedValue::forInContext(); |
| |
| // Add a cleanup for the temporary we allocated. |
| if (bufferTL.isTrivial()) |
| return ManagedValue::forUnmanaged(buffer); |
| |
| return ManagedValue(buffer, enterDestroyCleanup(buffer)); |
| } |
| |
| SILGenFunction::ForceTryEmission::ForceTryEmission(SILGenFunction &SGF, |
| ForceTryExpr *loc) |
| : SGF(SGF), Loc(loc), OldThrowDest(SGF.ThrowDest) { |
| assert(loc && "cannot pass a null location"); |
| |
| // Set up a "catch" block for when an error occurs. |
| SILBasicBlock *catchBB = SGF.createBasicBlock(FunctionSection::Postmatter); |
| SGF.ThrowDest = JumpDest(catchBB, SGF.Cleanups.getCleanupsDepth(), |
| CleanupLocation::get(loc)); |
| } |
| |
| void SILGenFunction::ForceTryEmission::finish() { |
| assert(Loc && "emission already finished"); |
| |
| auto catchBB = SGF.ThrowDest.getBlock(); |
| SGF.ThrowDest = OldThrowDest; |
| |
| // If there are no uses of the catch block, just drop it. |
| if (catchBB->pred_empty()) { |
| SGF.eraseBasicBlock(catchBB); |
| } else { |
| // Otherwise, we need to emit it. |
| SILGenSavedInsertionPoint scope(SGF, catchBB, FunctionSection::Postmatter); |
| |
| if (auto diagnoseError = SGF.getASTContext().getDiagnoseUnexpectedError()) { |
| ASTContext &ctx = SGF.getASTContext(); |
| auto error = SGF.B.createOwnedPhiArgument(SILType::getExceptionType(ctx)); |
| auto args = SGF.emitSourceLocationArgs(Loc->getExclaimLoc(), Loc); |
| |
| SGF.emitApplyOfLibraryIntrinsic( |
| Loc, |
| diagnoseError, |
| SubstitutionMap(), |
| { |
| error, |
| args.filenameStartPointer, |
| args.filenameLength, |
| args.filenameIsAscii, |
| args.line |
| }, |
| SGFContext()); |
| } |
| SGF.B.createUnreachable(Loc); |
| } |
| |
| // Prevent double-finishing and make the destructor a no-op. |
| Loc = nullptr; |
| } |
| |
| RValue RValueEmitter::visitForceTryExpr(ForceTryExpr *E, SGFContext C) { |
| SILGenFunction::ForceTryEmission emission(SGF, E); |
| |
| // Visit the sub-expression. |
| return visit(E->getSubExpr(), C); |
| } |
| |
| RValue RValueEmitter::visitOptionalTryExpr(OptionalTryExpr *E, SGFContext C) { |
| // FIXME: Much of this was copied from visitOptionalEvaluationExpr. |
| |
| // Prior to Swift 5, an optional try's subexpression is always wrapped in an additional optional |
| bool shouldWrapInOptional = !(SGF.getASTContext().LangOpts.isSwiftVersionAtLeast(5)); |
| |
| auto &optTL = SGF.getTypeLowering(E->getType()); |
| |
| Initialization *optInit = C.getEmitInto(); |
| bool usingProvidedContext = |
| optInit && optInit->canPerformInPlaceInitialization(); |
| |
| // Form the optional using address operations if the type is address-only or |
| // if we already have an address to use. |
| bool isByAddress = usingProvidedContext || optTL.isAddressOnly(); |
| |
| std::unique_ptr<TemporaryInitialization> optTemp; |
| if (!usingProvidedContext && isByAddress) { |
| // Allocate the temporary for the Optional<T> if we didn't get one from the |
| // context. |
| optTemp = SGF.emitTemporary(E, optTL); |
| optInit = optTemp.get(); |
| } else if (!usingProvidedContext) { |
| // If the caller produced a context for us, but we can't use it, then don't. |
| optInit = nullptr; |
| } |
| |
| FullExpr localCleanups(SGF.Cleanups, E); |
| |
| // Set up a "catch" block for when an error occurs. |
| SILBasicBlock *catchBB = SGF.createBasicBlock(FunctionSection::Postmatter); |
| llvm::SaveAndRestore<JumpDest> throwDest{ |
| SGF.ThrowDest, |
| JumpDest(catchBB, SGF.Cleanups.getCleanupsDepth(), E)}; |
| |
| SILValue branchArg; |
| if (shouldWrapInOptional) { |
| if (isByAddress) { |
| assert(optInit); |
| SILValue optAddr = optInit->getAddressForInPlaceInitialization(SGF, E); |
| SGF.emitInjectOptionalValueInto(E, E->getSubExpr(), optAddr, optTL); |
| } else { |
| ManagedValue subExprValue = SGF.emitRValueAsSingleValue(E->getSubExpr()); |
| ManagedValue wrapped = SGF.getOptionalSomeValue(E, subExprValue, optTL); |
| branchArg = wrapped.forward(SGF); |
| } |
| } |
| else { |
| if (isByAddress) { |
| assert(optInit); |
| SGF.emitExprInto(E->getSubExpr(), optInit); |
| } else { |
| ManagedValue subExprValue = SGF.emitRValueAsSingleValue(E->getSubExpr()); |
| branchArg = subExprValue.forward(SGF); |
| } |
| } |
| |
| localCleanups.pop(); |
| |
| // If it turns out there are no uses of the catch block, just drop it. |
| if (catchBB->pred_empty()) { |
| // Remove the dead failureBB. |
| SGF.eraseBasicBlock(catchBB); |
| |
| // The value we provide is the one we've already got. |
| if (!isByAddress) |
| return RValue(SGF, E, |
| SGF.emitManagedRValueWithCleanup(branchArg, optTL)); |
| |
| if (shouldWrapInOptional) { |
| optInit->finishInitialization(SGF); |
| } |
| |
| // If we emitted into the provided context, we're done. |
| if (usingProvidedContext) |
| return RValue::forInContext(); |
| |
| return RValue(SGF, E, optTemp->getManagedAddress()); |
| } |
| |
| SILBasicBlock *contBB = SGF.createBasicBlock(); |
| |
| // Branch to the continuation block. |
| if (isByAddress) |
| SGF.B.createBranch(E, contBB); |
| else |
| SGF.B.createBranch(E, contBB, branchArg); |
| |
| // If control branched to the failure block, inject .None into the |
| // result type. |
| SGF.B.emitBlock(catchBB); |
| FullExpr catchCleanups(SGF.Cleanups, E); |
| auto *errorArg = catchBB->createPhiArgument( |
| SILType::getExceptionType(SGF.getASTContext()), OwnershipKind::Owned); |
| (void) SGF.emitManagedRValueWithCleanup(errorArg); |
| catchCleanups.pop(); |
| |
| if (isByAddress) { |
| SGF.emitInjectOptionalNothingInto(E, |
| optInit->getAddressForInPlaceInitialization(SGF, E), optTL); |
| SGF.B.createBranch(E, contBB); |
| } else { |
| auto branchArg = SGF.getOptionalNoneValue(E, optTL); |
| SGF.B.createBranch(E, contBB, branchArg); |
| } |
| |
| // Emit the continuation block. |
| SGF.B.emitBlock(contBB); |
| |
| // If this was done in SSA registers, then the value is provided as an |
| // argument to the block. |
| if (!isByAddress) { |
| auto arg = |
| contBB->createPhiArgument(optTL.getLoweredType(), OwnershipKind::Owned); |
| return RValue(SGF, E, SGF.emitManagedRValueWithCleanup(arg, optTL)); |
| } |
| |
| if (shouldWrapInOptional) { |
| optInit->finishInitialization(SGF); |
| } |
| |
| // If we emitted into the provided context, we're done. |
| if (usingProvidedContext) |
| return RValue::forInContext(); |
| |
| assert(optTemp); |
| return RValue(SGF, E, optTemp->getManagedAddress()); |
| } |
| |
| static bool inExclusiveBorrowSelfSection( |
| SILGenFunction::SelfInitDelegationStates delegationState) { |
| return delegationState == SILGenFunction::WillExclusiveBorrowSelf || |
| delegationState == SILGenFunction::DidExclusiveBorrowSelf; |
| } |
| |
| static RValue visitDerivedToBaseExprOfSelf(SILGenFunction &SGF, |
| DeclRefExpr *dre, |
| DerivedToBaseExpr *E, SGFContext C) { |
| SGFContext ctx; |
| auto *vd = cast<ParamDecl>(dre->getDecl()); |
| SILType derivedType = SGF.getLoweredType(E->getType()); |
| ManagedValue selfValue; |
| |
| // If we have not exclusively borrowed self, we need to do so now. |
| if (SGF.SelfInitDelegationState == SILGenFunction::WillExclusiveBorrowSelf) { |
| // We need to use a full scope here to ensure that any underlying |
| // "normal cleanup" borrows are cleaned up. |
| Scope S(SGF, E); |
| selfValue = S.popPreservingValue(SGF.emitRValueAsSingleValue(dre)); |
| } else { |
| // If we already exclusively borrowed self, then we need to emit self |
| // using formal evaluation primitives. |
| |
| assert(SGF.SelfInitDelegationState == |
| SILGenFunction::DidExclusiveBorrowSelf); |
| // This needs to be inlined since there is a Formal Evaluation Scope |
| // in emitRValueForDecl that causing any borrow for this LValue to be |
| // popped too soon. |
| selfValue = |
| SGF.emitAddressOfLocalVarDecl(dre, vd, dre->getType()->getCanonicalType(), |
| SGFAccessKind::OwnedObjectRead); |
| selfValue = SGF.emitFormalEvaluationRValueForSelfInDelegationInit( |
| E, dre->getType()->getCanonicalType(), |
| selfValue.getLValueAddress(), ctx) |
| .getAsSingleValue(SGF, E); |
| } |
| assert(selfValue); |
| |
| // Check if we need to perform a conversion here. |
| if (derivedType && selfValue.getType() != derivedType) |
| selfValue = SGF.B.createUpcast(E, selfValue, derivedType); |
| return RValue(SGF, dre, selfValue); |
| } |
| |
| RValue RValueEmitter::visitDerivedToBaseExpr(DerivedToBaseExpr *E, |
| SGFContext C) { |
| // If we are going through a decl ref expr and have self and we are in the |
| // exclusive borrow section of delegating init emission, use a special case. |
| if (inExclusiveBorrowSelfSection(SGF.SelfInitDelegationState)) { |
| if (auto *dre = dyn_cast<DeclRefExpr>(E->getSubExpr())) { |
| if (isa<ParamDecl>(dre->getDecl()) && |
| dre->getDecl()->getName() == SGF.getASTContext().Id_self && |
| dre->getDecl()->isImplicit()) { |
| return visitDerivedToBaseExprOfSelf(SGF, dre, E, C); |
| } |
| } |
| } |
| |
| // We can pass down the SGFContext as a following projection. We have never |
| // actually implemented emit into here, so we are not changing behavior. |
| ManagedValue original = |
| SGF.emitRValueAsSingleValue(E->getSubExpr(), C.withFollowingProjection()); |
| |
| // Derived-to-base casts in the AST might not be reflected as such |
| // in the SIL type system, for example, a cast from DynamicSelf |
| // directly to its own Self type. |
| auto loweredResultTy = SGF.getLoweredType(E->getType()); |
| if (original.getType() == loweredResultTy) |
| return RValue(SGF, E, original); |
| |
| ManagedValue converted = SGF.B.createUpcast(E, original, loweredResultTy); |
| return RValue(SGF, E, converted); |
| } |
| |
| RValue RValueEmitter::visitMetatypeConversionExpr(MetatypeConversionExpr *E, |
| SGFContext C) { |
| SILValue metaBase = |
| SGF.emitRValueAsSingleValue(E->getSubExpr()).getUnmanagedValue(); |
| |
| // Metatype conversion casts in the AST might not be reflected as |
| // such in the SIL type system, for example, a cast from DynamicSelf.Type |
| // directly to its own Self.Type. |
| auto loweredResultTy = SGF.getLoweredLoadableType(E->getType()); |
| if (metaBase->getType() == loweredResultTy) |
| return RValue(SGF, E, ManagedValue::forUnmanaged(metaBase)); |
| |
| auto upcast = SGF.B.createUpcast(E, metaBase, loweredResultTy); |
| return RValue(SGF, E, ManagedValue::forUnmanaged(upcast)); |
| } |
| |
| RValue SILGenFunction::emitCollectionConversion(SILLocation loc, |
| FuncDecl *fn, |
| CanType fromCollection, |
| CanType toCollection, |
| ManagedValue mv, |
| SGFContext C) { |
| auto *fromDecl = fromCollection->getAnyNominal(); |
| auto *toDecl = toCollection->getAnyNominal(); |
| |
| auto fromSubMap = fromCollection->getContextSubstitutionMap( |
| SGM.SwiftModule, fromDecl); |
| auto toSubMap = toCollection->getContextSubstitutionMap( |
| SGM.SwiftModule, toDecl); |
| |
| // Form type parameter substitutions. |
| auto genericSig = fn->getGenericSignature(); |
| unsigned fromParamCount = fromDecl->getGenericSignature() |
| ->getGenericParams().size(); |
| |
| auto subMap = |
| SubstitutionMap::combineSubstitutionMaps(fromSubMap, |
| toSubMap, |
| CombineSubstitutionMaps::AtIndex, |
| fromParamCount, |
| 0, |
| genericSig); |
| return emitApplyOfLibraryIntrinsic(loc, fn, subMap, {mv}, C); |
| } |
| |
| RValue RValueEmitter:: |
| visitCollectionUpcastConversionExpr(CollectionUpcastConversionExpr *E, |
| SGFContext C) { |
| |
| SILLocation loc = RegularLocation(E); |
| |
| // Get the sub expression argument as a managed value |
| auto mv = SGF.emitRValueAsSingleValue(E->getSubExpr()); |
| |
| // Compute substitutions for the intrinsic call. |
| auto fromCollection = E->getSubExpr()->getType()->getCanonicalType(); |
| auto toCollection = E->getType()->getCanonicalType(); |
| |
| // Get the intrinsic function. |
| auto &ctx = SGF.getASTContext(); |
| FuncDecl *fn = nullptr; |
| if (fromCollection->getAnyNominal() == ctx.getArrayDecl()) { |
| fn = SGF.SGM.getArrayForceCast(loc); |
| } else if (fromCollection->getAnyNominal() == ctx.getDictionaryDecl()) { |
| fn = SGF.SGM.getDictionaryUpCast(loc); |
| } else if (fromCollection->getAnyNominal() == ctx.getSetDecl()) { |
| fn = SGF.SGM.getSetUpCast(loc); |
| } else { |
| llvm_unreachable("unsupported collection upcast kind"); |
| } |
| |
| return SGF.emitCollectionConversion(loc, fn, fromCollection, toCollection, |
| mv, C); |
| } |
| |
| RValue |
| RValueEmitter::visitConditionalBridgeFromObjCExpr( |
| ConditionalBridgeFromObjCExpr *E, SGFContext C) { |
| // Get the sub expression argument as a managed value |
| auto mv = SGF.emitRValueAsSingleValue(E->getSubExpr()); |
| |
| auto conversionRef = E->getConversion(); |
| auto conversion = cast<FuncDecl>(conversionRef.getDecl()); |
| auto subs = conversionRef.getSubstitutions(); |
| |
| auto nativeType = |
| Type(GenericTypeParamType::get(0, 0, SGF.getASTContext())).subst(subs); |
| |
| auto metatypeType = SGF.getLoweredType(MetatypeType::get(nativeType)); |
| auto metatype = |
| ManagedValue::forUnmanaged(SGF.B.createMetatype(E, metatypeType)); |
| |
| return SGF.emitApplyOfLibraryIntrinsic(E, conversion, subs, |
| { mv, metatype }, C); |
| } |
| |
| /// Given an implicit bridging conversion, check whether the context |
| /// can be peepholed. |
| static bool |
| tryPeepholeBridgingConversion(SILGenFunction &SGF, Conversion::KindTy kind, |
| ImplicitConversionExpr *E, SGFContext C) { |
| assert(isa<BridgeFromObjCExpr>(E) || isa<BridgeToObjCExpr>(E)); |
| if (auto outerConversion = C.getAsConversion()) { |
| auto subExpr = E->getSubExpr(); |
| CanType sourceType = subExpr->getType()->getCanonicalType(); |
| CanType resultType = E->getType()->getCanonicalType(); |
| SILType loweredResultTy = SGF.getLoweredType(resultType); |
| auto conversion = Conversion::getBridging(kind, sourceType, resultType, |
| loweredResultTy); |
| if (outerConversion->tryPeephole(SGF, E->getSubExpr(), conversion)) { |
| outerConversion->finishInitialization(SGF); |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| RValue |
| RValueEmitter::visitBridgeFromObjCExpr(BridgeFromObjCExpr *E, SGFContext C) { |
| if (tryPeepholeBridgingConversion(SGF, Conversion::BridgeFromObjC, E, C)) |
| return RValue::forInContext(); |
| |
| // Emit the sub-expression. |
| auto mv = SGF.emitRValueAsSingleValue(E->getSubExpr()); |
| |
| CanType origType = E->getSubExpr()->getType()->getCanonicalType(); |
| CanType resultType = E->getType()->getCanonicalType(); |
| SILType loweredResultTy = SGF.getLoweredType(resultType); |
| auto result = SGF.emitBridgedToNativeValue(E, mv, origType, resultType, |
| loweredResultTy, C); |
| return RValue(SGF, E, result); |
| } |
| |
| RValue |
| RValueEmitter::visitBridgeToObjCExpr(BridgeToObjCExpr *E, SGFContext C) { |
| if (tryPeepholeBridgingConversion(SGF, Conversion::BridgeToObjC, E, C)) |
| return RValue::forInContext(); |
| |
| // Emit the sub-expression. |
| auto mv = SGF.emitRValueAsSingleValue(E->getSubExpr()); |
| |
| CanType origType = E->getSubExpr()->getType()->getCanonicalType(); |
| CanType resultType = E->getType()->getCanonicalType(); |
| SILType loweredResultTy = SGF.getLoweredType(resultType); |
| auto result = SGF.emitNativeToBridgedValue(E, mv, origType, resultType, |
| loweredResultTy, C); |
| return RValue(SGF, E, result); |
| } |
| |
| RValue RValueEmitter::visitArchetypeToSuperExpr(ArchetypeToSuperExpr *E, |
| SGFContext C) { |
| ManagedValue archetype = SGF.emitRValueAsSingleValue(E->getSubExpr()); |
| auto loweredTy = SGF.getLoweredLoadableType(E->getType()); |
| if (loweredTy == archetype.getType()) |
| return RValue(SGF, E, archetype); |
| |
| // Replace the cleanup with a new one on the superclass value so we always use |
| // concrete retain/release operations. |
| auto base = SGF.B.createUpcast(E, archetype, loweredTy); |
| return RValue(SGF, E, base); |
| } |
| |
| static ManagedValue convertCFunctionSignature(SILGenFunction &SGF, |
| FunctionConversionExpr *e, |
| SILType loweredResultTy, |
| llvm::function_ref<ManagedValue ()> fnEmitter) { |
| SILType loweredDestTy = SGF.getLoweredType(e->getType()); |
| ManagedValue result; |
| |
| // We're converting between C function pointer types. They better be |
| // ABI-compatible, since we can't emit a thunk. |
| switch (SGF.SGM.Types.checkForABIDifferences(SGF.SGM.M, |
| loweredResultTy, loweredDestTy)){ |
| case TypeConverter::ABIDifference::CompatibleRepresentation: |
| case TypeConverter::ABIDifference::CompatibleCallingConvention: |
| result = fnEmitter(); |
| assert(result.getType() == loweredResultTy); |
| |
| if (loweredResultTy != loweredDestTy) { |
| assert(!result.hasCleanup()); |
| result = SGF.B.createConvertFunction(e, result, loweredDestTy); |
| } |
| |
| break; |
| |
| case TypeConverter::ABIDifference::NeedsThunk: |
| // Note: in this case, we don't call the emitter at all -- doing so |
| // just runs the risk of tripping up asserts in SILGenBridging.cpp |
| SGF.SGM.diagnose(e, diag::unsupported_c_function_pointer_conversion, |
| e->getSubExpr()->getType(), e->getType()); |
| result = SGF.emitUndef(loweredDestTy); |
| break; |
| |
| case TypeConverter::ABIDifference::CompatibleCallingConvention_ThinToThick: |
| case TypeConverter::ABIDifference::CompatibleRepresentation_ThinToThick: |
| llvm_unreachable("Cannot have thin to thick conversion here"); |
| } |
| |
| return result; |
| } |
| |
| static |
| ManagedValue emitCFunctionPointer(SILGenFunction &SGF, |
| FunctionConversionExpr *conversionExpr) { |
| auto expr = conversionExpr->getSubExpr(); |
| |
| // Look through base-ignored exprs to get to the function ref. |
| auto semanticExpr = expr->getSemanticsProvidingExpr(); |
| while (auto ignoredBase = dyn_cast<DotSyntaxBaseIgnoredExpr>(semanticExpr)){ |
| SGF.emitIgnoredExpr(ignoredBase->getLHS()); |
| semanticExpr = ignoredBase->getRHS()->getSemanticsProvidingExpr(); |
| } |
| |
| // Recover the decl reference. |
| SILDeclRef::Loc loc; |
| |
| auto setLocFromConcreteDeclRef = [&](ConcreteDeclRef declRef) { |
| // TODO: Handle generic instantiations, where we need to eagerly specialize |
| // on the given generic parameters, and static methods, where we need to drop |
| // in the metatype. |
| assert(!declRef.getDecl()->getDeclContext()->isTypeContext() |
| && "c pointers to static methods not implemented"); |
| loc = declRef.getDecl(); |
| }; |
| |
| if (auto declRef = dyn_cast<DeclRefExpr>(semanticExpr)) { |
| setLocFromConcreteDeclRef(declRef->getDeclRef()); |
| } else if (auto memberRef = dyn_cast<MemberRefExpr>(semanticExpr)) { |
| setLocFromConcreteDeclRef(memberRef->getMember()); |
| } else if (auto closure = dyn_cast<AbstractClosureExpr>(semanticExpr)) { |
| // Emit the closure body. |
| SGF.SGM.emitClosure(closure); |
| |
| loc = closure; |
| } else if (auto captureList = dyn_cast<CaptureListExpr>(semanticExpr)) { |
| // Ensure that weak captures are in a separate scope. |
| DebugScope scope(SGF, CleanupLocation(captureList)); |
| // CaptureListExprs evaluate their bound variables. |
| for (auto capture : captureList->getCaptureList()) { |
| SGF.visit(capture.Var); |
| SGF.visit(capture.Init); |
| } |
| |
| // Emit the closure body. |
| auto *closure = captureList->getClosureBody(); |
| SGF.SGM.emitClosure(closure); |
| |
| loc = closure; |
| } else { |
| llvm_unreachable("c function pointer converted from a non-concrete decl ref"); |
| } |
| |
| // Produce a reference to the C-compatible entry point for the function. |
| SILDeclRef constant(loc, /*foreign*/ true); |
| SILConstantInfo constantInfo = |
| SGF.getConstantInfo(SGF.getTypeExpansionContext(), constant); |
| |
| // C function pointers cannot capture anything from their context. |
| auto captures = SGF.SGM.Types.getLoweredLocalCaptures(constant); |
| |
| if (!captures.getCaptures().empty() || |
| captures.hasGenericParamCaptures() || |
| captures.hasDynamicSelfCapture() || |
| captures.hasOpaqueValueCapture()) { |
| unsigned kind = 0; |
| if (captures.hasGenericParamCaptures()) |
| kind = 1; |
| else if (captures.hasDynamicSelfCapture()) |
| kind = 2; |
| SGF.SGM.diagnose(expr->getLoc(), |
| diag::c_function_pointer_from_function_with_context, |
| /*closure*/ constant.hasClosureExpr(), |
| kind); |
| |
| auto loweredTy = SGF.getLoweredType(conversionExpr->getType()); |
| return SGF.emitUndef(loweredTy); |
| } |
| |
| return convertCFunctionSignature( |
| SGF, conversionExpr, |
| constantInfo.getSILType(), |
| [&]() -> ManagedValue { |
| SILValue cRef = SGF.emitGlobalFunctionRef(expr, constant); |
| return ManagedValue::forUnmanaged(cRef); |
| }); |
| } |
| |
| // Change the representation without changing the signature or |
| // abstraction level. |
| static ManagedValue convertFunctionRepresentation(SILGenFunction &SGF, |
| SILLocation loc, |
| ManagedValue source, |
| CanAnyFunctionType sourceFormalTy, |
| CanAnyFunctionType resultFormalTy) { |
| auto sourceTy = source.getType().castTo<SILFunctionType>(); |
| CanSILFunctionType resultTy = |
| SGF.getLoweredType(resultFormalTy).castTo<SILFunctionType>(); |
| |
| // Note that conversions to and from block require a thunk |
| switch (resultFormalTy->getRepresentation()) { |
| |
| // Convert thin, c, block => thick |
| case AnyFunctionType::Representation::Swift: { |
| switch (sourceTy->getRepresentation()) { |
| case SILFunctionType::Representation::Thin: { |
| auto v = SGF.B.createThinToThickFunction( |
| loc, source.getValue(), |
| SILType::getPrimitiveObjectType( |
| sourceTy->getWithRepresentation( |
| SILFunctionTypeRepresentation::Thick))); |
| // FIXME: what if other reabstraction is required? |
| return ManagedValue(v, source.getCleanup()); |
| } |
| case SILFunctionType::Representation::Thick: |
| llvm_unreachable("should not try thick-to-thick repr change"); |
| case SILFunctionType::Representation::CFunctionPointer: |
| case SILFunctionType::Representation::Block: |
| return SGF.emitBlockToFunc(loc, source, sourceFormalTy, resultFormalTy, |
| resultTy); |
| case SILFunctionType::Representation::Method: |
| case SILFunctionType::Representation::Closure: |
| case SILFunctionType::Representation::ObjCMethod: |
| case SILFunctionType::Representation::WitnessMethod: |
| llvm_unreachable("should not do function conversion from method rep"); |
| } |
| llvm_unreachable("bad representation"); |
| } |
| |
| // Convert thin, thick, c => block |
| case AnyFunctionType::Representation::Block: |
| switch (sourceTy->getRepresentation()) { |
| case SILFunctionType::Representation::Thin: { |
| // Make thick first. |
| auto v = SGF.B.createThinToThickFunction( |
| loc, source.getValue(), |
| SILType::getPrimitiveObjectType( |
| sourceTy->getWithRepresentation( |
| SILFunctionTypeRepresentation::Thick))); |
| source = ManagedValue(v, source.getCleanup()); |
| LLVM_FALLTHROUGH; |
| } |
| case SILFunctionType::Representation::Thick: |
| case SILFunctionType::Representation::CFunctionPointer: |
| // Convert to a block. |
| return SGF.emitFuncToBlock(loc, source, sourceFormalTy, resultFormalTy, |
| resultTy); |
| case SILFunctionType::Representation::Block: |
| llvm_unreachable("should not try block-to-block repr change"); |
| case SILFunctionType::Representation::Method: |
| case SILFunctionType::Representation::Closure: |
| case SILFunctionType::Representation::ObjCMethod: |
| case SILFunctionType::Representation::WitnessMethod: |
| llvm_unreachable("should not do function conversion from method rep"); |
| } |
| llvm_unreachable("bad representation"); |
| |
| // Unsupported |
| case AnyFunctionType::Representation::Thin: |
| llvm_unreachable("should not do function conversion to thin"); |
| case AnyFunctionType::Representation::CFunctionPointer: |
| llvm_unreachable("should not do C function pointer conversion here"); |
| } |
| llvm_unreachable("bad representation"); |
| } |
| |
| RValue RValueEmitter::visitFunctionConversionExpr(FunctionConversionExpr *e, |
| SGFContext C) |
| { |
| CanAnyFunctionType srcRepTy = |
| cast<FunctionType>(e->getSubExpr()->getType()->getCanonicalType()); |
| CanAnyFunctionType destRepTy = |
| cast<FunctionType>(e->getType()->getCanonicalType()); |
| |
| if (destRepTy->getRepresentation() == |
| FunctionTypeRepresentation::CFunctionPointer) { |
| ManagedValue result; |
| |
| if (srcRepTy->getRepresentation() != |
| FunctionTypeRepresentation::CFunctionPointer) { |
| // A "conversion" of a DeclRef a C function pointer is done by referencing |
| // the thunk (or original C function) with the C calling convention. |
| result = emitCFunctionPointer(SGF, e); |
| } else { |
| // Ok, we're converting a C function pointer value to another C function |
| // pointer. |
| |
| // Emit the C function pointer |
| result = SGF.emitRValueAsSingleValue(e->getSubExpr()); |
| |
| // Possibly bitcast the C function pointer to account for ABI-compatible |
| // parameter and result type conversions |
| result = convertCFunctionSignature(SGF, e, result.getType(), |
| [&]() -> ManagedValue { |
| return result; |
| }); |
| } |
| return RValue(SGF, e, result); |
| } |
| |
| // Handle a reference to a "thin" native Swift function that only changes |
| // representation and refers to an inherently thin function reference. |
| if (destRepTy->getRepresentation() == FunctionTypeRepresentation::Thin) { |
| if (srcRepTy->getRepresentation() == FunctionTypeRepresentation::Swift |
| && srcRepTy->withExtInfo(destRepTy->getExtInfo())->isEqual(destRepTy)) { |
| auto value = SGF.emitRValueAsSingleValue(e->getSubExpr()); |
| auto expectedTy = SGF.getLoweredType(e->getType()); |
| if (auto thinToThick = |
| dyn_cast<ThinToThickFunctionInst>(value.getValue())) { |
| value = ManagedValue::forUnmanaged(thinToThick->getOperand()); |
| } else { |
| SGF.SGM.diagnose(e->getLoc(), diag::not_implemented, |
| "nontrivial thin function reference"); |
| value = SGF.emitUndef(expectedTy); |
| } |
| |
| if (value.getType() != expectedTy) { |
| SGF.SGM.diagnose(e->getLoc(), diag::not_implemented, |
| "nontrivial thin function reference"); |
| value = SGF.emitUndef(expectedTy); |
| } |
| return RValue(SGF, e, value); |
| } |
| } |
| |
| // Break the conversion into three stages: |
| // 1) changing the representation from foreign to native |
| // 2) changing the signature within the representation |
| // 3) changing the representation from native to foreign |
| // |
| // We only do one of 1) or 3), but we have to do them in the right order |
| // with respect to 2). |
| |
| CanAnyFunctionType srcTy = srcRepTy; |
| CanAnyFunctionType destTy = destRepTy; |
| |
| switch(srcRepTy->getRepresentation()) { |
| case AnyFunctionType::Representation::Swift: |
| case AnyFunctionType::Representation::Thin: |
| // Source is native, so we can convert signature first. |
| destTy = adjustFunctionType(destRepTy, srcTy->getRepresentation(), |
| srcTy->getClangTypeInfo()); |
| break; |
| case AnyFunctionType::Representation::Block: |
| case AnyFunctionType::Representation::CFunctionPointer: |
| // Source is foreign, so do the representation change first. |
| srcTy = adjustFunctionType(srcRepTy, destRepTy->getRepresentation(), |
| destRepTy->getClangTypeInfo()); |
| } |
| |
| auto result = SGF.emitRValueAsSingleValue(e->getSubExpr()); |
| |
| if (srcRepTy != srcTy) |
| result = convertFunctionRepresentation(SGF, e, result, srcRepTy, srcTy); |
| |
| if (srcTy != destTy) { |
| result = SGF.emitTransformedValue(e, result, srcTy, destTy, SGFContext()); |
| } |
| |
| if (destTy != destRepTy) |
| result = convertFunctionRepresentation(SGF, e, result, destTy, destRepTy); |
| |
| return RValue(SGF, e, result); |
| } |
| |
| RValue RValueEmitter::visitCovariantFunctionConversionExpr( |
| CovariantFunctionConversionExpr *e, |
| SGFContext C) { |
| ManagedValue original = SGF.emitRValueAsSingleValue(e->getSubExpr()); |
| CanAnyFunctionType destTy |
| = cast<AnyFunctionType>(e->getType()->getCanonicalType()); |
| SILType resultType = SGF.getLoweredType(destTy); |
| SILValue result = |
| SGF.B.createConvertFunction(e, original.forward(SGF), resultType, |
| /*Withoutactuallyescaping=*/false); |
| return RValue(SGF, e, SGF.emitManagedRValueWithCleanup(result)); |
| } |
| |
| RValue RValueEmitter::visitCovariantReturnConversionExpr( |
| CovariantReturnConversionExpr *e, |
| SGFContext C) { |
| ManagedValue original = SGF.emitRValueAsSingleValue(e->getSubExpr()); |
| SILType resultType = SGF.getLoweredType(e->getType()); |
| |
| // DynamicSelfType lowers as its self type, so no SIL-level conversion |
| // is required in this case. |
| if (resultType == original.getType()) |
| return RValue(SGF, e, original); |
| |
| ManagedValue result = SGF.B.createUncheckedRefCast(e, original, resultType); |
| |
| return RValue(SGF, e, result); |
| } |
| |
| RValue RValueEmitter::visitImplicitlyUnwrappedFunctionConversionExpr( |
| ImplicitlyUnwrappedFunctionConversionExpr *e, SGFContext C) { |
| // These are generated for short term use in the type checker. |
| llvm_unreachable( |
| "We should not see ImplicitlyUnwrappedFunctionConversionExpr here"); |
| } |
| |
| RValue RValueEmitter::visitErasureExpr(ErasureExpr *E, SGFContext C) { |
| if (auto result = tryEmitAsBridgingConversion(SGF, E, false, C)) { |
| return RValue(SGF, E, *result); |
| } |
| |
| auto &existentialTL = SGF.getTypeLowering(E->getType()); |
| auto concreteFormalType = E->getSubExpr()->getType()->getCanonicalType(); |
| |
| auto archetype = OpenedArchetypeType::getAny(E->getType()); |
| AbstractionPattern abstractionPattern(archetype); |
| auto &concreteTL = SGF.getTypeLowering(abstractionPattern, |
| concreteFormalType); |
| |
| ManagedValue mv = SGF.emitExistentialErasure(E, concreteFormalType, |
| concreteTL, existentialTL, |
| E->getConformances(), C, |
| [&](SGFContext C) -> ManagedValue { |
| return SGF.emitRValueAsOrig(E->getSubExpr(), |
| abstractionPattern, |
| concreteTL, C); |
| }); |
| |
| return RValue(SGF, E, mv); |
| } |
| |
| RValue SILGenFunction::emitAnyHashableErasure(SILLocation loc, |
| ManagedValue value, |
| Type type, |
| ProtocolConformanceRef conformance, |
| SGFContext C) { |
| // Ensure that the intrinsic function exists. |
| auto convertFn = SGM.getConvertToAnyHashable(loc); |
| if (!convertFn) |
| return emitUndefRValue( |
| loc, getASTContext().getAnyHashableDecl()->getDeclaredInterfaceType()); |
| |
| // Construct the substitution for T: Hashable. |
| auto subMap = SubstitutionMap::getProtocolSubstitutions( |
| conformance.getRequirement(), type, conformance); |
| |
| return emitApplyOfLibraryIntrinsic(loc, convertFn, subMap, value, C); |
| } |
| |
| RValue RValueEmitter::visitAnyHashableErasureExpr(AnyHashableErasureExpr *E, |
| SGFContext C) { |
| // Emit the source value into a temporary. |
| auto sourceOrigType = AbstractionPattern::getOpaque(); |
| auto source = |
| SGF.emitMaterializedRValueAsOrig(E->getSubExpr(), sourceOrigType); |
| |
| return SGF.emitAnyHashableErasure(E, source, |
| E->getSubExpr()->getType(), |
| E->getConformance(), C); |
| } |
| |
| /// Treating this as a successful operation, turn a CMV into a +1 MV. |
| ManagedValue SILGenFunction::getManagedValue(SILLocation loc, |
| ConsumableManagedValue value) { |
| // If the consumption rules say that this is already +1 given a |
| // successful operation, just use the value. |
| if (value.isOwned()) |
| return value.getFinalManagedValue(); |
| |
| SILType valueTy = value.getType(); |
| auto &valueTL = getTypeLowering(valueTy); |
| |
| // If the type is trivial, it's always +1. |
| if (valueTL.isTrivial()) |
| return ManagedValue::forUnmanaged(value.getValue()); |
| |
| // If it's an object... |
| if (valueTy.isObject()) { |
| // See if we have more accurate information from the ownership kind. This |
| // detects trivial cases of enums. |
| if (value.getOwnershipKind() == OwnershipKind::None) |
| return ManagedValue::forUnmanaged(value.getValue()); |
| |
| // Otherwise, copy the value and return. |
| return value.getFinalManagedValue().copy(*this, loc); |
| } |
| |
| // Otherwise, produce a temporary and copy into that. |
| auto temporary = emitTemporary(loc, valueTL); |
| valueTL.emitCopyInto(B, loc, value.getValue(), temporary->getAddress(), |
| IsNotTake, IsInitialization); |
| temporary->finishInitialization(*this); |
| return temporary->getManagedAddress(); |
| } |
| |
| RValue RValueEmitter::visitForcedCheckedCastExpr(ForcedCheckedCastExpr *E, |
| SGFContext C) { |
| return emitUnconditionalCheckedCast(SGF, E, E->getSubExpr(), E->getType(), |
| E->getCastKind(), C); |
| } |
| |
| |
| RValue RValueEmitter:: |
| visitConditionalCheckedCastExpr(ConditionalCheckedCastExpr *E, |
| SGFContext C) { |
| ProfileCounter trueCount = ProfileCounter(); |
| ProfileCounter falseCount = ProfileCounter(); |
| auto parent = SGF.getPGOParent(E); |
| if (parent) { |
| auto &Node = parent.getValue(); |
| auto *NodeS = Node.get<Stmt *>(); |
| if (auto *IS = dyn_cast<IfStmt>(NodeS)) { |
| trueCount = SGF.loadProfilerCount(IS->getThenStmt()); |
| if (auto *ElseStmt = IS->getElseStmt()) { |
| falseCount = SGF.loadProfilerCount(ElseStmt); |
| } |
| } |
| } |
| ManagedValue operand = SGF.emitRValueAsSingleValue(E->getSubExpr()); |
| return emitConditionalCheckedCast(SGF, E, operand, E->getSubExpr()->getType(), |
| E->getType(), E->getCastKind(), C, |
| trueCount, falseCount); |
| } |
| |
| static RValue emitBoolLiteral(SILGenFunction &SGF, SILLocation loc, |
| SILValue builtinBool, |
| SGFContext C) { |
| // Call the Bool(_builtinBooleanLiteral:) initializer |
| ASTContext &ctx = SGF.getASTContext(); |
| auto init = ctx.getBoolBuiltinInitDecl(); |
| auto builtinArgType = CanType(BuiltinIntegerType::get(1, ctx)); |
| RValue builtinArg(SGF, ManagedValue::forUnmanaged(builtinBool), |
| builtinArgType); |
| |
| PreparedArguments builtinArgs((AnyFunctionType::Param(builtinArgType))); |
| builtinArgs.add(loc, std::move(builtinArg)); |
| |
| auto result = |
| SGF.emitApplyAllocatingInitializer(loc, ConcreteDeclRef(init), |
| std::move(builtinArgs), Type(), |
| C); |
| return result; |
| } |
| RValue RValueEmitter::visitIsExpr(IsExpr *E, SGFContext C) { |
| SILValue isa = emitIsa(SGF, E, E->getSubExpr(), |
| E->getCastType(), E->getCastKind()); |
| return emitBoolLiteral(SGF, E, isa, C); |
| } |
| |
| RValue RValueEmitter::visitEnumIsCaseExpr(EnumIsCaseExpr *E, |
| SGFContext C) { |
| // Get the enum value. |
| auto subExpr = SGF.emitRValueAsSingleValue(E->getSubExpr(), |
| SGFContext(SGFContext::AllowImmediatePlusZero)); |
| // Test its case. |
| auto i1Ty = SILType::getBuiltinIntegerType(1, SGF.getASTContext()); |
| auto t = SGF.B.createIntegerLiteral(E, i1Ty, 1); |
| auto f = SGF.B.createIntegerLiteral(E, i1Ty, 0); |
| |
| SILValue selected; |
| if (subExpr.getType().isAddress()) { |
| selected = SGF.B.createSelectEnumAddr(E, subExpr.getValue(), i1Ty, f, |
| {{E->getEnumElement(), t}}); |
| } else { |
| selected = SGF.B.createSelectEnum(E, subExpr.getValue(), i1Ty, f, |
| {{E->getEnumElement(), t}}); |
| } |
| |
| return emitBoolLiteral(SGF, E, selected, C); |
| } |
| |
| RValue RValueEmitter::visitCoerceExpr(CoerceExpr *E, SGFContext C) { |
| if (auto result = tryEmitAsBridgingConversion(SGF, E->getSubExpr(), true, C)) |
| return RValue(SGF, E, *result); |
| |
| return visit(E->getSubExpr(), C); |
| } |
| |
| RValue RValueEmitter::visitUnderlyingToOpaqueExpr(UnderlyingToOpaqueExpr *E, |
| SGFContext C) { |
| // The opaque type has the layout of the underlying type, abstracted as |
| // a type parameter. |
| auto &opaqueTL = SGF.getTypeLowering(E->getType()); |
| auto &underlyingTL = SGF.getTypeLowering(AbstractionPattern::getOpaque(), |
| E->getSubExpr()->getType()); |
| |
| auto &underlyingSubstTL = SGF.getTypeLowering(E->getSubExpr()->getType()); |
| |
| if (underlyingSubstTL.getLoweredType() == opaqueTL.getLoweredType()) { |
| return SGF.emitRValue(E->getSubExpr(), C); |
| } |
| |
| // If the opaque type is address only, initialize in place. |
| if (opaqueTL.getLoweredType().isAddress()) { |
| auto opaqueAddr = SGF.getBufferForExprResult( |
| E, opaqueTL.getLoweredType(), C); |
| // Initialize the buffer as the underlying type. |
| auto underlyingAddr = SGF.B.createUncheckedAddrCast(E, |
| opaqueAddr, |
| underlyingTL.getLoweredType().getAddressType()); |
| |
| auto underlyingInit = SGF.useBufferAsTemporary(underlyingAddr, underlyingTL); |
| |
| // Try to emit directly into the buffer if no reabstraction is necessary. |
| ManagedValue underlying; |
| if (underlyingSubstTL.getLoweredType() == underlyingTL.getLoweredType()) { |
| underlying = SGF.emitRValueAsSingleValue(E->getSubExpr(), |
| SGFContext(underlyingInit.get())); |
| } else { |
| // Otherwise, emit the underlying value then bring it to the right |
| // abstraction level. |
| underlying = SGF.emitRValueAsSingleValue(E->getSubExpr()); |
| underlying = SGF.emitSubstToOrigValue(E, underlying, |
| AbstractionPattern::getOpaque(), |
| E->getSubExpr()->getType()->getCanonicalType()); |
| } |
| if (!underlying.isInContext()) { |
| underlyingInit->copyOrInitValueInto(SGF, E, underlying, /*init*/ true); |
| underlyingInit->finishInitialization(SGF); |
| } |
| // Kill the cleanup on the underlying value, and hand off the opaque buffer |
| // as the result. |
| underlyingInit->getManagedAddress().forward(SGF); |
| |
| auto opaque = SGF.manageBufferForExprResult(opaqueAddr, opaqueTL, C); |
| return RValue(SGF, E, opaque); |
| } |
| |
| // If the opaque type is loadable, emit the subexpression and bitcast it. |
| auto value = SGF.emitRValueAsSingleValue(E->getSubExpr()); |
| if (underlyingSubstTL.getLoweredType() != underlyingTL.getLoweredType()) { |
| value = SGF.emitSubstToOrigValue(E, value, AbstractionPattern::getOpaque(), |
| E->getSubExpr()->getType()->getCanonicalType()); |
| } |
| |
| if (value.getType() == opaqueTL.getLoweredType()) |
| return RValue(SGF, E, value); |
| |
| auto cast = SGF.B.createUncheckedReinterpretCast(E, value.forward(SGF), |
| opaqueTL.getLoweredType()); |
| value = SGF.emitManagedRValueWithCleanup(cast); |
| |
| return RValue(SGF, E, value); |
| } |
| |
| VarargsInfo Lowering::emitBeginVarargs(SILGenFunction &SGF, SILLocation loc, |
| CanType baseTy, CanType arrayTy, |
| unsigned numElements) { |
| // Reabstract the base type against the array element type. |
| auto baseAbstraction = AbstractionPattern::getOpaque(); |
| auto &baseTL = SGF.getTypeLowering(baseAbstraction, baseTy); |
| |
| // Allocate the array. |
| SILValue numEltsVal = SGF.B.createIntegerLiteral(loc, |
| SILType::getBuiltinWordType(SGF.getASTContext()), |
| numElements); |
| // The first result is the array value. |
| ManagedValue array; |
| // The second result is a RawPointer to the base address of the array. |
| SILValue basePtr; |
| std::tie(array, basePtr) |
| = SGF.emitUninitializedArrayAllocation(arrayTy, numEltsVal, loc); |
| |
| // Temporarily deactivate the main array cleanup. |
| if (array.hasCleanup()) |
| SGF.Cleanups.setCleanupState(array.getCleanup(), CleanupState::Dormant); |
| |
| // Push a new cleanup to deallocate the array. |
| auto abortCleanup = |
| SGF.enterDeallocateUninitializedArrayCleanup(array.getValue()); |
| |
| // Turn the pointer into an address. |
| basePtr = SGF.B.createPointerToAddress( |
| loc, basePtr, baseTL.getLoweredType().getAddressType(), |
| /*isStrict*/ true, |
| /*isInvariant*/ false); |
| |
| return VarargsInfo(array, abortCleanup, basePtr, baseTL, baseAbstraction); |
| } |
| |
| ManagedValue Lowering::emitEndVarargs(SILGenFunction &SGF, SILLocation loc, |
| VarargsInfo &&varargs, |
| unsigned numElements) { |
| // Kill the abort cleanup. |
| SGF.Cleanups.setCleanupState(varargs.getAbortCleanup(), CleanupState::Dead); |
| |
| // Reactivate the result cleanup. |
| auto array = varargs.getArray(); |
| if (array.hasCleanup()) |
| SGF.Cleanups.setCleanupState(array.getCleanup(), CleanupState::Active); |
| |
| // Array literals only need to be finalized, if the array is really allocated. |
| // In case of zero elements, no allocation is done, but the empty-array |
| // singleton is used. "Finalization" means to emit an end_cow_mutation |
| // instruction on the array. As the empty-array singleton is a read-only and |
| // shared object, it's not legal to do a end_cow_mutation on it. |
| if (numElements == 0) |
| return array; |
| |
| return SGF.emitUninitializedArrayFinalization(loc, std::move(array)); |
| } |
| |
| RValue RValueEmitter::visitTupleExpr(TupleExpr *E, SGFContext C) { |
| auto type = cast<TupleType>(E->getType()->getCanonicalType()); |
| |
| // If we have an Initialization, emit the tuple elements into its elements. |
| if (Initialization *I = C.getEmitInto()) { |
| |
| bool implodeTuple = false; |
| |
| if (I->canPerformInPlaceInitialization() && |
| I->isInPlaceInitializationOfGlobal() && |
| SGF.getLoweredType(type).isTrivial(SGF.F)) { |
| // Implode tuples in initialization of globals if they are |
| // of trivial types. |
| implodeTuple = true; |
| } |
| |
| if (!implodeTuple && I->canSplitIntoTupleElements()) { |
| SmallVector<InitializationPtr, 4> subInitializationBuf; |
| auto subInitializations = |
| I->splitIntoTupleElements(SGF, RegularLocation(E), type, |
| subInitializationBuf); |
| assert(subInitializations.size() == E->getElements().size() && |
| "initialization for tuple has wrong number of elements"); |
| for (unsigned i = 0, size = subInitializations.size(); i < size; ++i) |
| SGF.emitExprInto(E->getElement(i), subInitializations[i].get()); |
| I->finishInitialization(SGF); |
| return RValue::forInContext(); |
| } |
| } |
| |
| llvm::SmallVector<RValue, 8> tupleElts; |
| bool hasAtleastOnePlusOneValue = false; |
| for (Expr *elt : E->getElements()) { |
| RValue RV = SGF.emitRValue(elt); |
| hasAtleastOnePlusOneValue |= RV.isPlusOne(SGF); |
| tupleElts.emplace_back(std::move(RV)); |
| } |
| |
| // Once we have found if we have any plus one arguments, add each element of |
| // tuple elts into result, making sure each value is at plus 1. |
| RValue result(type); |
| if (hasAtleastOnePlusOneValue) { |
| for (unsigned i : indices(tupleElts)) { |
| result.addElement(std::move(tupleElts[i]).ensurePlusOne(SGF, E)); |
| } |
| } else { |
| for (unsigned i : indices(tupleElts)) { |
| result.addElement(std::move(tupleElts[i])); |
| } |
| } |
| |
| return result; |
| } |
| |
| RValue RValueEmitter::visitMemberRefExpr(MemberRefExpr *e, |
| SGFContext resultCtx) { |
| assert(!e->getType()->is<LValueType>() && |
| "RValueEmitter shouldn't be called on lvalues"); |
| assert(isa<VarDecl>(e->getMember().getDecl())); |
| |
| // Everything else should use the l-value logic. |
| |
| // Any writebacks for this access are tightly scoped. |
| FormalEvaluationScope scope(SGF); |
| |
| LValue lv = SGF.emitLValue(e, SGFAccessKind::OwnedObjectRead); |
| |
| // Otherwise, we can't load at +0 without further analysis, since the formal |
| // access into the lvalue will end immediately. |
| return SGF.emitLoadOfLValue(e, std::move(lv), |
| resultCtx.withFollowingSideEffects()); |
| } |
| |
| RValue RValueEmitter::visitDynamicMemberRefExpr(DynamicMemberRefExpr *E, |
| SGFContext C) { |
| return SGF.emitDynamicMemberRefExpr(E, C); |
| } |
| |
| RValue RValueEmitter:: |
| visitDotSyntaxBaseIgnoredExpr(DotSyntaxBaseIgnoredExpr *E, SGFContext C) { |
| visit(E->getLHS()); |
| return visit(E->getRHS()); |
| } |
| |
| RValue RValueEmitter::visitSubscriptExpr(SubscriptExpr *E, SGFContext C) { |
| // Any writebacks for this access are tightly scoped. |
| FormalEvaluationScope scope(SGF); |
| |
| LValue lv = SGF.emitLValue(E, SGFAccessKind::OwnedObjectRead); |
| // We can't load at +0 without further analysis, since the formal access into |
| // the lvalue will end immediately. |
| return SGF.emitLoadOfLValue(E, std::move(lv), C.withFollowingSideEffects()); |
| } |
| |
| RValue RValueEmitter::visitDynamicSubscriptExpr( |
| DynamicSubscriptExpr *E, SGFContext C) { |
| return SGF.emitDynamicSubscriptExpr(E, C); |
| } |
| |
| |
| RValue RValueEmitter::visitTupleElementExpr(TupleElementExpr *E, |
| SGFContext C) { |
| assert(!E->getType()->is<LValueType>() && |
| "RValueEmitter shouldn't be called on lvalues"); |
| |
| // If our client is ok with a +0 result, then we can compute our base as +0 |
| // and return its element that way. It would not be ok to reuse the Context's |
| // address buffer though, since our base value will a different type than the |
| // element. |
| SGFContext SubContext = C.withFollowingProjection(); |
| |
| return visit(E->getBase(), SubContext).extractElement(E->getFieldNumber()); |
| } |
| |
| RValue |
| SILGenFunction::emitApplyOfDefaultArgGenerator(SILLocation loc, |
| ConcreteDeclRef defaultArgsOwner, |
| unsigned destIndex, |
| CanType resultType, |
| AbstractionPattern origResultType, |
| SGFContext C) { |
| SILDeclRef generator |
| = SILDeclRef::getDefaultArgGenerator(defaultArgsOwner.getDecl(), |
| destIndex); |
| |
| auto fnRef = ManagedValue::forUnmanaged(emitGlobalFunctionRef(loc,generator)); |
| auto fnType = fnRef.getType().castTo<SILFunctionType>(); |
| |
| SubstitutionMap subs; |
| if (fnType->isPolymorphic()) |
| subs = defaultArgsOwner.getSubstitutions(); |
| |
| auto substFnType = |
| fnType->substGenericArgs(SGM.M, subs, getTypeExpansionContext()); |
| |
| CalleeTypeInfo calleeTypeInfo(substFnType, origResultType, resultType); |
| ResultPlanPtr resultPtr = |
| ResultPlanBuilder::computeResultPlan(*this, calleeTypeInfo, loc, C); |
| ArgumentScope argScope(*this, loc); |
| |
| SmallVector<ManagedValue, 4> captures; |
| emitCaptures(loc, generator, CaptureEmission::ImmediateApplication, |
| captures); |
| |
| return emitApply(std::move(resultPtr), std::move(argScope), loc, fnRef, |
| subs, captures, calleeTypeInfo, ApplyOptions::None, C, None); |
| } |
| |
| RValue SILGenFunction::emitApplyOfStoredPropertyInitializer( |
| SILLocation loc, |
| VarDecl *var, |
| SubstitutionMap subs, |
| CanType resultType, |
| AbstractionPattern origResultType, |
| SGFContext C) { |
| |
| SILDeclRef constant(var, SILDeclRef::Kind::StoredPropertyInitializer); |
| auto fnRef = ManagedValue::forUnmanaged(emitGlobalFunctionRef(loc, constant)); |
| auto fnType = fnRef.getType().castTo<SILFunctionType>(); |
| |
| auto substFnType = |
| fnType->substGenericArgs(SGM.M, subs, getTypeExpansionContext()); |
| |
| CalleeTypeInfo calleeTypeInfo(substFnType, origResultType, resultType); |
| ResultPlanPtr resultPlan = |
| ResultPlanBuilder::computeResultPlan(*this, calleeTypeInfo, loc, C); |
| ArgumentScope argScope(*this, loc); |
| return emitApply(std::move(resultPlan), std::move(argScope), loc, fnRef, |
| subs, {}, calleeTypeInfo, ApplyOptions::None, C, None); |
| } |
| |
| RValue RValueEmitter::visitDestructureTupleExpr(DestructureTupleExpr *E, |
| SGFContext C) { |
| // Emit the sub-expression tuple and destructure it into elements. |
| SmallVector<RValue, 4> elements; |
| visit(E->getSubExpr()).extractElements(elements); |
| |
| // Bind each element of the input tuple to its corresponding |
| // opaque value. |
| for (unsigned i = 0, e = E->getDestructuredElements().size(); |
| i != e; ++i) { |
| auto *opaqueElt = E->getDestructuredElements()[i]; |
| assert(!SGF.OpaqueValues.count(opaqueElt)); |
| |
| auto opaqueMV = std::move(elements[i]).getAsSingleValue(SGF, E); |
| SGF.OpaqueValues[opaqueElt] = opaqueMV; |
| } |
| |
| // Emit the result expression written in terms of the above |
| // opaque values. |
| auto result = visit(E->getResultExpr(), C); |
| |
| // Clean up. |
| for (unsigned i = 0, e = E->getDestructuredElements().size(); |
| i != e; ++i) { |
| auto *opaqueElt = E->getDestructuredElements()[i]; |
| SGF.OpaqueValues.erase(opaqueElt); |
| } |
| |
| return result; |
| } |
| |
| static SILValue emitMetatypeOfDelegatingInitExclusivelyBorrowedSelf( |
| SILGenFunction &SGF, SILLocation loc, DeclRefExpr *dre, SILType metaTy) { |
| SGFContext ctx; |
| auto *vd = cast<ParamDecl>(dre->getDecl()); |
| ManagedValue selfValue; |
| |
| Scope S(SGF, loc); |
| Optional<FormalEvaluationScope> FES; |
| |
| // If we have not exclusively borrowed self, we need to do so now. |
| if (SGF.SelfInitDelegationState == SILGenFunction::WillExclusiveBorrowSelf) { |
| // We need to use a full scope here to ensure that any underlying |
| // "normal cleanup" borrows are cleaned up. |
| selfValue = SGF.emitRValueAsSingleValue(dre); |
| } else { |
| // If we already exclusively borrowed self, then we need to emit self |
| // using formal evaluation primitives. |
| |
| assert(SGF.SelfInitDelegationState == |
| SILGenFunction::DidExclusiveBorrowSelf); |
| // This needs to be inlined since there is a Formal Evaluation Scope |
| // in emitRValueForDecl that causing any borrow for this LValue to be |
| // popped too soon. |
| FES.emplace(SGF); |
| CanType formalRValueType = dre->getType()->getCanonicalType(); |
| selfValue = SGF.emitAddressOfLocalVarDecl(dre, vd, formalRValueType, |
| SGFAccessKind::OwnedObjectRead); |
| selfValue = SGF.emitFormalEvaluationRValueForSelfInDelegationInit( |
| loc, formalRValueType, |
| selfValue.getLValueAddress(), ctx) |
| .getAsSingleValue(SGF, loc); |
| } |
| |
| return SGF.B.createValueMetatype(loc, metaTy, selfValue.getValue()); |
| } |
| |
| SILValue SILGenFunction::emitMetatypeOfValue(SILLocation loc, Expr *baseExpr) { |
| Type formalBaseType = baseExpr->getType()->getWithoutSpecifierType(); |
| CanType baseTy = formalBaseType->getCanonicalType(); |
| |
| // For class, archetype, and protocol types, look up the dynamic metatype. |
| if (baseTy.isAnyExistentialType()) { |
| SILType metaTy = getLoweredLoadableType( |
| CanExistentialMetatypeType::get(baseTy)); |
| auto base = emitRValueAsSingleValue(baseExpr, |
| SGFContext::AllowImmediatePlusZero).getValue(); |
| return B.createExistentialMetatype(loc, metaTy, base); |
| } |
| SILType metaTy = getLoweredLoadableType(CanMetatypeType::get(baseTy)); |
| // If the lowered metatype has a thick representation, we need to derive it |
| // dynamically from the instance. |
| if (metaTy.castTo<MetatypeType>()->getRepresentation() |
| != MetatypeRepresentation::Thin) { |
| if (inExclusiveBorrowSelfSection(SelfInitDelegationState)) { |
| if (auto *dre = dyn_cast<DeclRefExpr>(baseExpr)) { |
| if (isa<ParamDecl>(dre->getDecl()) && |
| dre->getDecl()->getName() == getASTContext().Id_self && |
| dre->getDecl()->isImplicit()) { |
| return emitMetatypeOfDelegatingInitExclusivelyBorrowedSelf( |
| *this, loc, dre, metaTy); |
| } |
| } |
| } |
| |
| Scope S(*this, loc); |
| auto base = emitRValueAsSingleValue(baseExpr, SGFContext::AllowImmediatePlusZero); |
| return S.popPreservingValue(B.createValueMetatype(loc, metaTy, base)) |
| .getValue(); |
| } |
| // Otherwise, ignore the base and return the static thin metatype. |
| emitIgnoredExpr(baseExpr); |
| return B.createMetatype(loc, metaTy); |
| } |
| |
| RValue RValueEmitter::visitDynamicTypeExpr(DynamicTypeExpr *E, SGFContext C) { |
| auto metatype = SGF.emitMetatypeOfValue(E, E->getBase()); |
| return RValue(SGF, E, ManagedValue::forUnmanaged(metatype)); |
| } |
| |
| RValue RValueEmitter::visitCaptureListExpr(CaptureListExpr *E, SGFContext C) { |
| // Ensure that weak captures are in a separate scope. |
| DebugScope scope(SGF, CleanupLocation(E)); |
| // CaptureListExprs evaluate their bound variables. |
| for (auto capture : E->getCaptureList()) { |
| SGF.visit(capture.Var); |
| SGF.visit(capture.Init); |
| } |
| |
| // Then they evaluate to their body. |
| return visit(E->getClosureBody(), C); |
| } |
| |
| /// Returns the wrapped value placeholder that is meant to be substituted |
| /// in for the given autoclosure. This autoclosure placeholder is created |
| /// when \c init(wrappedValue:) takes an autoclosure for the \c wrappedValue |
| /// parameter. |
| static PropertyWrapperValuePlaceholderExpr * |
| wrappedValueAutoclosurePlaceholder(const AbstractClosureExpr *e) { |
| if (auto ace = dyn_cast<AutoClosureExpr>(e)) { |
| if (auto ce = dyn_cast<CallExpr>(ace->getSingleExpressionBody())) { |
| return dyn_cast<PropertyWrapperValuePlaceholderExpr>(ce->getFn()); |
| } |
| } |
| return nullptr; |
| } |
| |
| RValue RValueEmitter::visitAbstractClosureExpr(AbstractClosureExpr *e, |
| SGFContext C) { |
| if (auto *placeholder = wrappedValueAutoclosurePlaceholder(e)) |
| return visitPropertyWrapperValuePlaceholderExpr(placeholder, C); |
| |
| // Emit the closure body. |
| SGF.SGM.emitClosure(e); |
| |
| SubstitutionMap subs; |
| if (e->getCaptureInfo().hasGenericParamCaptures()) |
| subs = SGF.getForwardingSubstitutionMap(); |
| |
| // Generate the closure value (if any) for the closure expr's function |
| // reference. |
| auto refType = e->getType()->getCanonicalType(); |
| SILLocation L = e; |
| L.markAutoGenerated(); |
| ManagedValue result = SGF.emitClosureValue(L, SILDeclRef(e), |
| refType, subs); |
| return RValue(SGF, e, refType, result); |
| } |
| |
| RValue RValueEmitter:: |
| visitInterpolatedStringLiteralExpr(InterpolatedStringLiteralExpr *E, |
| SGFContext C) { |
| RValue interpolation; |
| { |
| TapExpr *ETap = E->getAppendingExpr(); |
| // Inlined from TapExpr: |
| // TODO: This is only necessary because constant evaluation requires that |
| // the box for the var gets defined before the initializer happens. |
| auto Var = ETap->getVar(); |
| auto VarType = ETap->getType()->getCanonicalType(); |
| |
| Scope outerScope(SGF, CleanupLocation(ETap)); |
| |
| // Initialize the var with our SubExpr. |
| auto VarInit = |
| SGF.emitInitializationForVarDecl(Var, /*forceImmutable=*/false); |
| { |
| // Modified from TapExpr to evaluate the SubExpr directly rather than |
| // indirectly through the OpaqueValue system. |
| PreparedArguments builderInitArgs; |
| RValue literalCapacity = visit(E->getLiteralCapacityExpr(), SGFContext()); |
| RValue interpolationCount = |
| visit(E->getInterpolationCountExpr(), SGFContext()); |
| builderInitArgs.emplace( |
| {AnyFunctionType::Param(literalCapacity.getType()), |
| AnyFunctionType::Param(interpolationCount.getType())}); |
| builderInitArgs.add(E, std::move(literalCapacity)); |
| builderInitArgs.add(E, std::move(interpolationCount)); |
| RValue subexpr_result = SGF.emitApplyAllocatingInitializer( |
| E, E->getBuilderInit(), std::move(builderInitArgs), Type(), |
| SGFContext(VarInit.get())); |
| if (!subexpr_result.isInContext()) { |
| ArgumentSource( |
| SILLocation(E), |
| std::move(subexpr_result).ensurePlusOne(SGF, SILLocation(E))) |
| .forwardInto(SGF, VarInit.get()); |
| } |
| } |
| |
| // Emit the body and let it mutate the var if it chooses. |
| SGF.emitStmt(ETap->getBody()); |
| |
| // Retrieve and return the var, making it +1 so it survives the scope. |
| auto result = SGF.emitRValueForDecl(SILLocation(ETap), Var, VarType, |
| AccessSemantics::Ordinary, SGFContext()); |
| result = std::move(result).ensurePlusOne(SGF, SILLocation(ETap)); |
| interpolation = outerScope.popPreservingValue(std::move(result)); |
| } |
| |
| PreparedArguments resultInitArgs; |
| resultInitArgs.emplace(AnyFunctionType::Param(interpolation.getType())); |
| resultInitArgs.add(E, std::move(interpolation)); |
| |
| return SGF.emitApplyAllocatingInitializer( |
| E, E->getInitializer(), std::move(resultInitArgs), Type(), C); |
| } |
| |
| RValue RValueEmitter:: |
| visitObjectLiteralExpr(ObjectLiteralExpr *E, SGFContext C) { |
| ConcreteDeclRef init = E->getInitializer(); |
| auto *decl = cast<ConstructorDecl>(init.getDecl()); |
| AnyFunctionType *fnTy = decl->getMethodInterfaceType() |
| .subst(init.getSubstitutions()) |
| ->getAs<AnyFunctionType>(); |
| PreparedArguments args(fnTy->getParams(), E->getArg()); |
| return SGF.emitApplyAllocatingInitializer(SILLocation(E), init, |
| std::move(args), E->getType(), C); |
| } |
| |
| RValue RValueEmitter:: |
| visitEditorPlaceholderExpr(EditorPlaceholderExpr *E, SGFContext C) { |
| return visit(E->getSemanticExpr(), C); |
| } |
| |
| RValue RValueEmitter::visitObjCSelectorExpr(ObjCSelectorExpr *e, SGFContext C) { |
| SILType loweredSelectorTy = SGF.getLoweredType(e->getType()); |
| |
| // Dig out the declaration of the Selector type. |
| auto selectorDecl = e->getType()->getAs<StructType>()->getDecl(); |
| |
| // Dig out the type of its pointer. |
| Type selectorMemberTy; |
| for (auto member : selectorDecl->getMembers()) { |
| if (auto var = dyn_cast<VarDecl>(member)) { |
| if (!var->isStatic() && var->hasStorage()) { |
| selectorMemberTy = var->getInterfaceType(); |
| break; |
| } |
| } |
| } |
| if (!selectorMemberTy) { |
| SGF.SGM.diagnose(e, diag::objc_selector_malformed); |
| return RValue(SGF, e, SGF.emitUndef(loweredSelectorTy)); |
| } |
| |
| // Form the selector string. |
| llvm::SmallString<64> selectorScratch; |
| auto selectorString = |
| e->getMethod()->getObjCSelector().getString(selectorScratch); |
| |
| // Create an Objective-C selector string literal. |
| auto selectorLiteral = |
| SGF.B.createStringLiteral(e, selectorString, |
| StringLiteralInst::Encoding::ObjCSelector); |
| |
| // Create the pointer struct from the raw pointer. |
| SILType loweredPtrTy = SGF.getLoweredType(selectorMemberTy); |
| auto ptrValue = SGF.B.createStruct(e, loweredPtrTy, { selectorLiteral }); |
| |
| // Wrap that up in a Selector and return it. |
| auto selectorValue = SGF.B.createStruct(e, loweredSelectorTy, { ptrValue }); |
| return RValue(SGF, e, ManagedValue::forUnmanaged(selectorValue)); |
| } |
| |
| static ManagedValue |
| emitKeyPathRValueBase(SILGenFunction &subSGF, |
| AbstractStorageDecl *storage, |
| SILLocation loc, |
| SILValue paramArg, |
| CanType &baseType, |
| SubstitutionMap subs) { |
| // If the storage is at global scope, then the base value () is a formality. |
| // There no real argument to pass to the underlying accessors. |
| if (!storage->getDeclContext()->isTypeContext()) |
| return ManagedValue(); |
| |
| auto paramOrigValue = |
| ManagedValue::forBorrowedRValue(paramArg).copy(subSGF, loc); |
| auto paramSubstValue = subSGF.emitOrigToSubstValue(loc, paramOrigValue, |
| AbstractionPattern::getOpaque(), |
| baseType); |
| |
| // Pop open an existential container base. |
| if (baseType->isAnyExistentialType()) { |
| // Use the opened archetype from the AST for a protocol member, or make a |
| // new one (which we'll upcast immediately below) for a class member. |
| ArchetypeType *opened; |
| if (storage->getDeclContext()->getSelfClassDecl()) { |
| opened = OpenedArchetypeType::get(baseType); |
| } else { |
| opened = subs.getReplacementTypes()[0]->castTo<ArchetypeType>(); |
| } |
| assert(opened->isOpenedExistential()); |
| |
| FormalEvaluationScope scope(subSGF); |
| |
| baseType = opened->getCanonicalType(); |
| auto openedOpaqueValue = subSGF.emitOpenExistential(loc, paramSubstValue, |
| subSGF.getLoweredType(baseType), |
| AccessKind::Read); |
| // Maybe we could peephole this if we know the property load can borrow the |
| // base value… |
| paramSubstValue = openedOpaqueValue.ensurePlusOne(subSGF, loc); |
| } |
| |
| // Upcast a class instance to the property's declared type if necessary. |
| if (auto propertyClass = storage->getDeclContext()->getSelfClassDecl()) { |
| if (baseType->getClassOrBoundGenericClass() != propertyClass) { |
| baseType = baseType->getSuperclassForDecl(propertyClass) |
| ->getCanonicalType(); |
| paramSubstValue = subSGF.B.createUpcast(loc, paramSubstValue, |
| SILType::getPrimitiveObjectType(baseType)); |
| } |
| } |
| // …or pop open an existential container. |
| return paramSubstValue; |
| } |
| |
| using IndexTypePair = std::pair<CanType, SILType>; |
| |
| /// Helper function to load the captured indexes out of a key path component |
| /// in order to invoke the accessors on that key path. A component with captured |
| /// indexes passes down a pointer to those captures to the accessor thunks, |
| /// which we can copy out of to produce values we can pass to the real |
| /// accessor functions. |
| static PreparedArguments |
| loadIndexValuesForKeyPathComponent(SILGenFunction &SGF, SILLocation loc, |
| AbstractStorageDecl *storage, |
| ArrayRef<IndexTypePair> indexes, |
| SILValue pointer) { |
| // If not a subscript, do nothing. |
| if (!isa<SubscriptDecl>(storage)) |
| return PreparedArguments(); |
| |
| SmallVector<AnyFunctionType::Param, 8> indexParams; |
| for (auto &elt : indexes) { |
| // FIXME: Varargs? |
| indexParams.emplace_back(SGF.F.mapTypeIntoContext(elt.first)); |
| } |
| |
| PreparedArguments indexValues(indexParams); |
| if (indexes.empty()) { |
| assert(indexValues.isValid()); |
| return indexValues; |
| } |
| |
| auto indexLoweredTy = |
| SGF.getLoweredType( |
| AnyFunctionType::composeInput(SGF.getASTContext(), indexParams, |
| /*canonicalVararg=*/false)); |
| |
| auto addr = SGF.B.createPointerToAddress(loc, pointer, |
| indexLoweredTy.getAddressType(), |
| /*isStrict*/ false); |
| |
| for (unsigned i : indices(indexes)) { |
| SILValue eltAddr = addr; |
| if (indexes.size() > 1) { |
| eltAddr = SGF.B.createTupleElementAddr(loc, eltAddr, i); |
| } |
| auto ty = SGF.F.mapTypeIntoContext(indexes[i].second); |
| auto value = SGF.emitLoad(loc, eltAddr, |
| SGF.getTypeLowering(ty), |
| SGFContext(), IsNotTake); |
| auto substType = |
| SGF.F.mapTypeIntoContext(indexes[i].first)->getCanonicalType(); |
| indexValues.add(loc, RValue(SGF, loc, substType, value)); |
| } |
| |
| assert(indexValues.isValid()); |
| return indexValues; |
| } |
| |
| static AccessorDecl * |
| getRepresentativeAccessorForKeyPath(AbstractStorageDecl *storage) { |
| if (storage->requiresOpaqueGetter()) |
| return storage->getOpaqueAccessor(AccessorKind::Get); |
| assert(storage->requiresOpaqueReadCoroutine()); |
| return storage->getOpaqueAccessor(AccessorKind::Read); |
| } |
| |
| static SILFunction *getOrCreateKeyPathGetter(SILGenModule &SGM, |
| SILLocation loc, |
| AbstractStorageDecl *property, |
| SubstitutionMap subs, |
| GenericEnvironment *genericEnv, |
| ResilienceExpansion expansion, |
| ArrayRef<IndexTypePair> indexes, |
| CanType baseType, |
| CanType propertyType) { |
| // If the storage declaration is from a protocol, chase the override chain |
| // back to the declaration whose getter introduced the witness table |
| // entry. |
| if (isa<ProtocolDecl>(property->getDeclContext())) { |
| auto accessor = getRepresentativeAccessorForKeyPath(property); |
| if (!SILDeclRef::requiresNewWitnessTableEntry(accessor)) { |
| // Find the getter that does have a witness table entry. |
| auto wtableAccessor = |
| cast<AccessorDecl>(SILDeclRef::getOverriddenWitnessTableEntry(accessor)); |
| |
| // Substitute the 'Self' type of the base protocol. |
| subs = SILGenModule::mapSubstitutionsForWitnessOverride( |
| accessor, wtableAccessor, subs); |
| property = wtableAccessor->getStorage(); |
| } |
| } |
| |
| auto genericSig = |
| genericEnv ? genericEnv->getGenericSignature().getCanonicalSignature() |
| : nullptr; |
| if (genericSig && genericSig->areAllParamsConcrete()) { |
| genericSig = nullptr; |
| genericEnv = nullptr; |
| } |
| |
| // Build the signature of the thunk as expected by the keypath runtime. |
| auto signature = [&]() { |
| CanType loweredBaseTy, loweredPropTy; |
| AbstractionPattern opaque =
|