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"); }
/// Emit a materializeForSet operation that projects storage, assuming /// that no cleanups or callbacks are required. SILValue MaterializeForSetEmitter::emitUsingStorage(SILGenFunction &SGF, SILLocation loc, ManagedValue self, RValue &&indices, SILValue callbackBuffer, SILFunction *&callback) { LValue lvalue = buildLValue(SGF, loc, self, std::move(indices), AccessKind::ReadWrite); SILGenFunction::UnpairedAccesses unpairedAccesses(callbackBuffer); SGF.UnpairedAccessesForMaterializeForSet = &unpairedAccesses; ManagedValue address = SGF.emitAddressOfLValue(loc, std::move(lvalue), AccessKind::ReadWrite); SGF.UnpairedAccessesForMaterializeForSet = nullptr; // Create a callback to end the unpaired accesses if any were pushed. if (unpairedAccesses.NumAccesses) { // If it ever proves necessary, we can make this work by allocating // a (ValueBuffer x N) tuple in callbackBuffer and rewriting the existing // uses. But it probably won't ever prove necessary. assert(unpairedAccesses.NumAccesses == 1 && "multiple unpaired accesses not supported"); callback = createEndUnpairedAccessesCallback(SGF.F, unpairedAccesses); } return address.getUnmanagedValue(); }
/// 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); }
/// 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(); }
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"); }