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:
@@ -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
|
||||||
|
|||||||
@@ -522,17 +522,14 @@ static bool isLocalLinkageGenericClause(const GenericParamList ¶ms) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
@@ -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});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user