void ArgumentSource::forwardInto(SILGenFunction &SGF, Initialization *dest) && { switch (StoredKind) { case Kind::Invalid: llvm_unreachable("argument source is invalid"); case Kind::LValue: llvm_unreachable("cannot forward an l-value"); case Kind::RValue: { auto loc = getKnownRValueLocation(); std::move(*this).asKnownRValue().forwardInto(SGF, loc, dest); return; } case Kind::Expr: { auto e = std::move(*this).asKnownExpr(); SGF.emitExprInto(e, dest); return; } case Kind::Tuple: { auto loc = getKnownTupleLocation(); auto rvalue = std::move(*this).getKnownTupleAsRValue(SGF, SGFContext(dest)); if (!rvalue.isInContext()) std::move(rvalue).forwardInto(SGF, loc, dest); return; } } llvm_unreachable("bad kind"); }
/// 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)); }
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); }
ManagedValue ArgumentSource::materialize(SILGenFunction &gen) && { assert(!isLValue()); if (isRValue()) { auto loc = getKnownRValueLocation(); return std::move(*this).asKnownRValue().materialize(gen, loc); } auto expr = std::move(*this).asKnownExpr(); auto temp = gen.emitTemporary(expr, gen.getTypeLowering(expr->getType())); gen.emitExprInto(expr, temp.get()); return temp->getManagedAddress(); }
void ArgumentSource::forwardInto(SILGenFunction &SGF, Initialization *dest) && { switch (StoredKind) { case Kind::Invalid: llvm_unreachable("argument source is invalid"); case Kind::LValue: llvm_unreachable("cannot forward an l-value"); case Kind::RValue: { auto loc = getKnownRValueLocation(); std::move(*this).asKnownRValue(SGF).ensurePlusOne(SGF, loc).forwardInto(SGF, loc, dest); return; } case Kind::Expr: { auto e = std::move(*this).asKnownExpr(); SGF.emitExprInto(e, dest); return; } } llvm_unreachable("bad kind"); }
/// 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 void emitImplicitValueConstructor(SILGenFunction &gen, ConstructorDecl *ctor) { RegularLocation Loc(ctor); Loc.markAutoGenerated(); // FIXME: Handle 'self' along with the other arguments. auto *paramList = ctor->getParameterList(1); auto selfTyCan = ctor->getImplicitSelfDecl()->getType()->getInOutObjectType(); SILType selfTy = gen.getLoweredType(selfTyCan); // Emit the indirect return argument, if any. SILValue resultSlot; if (selfTy.isAddressOnly(gen.SGM.M)) { auto &AC = gen.getASTContext(); auto VD = new (AC) ParamDecl(/*IsLet*/ false, SourceLoc(), SourceLoc(), AC.getIdentifier("$return_value"), SourceLoc(), AC.getIdentifier("$return_value"), selfTyCan, ctor); resultSlot = new (gen.F.getModule()) SILArgument(gen.F.begin(), selfTy, VD); } // Emit the elementwise arguments. SmallVector<RValue, 4> elements; for (size_t i = 0, size = paramList->size(); i < size; ++i) { auto ¶m = paramList->get(i); elements.push_back( emitImplicitValueConstructorArg(gen, Loc, param->getType()->getCanonicalType(), ctor)); } emitConstructorMetatypeArg(gen, ctor); auto *decl = selfTy.getStructOrBoundGenericStruct(); assert(decl && "not a struct?!"); // If we have an indirect return slot, initialize it in-place. if (resultSlot) { auto elti = elements.begin(), eltEnd = elements.end(); for (VarDecl *field : decl->getStoredProperties()) { auto fieldTy = selfTy.getFieldType(field, gen.SGM.M); auto &fieldTL = gen.getTypeLowering(fieldTy); SILValue slot = gen.B.createStructElementAddr(Loc, resultSlot, field, fieldTL.getLoweredType().getAddressType()); InitializationPtr init(new KnownAddressInitialization(slot)); // An initialized 'let' property has a single value specified by the // initializer - it doesn't come from an argument. if (!field->isStatic() && field->isLet() && field->getParentInitializer()) { assert(field->getType()->isEqual(field->getParentInitializer() ->getType()) && "Checked by sema"); // Cleanup after this initialization. FullExpr scope(gen.Cleanups, field->getParentPatternBinding()); gen.emitExprInto(field->getParentInitializer(), init.get()); continue; } assert(elti != eltEnd && "number of args does not match number of fields"); (void)eltEnd; std::move(*elti).forwardInto(gen, Loc, init.get()); ++elti; } gen.B.createReturn(ImplicitReturnLocation::getImplicitReturnLoc(Loc), gen.emitEmptyTuple(Loc)); return; } // Otherwise, build a struct value directly from the elements. SmallVector<SILValue, 4> eltValues; auto elti = elements.begin(), eltEnd = elements.end(); for (VarDecl *field : decl->getStoredProperties()) { auto fieldTy = selfTy.getFieldType(field, gen.SGM.M); SILValue v; // An initialized 'let' property has a single value specified by the // initializer - it doesn't come from an argument. if (!field->isStatic() && field->isLet() && field->getParentInitializer()) { // Cleanup after this initialization. FullExpr scope(gen.Cleanups, field->getParentPatternBinding()); v = gen.emitRValue(field->getParentInitializer()) .forwardAsSingleStorageValue(gen, fieldTy, Loc); } else { assert(elti != eltEnd && "number of args does not match number of fields"); (void)eltEnd; v = std::move(*elti).forwardAsSingleStorageValue(gen, fieldTy, Loc); ++elti; } eltValues.push_back(v); } SILValue selfValue = gen.B.createStruct(Loc, selfTy, eltValues); gen.B.createReturn(ImplicitReturnLocation::getImplicitReturnLoc(Loc), selfValue); return; }