static void emitOnceCall(SILGenFunction &SGF, VarDecl *global, SILGlobalVariable *onceToken, SILFunction *onceFunc) { SILType rawPointerSILTy = SGF.getLoweredLoadableType(SGF.getASTContext().TheRawPointerType); // Emit a reference to the global token. SILValue onceTokenAddr = SGF.B.createGlobalAddr(global, onceToken); onceTokenAddr = SGF.B.createAddressToPointer(global, onceTokenAddr, rawPointerSILTy); // Emit a reference to the function to execute. SILValue onceFuncRef = SGF.B.createFunctionRef(global, onceFunc); // Call Builtin.once. SILValue onceArgs[] = {onceTokenAddr, onceFuncRef}; SGF.B.createBuiltin(global, SGF.getASTContext().getIdentifier("once"), SGF.SGM.Types.getEmptyTupleType(), {}, onceArgs); }
static SILValue emitConstructorMetatypeArg(SILGenFunction &gen, ValueDecl *ctor) { // In addition to the declared arguments, the constructor implicitly takes // the metatype as its first argument, like a static function. Type metatype = ctor->getInterfaceType()->castTo<AnyFunctionType>()->getInput(); auto *DC = ctor->getInnermostDeclContext(); auto &AC = gen.getASTContext(); auto VD = new (AC) ParamDecl(/*IsLet*/ true, SourceLoc(), SourceLoc(), AC.getIdentifier("$metatype"), SourceLoc(), AC.getIdentifier("$metatype"), Type(), DC); VD->setInterfaceType(metatype); gen.AllocatorMetatype = gen.F.begin()->createFunctionArgument( gen.getLoweredType(DC->mapTypeIntoContext(metatype)), VD); return gen.AllocatorMetatype; }
static ManagedValue emitBuiltinBindMemory(SILGenFunction &gen, SILLocation loc, SubstitutionList subs, ArrayRef<ManagedValue> args, CanFunctionType formalApplyType, SGFContext C) { assert(subs.size() == 1 && "bindMemory should have a single substitution"); assert(args.size() == 3 && "bindMemory should have three argument"); // The substitution determines the element type for bound memory. CanType boundFormalType = subs[0].getReplacement()->getCanonicalType(); SILType boundType = gen.getLoweredType(boundFormalType); gen.B.createBindMemory(loc, args[0].getValue(), args[1].getValue(), boundType); return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc)); }
static LValue emitLValueForMemberInit(SILGenFunction &SGF, SILLocation loc, VarDecl *selfDecl, VarDecl *property) { CanType selfFormalType = selfDecl->getType()->getCanonicalType(); auto self = emitSelfForMemberInit(SGF, loc, selfDecl); return SGF.emitPropertyLValue(loc, self, selfFormalType, property, LValueOptions(), SGFAccessKind::Write, AccessSemantics::DirectToStorage); }
static ManagedValue emitBuiltinTypeTrait(SILGenFunction &gen, SILLocation loc, SubstitutionList substitutions, ArrayRef<ManagedValue> args, CanFunctionType formalApplyType, SGFContext C) { assert(substitutions.size() == 1 && "type trait should take a single type parameter"); assert(args.size() == 1 && "type trait should take a single argument"); unsigned result; auto traitTy = substitutions[0].getReplacement()->getCanonicalType(); switch ((traitTy.getPointer()->*Trait)()) { // If the type obviously has or lacks the trait, emit a constant result. case TypeTraitResult::IsNot: result = 0; break; case TypeTraitResult::Is: result = 1; break; // If not, emit the builtin call normally. Specialization may be able to // eliminate it later, or we'll lower it away at IRGen time. case TypeTraitResult::CanBe: { auto &C = gen.getASTContext(); auto int8Ty = BuiltinIntegerType::get(8, C)->getCanonicalType(); auto apply = gen.B.createBuiltin(loc, C.getIdentifier(getBuiltinName(Kind)), SILType::getPrimitiveObjectType(int8Ty), substitutions, args[0].getValue()); return ManagedValue::forUnmanaged(apply); } } // Produce the result as an integer literal constant. auto val = gen.B.createIntegerLiteral( loc, SILType::getBuiltinIntegerType(8, gen.getASTContext()), (uintmax_t)result); return ManagedValue::forUnmanaged(val); }
static ManagedValue adjustForConditionalCheckedCastOperand(SILLocation loc, ManagedValue src, CanType sourceType, CanType targetType, SILGenFunction &SGF) { // Reabstract to the most general abstraction, and put it into a // temporary if necessary. // Figure out if we need the value to be in a temporary. bool requiresAddress = !canUseScalarCheckedCastInstructions(SGF.SGM.M, sourceType, targetType); AbstractionPattern abstraction = SGF.SGM.M.Types.getMostGeneralAbstraction(); auto &srcAbstractTL = SGF.getTypeLowering(abstraction, sourceType); bool hasAbstraction = (src.getType() != srcAbstractTL.getLoweredType()); // Fast path: no re-abstraction required. if (!hasAbstraction && (!requiresAddress || src.getType().isAddress())) { return src; } std::unique_ptr<TemporaryInitialization> init; SGFContext ctx; if (requiresAddress) { init = SGF.emitTemporary(loc, srcAbstractTL); // Okay, if all we need to do is drop the value in an address, // this is easy. if (!hasAbstraction) { SGF.B.createStore(loc, src.forward(SGF), init->getAddress()); init->finishInitialization(SGF); return init->getManagedAddress(); } ctx = SGFContext(init.get()); } assert(hasAbstraction); assert(src.getType().isObject() && "address-only type with abstraction difference?"); // Produce the value at +1. return SGF.emitSubstToOrigValue(loc, src, abstraction, sourceType); }
ManagedValue ManagedValue::materialize(SILGenFunction &SGF, SILLocation loc) const { auto temporary = SGF.emitTemporaryAllocation(loc, getType()); bool hadCleanup = hasCleanup(); // The temporary memory is +0 if the value was. if (hadCleanup) { SGF.B.emitStoreValueOperation(loc, forward(SGF), temporary, StoreOwnershipQualifier::Init); // SEMANTIC SIL TODO: This should really be called a temporary LValue. return ManagedValue::forOwnedAddressRValue(temporary, SGF.enterDestroyCleanup(temporary)); } else { auto object = SGF.emitManagedBeginBorrow(loc, getValue()); SGF.emitManagedStoreBorrow(loc, object.getValue(), temporary); return ManagedValue::forBorrowedAddressRValue(temporary); } }
/// Specialized emitter for Builtin.condfail. static ManagedValue emitBuiltinCondFail(SILGenFunction &SGF, SILLocation loc, SubstitutionMap substitutions, ArrayRef<ManagedValue> args, SGFContext C) { assert(args.size() == 1 && "condfail should be given one argument"); SGF.B.createCondFail(loc, args[0].getUnmanagedValue()); return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc)); }
/// Specialized emitter for Builtin.fixLifetime. static ManagedValue emitBuiltinFixLifetime(SILGenFunction &SGF, SILLocation loc, SubstitutionMap substitutions, ArrayRef<ManagedValue> args, SGFContext C) { for (auto arg : args) { SGF.B.createFixLifetime(loc, arg.getValue()); } return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc)); }
static ManagedValue emitBuiltinAutorelease(SILGenFunction &gen, SILLocation loc, SubstitutionList substitutions, ArrayRef<ManagedValue> args, CanFunctionType formalApplyType, SGFContext C) { gen.B.createUnmanagedAutoreleaseValue(loc, args[0].getValue(), gen.B.getDefaultAtomicity()); return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc)); }
/// This is the same operation as 'copy', but works on +0 values that don't /// have cleanups. It returns a +1 value with one. ManagedValue ManagedValue::formalAccessCopyUnmanaged(SILGenFunction &SGF, SILLocation loc) { if (getType().isObject()) { return SGF.B.createFormalAccessCopyValue(loc, *this); } SILValue result = SGF.emitTemporaryAllocation(loc, getType()); return SGF.B.createFormalAccessCopyAddr(loc, *this, result, IsNotTake, IsInitialization); }
/// Emit a materializeForSet operation that projects storage, assuming /// that no cleanups or callbacks are required. SILValue MaterializeForSetEmitter::emitUsingStorage(SILGenFunction &gen, SILLocation loc, ManagedValue self, RValue &&indices) { LValue lvalue = buildLValue(gen, loc, self, std::move(indices), AccessKind::ReadWrite); ManagedValue address = gen.emitAddressOfLValue(loc, std::move(lvalue), AccessKind::ReadWrite); return address.getUnmanagedValue(); }
/// Store a copy of this value with independent ownership into the given /// uninitialized address. void ManagedValue::copyInto(SILGenFunction &gen, SILValue dest, SILLocation L) { auto &lowering = gen.getTypeLowering(getType()); if (lowering.isAddressOnly()) { gen.B.createCopyAddr(L, getValue(), dest, IsNotTake, IsInitialization); return; } lowering.emitRetainValue(gen.B, L, getValue()); gen.B.createStore(L, getValue(), dest); }
ManagedValue ArgumentSource::getAsSingleValue(SILGenFunction &gen, AbstractionPattern origFormalType, SGFContext C) && { auto loc = getLocation(); auto substFormalType = getSubstType(); ManagedValue outputValue = std::move(*this).getAsSingleValue(gen); return gen.emitSubstToOrigValue(loc, outputValue, origFormalType, substFormalType, C); }
void ArgumentSource::forwardInto(SILGenFunction &gen, Initialization *dest) && { assert(!isLValue()); if (isRValue()) { auto loc = getKnownRValueLocation(); return std::move(*this).asKnownRValue().forwardInto(gen, loc, dest); } auto e = std::move(*this).asKnownExpr(); return gen.emitExprInto(e, dest); }
/// Emit a materializeForSet operation that calls a mutable addressor. /// /// If it's not an unsafe addressor, this uses a callback function to /// write the l-value back. SILValue MaterializeForSetEmitter::emitUsingAddressor(SILGenFunction &SGF, SILLocation loc, ManagedValue self, RValue &&indices, SILValue callbackBuffer, SILFunction *&callback) { bool isDirect = (TheAccessSemantics != AccessSemantics::Ordinary); // Call the mutable addressor. auto addressor = SGF.getAddressorDeclRef(WitnessStorage, AccessKind::ReadWrite, isDirect); std::pair<ManagedValue, ManagedValue> result; { FormalEvaluationScope Scope(SGF); SILType addressType = WitnessStorageType.getAddressType(); ArgumentSource baseRV = SGF.prepareAccessorBaseArg(loc, self, SubstSelfType, addressor); result = SGF.emitAddressorAccessor(loc, addressor, WitnessSubs, std::move(baseRV), IsSuper, isDirect, std::move(indices), addressType); } SILValue address = result.first.getUnmanagedValue(); AddressorKind addressorKind = WitnessStorage->getMutableAddressor()->getAddressorKind(); ManagedValue owner = result.second; if (!owner) { assert(addressorKind == AddressorKind::Unsafe); } else { SILValue allocatedCallbackBuffer = SGF.B.createAllocValueBuffer(loc, owner.getType(), callbackBuffer); SGF.B.emitStoreValueOperation(loc, owner.forward(SGF), allocatedCallbackBuffer, StoreOwnershipQualifier::Init); callback = createAddressorCallback(SGF.F, owner.getType(), addressorKind); } return address; }
/// Store a copy of this value with independent ownership into the given /// uninitialized address. void ManagedValue::copyInto(SILGenFunction &SGF, SILValue dest, SILLocation loc) { auto &lowering = SGF.getTypeLowering(getType()); if (lowering.isAddressOnly() && SGF.silConv.useLoweredAddresses()) { SGF.B.createCopyAddr(loc, getValue(), dest, IsNotTake, IsInitialization); return; } SILValue copy = lowering.emitCopyValue(SGF.B, loc, getValue()); lowering.emitStoreOfCopy(SGF.B, loc, copy, dest, IsInitialization); }
/// Specialized emitter for Builtin.condfail. static ManagedValue emitBuiltinCondFail(SILGenFunction &gen, SILLocation loc, SubstitutionList substitutions, ArrayRef<ManagedValue> args, CanFunctionType formalApplyType, SGFContext C) { assert(args.size() == 1 && "condfail should be given one argument"); gen.B.createCondFail(loc, args[0].getUnmanagedValue()); return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc)); }
/// Specialized emitter for Builtin.fixLifetime. static ManagedValue emitBuiltinFixLifetime(SILGenFunction &gen, SILLocation loc, SubstitutionList substitutions, ArrayRef<ManagedValue> args, CanFunctionType formalApplyType, SGFContext C) { for (auto arg : args) { gen.B.createFixLifetime(loc, arg.getValue()); } return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc)); }
static ManagedValue emitBuiltinAutorelease(SILGenFunction &gen, SILLocation loc, ArrayRef<Substitution> substitutions, ArrayRef<ManagedValue> args, CanFunctionType formalApplyType, SGFContext C) { // The value was produced at +1, so to produce an unbalanced // autorelease we need to leave the cleanup intact. gen.B.createAutoreleaseValue(loc, args[0].getValue(), Atomicity::Atomic); return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc)); }
static ManagedValue emitBuiltinRetain(SILGenFunction &gen, SILLocation loc, ArrayRef<Substitution> substitutions, ArrayRef<ManagedValue> args, CanFunctionType formalApplyType, SGFContext C) { // The value was produced at +1; we can produce an unbalanced // retain simply by disabling the cleanup. args[0].forward(gen); return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc)); }
/// Emit Builtin.initialize by evaluating the operand directly into /// the address. static ManagedValue emitBuiltinInit(SILGenFunction &gen, SILLocation loc, ArrayRef<Substitution> substitutions, Expr *tuple, CanFunctionType formalApplyType, SGFContext C) { auto args = decomposeArguments(gen, tuple, 2); CanType formalType = substitutions[0].getReplacement()->getCanonicalType(); auto &formalTL = gen.getTypeLowering(formalType); SILValue addr = gen.emitRValueAsSingleValue(args[1]).getUnmanagedValue(); addr = gen.B.createPointerToAddress(loc, addr, formalTL.getLoweredType().getAddressType()); TemporaryInitialization init(addr, CleanupHandle::invalid()); gen.emitExprInto(args[0], &init); return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc)); }
static ManagedValue emitBuiltinValueToBridgeObject(SILGenFunction &SGF, SILLocation loc, SubstitutionMap subs, ArrayRef<ManagedValue> args, SGFContext C) { assert(args.size() == 1 && "ValueToBridgeObject should have one argument"); assert(subs.getReplacementTypes().size() == 1 && "ValueToBridgeObject should have one sub"); Type argTy = subs.getReplacementTypes()[0]; if (!argTy->is<BuiltinIntegerType>()) { SGF.SGM.diagnose(loc, diag::invalid_sil_builtin, "argument to builtin should be a builtin integer"); SILType objPointerType = SILType::getBridgeObjectType(SGF.F.getASTContext()); return SGF.emitUndef(objPointerType); } SILValue result = SGF.B.createValueToBridgeObject(loc, args[0].getValue()); return SGF.emitManagedRetain(loc, result); }
static ManagedValue emitBuiltinTryPin(SILGenFunction &SGF, SILLocation loc, SubstitutionList subs, ArrayRef<ManagedValue> args, SGFContext C) { assert(args.size() == 1); if (!requireIsOptionalNativeObject(SGF, loc, subs[0].getReplacement())) { return SGF.emitUndef(loc, subs[0].getReplacement()); } // The value was produced at +1, but pinning is only a conditional // retain, so we have to leave the cleanup in place. TODO: try to // emit the argument at +0. SILValue result = SGF.B.createStrongPin(loc, args[0].getValue(), SGF.B.getDefaultAtomicity()); // The handle, if non-null, is effectively +1. return SGF.emitManagedRValueWithCleanup(result); }
ManagedValue ArgumentSource::getAsSingleValue(SILGenFunction &gen, SGFContext C) && { if (isRValue()) { auto loc = getKnownRValueLocation(); return std::move(*this).asKnownRValue().getAsSingleValue(gen, loc); } if (isLValue()) { auto loc = getKnownLValueLocation(); return gen.emitAddressOfLValue(loc, std::move(*this).asKnownLValue(), AccessKind::ReadWrite); } auto e = std::move(*this).asKnownExpr(); if (e->getType()->is<InOutType>()) { return gen.emitAddressOfLValue(e, gen.emitLValue(e, AccessKind::ReadWrite), AccessKind::ReadWrite); } else { return gen.emitRValueAsSingleValue(e, C); } }
static void forwardCaptureArgs(SILGenFunction &gen, SmallVectorImpl<SILValue> &args, CapturedValue capture) { auto addSILArgument = [&](SILType t, ValueDecl *d) { args.push_back(gen.F.begin()->createFunctionArgument(t, d)); }; auto *vd = capture.getDecl(); switch (gen.SGM.Types.getDeclCaptureKind(capture)) { case CaptureKind::None: break; case CaptureKind::Constant: { auto *var = dyn_cast<VarDecl>(vd); addSILArgument(gen.getLoweredType(var->getType()), vd); break; } case CaptureKind::Box: { // Forward the captured owning box. auto *var = cast<VarDecl>(vd); auto boxTy = gen.SGM.Types .getInterfaceBoxTypeForCapture(vd, gen.getLoweredType(var->getType()) .getSwiftRValueType(), /*mutable*/ true); addSILArgument(SILType::getPrimitiveObjectType(boxTy), vd); break; } case CaptureKind::StorageAddress: { auto *var = dyn_cast<VarDecl>(vd); SILType ty = gen.getLoweredType(var->getType()->getRValueType()) .getAddressType(); // Forward the captured value address. addSILArgument(ty, vd); break; } } }
static ManagedValue emitBridgeNSStringToString(SILGenFunction &gen, SILLocation loc, ManagedValue nsstr) { SILValue bridgeFn = gen.emitGlobalFunctionRef(loc, gen.SGM.getNSStringToStringFn()); Type inputType = nsstr.getType().getSwiftRValueType(); if (!inputType->getOptionalObjectType()) { SILType loweredOptTy = gen.SGM.getLoweredType(OptionalType::get(inputType)); auto *someDecl = gen.getASTContext().getOptionalSomeDecl(); auto *enumInst = gen.B.createEnum(loc, nsstr.getValue(), someDecl, loweredOptTy); nsstr = ManagedValue(enumInst, nsstr.getCleanup()); } SILType nativeTy = gen.getLoweredType(gen.SGM.Types.getStringType()); SILValue str = gen.B.createApply(loc, bridgeFn, bridgeFn.getType(), nativeTy, {}, { nsstr.forward(gen) }); return gen.emitManagedRValueWithCleanup(str); }
static ManagedValue emitBuiltinRelease(SILGenFunction &gen, SILLocation loc, SubstitutionList substitutions, ArrayRef<ManagedValue> args, CanFunctionType formalApplyType, SGFContext C) { // The value was produced at +1, so to produce an unbalanced // release we need to leave the cleanup intact and then do a *second* // release. gen.B.createUnmanagedReleaseValue(loc, args[0].getValue()); return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc)); }
static ManagedValue emitBuiltinRetain(SILGenFunction &gen, SILLocation loc, SubstitutionList substitutions, ArrayRef<ManagedValue> args, CanFunctionType formalApplyType, SGFContext C) { // The value was produced at +1; we can produce an unbalanced retain simply by // disabling the cleanup. But this would violate ownership semantics. Instead, // we must allow for the cleanup and emit a new unmanaged retain value. gen.B.createUnmanagedRetainValue(loc, args[0].getValue()); return ManagedValue::forUnmanaged(gen.emitEmptyTuple(loc)); }
/// Given a list of direct results, form the direct result value. /// /// Note that this intentionally loses any tuple sub-structure of the /// formal result type. static SILValue buildReturnValue(SILGenFunction &gen, SILLocation loc, ArrayRef<SILValue> directResults) { if (directResults.size() == 1) return directResults[0]; SmallVector<TupleTypeElt, 4> eltTypes; for (auto elt : directResults) eltTypes.push_back(elt->getType().getSwiftRValueType()); auto resultType = SILType::getPrimitiveObjectType( CanType(TupleType::get(eltTypes, gen.getASTContext()))); return gen.B.createTuple(loc, resultType, directResults); }