/// Emit Builtin.initialize by evaluating the operand directly into /// the address. static ManagedValue emitBuiltinInit(SILGenFunction &SGF, SILLocation loc, SubstitutionMap substitutions, PreparedArguments &&preparedArgs, SGFContext C) { auto argsOrError = decomposeArguments(SGF, loc, std::move(preparedArgs), 2); if (!argsOrError) return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc)); auto args = *argsOrError; CanType formalType = substitutions.getReplacementTypes()[0]->getCanonicalType(); auto &formalTL = SGF.getTypeLowering(formalType); SILValue addr = SGF.emitRValueAsSingleValue(args[1]).getUnmanagedValue(); addr = SGF.B.createPointerToAddress( loc, addr, formalTL.getLoweredType().getAddressType(), /*isStrict*/ true, /*isInvariant*/ false); TemporaryInitialization init(addr, CleanupHandle::invalid()); SGF.emitExprInto(args[0], &init); return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc)); }
ManagedValue ArgumentSource::getAsSingleValue(SILGenFunction &SGF, SGFContext C) && { switch (StoredKind) { case Kind::Invalid: llvm_unreachable("argument source is invalid"); case Kind::LValue: { auto loc = getKnownLValueLocation(); LValue &&lv = std::move(*this).asKnownLValue(); return SGF.emitAddressOfLValue(loc, std::move(lv)); } case Kind::RValue: { auto loc = getKnownRValueLocation(); if (auto init = C.getEmitInto()) { std::move(*this).asKnownRValue(SGF) .ensurePlusOne(SGF, loc) .forwardInto(SGF, loc, init); return ManagedValue::forInContext(); } else { return std::move(*this).asKnownRValue(SGF).getAsSingleValue(SGF, loc); } } case Kind::Expr: { auto e = std::move(*this).asKnownExpr(); if (e->isSemanticallyInOutExpr()) { auto lv = SGF.emitLValue(e, SGFAccessKind::ReadWrite); return SGF.emitAddressOfLValue(e, std::move(lv)); } else { return SGF.emitRValueAsSingleValue(e, C); } } } llvm_unreachable("bad kind"); }
SILValue Lowering::emitIsa(SILGenFunction &SGF, SILLocation loc, Expr *operand, Type targetType, CheckedCastKind castKind) { // Handle collection downcasts separately. if (castKind == CheckedCastKind::ArrayDowncast || castKind == CheckedCastKind::DictionaryDowncast || castKind == CheckedCastKind::SetDowncast) { ManagedValue operandMV = SGF.emitRValueAsSingleValue(operand); ManagedValue optValue = emitCollectionDowncastExpr( SGF, operandMV, operand->getType(), loc, targetType, SGFContext(), /*conditional=*/true) .getAsSingleValue(SGF, loc); // Materialize the input. SILValue optValueTemp; if (optValue.getType().isAddress()) { optValueTemp = optValue.forward(SGF); } else { optValueTemp = SGF.emitTemporaryAllocation(loc, optValue.getType()); optValue.forwardInto(SGF, loc, optValueTemp); } return SGF.emitDoesOptionalHaveValue(loc, optValueTemp); } // Prepare a jump destination here. ExitableFullExpr scope(SGF, CleanupLocation::get(loc)); auto i1Ty = SILType::getBuiltinIntegerType(1, SGF.getASTContext()); SGF.emitCheckedCastBranch(loc, operand, targetType, SGFContext(), [&](ManagedValue value) { SILValue yes = SGF.B.createIntegerLiteral(loc, i1Ty, 1); SGF.Cleanups.emitBranchAndCleanups(scope.getExitDest(), loc, yes); }, [&] { SILValue no = SGF.B.createIntegerLiteral(loc, i1Ty, 0); SGF.Cleanups.emitBranchAndCleanups(scope.getExitDest(), loc, no); }); auto contBB = scope.exit(); auto isa = new (SGF.SGM.M) SILArgument(contBB, i1Ty); return isa; }
/// 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)); }
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); } }
RValue Lowering::emitUnconditionalCheckedCast(SILGenFunction &SGF, SILLocation loc, Expr *operand, Type targetType, CheckedCastKind castKind, SGFContext C) { // Handle collection downcasts directly; they have specific library // entry points. if (castKind == CheckedCastKind::ArrayDowncast || castKind == CheckedCastKind::DictionaryDowncast || castKind == CheckedCastKind::SetDowncast) { ManagedValue operandMV = SGF.emitRValueAsSingleValue(operand); return emitCollectionDowncastExpr(SGF, operandMV, operand->getType(), loc, targetType, C, /*conditional=*/false); } CheckedCastEmitter emitter(SGF, loc, operand->getType(), targetType); ManagedValue operandValue = emitter.emitOperand(operand); return emitter.emitUnconditionalCast(operandValue, C); }
ManagedValue ArgumentSource::getAsSingleValue(SILGenFunction &SGF, SGFContext C) && { switch (StoredKind) { case Kind::Invalid: llvm_unreachable("argument source is invalid"); case Kind::LValue: { auto loc = getKnownLValueLocation(); return SGF.emitAddressOfLValue(loc, std::move(*this).asKnownLValue(), AccessKind::ReadWrite); } case Kind::RValue: { auto loc = getKnownRValueLocation(); if (auto init = C.getEmitInto()) { std::move(*this).asKnownRValue().forwardInto(SGF, loc, init); return ManagedValue::forInContext(); } else { return std::move(*this).asKnownRValue().getAsSingleValue(SGF, loc); } } case Kind::Expr: { auto e = std::move(*this).asKnownExpr(); if (e->getType()->is<InOutType>()) { return SGF.emitAddressOfLValue(e, SGF.emitLValue(e, AccessKind::ReadWrite), AccessKind::ReadWrite); } else { return SGF.emitRValueAsSingleValue(e, C); } } case Kind::Tuple: { auto loc = getKnownTupleLocation(); auto rvalue = std::move(*this).getKnownTupleAsRValue(SGF, C); if (rvalue.isInContext()) return ManagedValue::forInContext(); return std::move(rvalue).getAsSingleValue(SGF, loc); } } llvm_unreachable("bad kind"); }