// Allow casting a tuple by value when all elements in toType correspond to an // element of the same size or larger in fromType in the same order. static bool canUnsafeCastTuple(SILType fromType, CanTupleType fromTupleTy, SILType toType, SILModule &M) { unsigned numFromElts = fromTupleTy->getNumElements(); // Can the first element of fromTupleTy be cast by value into toType? if (numFromElts != 0 && SILType::canUnsafeCastValue( fromType.getTupleElementType(0), toType, M)) { return true; } // Otherwise, flatten one level of tuple elements on each side. CanTupleType toTupleTy = dyn_cast<TupleType>(toType.getSwiftRValueType()); if (!toTupleTy) return false; unsigned numToElts = toTupleTy->getNumElements(); if (numFromElts < numToElts) return false; for (unsigned i = 0; i != numToElts; ++i) { if (!SILType::canUnsafeCastValue(fromType.getTupleElementType(i), toType.getTupleElementType(i), M)) { return false; } } return true; }
bool AbstractionPattern::matchesTuple(CanTupleType substType) { switch (getKind()) { case Kind::Invalid: llvm_unreachable("querying invalid abstraction pattern!"); case Kind::PartialCurriedObjCMethodType: case Kind::CurriedObjCMethodType: case Kind::PartialCurriedCFunctionAsMethodType: case Kind::CurriedCFunctionAsMethodType: case Kind::CFunctionAsMethodType: case Kind::ObjCMethodType: return false; case Kind::Opaque: return true; case Kind::Tuple: return getNumTupleElements_Stored() == substType->getNumElements(); case Kind::ClangType: case Kind::Type: case Kind::Discard: if (isTypeParameter()) return true; auto tuple = dyn_cast<TupleType>(getType()); return (tuple && tuple->getNumElements() == substType->getNumElements()); } llvm_unreachable("bad kind"); }
void RValue::extractElements(SmallVectorImpl<RValue> &elements) && { assert(isComplete() && "rvalue is not complete"); CanTupleType tupleTy = dyn_cast<TupleType>(type); if (!tupleTy) { unsigned to = getRValueSize(type); assert(to == values.size()); // We use push_back instead of emplace_back since emplace_back can not // invoke the private constructor we are attempting to invoke. elements.push_back({nullptr, llvm::makeArrayRef(values).slice(0, to), type}); makeUsed(); return; } unsigned from = 0; for (auto eltType : tupleTy.getElementTypes()) { unsigned to = from + getRValueSize(eltType); // We use push_back instead of emplace_back since emplace_back can not // invoke the private constructor we are attempting to invoke. elements.push_back({nullptr, llvm::makeArrayRef(values).slice(from, to - from), eltType}); from = to; } assert(from == values.size()); makeUsed(); }
/// Return the range of indexes for the given tuple type element. static std::pair<unsigned,unsigned> getElementRange(CanTupleType tupleType, unsigned eltIndex) { assert(eltIndex < tupleType->getNumElements()); unsigned begin = 0; for (unsigned i = 0; i < eltIndex; ++i) { begin += getRValueSize(tupleType.getElementType(i)); } unsigned end = begin + getRValueSize(tupleType.getElementType(eltIndex)); return { begin, end }; }
clang::CanQualType GenClangType::visitTupleType(CanTupleType type) { unsigned e = type->getNumElements(); if (e == 0) return getClangASTContext().VoidTy; CanType eltTy = type.getElementType(0); for (unsigned i = 1; i < e; i++) { assert(eltTy == type.getElementType(i) && "Only tuples where all element types are equal " "map to fixed-size arrays"); } auto clangEltTy = Converter.convert(IGM, eltTy); if (!clangEltTy) return clang::CanQualType(); APInt size(32, e); auto &ctx = getClangASTContext(); return ctx.getCanonicalType( ctx.getConstantArrayType(clangEltTy, size, clang::ArrayType::Normal, 0)); llvm_unreachable("Unexpected tuple type in Clang type generation!"); }
void RValue::extractElements(SmallVectorImpl<RValue> &elements) && { assert(isComplete() && "rvalue is not complete"); CanTupleType tupleTy = dyn_cast<TupleType>(type); if (!tupleTy) { unsigned to = getRValueSize(type); assert(to == values.size()); elements.push_back({llvm::makeArrayRef(values).slice(0, to), type}); makeUsed(); return; } unsigned from = 0; for (auto eltType : tupleTy.getElementTypes()) { unsigned to = from + getRValueSize(eltType); elements.push_back({llvm::makeArrayRef(values).slice(from, to - from), eltType}); from = to; } assert(from == values.size()); makeUsed(); }