More canonical type preserving.

Swift SVN r6377
This commit is contained in:
John McCall
2013-07-19 07:08:38 +00:00
parent 4b4e7d0833
commit 69b64a09ce
17 changed files with 218 additions and 144 deletions

View File

@@ -618,6 +618,83 @@ public:
return getDefaultArgKind() != DefaultArgumentKind::None; return getDefaultArgKind() != DefaultArgumentKind::None;
} }
}; };
/// 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 /// TupleType - A tuple is a parenthesized list of types where each name has an
/// optional name. /// optional name.
@@ -637,11 +714,17 @@ public:
/// getFields - Return the fields of this tuple. /// getFields - Return the fields of this tuple.
ArrayRef<TupleTypeElt> getFields() const { return Fields; } ArrayRef<TupleTypeElt> getFields() const { return Fields; }
unsigned getNumElements() const { return Fields.size(); }
/// getElementType - Return the type of the specified field. /// getElementType - Return the type of the specified field.
Type getElementType(unsigned FieldNo) const { Type getElementType(unsigned FieldNo) const {
return Fields[FieldNo].getType(); return Fields[FieldNo].getType();
} }
TupleEltTypeArrayRef getElementTypes() const {
return TupleEltTypeArrayRef(getFields());
};
/// getNamedElementId - If this tuple has a field with the specified name, /// getNamedElementId - If this tuple has a field with the specified name,
/// return the field index, otherwise return -1. /// return the field index, otherwise return -1.
@@ -677,6 +760,9 @@ BEGIN_CAN_TYPE_WRAPPER(TupleType, Type)
CanType getElementType(unsigned fieldNo) { CanType getElementType(unsigned fieldNo) {
return CanType(getPointer()->getElementType(fieldNo)); return CanType(getPointer()->getElementType(fieldNo));
} }
CanTupleEltTypeArrayRef getElementTypes() const {
return CanTupleEltTypeArrayRef(getPointer()->getFields());
};
END_CAN_TYPE_WRAPPER(TupleType, Type) END_CAN_TYPE_WRAPPER(TupleType, Type)
/// UnboundGenericType - Represents a generic nominal type where the /// UnboundGenericType - Represents a generic nominal type where the

View File

@@ -522,17 +522,14 @@ static bool isLocalLinkageGenericClause(const GenericParamList &params) {
} }
static bool isLocalLinkageType(CanType type) { static bool isLocalLinkageType(CanType type) {
TypeBase *base = type.getPointer(); switch (type->getKind()) {
switch (base->getKind()) {
case TypeKind::Error: case TypeKind::Error:
llvm_unreachable("error type in IRGen"); llvm_unreachable("error type in IRGen");
case TypeKind::TypeVariable: case TypeKind::TypeVariable:
llvm_unreachable("type variable in IRgen"); llvm_unreachable("type variable in IRgen");
case TypeKind::MetaType: case TypeKind::MetaType:
return isLocalLinkageType(CanType(cast<MetaTypeType>(base) return isLocalLinkageType(cast<MetaTypeType>(type).getInstanceType());
->getInstanceType()));
case TypeKind::Module: case TypeKind::Module:
return false; return false;
@@ -557,29 +554,28 @@ static bool isLocalLinkageType(CanType type) {
#include "swift/AST/TypeNodes.def" #include "swift/AST/TypeNodes.def"
case TypeKind::LValue: case TypeKind::LValue:
return isLocalLinkageType(CanType(cast<LValueType>(base) return isLocalLinkageType(cast<LValueType>(type).getObjectType());
->getObjectType()));
case TypeKind::Tuple: { case TypeKind::Tuple: {
TupleType *tuple = cast<TupleType>(base); CanTupleType tuple = cast<TupleType>(type);
for (auto &field : tuple->getFields()) { for (auto fieldType : tuple.getElementTypes()) {
if (isLocalLinkageType(CanType(field.getType()))) if (isLocalLinkageType(fieldType))
return true; return true;
} }
return false; return false;
} }
case TypeKind::UnboundGeneric: case TypeKind::UnboundGeneric:
return isLocalLinkageDecl(cast<UnboundGenericType>(base)->getDecl()); return isLocalLinkageDecl(cast<UnboundGenericType>(type)->getDecl());
case TypeKind::BoundGenericClass: case TypeKind::BoundGenericClass:
case TypeKind::BoundGenericOneOf: case TypeKind::BoundGenericOneOf:
case TypeKind::BoundGenericStruct: { case TypeKind::BoundGenericStruct: {
BoundGenericType *BGT = cast<BoundGenericType>(base); CanBoundGenericType BGT = cast<BoundGenericType>(type);
if (isLocalLinkageDecl(BGT->getDecl())) if (isLocalLinkageDecl(BGT->getDecl()))
return true; return true;
for (Type Arg : BGT->getGenericArgs()) { for (Type arg : BGT->getGenericArgs()) {
if (isLocalLinkageType(CanType(Arg))) if (isLocalLinkageType(CanType(arg)))
return true; return true;
} }
return false; return false;
@@ -589,30 +585,30 @@ static bool isLocalLinkageType(CanType type) {
case TypeKind::Struct: case TypeKind::Struct:
case TypeKind::Class: case TypeKind::Class:
case TypeKind::Protocol: case TypeKind::Protocol:
return isLocalLinkageDecl(cast<NominalType>(base)->getDecl()); return isLocalLinkageDecl(cast<NominalType>(type)->getDecl());
case TypeKind::PolymorphicFunction: { case TypeKind::PolymorphicFunction: {
auto fn = cast<PolymorphicFunctionType>(base); auto fn = cast<PolymorphicFunctionType>(type);
if (isLocalLinkageGenericClause(fn->getGenericParams())) if (isLocalLinkageGenericClause(fn->getGenericParams()))
return true; return true;
SWIFT_FALLTHROUGH; SWIFT_FALLTHROUGH;
} }
case TypeKind::Function: { case TypeKind::Function: {
AnyFunctionType *fn = cast<AnyFunctionType>(base); CanAnyFunctionType fn = cast<AnyFunctionType>(type);
return isLocalLinkageType(CanType(fn->getInput())) || return isLocalLinkageType(fn.getInput()) ||
isLocalLinkageType(CanType(fn->getResult())); isLocalLinkageType(fn.getResult());
} }
case TypeKind::ReferenceStorage: { case TypeKind::ReferenceStorage: {
auto ref = cast<ReferenceStorageType>(base); auto ref = cast<ReferenceStorageType>(type);
return isLocalLinkageType(CanType(ref->getReferentType())); return isLocalLinkageType(ref.getReferentType());
} }
case TypeKind::Array: case TypeKind::Array:
return isLocalLinkageType(CanType(cast<ArrayType>(base)->getBaseType())); return isLocalLinkageType(cast<ArrayType>(type).getBaseType());
case TypeKind::ProtocolComposition: case TypeKind::ProtocolComposition:
for (Type t : cast<ProtocolCompositionType>(base)->getProtocols()) for (Type t : cast<ProtocolCompositionType>(type)->getProtocols())
if (isLocalLinkageType(CanType(t))) if (isLocalLinkageType(CanType(t)))
return true; return true;
return false; return false;

View File

@@ -546,9 +546,9 @@ static CanType decomposeFunctionType(IRGenModule &IGM, CanType type,
// Explode the argument. // Explode the argument.
auto decomposeTopLevelArg = [&](CanType inputTy) { auto decomposeTopLevelArg = [&](CanType inputTy) {
if (TupleType *tupleTy = inputTy->getAs<TupleType>()) { if (auto tupleTy = dyn_cast<TupleType>(inputTy)) {
for (auto &field : tupleTy->getFields()) { for (auto fieldType : tupleTy.getElementTypes()) {
decomposeFunctionArg(IGM, CanType(field.getType()), cc, explosionKind, decomposeFunctionArg(IGM, fieldType, cc, explosionKind,
argTypes, byvals, attrs); argTypes, byvals, attrs);
} }
} else { } else {
@@ -557,7 +557,7 @@ static CanType decomposeFunctionType(IRGenModule &IGM, CanType type,
} }
}; };
CanType inputTy = CanType(fn->getInput()); CanType inputTy = fn.getInput();
switch (cc) { switch (cc) {
case AbstractCC::Freestanding: case AbstractCC::Freestanding:
case AbstractCC::Method: case AbstractCC::Method:
@@ -567,11 +567,11 @@ static CanType decomposeFunctionType(IRGenModule &IGM, CanType type,
case AbstractCC::ObjCMethod: { case AbstractCC::ObjCMethod: {
// ObjC methods take an implicit _cmd argument after the self argument. // ObjC methods take an implicit _cmd argument after the self argument.
TupleType *inputTuple = cast<TupleType>(inputTy); CanTupleType inputTuple = cast<TupleType>(inputTy);
assert(inputTuple->getFields().size() == 2 && "invalid objc method type"); assert(inputTuple->getNumElements() == 2 && "invalid objc method type");
decomposeTopLevelArg(CanType(inputTuple->getFields()[0].getType())); decomposeTopLevelArg(inputTuple.getElementType(0));
argTypes.push_back(IGM.Int8PtrTy); argTypes.push_back(IGM.Int8PtrTy);
decomposeTopLevelArg(CanType(inputTuple->getFields()[1].getType())); decomposeTopLevelArg(inputTuple.getElementType(1));
break; break;
} }
} }
@@ -1408,10 +1408,9 @@ void CallEmission::externalizeArgument(Explosion &out, Explosion &in,
void CallEmission::externalizeArguments(Explosion &out, Explosion &arg, void CallEmission::externalizeArguments(Explosion &out, Explosion &arg,
SmallVectorImpl<std::pair<unsigned, Alignment>> &newByvals, SmallVectorImpl<std::pair<unsigned, Alignment>> &newByvals,
CanType inputsTy) { CanType inputsTy) {
if (TupleType *tupleTy = inputsTy->getAs<TupleType>()) { if (CanTupleType tupleType = dyn_cast<TupleType>(inputsTy)) {
for (auto &elt : tupleTy->getFields()) { for (auto eltType : tupleType.getElementTypes()) {
externalizeArgument(out, arg, newByvals, externalizeArgument(out, arg, newByvals, eltType);
elt.getType()->getCanonicalType());
} }
} else { } else {
externalizeArgument(out, arg, newByvals, inputsTy); externalizeArgument(out, arg, newByvals, inputsTy);
@@ -1443,11 +1442,11 @@ void CallEmission::addArg(Explosion &arg) {
// _cmd // _cmd
externalized.add(arg.claimNext()); externalized.add(arg.claimNext());
// method args // method args
TupleType *inputTuple = CurOrigType->castTo<AnyFunctionType>()->getInput() CanTupleType inputTuple =
->castTo<TupleType>(); cast<TupleType>(cast<AnyFunctionType>(CurOrigType).getInput());
assert(inputTuple->getFields().size() == 2 && "invalid objc method type"); assert(inputTuple->getNumElements() == 2 && "invalid objc method type");
externalizeArguments(externalized, arg, newByvals, externalizeArguments(externalized, arg, newByvals,
CanType(inputTuple->getFields()[1].getType())); inputTuple.getElementType(1));
arg = std::move(externalized); arg = std::move(externalized);
break; break;
} }

View File

@@ -237,7 +237,7 @@ bool irgen::hasKnownVTableEntry(IRGenModule &IGM, FuncDecl *theMethod) {
/// Emit a string encoding the labels in the given tuple type. /// Emit a string encoding the labels in the given tuple type.
static llvm::Constant *getTupleLabelsString(IRGenModule &IGM, static llvm::Constant *getTupleLabelsString(IRGenModule &IGM,
TupleType *type) { CanTupleType type) {
bool hasLabels = false; bool hasLabels = false;
llvm::SmallString<128> buffer; llvm::SmallString<128> buffer;
for (auto &elt : type->getFields()) { for (auto &elt : type->getFields()) {
@@ -329,9 +329,7 @@ namespace {
// Er, varargs bit? Should that go in? // Er, varargs bit? Should that go in?
auto elements = type->getFields(); switch (type->getNumElements()) {
switch (elements.size()) {
case 0: {// Special case the empty tuple, just use the global descriptor. case 0: {// Special case the empty tuple, just use the global descriptor.
llvm::Constant *fullMetadata = IGF.IGM.getEmptyTupleMetadata(); llvm::Constant *fullMetadata = IGF.IGM.getEmptyTupleMetadata();
llvm::Constant *indices[] = { llvm::Constant *indices[] = {
@@ -389,13 +387,14 @@ namespace {
llvm::Value *pointerToFirst = nullptr; // appease -Wuninitialized llvm::Value *pointerToFirst = nullptr; // appease -Wuninitialized
auto elements = type.getElementTypes();
auto arrayTy = llvm::ArrayType::get(IGF.IGM.TypeMetadataPtrTy, auto arrayTy = llvm::ArrayType::get(IGF.IGM.TypeMetadataPtrTy,
elements.size()); elements.size());
Address buffer = IGF.createAlloca(arrayTy,IGF.IGM.getPointerAlignment(), Address buffer = IGF.createAlloca(arrayTy,IGF.IGM.getPointerAlignment(),
"tuple-elements"); "tuple-elements");
for (unsigned i = 0, e = elements.size(); i != e; ++i) { for (unsigned i = 0, e = elements.size(); i != e; ++i) {
// Find the metadata pointer for this element. // 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. // GEP to the appropriate element and store.
Address eltPtr = IGF.Builder.CreateStructGEP(buffer, i, Address eltPtr = IGF.Builder.CreateStructGEP(buffer, i,
@@ -418,7 +417,7 @@ namespace {
call->setDoesNotThrow(); call->setDoesNotThrow();
call->setCallingConv(IGF.IGM.RuntimeCC); 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) { bool visitTupleType(CanTupleType overridden, CanType overrideTy) {
CanTupleType override = cast<TupleType>(overrideTy); CanTupleType override = cast<TupleType>(overrideTy);
assert(overridden->getFields().size() == override->getFields().size()); assert(overridden->getNumElements() == override->getNumElements());
for (unsigned i = 0, e = overridden->getFields().size(); i != e; ++i) { for (unsigned i = 0, e = overridden->getNumElements(); i != e; ++i) {
if (visit(overridden.getElementType(i), override.getElementType(i))) if (visit(overridden.getElementType(i), override.getElementType(i)))
return true; return true;
} }

View File

@@ -555,8 +555,8 @@ static bool isObjCSetterSignature(IRGenModule &IGM,
if (hasObjCClassRepresentation(IGM, methodType->getInput())) if (hasObjCClassRepresentation(IGM, methodType->getInput()))
return true; return true;
if (TupleType *inputTuple = methodType->getInput()->getAs<TupleType>()) { if (TupleType *inputTuple = methodType->getInput()->getAs<TupleType>()) {
return inputTuple->getFields().size() == 1 return inputTuple->getNumElements() == 1
&& hasObjCClassRepresentation(IGM, inputTuple->getFields()[0].getType()); && hasObjCClassRepresentation(IGM, inputTuple->getElementType(0));
} }
return false; return false;
} }

View File

@@ -259,8 +259,8 @@ namespace {
bool isObviouslyEmptyType(CanType type) { bool isObviouslyEmptyType(CanType type) {
if (auto tuple = dyn_cast<TupleType>(type)) { if (auto tuple = dyn_cast<TupleType>(type)) {
for (auto &field : tuple->getFields()) for (auto eltType : tuple.getElementTypes())
if (!isObviouslyEmptyType(CanType(field.getType()))) if (!isObviouslyEmptyType(eltType))
return false; return false;
return true; return true;
} }

View File

@@ -209,24 +209,24 @@ namespace {
// We assume that all reference storage types have equivalent // We assume that all reference storage types have equivalent
// representation. This may not be true. // representation. This may not be true.
bool visitReferenceStorageType(ReferenceStorageType *origTy, bool visitReferenceStorageType(CanReferenceStorageType origTy,
ReferenceStorageType *substTy) { CanReferenceStorageType substTy) {
return false; return false;
} }
CanType getArchetypeReprType(ArchetypeType *a) { CanType getArchetypeReprType(CanArchetypeType a) {
if (Type super = a->getSuperclass()) if (Type super = a->getSuperclass())
return super->getCanonicalType(); return CanType(super);
return CanType(IGM.Context.TheObjCPointerType); 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. // Archetypes vary by what we're considering this for.
if (origTy->requiresClass()) { if (origTy->requiresClass()) {
// Class archetypes are represented as some refcounted // Class archetypes are represented as some refcounted
// pointer type that needs to be bitcast. // 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 // Archetypes are laid out in memory in the same way as a
@@ -239,13 +239,12 @@ namespace {
return !IGM.isSingleIndirectValue(substTy, ExplosionLevel); return !IGM.isSingleIndirectValue(substTy, ExplosionLevel);
} }
bool visitArrayType(ArrayType *origTy, ArrayType *substTy) { bool visitArrayType(CanArrayType origTy, CanArrayType substTy) {
return visit(CanType(origTy->getBaseType()), return visit(origTy.getBaseType(), substTy.getBaseType());
CanType(substTy->getBaseType()));
} }
bool visitBoundGenericType(BoundGenericType *origTy, bool visitBoundGenericType(CanBoundGenericType origTy,
BoundGenericType *substTy) { CanBoundGenericType substTy) {
assert(origTy->getDecl() == substTy->getDecl()); assert(origTy->getDecl() == substTy->getDecl());
// Bound generic types with reference semantics will never // Bound generic types with reference semantics will never
@@ -258,8 +257,8 @@ namespace {
/// Functions use a more complicated algorithm which calls back /// Functions use a more complicated algorithm which calls back
/// into this. /// into this.
bool visitAnyFunctionType(AnyFunctionType *origTy, bool visitAnyFunctionType(CanAnyFunctionType origTy,
AnyFunctionType *substTy) { CanAnyFunctionType substTy) {
return differsByAbstractionAsFunction(IGM, origTy, substTy, return differsByAbstractionAsFunction(IGM, origTy, substTy,
ExplosionKind::Minimal, ExplosionKind::Minimal,
/*uncurry*/ 0); /*uncurry*/ 0);
@@ -267,17 +266,17 @@ namespace {
// L-values go by the object type; note that we ask the ordinary // L-values go by the object type; note that we ask the ordinary
// question, not the argument question. // question, not the argument question.
bool visitLValueType(LValueType *origTy, LValueType *substTy) { bool visitLValueType(CanLValueType origTy, CanLValueType substTy) {
return differsByAbstractionInMemory(IGM, return differsByAbstractionInMemory(IGM,
CanType(origTy->getObjectType()), origTy.getObjectType(),
CanType(substTy->getObjectType())); substTy.getObjectType());
} }
bool visitMetaTypeType(MetaTypeType *origTy, MetaTypeType *substTy) { bool visitMetaTypeType(CanMetaTypeType origTy, CanMetaTypeType substTy) {
// Metatypes can differ by abstraction if the substitution // Metatypes can differ by abstraction if the substitution
// reveals that the type is actually not a class type. // reveals that the type is actually not a class type.
return (IGM.hasTrivialMetatype(CanType(substTy->getInstanceType())) && return (IGM.hasTrivialMetatype(substTy.getInstanceType()) &&
!IGM.hasTrivialMetatype(CanType(origTy->getInstanceType()))); !IGM.hasTrivialMetatype(origTy.getInstanceType()));
} }
/// Whether we're checking for memory or for an explosion, tuples /// 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, /// TODO: unless the original tuple contains a variadic explosion,
/// in which case that portion of the tuple is passed indirectly /// in which case that portion of the tuple is passed indirectly
/// in an explosion! /// in an explosion!
bool visitTupleType(TupleType *origTy, TupleType *substTy) { bool visitTupleType(CanTupleType origTy, CanTupleType substTy) {
assert(origTy->getFields().size() == substTy->getFields().size()); assert(origTy->getNumElements() == substTy->getNumElements());
for (unsigned i = 0, e = origTy->getFields().size(); i != e; ++i) for (unsigned i = 0, e = origTy->getNumElements(); i != e; ++i)
if (visit(CanType(origTy->getElementType(i)), if (visit(origTy.getElementType(i), substTy.getElementType(i)))
CanType(substTy->getElementType(i))))
return true; return true;
return false; return false;
} }
@@ -322,8 +320,8 @@ struct EmbedsArchetype : irgen::DeclVisitor<EmbedsArchetype, bool>,
using CanTypeVisitor<EmbedsArchetype, bool>::visit; using CanTypeVisitor<EmbedsArchetype, bool>::visit;
bool visitTupleType(CanTupleType type) { bool visitTupleType(CanTupleType type) {
for (auto &field : type->getFields()) for (auto eltType : type.getElementTypes())
if (visit(CanType(field.getType()))) if (visit(eltType))
return true; return true;
return false; return false;
} }
@@ -615,8 +613,8 @@ namespace {
} }
void visitTupleType(CanTupleType origTy, CanTupleType substTy) { void visitTupleType(CanTupleType origTy, CanTupleType substTy) {
assert(origTy->getFields().size() == substTy->getFields().size()); assert(origTy->getNumElements() == substTy->getNumElements());
for (unsigned i = 0, e = origTy->getFields().size(); i != e; ++i) { for (unsigned i = 0, e = origTy->getNumElements(); i != e; ++i) {
visit(origTy.getElementType(i), substTy.getElementType(i)); visit(origTy.getElementType(i), substTy.getElementType(i));
} }
} }
@@ -763,8 +761,8 @@ namespace {
} }
void visitTupleType(CanTupleType origTy, CanTupleType substTy) { void visitTupleType(CanTupleType origTy, CanTupleType substTy) {
assert(origTy->getFields().size() == substTy->getFields().size()); assert(origTy->getNumElements() == substTy->getNumElements());
for (unsigned i = 0, e = origTy->getFields().size(); i != e; ++i) { for (unsigned i = 0, e = origTy->getNumElements(); i != e; ++i) {
visit(origTy.getElementType(i), substTy.getElementType(i)); visit(origTy.getElementType(i), substTy.getElementType(i));
} }
} }

View File

@@ -2212,8 +2212,8 @@ static llvm::Constant *getValueWitness(IRGenModule &IGM,
/// FIXME: We could get fulfillments from any tuple element. /// FIXME: We could get fulfillments from any tuple element.
static CanType stripLabel(CanType input) { static CanType stripLabel(CanType input) {
if (auto tuple = dyn_cast<TupleType>(input)) if (auto tuple = dyn_cast<TupleType>(input))
if (tuple->getFields().size() > 0) if (tuple->getNumElements() > 0)
return stripLabel(CanType(tuple->getFields().back().getType())); return stripLabel(tuple.getElementTypes().back());
return input; return input;
} }
@@ -3315,8 +3315,9 @@ namespace {
// We need to walk into tuples. // We need to walk into tuples.
void visitTupleType(CanTupleType tuple) { void visitTupleType(CanTupleType tuple) {
for (auto &elt : tuple->getFields()) for (auto eltType : tuple.getElementTypes()) {
visit(CanType(elt.getType())); visit(eltType);
}
} }
// We need to walk into constant-sized arrays. // We need to walk into constant-sized arrays.

View File

@@ -595,9 +595,9 @@ void IRGenModule::getSchema(CanType type, ExplosionSchema &schema) {
// As an optimization, avoid actually building a TypeInfo for any // As an optimization, avoid actually building a TypeInfo for any
// obvious TupleTypes. This assumes that a TupleType's explosion // obvious TupleTypes. This assumes that a TupleType's explosion
// schema is always the concatenation of its component's schemas. // schema is always the concatenation of its component's schemas.
if (TupleType *tuple = dyn_cast<TupleType>(type)) { if (CanTupleType tuple = dyn_cast<TupleType>(type)) {
for (const TupleTypeElt &field : tuple->getFields()) for (auto eltType : tuple.getElementTypes())
getSchema(CanType(field.getType()), schema); getSchema(eltType, schema);
return; return;
} }
@@ -610,10 +610,10 @@ unsigned IRGenModule::getExplosionSize(CanType type, ExplosionKind kind) {
// As an optimization, avoid actually building a TypeInfo for any // As an optimization, avoid actually building a TypeInfo for any
// obvious TupleTypes. This assumes that a TupleType's explosion // obvious TupleTypes. This assumes that a TupleType's explosion
// schema is always the concatenation of its component's schemas. // 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; unsigned count = 0;
for (const TupleTypeElt &field : tuple->getFields()) for (auto eltType : tuple.getElementTypes())
count += getExplosionSize(CanType(field.getType()), kind); count += getExplosionSize(eltType, kind);
return count; return count;
} }
@@ -653,8 +653,8 @@ bool IRGenModule::isPOD(CanType type, ResilienceScope scope) {
if (isa<ClassType>(type)) return false; if (isa<ClassType>(type)) return false;
if (isa<BoundGenericClassType>(type)) return false; if (isa<BoundGenericClassType>(type)) return false;
if (auto tuple = dyn_cast<TupleType>(type)) { if (auto tuple = dyn_cast<TupleType>(type)) {
for (auto &elt : tuple->getFields()) for (auto eltType : tuple.getElementTypes())
if (!isPOD(CanType(elt.getType()), scope)) if (!isPOD(eltType, scope))
return false; return false;
return true; return true;
} }
@@ -689,8 +689,8 @@ namespace {
ObjectSize visitTupleType(CanTupleType tuple) { ObjectSize visitTupleType(CanTupleType tuple) {
ObjectSize result = ObjectSize::Fixed; ObjectSize result = ObjectSize::Fixed;
for (auto &field : tuple->getFields()) { for (auto eltType : tuple.getElementTypes()) {
result = std::max(result, visit(CanType(field.getType()))); result = std::max(result, visit(eltType));
} }
return result; return result;
} }

View File

@@ -31,7 +31,7 @@ namespace {
static unsigned getTupleSize(CanType t) { static unsigned getTupleSize(CanType t) {
if (TupleType *tt = dyn_cast<TupleType>(t)) if (TupleType *tt = dyn_cast<TupleType>(t))
return tt->getFields().size(); return tt->getNumElements();
return 1; return 1;
} }
@@ -65,7 +65,7 @@ public:
SILValue v = mv.forward(gen); SILValue v = mv.forward(gen);
if (v.getType().isAddressOnly(gen.F.getModule())) { if (v.getType().isAddressOnly(gen.F.getModule())) {
// Destructure address-only types by addressing the individual members. // 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); CanType fieldCanTy = t.getElementType(i);
SILType fieldTy = gen.getLoweredType(fieldCanTy); SILType fieldTy = gen.getLoweredType(fieldCanTy);
SILValue member = gen.B.createTupleElementAddr(SILLocation(), SILValue member = gen.B.createTupleElementAddr(SILLocation(),
@@ -80,7 +80,7 @@ public:
} }
} else { } else {
// Extract the elements from loadable tuples. // 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); CanType fieldCanTy = t.getElementType(i);
SILType fieldTy = gen.getLoweredLoadableType(fieldCanTy); SILType fieldTy = gen.getLoweredLoadableType(fieldCanTy);
SILValue member = gen.B.createTupleExtract(SILLocation(), SILValue member = gen.B.createTupleExtract(SILLocation(),
@@ -128,8 +128,8 @@ public:
SILValue visitTupleType(CanTupleType t) { SILValue visitTupleType(CanTupleType t) {
SmallVector<SILValue, 4> elts; SmallVector<SILValue, 4> elts;
for (auto &field : t->getFields()) for (auto fieldTy : t.getElementTypes())
elts.push_back(this->visit(CanType(field.getType()))); elts.push_back(this->visit(fieldTy));
SILType ty = gen.getLoweredLoadableType(t); SILType ty = gen.getLoweredLoadableType(t);
return gen.B.createTuple(SILLocation(), ty, elts); return gen.B.createTuple(SILLocation(), ty, elts);
} }
@@ -160,7 +160,7 @@ public:
} }
void visitTupleType(CanTupleType t, SILValue address) { 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); CanType fieldCanTy = t.getElementType(n);
SILType fieldTy = gen.getLoweredType(fieldCanTy); SILType fieldTy = gen.getLoweredType(fieldCanTy);
SILValue fieldAddr = gen.B.createTupleElementAddr(SILLocation(), SILValue fieldAddr = gen.B.createTupleElementAddr(SILLocation(),
@@ -212,8 +212,8 @@ public:
} }
void visitTupleType(CanTupleType t) { void visitTupleType(CanTupleType t) {
for (auto &field : t->getFields()) for (auto fieldType : t.getElementTypes())
visit(CanType(field.getType())); visit(fieldType);
} }
}; };
@@ -230,8 +230,8 @@ static void computeElementOffsets(std::vector<unsigned> &offsets,
// Visit each field and record its ending value offset. // Visit each field and record its ending value offset.
ComputeElementOffsets visitor; ComputeElementOffsets visitor;
for (auto &field : tuple->getFields()) { for (auto fieldType : tuple.getElementTypes()) {
visitor.visit(CanType(field.getType())); visitor.visit(fieldType);
offsets.push_back(visitor.offset); offsets.push_back(visitor.offset);
} }
} }
@@ -285,7 +285,7 @@ public:
SmallVector<InitializationPtr, 4> subInitBuf; SmallVector<InitializationPtr, 4> subInitBuf;
auto subInits = I->getSubInitializations(gen, subInitBuf); auto subInits = I->getSubInitializations(gen, subInitBuf);
assert(subInits.size() == t->getFields().size() && assert(subInits.size() == t->getNumElements() &&
"initialization does not match tuple?!"); "initialization does not match tuple?!");
for (unsigned i = 0, e = subInits.size(); i < e; ++i) for (unsigned i = 0, e = subInits.size(); i < e; ++i)
@@ -316,8 +316,8 @@ public:
RValue visitTupleType(CanTupleType t) { RValue visitTupleType(CanTupleType t) {
RValue rv{t}; RValue rv{t};
for (auto &field : t->getFields()) for (auto fieldType : t.getElementTypes())
rv.addElement(visit(CanType(field.getType()))); rv.addElement(visit(fieldType));
return rv; return rv;
} }
@@ -431,7 +431,7 @@ RValue RValue::extractElement(unsigned n) && {
assert(isComplete() && "rvalue is not complete"); assert(isComplete() && "rvalue is not complete");
unsigned from = elementOffsets[n], to = elementOffsets[n+1]; 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); RValue element(llvm::makeArrayRef(values).slice(from, to - from), eltTy);
makeUsed(); makeUsed();
@@ -441,12 +441,12 @@ RValue RValue::extractElement(unsigned n) && {
void RValue::extractElements(SmallVectorImpl<RValue> &elements) && { void RValue::extractElements(SmallVectorImpl<RValue> &elements) && {
assert(isComplete() && "rvalue is not complete"); 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]; unsigned from = elementOffsets[n], to = elementOffsets[n+1];
elements.push_back({llvm::makeArrayRef(values).slice(from, to - from), elements.push_back({llvm::makeArrayRef(values).slice(from, to - from),
CanType(fields[n].getType())}); elementTypes[n]});
} }
makeUsed(); makeUsed();
} }

View File

@@ -73,18 +73,17 @@ ArrayRef<InitializationPtr> Initialization::getSubInitializations(
return getSubInitializations(); return getSubInitializations();
case Kind::Ignored: { case Kind::Ignored: {
// "Destructure" an ignored binding into multiple ignored bindings. // "Destructure" an ignored binding into multiple ignored bindings.
for (auto &field : tupleTy->getFields()) { for (auto fieldType : tupleTy->getElementTypes()) {
buf.push_back(InitializationPtr( buf.push_back(InitializationPtr(new BlackHoleInitialization(fieldType)));
new BlackHoleInitialization(field.getType())));
} }
return buf; return buf;
} }
case Kind::SingleBuffer: { case Kind::SingleBuffer: {
// Destructure the buffer into per-element buffers. // Destructure the buffer into per-element buffers.
SILValue baseAddr = getAddress(); SILValue baseAddr = getAddress();
for (unsigned i = 0, size = tupleTy->getFields().size(); i < size; ++i) { for (unsigned i = 0, size = tupleTy->getNumElements(); i < size; ++i) {
auto &field = tupleTy->getFields()[i]; auto fieldType = tupleTy->getElementType(i);
SILType fieldTy = gen.getLoweredType(field.getType()).getAddressType(); SILType fieldTy = gen.getLoweredType(fieldType).getAddressType();
SILValue fieldAddr = gen.B.createTupleElementAddr(SILLocation(), SILValue fieldAddr = gen.B.createTupleElementAddr(SILLocation(),
baseAddr, i, baseAddr, i,
fieldTy); fieldTy);

View File

@@ -1356,9 +1356,8 @@ static RValue emitImplicitValueConstructorArg(SILGenFunction &gen,
// Restructure tuple arguments. // Restructure tuple arguments.
if (TupleType *tupleTy = argTy.getAs<TupleType>()) { if (TupleType *tupleTy = argTy.getAs<TupleType>()) {
RValue tuple(tupleTy->getCanonicalType()); RValue tuple(tupleTy->getCanonicalType());
for (auto &field : tupleTy->getFields()) for (auto fieldType : tupleTy->getElementTypes())
tuple.addElement( tuple.addElement(emitImplicitValueConstructorArg(gen, loc, fieldType));
emitImplicitValueConstructorArg(gen, loc, field.getType()));
return tuple; return tuple;
} else { } else {
@@ -1579,8 +1578,8 @@ namespace {
assert(ty && "no type?!"); assert(ty && "no type?!");
// Destructure tuple arguments. // Destructure tuple arguments.
if (TupleType *tupleTy = ty->getAs<TupleType>()) { if (TupleType *tupleTy = ty->getAs<TupleType>()) {
for (auto &field : tupleTy->getFields()) for (auto fieldType : tupleTy->getElementTypes())
makeArgument(field.getType()); makeArgument(fieldType);
} else { } else {
SILValue arg = new (gen.F.getModule()) SILArgument(gen.getLoweredType(ty), SILValue arg = new (gen.F.getModule()) SILArgument(gen.getLoweredType(ty),
gen.F.begin()); gen.F.begin());

View File

@@ -88,8 +88,7 @@ static SILBasicBlock *emitBranchAndDestructure(SILGenFunction &gen,
auto tupleSILTy = gen.getLoweredType(tupleTy); auto tupleSILTy = gen.getLoweredType(tupleTy);
if (tupleSILTy.isAddressOnly(gen.F.getModule())) { if (tupleSILTy.isAddressOnly(gen.F.getModule())) {
for (unsigned i = 0, e = tupleTy->getFields().size(); i < e; ++i) { for (unsigned i = 0, e = tupleTy->getFields().size(); i < e; ++i) {
auto &field = tupleTy->getFields()[i]; SILType fieldTy = gen.getLoweredType(tupleTy->getElementType(i));
SILType fieldTy = gen.getLoweredType(field.getType());
SILValue member = gen.B.createTupleElementAddr(SILLocation(), SILValue member = gen.B.createTupleElementAddr(SILLocation(),
v, i, fieldTy.getAddressType()); v, i, fieldTy.getAddressType());
if (!fieldTy.isAddressOnly(gen.F.getModule())) if (!fieldTy.isAddressOnly(gen.F.getModule()))
@@ -98,8 +97,8 @@ static SILBasicBlock *emitBranchAndDestructure(SILGenFunction &gen,
} }
} else { } else {
for (unsigned i = 0, e = tupleTy->getFields().size(); i < e; ++i) { for (unsigned i = 0, e = tupleTy->getFields().size(); i < e; ++i) {
auto &field = tupleTy->getFields()[i]; auto fieldType = tupleTy->getElementType(i);
SILType fieldTy = gen.getLoweredLoadableType(field.getType()); SILType fieldTy = gen.getLoweredLoadableType(fieldType);
SILValue member = gen.B.createTupleExtract(SILLocation(), SILValue member = gen.B.createTupleExtract(SILLocation(),
v, i, fieldTy); v, i, fieldTy);
destructured.push_back(member); destructured.push_back(member);
@@ -1289,4 +1288,4 @@ void SILGenFunction::emitSwitchFallthrough(FallthroughStmt *S) {
// Jump to it. // Jump to it.
Cleanups.emitBranchAndCleanups(JumpDest{dest, context->outerScope}); Cleanups.emitBranchAndCleanups(JumpDest{dest, context->outerScope});
} }

View File

@@ -104,8 +104,8 @@ namespace {
} }
void visitTupleType(CanTupleType tt) { void visitTupleType(CanTupleType tt) {
for (auto &field : tt->getFields()) { for (auto eltType : tt.getElementTypes()) {
visit(CanType(field.getType())); visit(eltType);
} }
} }
}; };

View File

@@ -37,15 +37,15 @@ bool SILType::isAddressOnly(CanType Ty, SILModule &M) {
// AddressOnly. // AddressOnly.
// Structs and tuples are address-only if any of their elements are. // 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. // Check to see if we've computed this property for this tuple yet.
auto Entry = M.AddressOnlyTypeCache.find(TTy); auto Entry = M.AddressOnlyTypeCache.find(TTy);
// If we got a hit, then return the precomputed value. // If we got a hit, then return the precomputed value.
if (Entry != M.AddressOnlyTypeCache.end()) if (Entry != M.AddressOnlyTypeCache.end())
return Entry->second; return Entry->second;
for (const TupleTypeElt &elt : TTy->getFields()) for (auto eltType : TTy.getElementTypes())
if (isAddressOnly(elt.getType()->getCanonicalType(), M)) if (isAddressOnly(eltType, M))
return M.AddressOnlyTypeCache[TTy] = true; return M.AddressOnlyTypeCache[TTy] = true;
return M.AddressOnlyTypeCache[TTy] = false; return M.AddressOnlyTypeCache[TTy] = false;

View File

@@ -82,14 +82,13 @@ static CanType getBridgedInputType(TypeConverter &tc,
if (auto tuple = dyn_cast<TupleType>(input)) { if (auto tuple = dyn_cast<TupleType>(input)) {
SmallVector<TupleTypeElt, 4> bridgedFields; SmallVector<TupleTypeElt, 4> bridgedFields;
bool changed = false; bool changed = false;
for (TupleTypeElt const &field : tuple->getFields()) { for (auto &elt : tuple->getFields()) {
CanType bridged = CanType bridged = CanType(tc.getLoweredBridgedType(elt.getType(), cc));
tc.getLoweredBridgedType(field.getType(), cc)->getCanonicalType(); if (bridged != CanType(elt.getType())) {
if (bridged != CanType(field.getType())) {
changed = true; changed = true;
bridgedFields.push_back(field.getWithType(bridged)); bridgedFields.push_back(elt.getWithType(bridged));
} else { } else {
bridgedFields.push_back(field); bridgedFields.push_back(elt);
} }
} }
@@ -360,10 +359,9 @@ public:
void visitTupleType(CanTupleType t) { void visitTupleType(CanTupleType t) {
pushPath(); pushPath();
unsigned i = 0; unsigned i = 0;
for (TupleTypeElt const &elt : t->getFields()) { for (auto eltType : t.getElementTypes()) {
CanType ct = elt.getType()->getCanonicalType(); setPath(ReferenceTypePath::Component::forTupleElement(eltType, i++));
setPath(ReferenceTypePath::Component::forTupleElement(ct, i++)); visit(eltType);
visit(ct);
} }
popPath(); popPath();
} }

View File

@@ -339,7 +339,7 @@ public:
for (size_t i = 0, size = TI->getElements().size(); i < size; ++i) { for (size_t i = 0, size = TI->getElements().size(); i < size; ++i) {
require(TI->getElements()[i].getType().getSwiftType() require(TI->getElements()[i].getType().getSwiftType()
->isEqual(ResTy->getFields()[i].getType()), ->isEqual(ResTy->getElementType(i)),
"Tuple element arguments do not match tuple type!"); "Tuple element arguments do not match tuple type!");
} }
} }