RValue ArgumentSource::getAsRValue(SILGenFunction &gen, SGFContext C) && { assert(!isLValue()); if (isRValue()) return std::move(*this).asKnownRValue(); return gen.emitRValue(std::move(*this).asKnownExpr(), C); }
/// Specialized emitter for Builtin.addressOfBorrow. static ManagedValue emitBuiltinAddressOfBorrow(SILGenFunction &SGF, SILLocation loc, SubstitutionMap substitutions, PreparedArguments &&preparedArgs, SGFContext C) { SILType rawPointerType = SILType::getRawPointerType(SGF.getASTContext()); auto argsOrError = decomposeArguments(SGF, loc, std::move(preparedArgs), 1); if (!argsOrError) return SGF.emitUndef(rawPointerType); auto argument = (*argsOrError)[0]; SILValue addr; // Try to borrow the argument at +0. We only support if it's // naturally emitted borrowed in memory. auto borrow = SGF.emitRValue(argument, SGFContext::AllowGuaranteedPlusZero) .getAsSingleValue(SGF, argument); if (!borrow.isPlusZero() || !borrow.getType().isAddress()) { SGF.SGM.diagnose(argument->getLoc(), diag::non_borrowed_indirect_addressof); return SGF.emitUndef(rawPointerType); } addr = borrow.getValue(); // Take the address argument and cast it to RawPointer. SILValue result = SGF.B.createAddressToPointer(loc, addr, rawPointerType); return ManagedValue::forUnmanaged(result); }
RValue ArgumentSource::getAsRValue(SILGenFunction &SGF, SGFContext C) && { switch (StoredKind) { case Kind::Invalid: llvm_unreachable("argument source is invalid"); case Kind::LValue: llvm_unreachable("cannot get l-value as r-value"); case Kind::RValue: return std::move(*this).asKnownRValue(SGF); case Kind::Expr: return SGF.emitRValue(std::move(*this).asKnownExpr(), C); } llvm_unreachable("bad kind"); }
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; }