Skip to content

Commit 4ba96f2

Browse files
authored
Merge pull request #19723 from slavapestov/irgen-type-lowering-cleanup
IRGen type lowering cleanup
2 parents 0a4c1f1 + 73aff74 commit 4ba96f2

File tree

10 files changed

+47
-181
lines changed

10 files changed

+47
-181
lines changed

lib/IRGen/GenClass.cpp

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -970,22 +970,7 @@ void irgen::emitPartialClassDeallocation(IRGenFunction &IGF,
970970
llvm::Value *selfValue,
971971
llvm::Value *metadataValue) {
972972
auto *theClass = selfType.getClassOrBoundGenericClass();
973-
974-
// Foreign classes should not be freed by sending -release.
975-
// They should also probably not be freed with object_dispose(),
976-
// either.
977-
//
978-
// However, in practice, the only time we should try to free an
979-
// instance of a foreign class here is inside an initializer
980-
// delegating to a factory initializer. In this case, the object
981-
// was allocated with +allocWithZone:, so calling object_dispose()
982-
// should be OK.
983-
if (theClass->getForeignClassKind() == ClassDecl::ForeignKind::RuntimeOnly) {
984-
selfValue = IGF.Builder.CreateBitCast(selfValue, IGF.IGM.ObjCPtrTy);
985-
IGF.Builder.CreateCall(IGF.IGM.getObjectDisposeFn(),
986-
{selfValue});
987-
return;
988-
}
973+
assert(theClass->getForeignClassKind() == ClassDecl::ForeignKind::Normal);
989974

990975
llvm::Value *size, *alignMask;
991976
getInstanceSizeAndAlignMask(IGF, selfType, theClass, selfValue,

lib/IRGen/GenEnum.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6099,8 +6099,8 @@ const TypeInfo *TypeConverter::convertEnumType(TypeBase *key, CanType type,
60996099
else
61006100
storageType = IGM.createNominalType(type);
61016101

6102-
// Create a forward declaration for that type.
6103-
addForwardDecl(key, storageType);
6102+
// Create a forward declaration.
6103+
addForwardDecl(key);
61046104

61056105
SILType loweredTy = SILType::getPrimitiveAddressType(type);
61066106

lib/IRGen/GenMeta.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3402,8 +3402,8 @@ namespace {
34023402
B.add(offset);
34033403
return;
34043404
}
3405-
assert(IGM.isKnownEmpty(Type.getFieldType(field, IGM.getSILModule()),
3406-
ResilienceExpansion::Maximal));
3405+
assert(IGM.getTypeInfo(Type.getFieldType(field, IGM.getSILModule()))
3406+
.isKnownEmpty(ResilienceExpansion::Maximal));
34073407
B.addInt32(0);
34083408
}
34093409

lib/IRGen/GenPoly.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,16 @@ void irgen::reemitAsUnsubstituted(IRGenFunction &IGF,
6060
Explosion &in, Explosion &out) {
6161
expectedTy = applyContextArchetypes(IGF, expectedTy);
6262

63-
ExplosionSchema expectedSchema = IGF.IGM.getSchema(expectedTy);
63+
ExplosionSchema expectedSchema;
64+
cast<LoadableTypeInfo>(IGF.IGM.getTypeInfo(expectedTy))
65+
.getSchema(expectedSchema);
66+
67+
#ifndef NDEBUG
68+
auto &substTI = IGF.IGM.getTypeInfo(applyContextArchetypes(IGF, substTy));
6469
assert(expectedSchema.size() ==
65-
IGF.IGM.getExplosionSize(applyContextArchetypes(IGF, substTy)));
70+
cast<LoadableTypeInfo>(substTI).getExplosionSize());
71+
#endif
72+
6673
for (ExplosionSchema::Element &elt : expectedSchema) {
6774
llvm::Value *value = in.claimNext();
6875
assert(elt.isScalar());

lib/IRGen/GenStruct.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,7 @@ const TypeInfo *TypeConverter::convertStructType(TypeBase *key, CanType type,
860860
auto ty = IGM.createNominalType(type);
861861

862862
// Register a forward declaration before we look at any of the child types.
863-
addForwardDecl(key, ty);
863+
addForwardDecl(key);
864864

865865
// Use different rules for types imported from C.
866866
if (D->hasClangNode()) {

lib/IRGen/GenType.cpp

Lines changed: 20 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ Alignment IRGenModule::getCappedAlignment(Alignment align) {
5555
return std::min(align, Alignment(MaximumAlignment));
5656
}
5757

58-
llvm::DenseMap<TypeBase*, TypeCacheEntry> &
58+
llvm::DenseMap<TypeBase *, const TypeInfo *> &
5959
TypeConverter::Types_t::getCacheFor(bool isDependent, bool completelyFragile) {
6060
if (completelyFragile) {
6161
return (isDependent
@@ -1128,12 +1128,13 @@ GenericEnvironment *IRGenModule::getGenericEnvironment() {
11281128

11291129
/// Add a temporary forward declaration for a type. This will live
11301130
/// only until a proper mapping is added.
1131-
void TypeConverter::addForwardDecl(TypeBase *key, llvm::Type *type) {
1131+
void TypeConverter::addForwardDecl(TypeBase *key) {
11321132
assert(key->isCanonical());
11331133
assert(!key->hasTypeParameter());
11341134
auto &Cache = Types.getCacheFor(/*isDependent*/ false, CompletelyFragile);
1135-
assert(!Cache.count(key) && "entry already exists for type!");
1136-
Cache.insert(std::make_pair(key, type));
1135+
auto result = Cache.insert(std::make_pair(key, nullptr));
1136+
assert(result.second && "entry already exists for type!");
1137+
(void) result;
11371138
}
11381139

11391140
const TypeInfo &IRGenModule::getWitnessTablePtrTypeInfo() {
@@ -1322,17 +1323,9 @@ llvm::Type *IRGenModule::getStorageType(SILType T) {
13221323
return getStorageTypeForLowered(T.getASTType());
13231324
}
13241325

1325-
/// Get the storage type for the given type. Note that, unlike
1326-
/// fetching the type info and asking it for the storage type, this
1327-
/// operation will succeed for forward-declarations.
1326+
/// Get the storage type for the given type.
13281327
llvm::Type *IRGenModule::getStorageTypeForLowered(CanType T) {
1329-
// TODO: we can avoid creating entries for some obvious cases here.
1330-
auto entry = Types.getTypeEntry(T);
1331-
if (auto ti = entry.dyn_cast<const TypeInfo*>()) {
1332-
return ti->getStorageType();
1333-
} else {
1334-
return entry.get<llvm::Type*>();
1335-
}
1328+
return Types.getTypeEntry(T)->getStorageType();
13361329
}
13371330

13381331
/// Get the type information for the given type, which may not have
@@ -1370,9 +1363,7 @@ const TypeInfo &IRGenModule::getTypeInfoForLowered(CanType T) {
13701363

13711364
///
13721365
const TypeInfo &TypeConverter::getCompleteTypeInfo(CanType T) {
1373-
auto entry = getTypeEntry(T);
1374-
assert(entry.is<const TypeInfo*>() && "getting TypeInfo recursively!");
1375-
return *entry.get<const TypeInfo*>();
1366+
return *getTypeEntry(T);
13761367
}
13771368

13781369
ArchetypeType *TypeConverter::getExemplarArchetype(ArchetypeType *t) {
@@ -1428,7 +1419,7 @@ void TypeConverter::popCompletelyFragile() {
14281419
CompletelyFragile = false;
14291420
}
14301421

1431-
TypeCacheEntry TypeConverter::getTypeEntry(CanType canonicalTy) {
1422+
const TypeInfo *TypeConverter::getTypeEntry(CanType canonicalTy) {
14321423
// Cache this entry in the dependent or independent cache appropriate to it.
14331424
auto &Cache = Types.getCacheFor(canonicalTy->hasTypeParameter(),
14341425
CompletelyFragile);
@@ -1467,22 +1458,12 @@ TypeCacheEntry TypeConverter::getTypeEntry(CanType canonicalTy) {
14671458
}
14681459

14691460
// Convert the type.
1470-
TypeCacheEntry convertedEntry = convertType(exemplarTy);
1471-
auto convertedTI = convertedEntry.dyn_cast<const TypeInfo*>();
1472-
1473-
// If that gives us a forward declaration (which can happen with
1474-
// bound generic types), don't propagate that into the cache here,
1475-
// because we won't know how to clear it later.
1476-
if (!convertedTI) {
1477-
return convertedEntry;
1478-
}
1461+
auto *convertedTI = convertType(exemplarTy);
14791462

14801463
// Cache the entry under the original type and the exemplar type, so that
14811464
// we can avoid relowering equivalent types.
1482-
auto insertEntry = [&](TypeCacheEntry &entry) {
1483-
assert(entry == TypeCacheEntry() ||
1484-
(entry.is<llvm::Type*>() &&
1485-
entry.get<llvm::Type*>() == convertedTI->getStorageType()));
1465+
auto insertEntry = [&](const TypeInfo *&entry) {
1466+
assert(entry == nullptr);
14861467
entry = convertedTI;
14871468
};
14881469
insertEntry(Cache[canonicalTy.getPointer()]);
@@ -1600,7 +1581,7 @@ convertPrimitiveBuiltin(IRGenModule &IGM, CanType canTy) {
16001581
}
16011582
}
16021583

1603-
TypeCacheEntry TypeConverter::convertType(CanType ty) {
1584+
const TypeInfo *TypeConverter::convertType(CanType ty) {
16041585
PrettyStackTraceType stackTrace(IGM.Context, "converting", ty);
16051586

16061587
switch (ty->getKind()) {
@@ -1719,10 +1700,10 @@ TypeConverter::convert##Name##StorageType(Name##StorageType *refType) { \
17191700
}
17201701
#include "swift/AST/ReferenceStorage.def"
17211702

1722-
static void overwriteForwardDecl(llvm::DenseMap<TypeBase*, TypeCacheEntry> &cache,
1703+
static void overwriteForwardDecl(llvm::DenseMap<TypeBase *, const TypeInfo *> &cache,
17231704
TypeBase *key, const TypeInfo *result) {
17241705
assert(cache.count(key) && "no forward declaration?");
1725-
assert(cache[key].is<llvm::Type*>() && "overwriting real entry!");
1706+
assert(cache[key] == nullptr && "overwriting real entry!");
17261707
cache[key] = result;
17271708
}
17281709

@@ -1828,8 +1809,8 @@ static bool isIRTypeDependent(IRGenModule &IGM, NominalTypeDecl *decl) {
18281809
}
18291810
}
18301811

1831-
TypeCacheEntry TypeConverter::convertAnyNominalType(CanType type,
1832-
NominalTypeDecl *decl) {
1812+
const TypeInfo *TypeConverter::convertAnyNominalType(CanType type,
1813+
NominalTypeDecl *decl) {
18331814
// By "any", we don't mean existentials.
18341815
assert(!isa<ProtocolDecl>(decl));
18351816

@@ -1961,86 +1942,6 @@ IRGenModule::createNominalType(ProtocolCompositionType *type) {
19611942
return llvm::StructType::create(getLLVMContext(), StringRef(typeName));
19621943
}
19631944

1964-
/// Compute the explosion schema for the given type.
1965-
ExplosionSchema IRGenModule::getSchema(SILType type) {
1966-
ExplosionSchema schema;
1967-
getSchema(type, schema);
1968-
return schema;
1969-
}
1970-
1971-
/// Compute the explosion schema for the given type.
1972-
void IRGenModule::getSchema(SILType type, ExplosionSchema &schema) {
1973-
// As an optimization, avoid actually building a TypeInfo for any
1974-
// obvious TupleTypes. This assumes that a TupleType's explosion
1975-
// schema is always the concatenation of its component's schemas.
1976-
if (CanTupleType tuple = type.getAs<TupleType>()) {
1977-
for (auto index : indices(tuple.getElementTypes()))
1978-
getSchema(type.getTupleElementType(index), schema);
1979-
return;
1980-
}
1981-
1982-
// Okay, that didn't work; just do the general thing.
1983-
getTypeInfo(type).getSchema(schema);
1984-
}
1985-
1986-
/// Compute the explosion schema for the given type.
1987-
unsigned IRGenModule::getExplosionSize(SILType type) {
1988-
// As an optimization, avoid actually building a TypeInfo for any
1989-
// obvious TupleTypes. This assumes that a TupleType's explosion
1990-
// schema is always the concatenation of its component's schemas.
1991-
if (auto tuple = type.getAs<TupleType>()) {
1992-
unsigned count = 0;
1993-
for (auto index : indices(tuple.getElementTypes()))
1994-
count += getExplosionSize(type.getTupleElementType(index));
1995-
return count;
1996-
}
1997-
1998-
// If the type isn't loadable, the explosion size is always 1.
1999-
auto *loadableTI = dyn_cast<LoadableTypeInfo>(&getTypeInfo(type));
2000-
if (!loadableTI) return 1;
2001-
2002-
// Okay, that didn't work; just do the general thing.
2003-
return loadableTI->getExplosionSize();
2004-
}
2005-
2006-
/// Determine whether this type is a single value that is passed
2007-
/// indirectly at the given level.
2008-
llvm::PointerType *IRGenModule::isSingleIndirectValue(SILType type) {
2009-
if (auto archetype = type.getAs<ArchetypeType>()) {
2010-
if (!archetype->requiresClass())
2011-
return OpaquePtrTy;
2012-
}
2013-
2014-
ExplosionSchema schema;
2015-
getSchema(type, schema);
2016-
if (schema.size() == 1 && schema.begin()->isAggregate())
2017-
return schema.begin()->getAggregateType()->getPointerTo(0);
2018-
return nullptr;
2019-
}
2020-
2021-
/// Determine whether this type is known to be POD.
2022-
bool IRGenModule::isPOD(SILType type, ResilienceExpansion expansion) {
2023-
if (type.is<ArchetypeType>()) return false;
2024-
if (type.is<ClassType>()) return false;
2025-
if (type.is<BoundGenericClassType>()) return false;
2026-
if (auto tuple = type.getAs<TupleType>()) {
2027-
for (auto index : indices(tuple.getElementTypes()))
2028-
if (!isPOD(type.getTupleElementType(index), expansion))
2029-
return false;
2030-
return true;
2031-
}
2032-
return getTypeInfo(type).isPOD(expansion);
2033-
}
2034-
2035-
/// Determine whether this type is known to be empty.
2036-
bool IRGenModule::isKnownEmpty(SILType type, ResilienceExpansion expansion) {
2037-
if (auto tuple = type.getAs<TupleType>()) {
2038-
if (tuple->getNumElements() == 0)
2039-
return true;
2040-
}
2041-
return getTypeInfo(type).isKnownEmpty(expansion);
2042-
}
2043-
20441945
SpareBitVector IRGenModule::getSpareBitsForType(llvm::Type *scalarTy, Size size) {
20451946
auto it = SpareBitsForTypes.find(scalarTy);
20461947
if (it != SpareBitsForTypes.end())
@@ -2050,13 +1951,9 @@ SpareBitVector IRGenModule::getSpareBitsForType(llvm::Type *scalarTy, Size size)
20501951
"using a size that's smaller than LLVM's alloc size?");
20511952

20521953
{
2053-
// FIXME: Currently we only implement spare bits for single-element
2054-
// primitive integer types.
2055-
while (auto structTy = dyn_cast<llvm::StructType>(scalarTy)) {
2056-
if (structTy->getNumElements() != 1)
2057-
goto no_spare_bits;
2058-
scalarTy = structTy->getElementType(0);
2059-
}
1954+
// FIXME: Currently we only implement spare bits for primitive integer
1955+
// types.
1956+
assert(!isa<llvm::StructType>(scalarTy));
20601957

20611958
auto *intTy = dyn_cast<llvm::IntegerType>(scalarTy);
20621959
if (!intTy)

lib/IRGen/GenType.h

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,6 @@ namespace irgen {
5757
class LoadableTypeInfo;
5858
class TypeInfo;
5959

60-
/// Either a type or a forward-declaration.
61-
using TypeCacheEntry = llvm::PointerUnion<const TypeInfo *, llvm::Type *>;
62-
6360
/// The helper class for generating types.
6461
class TypeConverter {
6562
public:
@@ -100,10 +97,10 @@ class TypeConverter {
10097
const FixedTypeInfo *createImmovable(llvm::Type *T,
10198
Size size, Alignment align);
10299

103-
void addForwardDecl(TypeBase *key, llvm::Type *type);
100+
void addForwardDecl(TypeBase *key);
104101

105-
TypeCacheEntry convertType(CanType T);
106-
TypeCacheEntry convertAnyNominalType(CanType T, NominalTypeDecl *D);
102+
const TypeInfo *convertType(CanType T);
103+
const TypeInfo *convertAnyNominalType(CanType T, NominalTypeDecl *D);
107104
const TypeInfo *convertTupleType(TupleType *T);
108105
const TypeInfo *convertClassType(CanType type, ClassDecl *D);
109106
const TypeInfo *convertEnumType(TypeBase *key, CanType type, EnumDecl *D);
@@ -134,7 +131,7 @@ class TypeConverter {
134131
return CompletelyFragile;
135132
}
136133

137-
TypeCacheEntry getTypeEntry(CanType type);
134+
const TypeInfo *getTypeEntry(CanType type);
138135
const TypeInfo &getCompleteTypeInfo(CanType type);
139136
const LoadableTypeInfo &getNativeObjectTypeInfo();
140137
const LoadableTypeInfo &getUnknownObjectTypeInfo();
@@ -184,14 +181,14 @@ class TypeConverter {
184181
CanType getExemplarType(CanType t);
185182

186183
class Types_t {
187-
llvm::DenseMap<TypeBase*, TypeCacheEntry> IndependentCache;
188-
llvm::DenseMap<TypeBase*, TypeCacheEntry> DependentCache;
189-
llvm::DenseMap<TypeBase*, TypeCacheEntry> FragileIndependentCache;
190-
llvm::DenseMap<TypeBase*, TypeCacheEntry> FragileDependentCache;
184+
llvm::DenseMap<TypeBase *, const TypeInfo *> IndependentCache;
185+
llvm::DenseMap<TypeBase *, const TypeInfo *> DependentCache;
186+
llvm::DenseMap<TypeBase *, const TypeInfo *> FragileIndependentCache;
187+
llvm::DenseMap<TypeBase *, const TypeInfo *> FragileDependentCache;
191188

192189
public:
193-
llvm::DenseMap<TypeBase*, TypeCacheEntry> &getCacheFor(bool isDependent,
194-
bool completelyFragile);
190+
llvm::DenseMap<TypeBase *, const TypeInfo *> &getCacheFor(bool isDependent,
191+
bool completelyFragile);
195192
};
196193
Types_t Types;
197194
};

lib/IRGen/IRGenModule.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -748,12 +748,6 @@ class IRGenModule {
748748
llvm::PointerType *getStoragePointerType(SILType T);
749749
llvm::StructType *createNominalType(CanType type);
750750
llvm::StructType *createNominalType(ProtocolCompositionType *T);
751-
void getSchema(SILType T, ExplosionSchema &schema);
752-
ExplosionSchema getSchema(SILType T);
753-
unsigned getExplosionSize(SILType T);
754-
llvm::PointerType *isSingleIndirectValue(SILType T);
755-
bool isKnownEmpty(SILType type, ResilienceExpansion expansion);
756-
bool isPOD(SILType type, ResilienceExpansion expansion);
757751
clang::CanQual<clang::Type> getClangType(CanType type);
758752
clang::CanQual<clang::Type> getClangType(SILType type);
759753
clang::CanQual<clang::Type> getClangType(SILParameterInfo param);

lib/IRGen/IRGenSIL.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4234,8 +4234,8 @@ static SILAccessEnforcement getEffectiveEnforcement(IRGenFunction &IGF,
42344234
// of cases where this triggers, because of the restrictions on abstracting
42354235
// over addresses and the fact that we use static enforcement on inouts.
42364236
if (enforcement == SILAccessEnforcement::Dynamic &&
4237-
IGF.IGM.isKnownEmpty(access->getSource()->getType(),
4238-
ResilienceExpansion::Maximal)) {
4237+
IGF.IGM.getTypeInfo(access->getSource()->getType())
4238+
.isKnownEmpty(ResilienceExpansion::Maximal)) {
42394239
enforcement = SILAccessEnforcement::Unsafe;
42404240
}
42414241

test/IRGen/objc_runtime_visible.sil

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,3 @@ bb0:
1818
// CHECK-NEXT: ret %objc_class*
1919
return %0 : $@objc_metatype A.Type
2020
}
21-
22-
// CHECK: define {{(dllexport )?}}{{(protected )?}}swiftcc void @deallocA(%TSo1AC*) #0 {
23-
sil @deallocA : $@convention(thin) (@owned A) -> () {
24-
bb0(%0 : $A):
25-
%1 = metatype $@thick A.Type
26-
27-
// CHECK: call %objc_object* @object_dispose
28-
dealloc_partial_ref %0 : $A, %1 : $@thick A.Type
29-
30-
%2 = tuple ()
31-
32-
// CHECK-NEXT: ret
33-
return %2 : $()
34-
}

0 commit comments

Comments
 (0)