| //===--- SILGenBuilder.h ----------------------------------------*- C++ -*-===// |
| // |
| // 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 |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// \file |
| /// |
| /// This file defines SILGenBuilder, a subclass of SILBuilder that provides APIs |
| /// that traffic in ManagedValue. The intention is that if one is using a |
| /// SILGenBuilder, the SILGenBuilder will handle preserving ownership invariants |
| /// (or assert upon failure) freeing the implementor of such concerns. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_SILGEN_SILGENBUILDER_H |
| #define SWIFT_SILGEN_SILGENBUILDER_H |
| |
| #include "Cleanup.h" |
| #include "JumpDest.h" |
| #include "ManagedValue.h" |
| #include "RValue.h" |
| #include "swift/SIL/SILBuilder.h" |
| #include "swift/Basic/ProfileCounter.h" |
| |
| namespace swift { |
| namespace Lowering { |
| |
| class SILGenFunction; |
| class SGFContext; |
| class AssertingManualScope; |
| |
| /// A subclass of SILBuilder that wraps APIs to vend ManagedValues. |
| /// APIs only vend ManagedValues. |
| class SILGenBuilder : public SILBuilder { |
| SILGenFunction &SGF; |
| |
| public: |
| SILGenBuilder(SILGenFunction &SGF); |
| SILGenBuilder(SILGenFunction &SGF, SILBasicBlock *insertBB, |
| SmallVectorImpl<SILInstruction *> *insertedInsts = nullptr); |
| SILGenBuilder(SILGenFunction &SGF, SILBasicBlock *insertBB, |
| SILBasicBlock::iterator insertInst); |
| |
| // Create a new builder, inheriting the given builder's context and debug |
| // scope. |
| SILGenBuilder(SILGenBuilder &builder, SILBasicBlock *insertBB) |
| : SILBuilder(insertBB, builder.getCurrentDebugScope(), |
| builder.getBuilderContext()), |
| SGF(builder.SGF) {} |
| |
| SILGenModule &getSILGenModule() const; |
| SILGenFunction &getSILGenFunction() const { return SGF; } |
| |
| using SILBuilder::createInitExistentialValue; |
| ManagedValue |
| createInitExistentialValue(SILLocation loc, SILType existentialType, |
| CanType formalConcreteType, ManagedValue concrete, |
| ArrayRef<ProtocolConformanceRef> conformances); |
| using SILBuilder::createInitExistentialRef; |
| ManagedValue |
| createInitExistentialRef(SILLocation loc, SILType existentialType, |
| CanType formalConcreteType, ManagedValue concrete, |
| ArrayRef<ProtocolConformanceRef> conformances); |
| |
| using SILBuilder::createPartialApply; |
| ManagedValue createPartialApply(SILLocation loc, SILValue fn, |
| SubstitutionMap subs, |
| ArrayRef<ManagedValue> args, |
| ParameterConvention calleeConvention); |
| ManagedValue createPartialApply(SILLocation loc, ManagedValue fn, |
| SubstitutionMap subs, |
| ArrayRef<ManagedValue> args, |
| ParameterConvention calleeConvention) { |
| return createPartialApply(loc, fn.getValue(), subs, args, |
| calleeConvention); |
| } |
| |
| using SILBuilder::createStructExtract; |
| ManagedValue createStructExtract(SILLocation loc, ManagedValue base, |
| VarDecl *decl); |
| |
| using SILBuilder::createRefElementAddr; |
| ManagedValue createRefElementAddr(SILLocation loc, ManagedValue operand, |
| VarDecl *field, SILType resultTy); |
| |
| using SILBuilder::createCopyValue; |
| |
| /// Emit a +1 copy on \p originalValue that lives until the end of the current |
| /// lexical scope. |
| ManagedValue createCopyValue(SILLocation loc, ManagedValue originalValue); |
| |
| /// Emit a +1 copy on \p originalValue that lives until the end of the current |
| /// lexical scope. |
| /// |
| /// This reuses a passed in lowering. |
| ManagedValue createCopyValue(SILLocation loc, ManagedValue originalValue, |
| const TypeLowering &lowering); |
| |
| /// Emit a +1 copy of \p originalValue into newAddr that lives until the end |
| /// of the current Formal Evaluation Scope. |
| ManagedValue createFormalAccessCopyAddr(SILLocation loc, |
| ManagedValue originalAddr, |
| SILValue newAddr, IsTake_t isTake, |
| IsInitialization_t isInit); |
| |
| /// Emit a +1 copy of \p originalValue into newAddr that lives until the end |
| /// Formal Evaluation Scope. |
| ManagedValue createFormalAccessCopyValue(SILLocation loc, |
| ManagedValue originalValue); |
| |
| #define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \ |
| using SILBuilder::createStrongCopy##Name##Value; \ |
| ManagedValue createStrongCopy##Name##Value(SILLocation loc, \ |
| ManagedValue originalValue); |
| #define UNCHECKED_REF_STORAGE(Name, ...) \ |
| using SILBuilder::createStrongCopy##Name##Value; \ |
| ManagedValue createStrongCopy##Name##Value(SILLocation loc, \ |
| ManagedValue originalValue); |
| #include "swift/AST/ReferenceStorage.def" |
| |
| ManagedValue createOwnedPhiArgument(SILType type); |
| ManagedValue createGuaranteedPhiArgument(SILType type); |
| |
| /// For arguments from terminators that are "transforming terminators". These |
| /// types of guaranteed arguments are validated as part of the operand of the |
| /// transforming terminator since transforming terminators are guaranteed to |
| /// be the only predecessor of our parent block. |
| /// |
| /// NOTE: Two examples of transforming terminators are switch_enum, |
| /// checked_cast_br. |
| ManagedValue createGuaranteedTransformingTerminatorArgument(SILType type); |
| |
| using SILBuilder::createMarkUninitialized; |
| ManagedValue createMarkUninitialized(ValueDecl *decl, ManagedValue operand, |
| MarkUninitializedInst::Kind muKind); |
| |
| using SILBuilder::createAllocRef; |
| ManagedValue createAllocRef(SILLocation loc, SILType refType, bool objc, |
| bool canAllocOnStack, |
| ArrayRef<SILType> elementTypes, |
| ArrayRef<ManagedValue> elementCountOperands); |
| using SILBuilder::createAllocRefDynamic; |
| ManagedValue |
| createAllocRefDynamic(SILLocation loc, ManagedValue operand, SILType refType, |
| bool objc, ArrayRef<SILType> elementTypes, |
| ArrayRef<ManagedValue> elementCountOperands); |
| |
| using SILBuilder::createTuple; |
| ManagedValue createTuple(SILLocation loc, SILType type, |
| ArrayRef<ManagedValue> elements); |
| using SILBuilder::createTupleExtract; |
| ManagedValue createTupleExtract(SILLocation loc, ManagedValue value, |
| unsigned index, SILType type); |
| ManagedValue createTupleExtract(SILLocation loc, ManagedValue value, |
| unsigned index); |
| using SILBuilder::createTupleElementAddr; |
| ManagedValue createTupleElementAddr(SILLocation loc, ManagedValue addr, |
| unsigned index, SILType type); |
| ManagedValue createTupleElementAddr(SILLocation loc, ManagedValue addr, |
| unsigned index); |
| |
| using SILBuilder::createLoadBorrow; |
| ManagedValue createLoadBorrow(SILLocation loc, ManagedValue base); |
| ManagedValue createFormalAccessLoadBorrow(SILLocation loc, ManagedValue base); |
| |
| using SILBuilder::createStoreBorrow; |
| void createStoreBorrow(SILLocation loc, ManagedValue value, SILValue address); |
| |
| /// Create a store_borrow if we have a non-trivial value and a store [trivial] |
| /// otherwise. |
| void createStoreBorrowOrTrivial(SILLocation loc, ManagedValue value, |
| SILValue address); |
| |
| /// Prepares a buffer to receive the result of an expression, either using the |
| /// 'emit into' initialization buffer if available, or allocating a temporary |
| /// allocation if not. After the buffer has been prepared, the rvalueEmitter |
| /// closure will be called with the buffer ready for initialization. After the |
| /// emitter has been called, the buffer will complete its initialization. |
| /// |
| /// \return an empty value if the buffer was taken from the context. |
| ManagedValue bufferForExpr(SILLocation loc, SILType ty, |
| const TypeLowering &lowering, SGFContext context, |
| llvm::function_ref<void(SILValue)> rvalueEmitter); |
| |
| using SILBuilder::createUncheckedEnumData; |
| ManagedValue createUncheckedEnumData(SILLocation loc, ManagedValue operand, |
| EnumElementDecl *element); |
| |
| using SILBuilder::createUncheckedTakeEnumDataAddr; |
| ManagedValue createUncheckedTakeEnumDataAddr(SILLocation loc, ManagedValue operand, |
| EnumElementDecl *element, SILType ty); |
| |
| ManagedValue createLoadTake(SILLocation loc, ManagedValue addr); |
| ManagedValue createLoadTake(SILLocation loc, ManagedValue addr, |
| const TypeLowering &lowering); |
| ManagedValue createLoadCopy(SILLocation loc, ManagedValue addr); |
| ManagedValue createLoadCopy(SILLocation loc, ManagedValue addr, |
| const TypeLowering &lowering); |
| |
| /// Create a SILArgument for an input parameter. Asserts if used to create a |
| /// function argument for an out parameter. |
| ManagedValue createInputFunctionArgument(SILType type, ValueDecl *decl); |
| |
| /// Create a SILArgument for an input parameter. Uses \p loc to create any |
| /// copies necessary. Asserts if used to create a function argument for an out |
| /// parameter. |
| /// |
| /// *NOTE* This API purposely used an Optional<SILLocation> to distinguish |
| /// this API from the ValueDecl * API in C++. This is necessary since |
| /// ValueDecl * can implicitly convert to SILLocation. The optional forces the |
| /// user to be explicit that they want to use this API. |
| ManagedValue createInputFunctionArgument(SILType type, |
| Optional<SILLocation> loc); |
| |
| using SILBuilder::createEnum; |
| ManagedValue createEnum(SILLocation loc, ManagedValue payload, |
| EnumElementDecl *decl, SILType type); |
| |
| ManagedValue createSemanticLoadBorrow(SILLocation loc, ManagedValue addr); |
| |
| ManagedValue |
| formalAccessBufferForExpr(SILLocation loc, SILType ty, |
| const TypeLowering &lowering, SGFContext context, |
| llvm::function_ref<void(SILValue)> rvalueEmitter); |
| |
| using SILBuilder::createUnconditionalCheckedCastValue; |
| ManagedValue |
| createUnconditionalCheckedCastValue(SILLocation loc, |
| ManagedValue op, |
| CanType srcFormalTy, |
| SILType destLoweredTy, |
| CanType destFormalTy); |
| using SILBuilder::createUnconditionalCheckedCast; |
| ManagedValue createUnconditionalCheckedCast(SILLocation loc, |
| ManagedValue op, |
| SILType destLoweredTy, |
| CanType destFormalTy); |
| |
| using SILBuilder::createCheckedCastBranch; |
| void createCheckedCastBranch(SILLocation loc, bool isExact, |
| ManagedValue op, |
| SILType destLoweredTy, |
| CanType destFormalTy, |
| SILBasicBlock *trueBlock, |
| SILBasicBlock *falseBlock, |
| ProfileCounter Target1Count, |
| ProfileCounter Target2Count); |
| |
| using SILBuilder::createCheckedCastValueBranch; |
| void createCheckedCastValueBranch(SILLocation loc, |
| ManagedValue op, |
| CanType srcFormalTy, |
| SILType destLoweredTy, |
| CanType destFormalTy, |
| SILBasicBlock *trueBlock, |
| SILBasicBlock *falseBlock); |
| |
| using SILBuilder::createUpcast; |
| ManagedValue createUpcast(SILLocation loc, ManagedValue original, |
| SILType type); |
| |
| using SILBuilder::createUncheckedTrivialBitCast; |
| ManagedValue createUncheckedTrivialBitCast(SILLocation loc, |
| ManagedValue original, |
| SILType type); |
| |
| using SILBuilder::createUncheckedRefCast; |
| ManagedValue createUncheckedRefCast(SILLocation loc, ManagedValue original, |
| SILType type); |
| |
| using SILBuilder::createUncheckedAddrCast; |
| ManagedValue createUncheckedAddrCast(SILLocation loc, ManagedValue op, |
| SILType resultTy); |
| |
| using SILBuilder::createUncheckedReinterpretCast; |
| ManagedValue createUncheckedBitCast(SILLocation loc, ManagedValue original, |
| SILType type); |
| |
| using SILBuilder::createOpenExistentialRef; |
| ManagedValue createOpenExistentialRef(SILLocation loc, ManagedValue arg, |
| SILType openedType); |
| |
| using SILBuilder::createOpenExistentialValue; |
| ManagedValue createOpenExistentialValue(SILLocation loc, |
| ManagedValue original, SILType type); |
| |
| using SILBuilder::createOpenExistentialBoxValue; |
| ManagedValue createOpenExistentialBoxValue(SILLocation loc, |
| ManagedValue original, SILType type); |
| |
| using SILBuilder::createOpenExistentialBox; |
| ManagedValue createOpenExistentialBox(SILLocation loc, ManagedValue original, |
| SILType type); |
| |
| using SILBuilder::createOpenExistentialMetatype; |
| ManagedValue createOpenExistentialMetatype(SILLocation loc, |
| ManagedValue value, |
| SILType openedType); |
| |
| /// Convert a @convention(block) value to AnyObject. |
| ManagedValue createBlockToAnyObject(SILLocation loc, ManagedValue block, |
| SILType type); |
| |
| using SILBuilder::createOptionalSome; |
| ManagedValue createOptionalSome(SILLocation Loc, ManagedValue Arg); |
| ManagedValue createManagedOptionalNone(SILLocation Loc, SILType Type); |
| |
| // TODO: Rename this to createFunctionRef once all calls to createFunctionRef |
| // are removed. |
| ManagedValue createManagedFunctionRef(SILLocation loc, SILFunction *f); |
| |
| using SILBuilder::createConvertFunction; |
| ManagedValue createConvertFunction(SILLocation loc, ManagedValue fn, |
| SILType resultTy, |
| bool WithoutActuallyEscaping = false); |
| |
| using SILBuilder::createConvertEscapeToNoEscape; |
| ManagedValue |
| createConvertEscapeToNoEscape(SILLocation loc, ManagedValue fn, |
| SILType resultTy); |
| |
| using SILBuilder::createStore; |
| /// Forward \p value into \p address. |
| /// |
| /// This will forward value's cleanup (if it has one) into the equivalent |
| /// cleanup on address. In practice this means if the value is non-trivial, |
| /// the memory location will at end of scope have a destroy_addr applied to |
| /// it. |
| ManagedValue createStore(SILLocation loc, ManagedValue value, |
| SILValue address, StoreOwnershipQualifier qualifier); |
| |
| using SILBuilder::createSuperMethod; |
| ManagedValue createSuperMethod(SILLocation loc, ManagedValue operand, |
| SILDeclRef member, SILType methodTy); |
| |
| using SILBuilder::createObjCSuperMethod; |
| ManagedValue createObjCSuperMethod(SILLocation loc, ManagedValue operand, |
| SILDeclRef member, SILType methodTy); |
| |
| using SILBuilder::createValueMetatype; |
| ManagedValue createValueMetatype(SILLocation loc, SILType metatype, |
| ManagedValue base); |
| |
| using SILBuilder::createBridgeObjectToRef; |
| ManagedValue createBridgeObjectToRef(SILLocation loc, ManagedValue mv, |
| SILType destType); |
| |
| using SILBuilder::createRefToBridgeObject; |
| ManagedValue createRefToBridgeObject(SILLocation loc, ManagedValue mv, |
| SILValue bits); |
| |
| using SILBuilder::createBranch; |
| BranchInst *createBranch(SILLocation Loc, SILBasicBlock *TargetBlock, |
| ArrayRef<ManagedValue> Args); |
| |
| using SILBuilder::createReturn; |
| ReturnInst *createReturn(SILLocation Loc, ManagedValue ReturnValue); |
| |
| ReturnInst *createReturn(SILLocation Loc, SILValue ReturnValue, |
| AssertingManualScope &&functionLevelScope); |
| |
| using SILBuilder::emitDestructureValueOperation; |
| /// Perform either a tuple or struct destructure and then pass its components |
| /// as managed value one by one with an index to the closure. |
| void emitDestructureValueOperation( |
| SILLocation loc, ManagedValue value, |
| function_ref<void(unsigned, ManagedValue)> func); |
| |
| using SILBuilder::createProjectBox; |
| ManagedValue createProjectBox(SILLocation loc, ManagedValue mv, |
| unsigned index); |
| |
| using SILBuilder::createMarkDependence; |
| ManagedValue createMarkDependence(SILLocation loc, ManagedValue value, |
| ManagedValue base); |
| }; |
| |
| } // namespace Lowering |
| } // namespace swift |
| |
| #endif |