static ManagedValue implodeTupleValues(ArrayRef<ManagedValue> values, SILGenFunction &SGF, CanType tupleType, SILLocation l) { // Non-tuples don't need to be imploded. if (!isa<TupleType>(tupleType)) { assert(values.size() == 1 && "exploded non-tuple value?!"); return ImplodeLoadableTupleValue<KIND>::getValue(SGF, values[0], l); } const auto &TL = SGF.getTypeLowering(tupleType); // To implode an address-only tuple, we need to create a buffer to hold the // result tuple. if (TL.isAddressOnly() && SGF.silConv.useLoweredAddresses()) { assert(KIND != ImplodeKind::Unmanaged && "address-only values are always managed!"); auto buffer = SGF.emitTemporary(l, TL); ImplodeAddressOnlyTuple<KIND>(values, SGF) .visit(tupleType, buffer.get(), l); return buffer->getManagedAddress(); } // To implode loadable tuples, we just need to combine the elements with // TupleInsts. return ImplodeLoadableTupleValue<KIND>(values, SGF).visit(tupleType, l); }
ManagedValue ArgumentSource::materialize(SILGenFunction &SGF, AbstractionPattern origFormalType, SILType destType) && { auto substFormalType = getSubstRValueType(); assert(!destType || destType.getObjectType() == SGF.getLoweredType(origFormalType, substFormalType).getObjectType()); // Fast path: if the types match exactly, no abstraction difference // is possible and we can just materialize as normal. if (origFormalType.isExactType(substFormalType)) return std::move(*this).materialize(SGF); auto &destTL = (destType ? SGF.getTypeLowering(destType) : SGF.getTypeLowering(origFormalType, substFormalType)); if (!destType) destType = destTL.getLoweredType(); // If there's no abstraction difference, we can just materialize as normal. if (destTL.getLoweredType() == SGF.getLoweredType(substFormalType)) { return std::move(*this).materialize(SGF); } // Emit a temporary at the given address. auto temp = SGF.emitTemporary(getLocation(), destTL); // Forward into it. std::move(*this).forwardInto(SGF, origFormalType, temp.get(), destTL); return temp->getManagedAddress(); }
ManagedValue ArgumentSource::materialize(SILGenFunction &SGF) && { if (isRValue()) { auto loc = getKnownRValueLocation(); return std::move(*this).asKnownRValue(SGF).materialize(SGF, loc); } auto loc = getLocation(); auto temp = SGF.emitTemporary(loc, SGF.getTypeLowering(getSubstRValueType())); std::move(*this).forwardInto(SGF, temp.get()); return temp->getManagedAddress(); }
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(); }
ManagedValue RValue::materialize(SILGenFunction &gen, SILLocation loc) && { auto ¶mTL = gen.getTypeLowering(getType()); // If we're already materialized, we're done. if (values.size() == 1 && values[0].getType() == paramTL.getLoweredType().getAddressType()) { auto value = values[0]; makeUsed(); return value; } // Otherwise, emit to a temporary. auto temp = gen.emitTemporary(loc, paramTL); std::move(*this).forwardInto(gen, temp.get(), loc); return temp->getManagedAddress(); }
ManagedValue RValue::materialize(SILGenFunction &SGF, SILLocation loc) && { assert(isPlusOne(SGF) && "Can not materialize a non-plus one RValue"); auto ¶mTL = SGF.getTypeLowering(getType()); // If we're already materialized, we're done. if (values.size() == 1 && values[0].getType() == paramTL.getLoweredType().getAddressType()) { auto value = values[0]; makeUsed(); return value; } // Otherwise, emit to a temporary. auto temp = SGF.emitTemporary(loc, paramTL); std::move(*this).forwardInto(SGF, loc, temp.get()); return temp->getManagedAddress(); }
static ManagedValue adjustForConditionalCheckedCastOperand(SILLocation loc, ManagedValue src, CanType sourceType, CanType targetType, SILGenFunction &SGF) { // Reabstract to the most general abstraction, and put it into a // temporary if necessary. // Figure out if we need the value to be in a temporary. bool requiresAddress = !canUseScalarCheckedCastInstructions(SGF.SGM.M, sourceType, targetType); AbstractionPattern abstraction = SGF.SGM.M.Types.getMostGeneralAbstraction(); auto &srcAbstractTL = SGF.getTypeLowering(abstraction, sourceType); bool hasAbstraction = (src.getType() != srcAbstractTL.getLoweredType()); // Fast path: no re-abstraction required. if (!hasAbstraction && (!requiresAddress || src.getType().isAddress())) { return src; } std::unique_ptr<TemporaryInitialization> init; SGFContext ctx; if (requiresAddress) { init = SGF.emitTemporary(loc, srcAbstractTL); // Okay, if all we need to do is drop the value in an address, // this is easy. if (!hasAbstraction) { SGF.B.createStore(loc, src.forward(SGF), init->getAddress()); init->finishInitialization(SGF); return init->getManagedAddress(); } ctx = SGFContext(init.get()); } assert(hasAbstraction); assert(src.getType().isObject() && "address-only type with abstraction difference?"); // Produce the value at +1. return SGF.emitSubstToOrigValue(loc, src, abstraction, sourceType); }