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"); }
/// Specialized emitter for Builtin.addressof. static ManagedValue emitBuiltinAddressOf(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]; // If the argument is inout, try forming its lvalue. This builtin only works // if it's trivially physically projectable. auto inout = cast<InOutExpr>(argument->getSemanticsProvidingExpr()); auto lv = SGF.emitLValue(inout->getSubExpr(), SGFAccessKind::ReadWrite); if (!lv.isPhysical() || !lv.isLoadingPure()) { SGF.SGM.diagnose(argument->getLoc(), diag::non_physical_addressof); return SGF.emitUndef(rawPointerType); } auto addr = SGF.emitAddressOfLValue(argument, std::move(lv)) .getLValueAddress(); // Take the address argument and cast it to RawPointer. SILValue result = SGF.B.createAddressToPointer(loc, addr, rawPointerType); return ManagedValue::forUnmanaged(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); } }
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"); }