mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
More canonical type preserving.
Swift SVN r6377
This commit is contained in:
@@ -619,6 +619,83 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// An adapter for iterating over a range of the elements of a tuple
|
||||
/// type and returning their types.
|
||||
class TupleEltTypeArrayRef {
|
||||
ArrayRef<TupleTypeElt> Array;
|
||||
public:
|
||||
TupleEltTypeArrayRef(ArrayRef<TupleTypeElt> array) : Array(array) {}
|
||||
|
||||
class iterator {
|
||||
friend class TupleEltTypeArrayRef;
|
||||
const TupleTypeElt *Ptr;
|
||||
iterator(const TupleTypeElt *ptr) : Ptr(ptr) {}
|
||||
public:
|
||||
Type operator*() const { return Ptr->getType(); }
|
||||
iterator &operator++() { Ptr++; return *this; }
|
||||
iterator operator++(int) { return iterator(Ptr++); }
|
||||
bool operator==(iterator rhs) { return Ptr == rhs.Ptr; }
|
||||
bool operator!=(iterator rhs) { return Ptr != rhs.Ptr; }
|
||||
};
|
||||
iterator begin() const { return iterator(Array.begin()); }
|
||||
iterator end() const { return iterator(Array.end()); }
|
||||
|
||||
bool empty() const { return Array.empty(); }
|
||||
size_t size() const { return Array.size(); }
|
||||
Type operator[](unsigned i) const { return Array[i].getType(); }
|
||||
Type front() const { return Array.front().getType(); }
|
||||
Type back() const { return Array.back().getType(); }
|
||||
|
||||
TupleEltTypeArrayRef slice(unsigned start) const {
|
||||
return TupleEltTypeArrayRef(Array.slice(start));
|
||||
}
|
||||
TupleEltTypeArrayRef slice(unsigned start, unsigned length) const {
|
||||
return TupleEltTypeArrayRef(Array.slice(start, length));
|
||||
}
|
||||
};
|
||||
|
||||
/// An adapter for iterating over a range of the elements of a
|
||||
/// canonical tuple type and returning their types.
|
||||
///
|
||||
/// This class just assumes that it's given the elements of a
|
||||
/// canonical type.
|
||||
class CanTupleEltTypeArrayRef {
|
||||
ArrayRef<TupleTypeElt> Array;
|
||||
public:
|
||||
CanTupleEltTypeArrayRef(ArrayRef<TupleTypeElt> array) : Array(array) {}
|
||||
|
||||
class iterator {
|
||||
friend class CanTupleEltTypeArrayRef;
|
||||
const TupleTypeElt *Ptr;
|
||||
iterator(const TupleTypeElt *ptr) : Ptr(ptr) {}
|
||||
public:
|
||||
CanType operator*() const { return CanType(Ptr->getType()); }
|
||||
iterator &operator++() { Ptr++; return *this; }
|
||||
iterator operator++(int) { return iterator(Ptr++); }
|
||||
bool operator==(iterator rhs) { return Ptr == rhs.Ptr; }
|
||||
bool operator!=(iterator rhs) { return Ptr != rhs.Ptr; }
|
||||
};
|
||||
iterator begin() const { return iterator(Array.begin()); }
|
||||
iterator end() const { return iterator(Array.end()); }
|
||||
|
||||
bool empty() const { return Array.empty(); }
|
||||
size_t size() const { return Array.size(); }
|
||||
CanType operator[](unsigned i) const { return CanType(Array[i].getType()); }
|
||||
CanType front() const { return CanType(Array.front().getType()); }
|
||||
CanType back() const { return CanType(Array.back().getType()); }
|
||||
|
||||
CanTupleEltTypeArrayRef slice(unsigned start) const {
|
||||
return CanTupleEltTypeArrayRef(Array.slice(start));
|
||||
}
|
||||
CanTupleEltTypeArrayRef slice(unsigned start, unsigned length) const {
|
||||
return CanTupleEltTypeArrayRef(Array.slice(start, length));
|
||||
}
|
||||
|
||||
operator TupleEltTypeArrayRef() const {
|
||||
return TupleEltTypeArrayRef(Array);
|
||||
}
|
||||
};
|
||||
|
||||
/// TupleType - A tuple is a parenthesized list of types where each name has an
|
||||
/// optional name.
|
||||
///
|
||||
@@ -638,11 +715,17 @@ public:
|
||||
/// getFields - Return the fields of this tuple.
|
||||
ArrayRef<TupleTypeElt> getFields() const { return Fields; }
|
||||
|
||||
unsigned getNumElements() const { return Fields.size(); }
|
||||
|
||||
/// getElementType - Return the type of the specified field.
|
||||
Type getElementType(unsigned FieldNo) const {
|
||||
return Fields[FieldNo].getType();
|
||||
}
|
||||
|
||||
TupleEltTypeArrayRef getElementTypes() const {
|
||||
return TupleEltTypeArrayRef(getFields());
|
||||
};
|
||||
|
||||
/// getNamedElementId - If this tuple has a field with the specified name,
|
||||
/// return the field index, otherwise return -1.
|
||||
int getNamedElementId(Identifier I) const;
|
||||
@@ -677,6 +760,9 @@ BEGIN_CAN_TYPE_WRAPPER(TupleType, Type)
|
||||
CanType getElementType(unsigned fieldNo) {
|
||||
return CanType(getPointer()->getElementType(fieldNo));
|
||||
}
|
||||
CanTupleEltTypeArrayRef getElementTypes() const {
|
||||
return CanTupleEltTypeArrayRef(getPointer()->getFields());
|
||||
};
|
||||
END_CAN_TYPE_WRAPPER(TupleType, Type)
|
||||
|
||||
/// UnboundGenericType - Represents a generic nominal type where the
|
||||
|
||||
@@ -522,17 +522,14 @@ static bool isLocalLinkageGenericClause(const GenericParamList ¶ms) {
|
||||
}
|
||||
|
||||
static bool isLocalLinkageType(CanType type) {
|
||||
TypeBase *base = type.getPointer();
|
||||
|
||||
switch (base->getKind()) {
|
||||
switch (type->getKind()) {
|
||||
case TypeKind::Error:
|
||||
llvm_unreachable("error type in IRGen");
|
||||
case TypeKind::TypeVariable:
|
||||
llvm_unreachable("type variable in IRgen");
|
||||
|
||||
case TypeKind::MetaType:
|
||||
return isLocalLinkageType(CanType(cast<MetaTypeType>(base)
|
||||
->getInstanceType()));
|
||||
return isLocalLinkageType(cast<MetaTypeType>(type).getInstanceType());
|
||||
case TypeKind::Module:
|
||||
return false;
|
||||
|
||||
@@ -557,29 +554,28 @@ static bool isLocalLinkageType(CanType type) {
|
||||
#include "swift/AST/TypeNodes.def"
|
||||
|
||||
case TypeKind::LValue:
|
||||
return isLocalLinkageType(CanType(cast<LValueType>(base)
|
||||
->getObjectType()));
|
||||
return isLocalLinkageType(cast<LValueType>(type).getObjectType());
|
||||
|
||||
case TypeKind::Tuple: {
|
||||
TupleType *tuple = cast<TupleType>(base);
|
||||
for (auto &field : tuple->getFields()) {
|
||||
if (isLocalLinkageType(CanType(field.getType())))
|
||||
CanTupleType tuple = cast<TupleType>(type);
|
||||
for (auto fieldType : tuple.getElementTypes()) {
|
||||
if (isLocalLinkageType(fieldType))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
case TypeKind::UnboundGeneric:
|
||||
return isLocalLinkageDecl(cast<UnboundGenericType>(base)->getDecl());
|
||||
return isLocalLinkageDecl(cast<UnboundGenericType>(type)->getDecl());
|
||||
|
||||
case TypeKind::BoundGenericClass:
|
||||
case TypeKind::BoundGenericOneOf:
|
||||
case TypeKind::BoundGenericStruct: {
|
||||
BoundGenericType *BGT = cast<BoundGenericType>(base);
|
||||
CanBoundGenericType BGT = cast<BoundGenericType>(type);
|
||||
if (isLocalLinkageDecl(BGT->getDecl()))
|
||||
return true;
|
||||
for (Type Arg : BGT->getGenericArgs()) {
|
||||
if (isLocalLinkageType(CanType(Arg)))
|
||||
for (Type arg : BGT->getGenericArgs()) {
|
||||
if (isLocalLinkageType(CanType(arg)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -589,30 +585,30 @@ static bool isLocalLinkageType(CanType type) {
|
||||
case TypeKind::Struct:
|
||||
case TypeKind::Class:
|
||||
case TypeKind::Protocol:
|
||||
return isLocalLinkageDecl(cast<NominalType>(base)->getDecl());
|
||||
return isLocalLinkageDecl(cast<NominalType>(type)->getDecl());
|
||||
|
||||
case TypeKind::PolymorphicFunction: {
|
||||
auto fn = cast<PolymorphicFunctionType>(base);
|
||||
auto fn = cast<PolymorphicFunctionType>(type);
|
||||
if (isLocalLinkageGenericClause(fn->getGenericParams()))
|
||||
return true;
|
||||
SWIFT_FALLTHROUGH;
|
||||
}
|
||||
case TypeKind::Function: {
|
||||
AnyFunctionType *fn = cast<AnyFunctionType>(base);
|
||||
return isLocalLinkageType(CanType(fn->getInput())) ||
|
||||
isLocalLinkageType(CanType(fn->getResult()));
|
||||
CanAnyFunctionType fn = cast<AnyFunctionType>(type);
|
||||
return isLocalLinkageType(fn.getInput()) ||
|
||||
isLocalLinkageType(fn.getResult());
|
||||
}
|
||||
|
||||
case TypeKind::ReferenceStorage: {
|
||||
auto ref = cast<ReferenceStorageType>(base);
|
||||
return isLocalLinkageType(CanType(ref->getReferentType()));
|
||||
auto ref = cast<ReferenceStorageType>(type);
|
||||
return isLocalLinkageType(ref.getReferentType());
|
||||
}
|
||||
|
||||
case TypeKind::Array:
|
||||
return isLocalLinkageType(CanType(cast<ArrayType>(base)->getBaseType()));
|
||||
return isLocalLinkageType(cast<ArrayType>(type).getBaseType());
|
||||
|
||||
case TypeKind::ProtocolComposition:
|
||||
for (Type t : cast<ProtocolCompositionType>(base)->getProtocols())
|
||||
for (Type t : cast<ProtocolCompositionType>(type)->getProtocols())
|
||||
if (isLocalLinkageType(CanType(t)))
|
||||
return true;
|
||||
return false;
|
||||
|
||||
@@ -546,9 +546,9 @@ static CanType decomposeFunctionType(IRGenModule &IGM, CanType type,
|
||||
|
||||
// Explode the argument.
|
||||
auto decomposeTopLevelArg = [&](CanType inputTy) {
|
||||
if (TupleType *tupleTy = inputTy->getAs<TupleType>()) {
|
||||
for (auto &field : tupleTy->getFields()) {
|
||||
decomposeFunctionArg(IGM, CanType(field.getType()), cc, explosionKind,
|
||||
if (auto tupleTy = dyn_cast<TupleType>(inputTy)) {
|
||||
for (auto fieldType : tupleTy.getElementTypes()) {
|
||||
decomposeFunctionArg(IGM, fieldType, cc, explosionKind,
|
||||
argTypes, byvals, attrs);
|
||||
}
|
||||
} else {
|
||||
@@ -557,7 +557,7 @@ static CanType decomposeFunctionType(IRGenModule &IGM, CanType type,
|
||||
}
|
||||
};
|
||||
|
||||
CanType inputTy = CanType(fn->getInput());
|
||||
CanType inputTy = fn.getInput();
|
||||
switch (cc) {
|
||||
case AbstractCC::Freestanding:
|
||||
case AbstractCC::Method:
|
||||
@@ -567,11 +567,11 @@ static CanType decomposeFunctionType(IRGenModule &IGM, CanType type,
|
||||
|
||||
case AbstractCC::ObjCMethod: {
|
||||
// ObjC methods take an implicit _cmd argument after the self argument.
|
||||
TupleType *inputTuple = cast<TupleType>(inputTy);
|
||||
assert(inputTuple->getFields().size() == 2 && "invalid objc method type");
|
||||
decomposeTopLevelArg(CanType(inputTuple->getFields()[0].getType()));
|
||||
CanTupleType inputTuple = cast<TupleType>(inputTy);
|
||||
assert(inputTuple->getNumElements() == 2 && "invalid objc method type");
|
||||
decomposeTopLevelArg(inputTuple.getElementType(0));
|
||||
argTypes.push_back(IGM.Int8PtrTy);
|
||||
decomposeTopLevelArg(CanType(inputTuple->getFields()[1].getType()));
|
||||
decomposeTopLevelArg(inputTuple.getElementType(1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1408,10 +1408,9 @@ void CallEmission::externalizeArgument(Explosion &out, Explosion &in,
|
||||
void CallEmission::externalizeArguments(Explosion &out, Explosion &arg,
|
||||
SmallVectorImpl<std::pair<unsigned, Alignment>> &newByvals,
|
||||
CanType inputsTy) {
|
||||
if (TupleType *tupleTy = inputsTy->getAs<TupleType>()) {
|
||||
for (auto &elt : tupleTy->getFields()) {
|
||||
externalizeArgument(out, arg, newByvals,
|
||||
elt.getType()->getCanonicalType());
|
||||
if (CanTupleType tupleType = dyn_cast<TupleType>(inputsTy)) {
|
||||
for (auto eltType : tupleType.getElementTypes()) {
|
||||
externalizeArgument(out, arg, newByvals, eltType);
|
||||
}
|
||||
} else {
|
||||
externalizeArgument(out, arg, newByvals, inputsTy);
|
||||
@@ -1443,11 +1442,11 @@ void CallEmission::addArg(Explosion &arg) {
|
||||
// _cmd
|
||||
externalized.add(arg.claimNext());
|
||||
// method args
|
||||
TupleType *inputTuple = CurOrigType->castTo<AnyFunctionType>()->getInput()
|
||||
->castTo<TupleType>();
|
||||
assert(inputTuple->getFields().size() == 2 && "invalid objc method type");
|
||||
CanTupleType inputTuple =
|
||||
cast<TupleType>(cast<AnyFunctionType>(CurOrigType).getInput());
|
||||
assert(inputTuple->getNumElements() == 2 && "invalid objc method type");
|
||||
externalizeArguments(externalized, arg, newByvals,
|
||||
CanType(inputTuple->getFields()[1].getType()));
|
||||
inputTuple.getElementType(1));
|
||||
arg = std::move(externalized);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -237,7 +237,7 @@ bool irgen::hasKnownVTableEntry(IRGenModule &IGM, FuncDecl *theMethod) {
|
||||
|
||||
/// Emit a string encoding the labels in the given tuple type.
|
||||
static llvm::Constant *getTupleLabelsString(IRGenModule &IGM,
|
||||
TupleType *type) {
|
||||
CanTupleType type) {
|
||||
bool hasLabels = false;
|
||||
llvm::SmallString<128> buffer;
|
||||
for (auto &elt : type->getFields()) {
|
||||
@@ -329,9 +329,7 @@ namespace {
|
||||
// Er, varargs bit? Should that go in?
|
||||
|
||||
|
||||
auto elements = type->getFields();
|
||||
|
||||
switch (elements.size()) {
|
||||
switch (type->getNumElements()) {
|
||||
case 0: {// Special case the empty tuple, just use the global descriptor.
|
||||
llvm::Constant *fullMetadata = IGF.IGM.getEmptyTupleMetadata();
|
||||
llvm::Constant *indices[] = {
|
||||
@@ -389,13 +387,14 @@ namespace {
|
||||
|
||||
llvm::Value *pointerToFirst = nullptr; // appease -Wuninitialized
|
||||
|
||||
auto elements = type.getElementTypes();
|
||||
auto arrayTy = llvm::ArrayType::get(IGF.IGM.TypeMetadataPtrTy,
|
||||
elements.size());
|
||||
Address buffer = IGF.createAlloca(arrayTy,IGF.IGM.getPointerAlignment(),
|
||||
"tuple-elements");
|
||||
for (unsigned i = 0, e = elements.size(); i != e; ++i) {
|
||||
// Find the metadata pointer for this element.
|
||||
llvm::Value *eltMetadata = visit(type.getElementType(i));
|
||||
llvm::Value *eltMetadata = visit(elements[i]);
|
||||
|
||||
// GEP to the appropriate element and store.
|
||||
Address eltPtr = IGF.Builder.CreateStructGEP(buffer, i,
|
||||
@@ -418,7 +417,7 @@ namespace {
|
||||
call->setDoesNotThrow();
|
||||
call->setCallingConv(IGF.IGM.RuntimeCC);
|
||||
|
||||
return setLocal(CanType(type), call);
|
||||
return setLocal(type, call);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1038,8 +1037,8 @@ namespace {
|
||||
|
||||
bool visitTupleType(CanTupleType overridden, CanType overrideTy) {
|
||||
CanTupleType override = cast<TupleType>(overrideTy);
|
||||
assert(overridden->getFields().size() == override->getFields().size());
|
||||
for (unsigned i = 0, e = overridden->getFields().size(); i != e; ++i) {
|
||||
assert(overridden->getNumElements() == override->getNumElements());
|
||||
for (unsigned i = 0, e = overridden->getNumElements(); i != e; ++i) {
|
||||
if (visit(overridden.getElementType(i), override.getElementType(i)))
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -555,8 +555,8 @@ static bool isObjCSetterSignature(IRGenModule &IGM,
|
||||
if (hasObjCClassRepresentation(IGM, methodType->getInput()))
|
||||
return true;
|
||||
if (TupleType *inputTuple = methodType->getInput()->getAs<TupleType>()) {
|
||||
return inputTuple->getFields().size() == 1
|
||||
&& hasObjCClassRepresentation(IGM, inputTuple->getFields()[0].getType());
|
||||
return inputTuple->getNumElements() == 1
|
||||
&& hasObjCClassRepresentation(IGM, inputTuple->getElementType(0));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -259,8 +259,8 @@ namespace {
|
||||
|
||||
bool isObviouslyEmptyType(CanType type) {
|
||||
if (auto tuple = dyn_cast<TupleType>(type)) {
|
||||
for (auto &field : tuple->getFields())
|
||||
if (!isObviouslyEmptyType(CanType(field.getType())))
|
||||
for (auto eltType : tuple.getElementTypes())
|
||||
if (!isObviouslyEmptyType(eltType))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -209,24 +209,24 @@ namespace {
|
||||
|
||||
// We assume that all reference storage types have equivalent
|
||||
// representation. This may not be true.
|
||||
bool visitReferenceStorageType(ReferenceStorageType *origTy,
|
||||
ReferenceStorageType *substTy) {
|
||||
bool visitReferenceStorageType(CanReferenceStorageType origTy,
|
||||
CanReferenceStorageType substTy) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CanType getArchetypeReprType(ArchetypeType *a) {
|
||||
CanType getArchetypeReprType(CanArchetypeType a) {
|
||||
if (Type super = a->getSuperclass())
|
||||
return super->getCanonicalType();
|
||||
return CanType(super);
|
||||
return CanType(IGM.Context.TheObjCPointerType);
|
||||
}
|
||||
|
||||
bool visitArchetypeType(ArchetypeType *origTy, CanType substTy) {
|
||||
bool visitArchetypeType(CanArchetypeType origTy, CanType substTy) {
|
||||
// Archetypes vary by what we're considering this for.
|
||||
|
||||
if (origTy->requiresClass()) {
|
||||
// Class archetypes are represented as some refcounted
|
||||
// pointer type that needs to be bitcast.
|
||||
return CanType(origTy) != substTy;
|
||||
return origTy != substTy;
|
||||
}
|
||||
|
||||
// Archetypes are laid out in memory in the same way as a
|
||||
@@ -239,13 +239,12 @@ namespace {
|
||||
return !IGM.isSingleIndirectValue(substTy, ExplosionLevel);
|
||||
}
|
||||
|
||||
bool visitArrayType(ArrayType *origTy, ArrayType *substTy) {
|
||||
return visit(CanType(origTy->getBaseType()),
|
||||
CanType(substTy->getBaseType()));
|
||||
bool visitArrayType(CanArrayType origTy, CanArrayType substTy) {
|
||||
return visit(origTy.getBaseType(), substTy.getBaseType());
|
||||
}
|
||||
|
||||
bool visitBoundGenericType(BoundGenericType *origTy,
|
||||
BoundGenericType *substTy) {
|
||||
bool visitBoundGenericType(CanBoundGenericType origTy,
|
||||
CanBoundGenericType substTy) {
|
||||
assert(origTy->getDecl() == substTy->getDecl());
|
||||
|
||||
// Bound generic types with reference semantics will never
|
||||
@@ -258,8 +257,8 @@ namespace {
|
||||
|
||||
/// Functions use a more complicated algorithm which calls back
|
||||
/// into this.
|
||||
bool visitAnyFunctionType(AnyFunctionType *origTy,
|
||||
AnyFunctionType *substTy) {
|
||||
bool visitAnyFunctionType(CanAnyFunctionType origTy,
|
||||
CanAnyFunctionType substTy) {
|
||||
return differsByAbstractionAsFunction(IGM, origTy, substTy,
|
||||
ExplosionKind::Minimal,
|
||||
/*uncurry*/ 0);
|
||||
@@ -267,17 +266,17 @@ namespace {
|
||||
|
||||
// L-values go by the object type; note that we ask the ordinary
|
||||
// question, not the argument question.
|
||||
bool visitLValueType(LValueType *origTy, LValueType *substTy) {
|
||||
bool visitLValueType(CanLValueType origTy, CanLValueType substTy) {
|
||||
return differsByAbstractionInMemory(IGM,
|
||||
CanType(origTy->getObjectType()),
|
||||
CanType(substTy->getObjectType()));
|
||||
origTy.getObjectType(),
|
||||
substTy.getObjectType());
|
||||
}
|
||||
|
||||
bool visitMetaTypeType(MetaTypeType *origTy, MetaTypeType *substTy) {
|
||||
bool visitMetaTypeType(CanMetaTypeType origTy, CanMetaTypeType substTy) {
|
||||
// Metatypes can differ by abstraction if the substitution
|
||||
// reveals that the type is actually not a class type.
|
||||
return (IGM.hasTrivialMetatype(CanType(substTy->getInstanceType())) &&
|
||||
!IGM.hasTrivialMetatype(CanType(origTy->getInstanceType())));
|
||||
return (IGM.hasTrivialMetatype(substTy.getInstanceType()) &&
|
||||
!IGM.hasTrivialMetatype(origTy.getInstanceType()));
|
||||
}
|
||||
|
||||
/// Whether we're checking for memory or for an explosion, tuples
|
||||
@@ -286,11 +285,10 @@ namespace {
|
||||
/// TODO: unless the original tuple contains a variadic explosion,
|
||||
/// in which case that portion of the tuple is passed indirectly
|
||||
/// in an explosion!
|
||||
bool visitTupleType(TupleType *origTy, TupleType *substTy) {
|
||||
assert(origTy->getFields().size() == substTy->getFields().size());
|
||||
for (unsigned i = 0, e = origTy->getFields().size(); i != e; ++i)
|
||||
if (visit(CanType(origTy->getElementType(i)),
|
||||
CanType(substTy->getElementType(i))))
|
||||
bool visitTupleType(CanTupleType origTy, CanTupleType substTy) {
|
||||
assert(origTy->getNumElements() == substTy->getNumElements());
|
||||
for (unsigned i = 0, e = origTy->getNumElements(); i != e; ++i)
|
||||
if (visit(origTy.getElementType(i), substTy.getElementType(i)))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -322,8 +320,8 @@ struct EmbedsArchetype : irgen::DeclVisitor<EmbedsArchetype, bool>,
|
||||
using CanTypeVisitor<EmbedsArchetype, bool>::visit;
|
||||
|
||||
bool visitTupleType(CanTupleType type) {
|
||||
for (auto &field : type->getFields())
|
||||
if (visit(CanType(field.getType())))
|
||||
for (auto eltType : type.getElementTypes())
|
||||
if (visit(eltType))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -615,8 +613,8 @@ namespace {
|
||||
}
|
||||
|
||||
void visitTupleType(CanTupleType origTy, CanTupleType substTy) {
|
||||
assert(origTy->getFields().size() == substTy->getFields().size());
|
||||
for (unsigned i = 0, e = origTy->getFields().size(); i != e; ++i) {
|
||||
assert(origTy->getNumElements() == substTy->getNumElements());
|
||||
for (unsigned i = 0, e = origTy->getNumElements(); i != e; ++i) {
|
||||
visit(origTy.getElementType(i), substTy.getElementType(i));
|
||||
}
|
||||
}
|
||||
@@ -763,8 +761,8 @@ namespace {
|
||||
}
|
||||
|
||||
void visitTupleType(CanTupleType origTy, CanTupleType substTy) {
|
||||
assert(origTy->getFields().size() == substTy->getFields().size());
|
||||
for (unsigned i = 0, e = origTy->getFields().size(); i != e; ++i) {
|
||||
assert(origTy->getNumElements() == substTy->getNumElements());
|
||||
for (unsigned i = 0, e = origTy->getNumElements(); i != e; ++i) {
|
||||
visit(origTy.getElementType(i), substTy.getElementType(i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2212,8 +2212,8 @@ static llvm::Constant *getValueWitness(IRGenModule &IGM,
|
||||
/// FIXME: We could get fulfillments from any tuple element.
|
||||
static CanType stripLabel(CanType input) {
|
||||
if (auto tuple = dyn_cast<TupleType>(input))
|
||||
if (tuple->getFields().size() > 0)
|
||||
return stripLabel(CanType(tuple->getFields().back().getType()));
|
||||
if (tuple->getNumElements() > 0)
|
||||
return stripLabel(tuple.getElementTypes().back());
|
||||
return input;
|
||||
}
|
||||
|
||||
@@ -3315,8 +3315,9 @@ namespace {
|
||||
|
||||
// We need to walk into tuples.
|
||||
void visitTupleType(CanTupleType tuple) {
|
||||
for (auto &elt : tuple->getFields())
|
||||
visit(CanType(elt.getType()));
|
||||
for (auto eltType : tuple.getElementTypes()) {
|
||||
visit(eltType);
|
||||
}
|
||||
}
|
||||
|
||||
// We need to walk into constant-sized arrays.
|
||||
|
||||
@@ -595,9 +595,9 @@ void IRGenModule::getSchema(CanType type, ExplosionSchema &schema) {
|
||||
// As an optimization, avoid actually building a TypeInfo for any
|
||||
// obvious TupleTypes. This assumes that a TupleType's explosion
|
||||
// schema is always the concatenation of its component's schemas.
|
||||
if (TupleType *tuple = dyn_cast<TupleType>(type)) {
|
||||
for (const TupleTypeElt &field : tuple->getFields())
|
||||
getSchema(CanType(field.getType()), schema);
|
||||
if (CanTupleType tuple = dyn_cast<TupleType>(type)) {
|
||||
for (auto eltType : tuple.getElementTypes())
|
||||
getSchema(eltType, schema);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -610,10 +610,10 @@ unsigned IRGenModule::getExplosionSize(CanType type, ExplosionKind kind) {
|
||||
// As an optimization, avoid actually building a TypeInfo for any
|
||||
// obvious TupleTypes. This assumes that a TupleType's explosion
|
||||
// schema is always the concatenation of its component's schemas.
|
||||
if (TupleType *tuple = dyn_cast<TupleType>(type)) {
|
||||
if (auto tuple = dyn_cast<TupleType>(type)) {
|
||||
unsigned count = 0;
|
||||
for (const TupleTypeElt &field : tuple->getFields())
|
||||
count += getExplosionSize(CanType(field.getType()), kind);
|
||||
for (auto eltType : tuple.getElementTypes())
|
||||
count += getExplosionSize(eltType, kind);
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -653,8 +653,8 @@ bool IRGenModule::isPOD(CanType type, ResilienceScope scope) {
|
||||
if (isa<ClassType>(type)) return false;
|
||||
if (isa<BoundGenericClassType>(type)) return false;
|
||||
if (auto tuple = dyn_cast<TupleType>(type)) {
|
||||
for (auto &elt : tuple->getFields())
|
||||
if (!isPOD(CanType(elt.getType()), scope))
|
||||
for (auto eltType : tuple.getElementTypes())
|
||||
if (!isPOD(eltType, scope))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@@ -689,8 +689,8 @@ namespace {
|
||||
|
||||
ObjectSize visitTupleType(CanTupleType tuple) {
|
||||
ObjectSize result = ObjectSize::Fixed;
|
||||
for (auto &field : tuple->getFields()) {
|
||||
result = std::max(result, visit(CanType(field.getType())));
|
||||
for (auto eltType : tuple.getElementTypes()) {
|
||||
result = std::max(result, visit(eltType));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace {
|
||||
|
||||
static unsigned getTupleSize(CanType t) {
|
||||
if (TupleType *tt = dyn_cast<TupleType>(t))
|
||||
return tt->getFields().size();
|
||||
return tt->getNumElements();
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
SILValue v = mv.forward(gen);
|
||||
if (v.getType().isAddressOnly(gen.F.getModule())) {
|
||||
// Destructure address-only types by addressing the individual members.
|
||||
for (unsigned i = 0, size = t->getFields().size(); i < size; ++i) {
|
||||
for (unsigned i = 0, size = t->getNumElements(); i < size; ++i) {
|
||||
CanType fieldCanTy = t.getElementType(i);
|
||||
SILType fieldTy = gen.getLoweredType(fieldCanTy);
|
||||
SILValue member = gen.B.createTupleElementAddr(SILLocation(),
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
}
|
||||
} else {
|
||||
// Extract the elements from loadable tuples.
|
||||
for (unsigned i = 0, size = t->getFields().size(); i < size; ++i) {
|
||||
for (unsigned i = 0, size = t->getNumElements(); i < size; ++i) {
|
||||
CanType fieldCanTy = t.getElementType(i);
|
||||
SILType fieldTy = gen.getLoweredLoadableType(fieldCanTy);
|
||||
SILValue member = gen.B.createTupleExtract(SILLocation(),
|
||||
@@ -128,8 +128,8 @@ public:
|
||||
|
||||
SILValue visitTupleType(CanTupleType t) {
|
||||
SmallVector<SILValue, 4> elts;
|
||||
for (auto &field : t->getFields())
|
||||
elts.push_back(this->visit(CanType(field.getType())));
|
||||
for (auto fieldTy : t.getElementTypes())
|
||||
elts.push_back(this->visit(fieldTy));
|
||||
SILType ty = gen.getLoweredLoadableType(t);
|
||||
return gen.B.createTuple(SILLocation(), ty, elts);
|
||||
}
|
||||
@@ -160,7 +160,7 @@ public:
|
||||
}
|
||||
|
||||
void visitTupleType(CanTupleType t, SILValue address) {
|
||||
for (unsigned n = 0, size = t->getFields().size(); n < size; ++n) {
|
||||
for (unsigned n = 0, size = t->getNumElements(); n < size; ++n) {
|
||||
CanType fieldCanTy = t.getElementType(n);
|
||||
SILType fieldTy = gen.getLoweredType(fieldCanTy);
|
||||
SILValue fieldAddr = gen.B.createTupleElementAddr(SILLocation(),
|
||||
@@ -212,8 +212,8 @@ public:
|
||||
}
|
||||
|
||||
void visitTupleType(CanTupleType t) {
|
||||
for (auto &field : t->getFields())
|
||||
visit(CanType(field.getType()));
|
||||
for (auto fieldType : t.getElementTypes())
|
||||
visit(fieldType);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -230,8 +230,8 @@ static void computeElementOffsets(std::vector<unsigned> &offsets,
|
||||
|
||||
// Visit each field and record its ending value offset.
|
||||
ComputeElementOffsets visitor;
|
||||
for (auto &field : tuple->getFields()) {
|
||||
visitor.visit(CanType(field.getType()));
|
||||
for (auto fieldType : tuple.getElementTypes()) {
|
||||
visitor.visit(fieldType);
|
||||
offsets.push_back(visitor.offset);
|
||||
}
|
||||
}
|
||||
@@ -285,7 +285,7 @@ public:
|
||||
SmallVector<InitializationPtr, 4> subInitBuf;
|
||||
auto subInits = I->getSubInitializations(gen, subInitBuf);
|
||||
|
||||
assert(subInits.size() == t->getFields().size() &&
|
||||
assert(subInits.size() == t->getNumElements() &&
|
||||
"initialization does not match tuple?!");
|
||||
|
||||
for (unsigned i = 0, e = subInits.size(); i < e; ++i)
|
||||
@@ -316,8 +316,8 @@ public:
|
||||
RValue visitTupleType(CanTupleType t) {
|
||||
RValue rv{t};
|
||||
|
||||
for (auto &field : t->getFields())
|
||||
rv.addElement(visit(CanType(field.getType())));
|
||||
for (auto fieldType : t.getElementTypes())
|
||||
rv.addElement(visit(fieldType));
|
||||
|
||||
return rv;
|
||||
}
|
||||
@@ -431,7 +431,7 @@ RValue RValue::extractElement(unsigned n) && {
|
||||
assert(isComplete() && "rvalue is not complete");
|
||||
|
||||
unsigned from = elementOffsets[n], to = elementOffsets[n+1];
|
||||
CanType eltTy(cast<TupleType>(type)->getFields()[n].getType());
|
||||
CanType eltTy = cast<TupleType>(type).getElementType(n);
|
||||
|
||||
RValue element(llvm::makeArrayRef(values).slice(from, to - from), eltTy);
|
||||
makeUsed();
|
||||
@@ -441,12 +441,12 @@ RValue RValue::extractElement(unsigned n) && {
|
||||
void RValue::extractElements(SmallVectorImpl<RValue> &elements) && {
|
||||
assert(isComplete() && "rvalue is not complete");
|
||||
|
||||
auto fields = cast<TupleType>(type)->getFields();
|
||||
auto elementTypes = cast<TupleType>(type).getElementTypes();
|
||||
|
||||
for (unsigned n = 0, size = fields.size(); n < size; ++n) {
|
||||
for (unsigned n = 0, size = elementTypes.size(); n < size; ++n) {
|
||||
unsigned from = elementOffsets[n], to = elementOffsets[n+1];
|
||||
elements.push_back({llvm::makeArrayRef(values).slice(from, to - from),
|
||||
CanType(fields[n].getType())});
|
||||
elementTypes[n]});
|
||||
}
|
||||
makeUsed();
|
||||
}
|
||||
|
||||
@@ -73,18 +73,17 @@ ArrayRef<InitializationPtr> Initialization::getSubInitializations(
|
||||
return getSubInitializations();
|
||||
case Kind::Ignored: {
|
||||
// "Destructure" an ignored binding into multiple ignored bindings.
|
||||
for (auto &field : tupleTy->getFields()) {
|
||||
buf.push_back(InitializationPtr(
|
||||
new BlackHoleInitialization(field.getType())));
|
||||
for (auto fieldType : tupleTy->getElementTypes()) {
|
||||
buf.push_back(InitializationPtr(new BlackHoleInitialization(fieldType)));
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
case Kind::SingleBuffer: {
|
||||
// Destructure the buffer into per-element buffers.
|
||||
SILValue baseAddr = getAddress();
|
||||
for (unsigned i = 0, size = tupleTy->getFields().size(); i < size; ++i) {
|
||||
auto &field = tupleTy->getFields()[i];
|
||||
SILType fieldTy = gen.getLoweredType(field.getType()).getAddressType();
|
||||
for (unsigned i = 0, size = tupleTy->getNumElements(); i < size; ++i) {
|
||||
auto fieldType = tupleTy->getElementType(i);
|
||||
SILType fieldTy = gen.getLoweredType(fieldType).getAddressType();
|
||||
SILValue fieldAddr = gen.B.createTupleElementAddr(SILLocation(),
|
||||
baseAddr, i,
|
||||
fieldTy);
|
||||
|
||||
@@ -1356,9 +1356,8 @@ static RValue emitImplicitValueConstructorArg(SILGenFunction &gen,
|
||||
// Restructure tuple arguments.
|
||||
if (TupleType *tupleTy = argTy.getAs<TupleType>()) {
|
||||
RValue tuple(tupleTy->getCanonicalType());
|
||||
for (auto &field : tupleTy->getFields())
|
||||
tuple.addElement(
|
||||
emitImplicitValueConstructorArg(gen, loc, field.getType()));
|
||||
for (auto fieldType : tupleTy->getElementTypes())
|
||||
tuple.addElement(emitImplicitValueConstructorArg(gen, loc, fieldType));
|
||||
|
||||
return tuple;
|
||||
} else {
|
||||
@@ -1579,8 +1578,8 @@ namespace {
|
||||
assert(ty && "no type?!");
|
||||
// Destructure tuple arguments.
|
||||
if (TupleType *tupleTy = ty->getAs<TupleType>()) {
|
||||
for (auto &field : tupleTy->getFields())
|
||||
makeArgument(field.getType());
|
||||
for (auto fieldType : tupleTy->getElementTypes())
|
||||
makeArgument(fieldType);
|
||||
} else {
|
||||
SILValue arg = new (gen.F.getModule()) SILArgument(gen.getLoweredType(ty),
|
||||
gen.F.begin());
|
||||
|
||||
@@ -88,8 +88,7 @@ static SILBasicBlock *emitBranchAndDestructure(SILGenFunction &gen,
|
||||
auto tupleSILTy = gen.getLoweredType(tupleTy);
|
||||
if (tupleSILTy.isAddressOnly(gen.F.getModule())) {
|
||||
for (unsigned i = 0, e = tupleTy->getFields().size(); i < e; ++i) {
|
||||
auto &field = tupleTy->getFields()[i];
|
||||
SILType fieldTy = gen.getLoweredType(field.getType());
|
||||
SILType fieldTy = gen.getLoweredType(tupleTy->getElementType(i));
|
||||
SILValue member = gen.B.createTupleElementAddr(SILLocation(),
|
||||
v, i, fieldTy.getAddressType());
|
||||
if (!fieldTy.isAddressOnly(gen.F.getModule()))
|
||||
@@ -98,8 +97,8 @@ static SILBasicBlock *emitBranchAndDestructure(SILGenFunction &gen,
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0, e = tupleTy->getFields().size(); i < e; ++i) {
|
||||
auto &field = tupleTy->getFields()[i];
|
||||
SILType fieldTy = gen.getLoweredLoadableType(field.getType());
|
||||
auto fieldType = tupleTy->getElementType(i);
|
||||
SILType fieldTy = gen.getLoweredLoadableType(fieldType);
|
||||
SILValue member = gen.B.createTupleExtract(SILLocation(),
|
||||
v, i, fieldTy);
|
||||
destructured.push_back(member);
|
||||
|
||||
@@ -104,8 +104,8 @@ namespace {
|
||||
}
|
||||
|
||||
void visitTupleType(CanTupleType tt) {
|
||||
for (auto &field : tt->getFields()) {
|
||||
visit(CanType(field.getType()));
|
||||
for (auto eltType : tt.getElementTypes()) {
|
||||
visit(eltType);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -37,15 +37,15 @@ bool SILType::isAddressOnly(CanType Ty, SILModule &M) {
|
||||
// AddressOnly.
|
||||
|
||||
// Structs and tuples are address-only if any of their elements are.
|
||||
if (TupleType *TTy = Ty->getAs<TupleType>()) {
|
||||
if (CanTupleType TTy = dyn_cast<TupleType>(Ty)) {
|
||||
// Check to see if we've computed this property for this tuple yet.
|
||||
auto Entry = M.AddressOnlyTypeCache.find(TTy);
|
||||
// If we got a hit, then return the precomputed value.
|
||||
if (Entry != M.AddressOnlyTypeCache.end())
|
||||
return Entry->second;
|
||||
|
||||
for (const TupleTypeElt &elt : TTy->getFields())
|
||||
if (isAddressOnly(elt.getType()->getCanonicalType(), M))
|
||||
for (auto eltType : TTy.getElementTypes())
|
||||
if (isAddressOnly(eltType, M))
|
||||
return M.AddressOnlyTypeCache[TTy] = true;
|
||||
|
||||
return M.AddressOnlyTypeCache[TTy] = false;
|
||||
|
||||
@@ -82,14 +82,13 @@ static CanType getBridgedInputType(TypeConverter &tc,
|
||||
if (auto tuple = dyn_cast<TupleType>(input)) {
|
||||
SmallVector<TupleTypeElt, 4> bridgedFields;
|
||||
bool changed = false;
|
||||
for (TupleTypeElt const &field : tuple->getFields()) {
|
||||
CanType bridged =
|
||||
tc.getLoweredBridgedType(field.getType(), cc)->getCanonicalType();
|
||||
if (bridged != CanType(field.getType())) {
|
||||
for (auto &elt : tuple->getFields()) {
|
||||
CanType bridged = CanType(tc.getLoweredBridgedType(elt.getType(), cc));
|
||||
if (bridged != CanType(elt.getType())) {
|
||||
changed = true;
|
||||
bridgedFields.push_back(field.getWithType(bridged));
|
||||
bridgedFields.push_back(elt.getWithType(bridged));
|
||||
} else {
|
||||
bridgedFields.push_back(field);
|
||||
bridgedFields.push_back(elt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,10 +359,9 @@ public:
|
||||
void visitTupleType(CanTupleType t) {
|
||||
pushPath();
|
||||
unsigned i = 0;
|
||||
for (TupleTypeElt const &elt : t->getFields()) {
|
||||
CanType ct = elt.getType()->getCanonicalType();
|
||||
setPath(ReferenceTypePath::Component::forTupleElement(ct, i++));
|
||||
visit(ct);
|
||||
for (auto eltType : t.getElementTypes()) {
|
||||
setPath(ReferenceTypePath::Component::forTupleElement(eltType, i++));
|
||||
visit(eltType);
|
||||
}
|
||||
popPath();
|
||||
}
|
||||
|
||||
@@ -339,7 +339,7 @@ public:
|
||||
|
||||
for (size_t i = 0, size = TI->getElements().size(); i < size; ++i) {
|
||||
require(TI->getElements()[i].getType().getSwiftType()
|
||||
->isEqual(ResTy->getFields()[i].getType()),
|
||||
->isEqual(ResTy->getElementType(i)),
|
||||
"Tuple element arguments do not match tuple type!");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user