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

@@ -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

View File

@@ -522,17 +522,14 @@ static bool isLocalLinkageGenericClause(const GenericParamList &params) {
}
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;

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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));
}
}

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -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();
}

View File

@@ -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);

View File

@@ -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());

View File

@@ -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);

View File

@@ -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);
}
}
};

View File

@@ -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;

View File

@@ -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();
}

View File

@@ -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!");
}
}