Skip to content

Commit 4285a21

Browse files
committed
IRGen: Start support for embedded existentials
Allow storing struct, enum, and tuple types in an any.
1 parent c337446 commit 4285a21

File tree

14 files changed

+344
-36
lines changed

14 files changed

+344
-36
lines changed

include/swift/IRGen/Linking.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,17 @@ enum class TypeMetadataAddress {
8989
inline bool isEmbedded(CanType t) {
9090
return t->getASTContext().LangOpts.hasFeature(Feature::Embedded);
9191
}
92-
92+
inline bool isEmbeddedWithoutEmbeddedExitentials(CanType t) {
93+
return t->getASTContext().LangOpts.hasFeature(Feature::Embedded) &&
94+
!t->getASTContext().LangOpts.hasFeature(Feature::EmbeddedExistentials);
95+
}
9396
// Metadata is not generated and not allowed to be referenced in Embedded Swift,
9497
// expect for classes (both generic and non-generic), dynamic self, and
9598
// class-bound existentials.
9699
inline bool isMetadataAllowedInEmbedded(CanType t) {
100+
bool embeddedExistentials =
101+
t->getASTContext().LangOpts.hasFeature(Feature::EmbeddedExistentials);
102+
97103
if (isa<ClassType>(t) || isa<BoundGenericClassType>(t) ||
98104
isa<DynamicSelfType>(t)) {
99105
return true;
@@ -106,6 +112,9 @@ inline bool isMetadataAllowedInEmbedded(CanType t) {
106112
if (archeTy->requiresClass())
107113
return true;
108114
}
115+
116+
if (embeddedExistentials)
117+
return true;
109118
return false;
110119
}
111120

@@ -1098,7 +1107,7 @@ class LinkEntity {
10981107
}
10991108

11001109
static LinkEntity forValueWitnessTable(CanType type) {
1101-
assert(!isEmbedded(type));
1110+
assert(!isEmbeddedWithoutEmbeddedExitentials(type));
11021111
LinkEntity entity;
11031112
entity.setForType(Kind::ValueWitnessTable, type);
11041113
return entity;

lib/IRGen/ClassMetadataVisitor.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ template <class Impl> class ClassMetadataVisitor
7777
// The regular `layout` method can be used for layout tasks for which the
7878
// actual superclass pointer is not relevant.
7979
void layoutEmbedded(CanType classTy) {
80+
if (IGM.Context.LangOpts.hasFeature(Feature::EmbeddedExistentials))
81+
asImpl().addValueWitnessTable();
8082
asImpl().noteAddressPoint();
8183
asImpl().addEmbeddedSuperclass(classTy);
8284
asImpl().addDestructorFunction();
@@ -89,6 +91,8 @@ template <class Impl> class ClassMetadataVisitor
8991
"Adjustment index must be synchronized with this layout");
9092

9193
if (IGM.Context.LangOpts.hasFeature(Feature::Embedded)) {
94+
if (IGM.Context.LangOpts.hasFeature(Feature::EmbeddedExistentials))
95+
asImpl().addValueWitnessTable();
9296
asImpl().noteAddressPoint();
9397
asImpl().addSuperclass();
9498
asImpl().addDestructorFunction();

lib/IRGen/EnumMetadataVisitor.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ template <class Impl> class EnumMetadataVisitor
4343
: super(IGM), Target(target) {}
4444

4545
public:
46+
47+
void embeddedLayout() {
48+
// The embedded layout consists of:
49+
// + // -1 : vwt
50+
// + // 0 : metadata flags
51+
super::layout();
52+
}
53+
4654
void layout() {
4755
static_assert(MetadataAdjustmentIndex::ValueType == 2,
4856
"Adjustment index must be synchronized with this layout");

lib/IRGen/GenDecl.cpp

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1361,7 +1361,9 @@ deleteAndReenqueueForEmissionValuesDependentOnCanonicalPrespecializedMetadataRec
13611361
void IRGenerator::emitLazyDefinitions() {
13621362
if (SIL.getASTContext().LangOpts.hasFeature(Feature::Embedded)) {
13631363
// In embedded Swift, the compiler cannot emit any metadata, etc.
1364-
assert(LazyTypeMetadata.empty());
1364+
// Other than to support existentials.
1365+
assert(LazyTypeMetadata.empty() ||
1366+
SIL.getASTContext().LangOpts.hasFeature(Feature::EmbeddedExistentials));
13651367
assert(LazySpecializedTypeMetadataRecords.empty());
13661368
assert(LazyTypeContextDescriptors.empty());
13671369
assert(LazyOpaqueTypeDescriptors.empty());
@@ -1388,7 +1390,8 @@ void IRGenerator::emitLazyDefinitions() {
13881390
!LazyCanonicalSpecializedMetadataAccessors.empty() ||
13891391
!LazyMetadataAccessors.empty() ||
13901392
!LazyClassMetadata.empty() ||
1391-
!LazySpecializedClassMetadata.empty()
1393+
!LazySpecializedClassMetadata.empty() ||
1394+
!LazySpecializedValueMetadata.empty()
13921395
) {
13931396
// Emit any lazy type metadata we require.
13941397
while (!LazyTypeMetadata.empty()) {
@@ -1514,6 +1517,12 @@ void IRGenerator::emitLazyDefinitions() {
15141517
CurrentIGMPtr IGM = getGenModule(classType->getClassOrBoundGenericClass());
15151518
emitLazySpecializedClassMetadata(*IGM.get(), classType);
15161519
}
1520+
1521+
while(!LazySpecializedValueMetadata.empty()) {
1522+
CanType valueType = LazySpecializedValueMetadata.pop_back_val();
1523+
CurrentIGMPtr IGM = getGenModule(valueType->getNominalOrBoundGenericNominal());
1524+
emitLazySpecializedValueMetadata(*IGM.get(), valueType);
1525+
}
15171526
}
15181527

15191528
FinishedEmittingLazyDefinitions = true;
@@ -1580,6 +1589,14 @@ bool IRGenerator::hasLazyMetadata(TypeDecl *type) {
15801589
if (found != HasLazyMetadata.end())
15811590
return found->second;
15821591

1592+
if (SIL.getASTContext().LangOpts.hasFeature(Feature::EmbeddedExistentials) &&
1593+
(isa<StructDecl>(type) || isa<EnumDecl>(type))) {
1594+
bool isGeneric = cast<NominalTypeDecl>(type)->isGenericContext();
1595+
HasLazyMetadata[type] = !isGeneric;
1596+
1597+
return !isGeneric;
1598+
}
1599+
15831600
auto canBeLazy = [&]() -> bool {
15841601
auto *dc = type->getDeclContext();
15851602
if (isa<ClangModuleUnit>(dc->getModuleScopeContext())) {
@@ -1628,11 +1645,17 @@ void IRGenerator::noteUseOfClassMetadata(CanType classType) {
16281645
}
16291646

16301647
void IRGenerator::noteUseOfSpecializedClassMetadata(CanType classType) {
1631-
if (LazilyEmittedSpecializedClassMetadata.insert(classType.getPointer()).second) {
1648+
if (LazilyEmittedSpecializedMetadata.insert(classType.getPointer()).second) {
16321649
LazySpecializedClassMetadata.push_back(classType);
16331650
}
16341651
}
16351652

1653+
void IRGenerator::noteUseOfSpecializedValueMetadata(CanType valueType) {
1654+
if (LazilyEmittedSpecializedMetadata.insert(valueType.getPointer()).second) {
1655+
LazySpecializedValueMetadata.push_back(valueType);
1656+
}
1657+
}
1658+
16361659
void IRGenerator::noteUseOfTypeGlobals(NominalTypeDecl *type,
16371660
bool isUseOfMetadata,
16381661
RequireMetadata_t requireMetadata) {
@@ -5295,9 +5318,12 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(
52955318
: LinkEntity::forTypeMetadata(
52965319
concreteType, TypeMetadataAddress::FullMetadata));
52975320

5298-
if (Context.LangOpts.hasFeature(Feature::Embedded)) {
5321+
if (Context.LangOpts.hasFeature(Feature::Embedded) ) {
52995322
entity = LinkEntity::forTypeMetadata(concreteType,
53005323
TypeMetadataAddress::AddressPoint);
5324+
if (Context.LangOpts.hasFeature(Feature::EmbeddedExistentials))
5325+
entity = LinkEntity::forTypeMetadata(concreteType,
5326+
TypeMetadataAddress::FullMetadata);
53015327
}
53025328

53035329
auto DbgTy = DebugTypeInfo::getGlobalMetadata(MetatypeType::get(concreteType),
@@ -5320,7 +5346,8 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(
53205346
LinkInfo link = LinkInfo::get(*this, entity, ForDefinition);
53215347
markGlobalAsUsedBasedOnLinkage(*this, link, var);
53225348

5323-
if (Context.LangOpts.hasFeature(Feature::Embedded)) {
5349+
if (Context.LangOpts.hasFeature(Feature::Embedded) &&
5350+
!Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) {
53245351
return var;
53255352
}
53265353

@@ -5331,12 +5358,15 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(
53315358
if (auto nominal = concreteType->getAnyNominal()) {
53325359
// Keep type metadata around for all types (except @_objcImplementation,
53335360
// since we're using ObjC metadata for that).
5334-
if (!isObjCImpl)
5361+
if (!isObjCImpl &&
5362+
!Context.LangOpts.hasFeature(Feature::EmbeddedExistentials))
53355363
addRuntimeResolvableType(nominal);
53365364

53375365
// Don't define the alias for foreign type metadata, prespecialized
53385366
// generic metadata, or @_objcImplementation classes, since they're not ABI.
5339-
if (requiresForeignTypeMetadata(nominal) || isPrespecialized || isObjCImpl)
5367+
if (requiresForeignTypeMetadata(nominal) ||
5368+
(isPrespecialized && !Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) ||
5369+
isObjCImpl)
53405370
return var;
53415371

53425372
// Native Swift class metadata has a destructor before the address point.
@@ -5349,6 +5379,10 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(
53495379
}
53505380
}
53515381

5382+
if (Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) {
5383+
adjustmentIndex = MetadataAdjustmentIndex::EmbeddedWithExistentials;
5384+
}
5385+
53525386
llvm::Constant *indices[] = {
53535387
llvm::ConstantInt::get(Int32Ty, 0),
53545388
llvm::ConstantInt::get(Int32Ty, adjustmentIndex)};
@@ -5390,7 +5424,10 @@ IRGenModule::getAddrOfTypeMetadata(CanType concreteType,
53905424

53915425
llvm::Type *defaultVarTy;
53925426
unsigned adjustmentIndex;
5393-
if (concreteType->isAny() || concreteType->isAnyObject() || concreteType->isVoid() || concreteType->is<TupleType>() || concreteType->is<BuiltinType>()) {
5427+
if (Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) {
5428+
adjustmentIndex = 0;
5429+
defaultVarTy = EmbeddedExistentialsMetadataStructTy;
5430+
} else if (concreteType->isAny() || concreteType->isAnyObject() || concreteType->isVoid() || concreteType->is<TupleType>() || concreteType->is<BuiltinType>()) {
53945431
defaultVarTy = FullExistentialTypeMetadataStructTy;
53955432
adjustmentIndex = MetadataAdjustmentIndex::NoTypeLayoutString;
53965433
} else if (fullMetadata) {
@@ -5433,6 +5470,18 @@ IRGenModule::getAddrOfTypeMetadata(CanType concreteType,
54335470
}
54345471
}
54355472
}
5473+
5474+
if (Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) {
5475+
if ((isa<StructDecl>(nominal) || isa<EnumDecl>(nominal)) &&
5476+
nominal->isGenericContext()) {
5477+
IRGen.noteUseOfSpecializedValueMetadata(concreteType);
5478+
}
5479+
}
5480+
}
5481+
5482+
if (Context.LangOpts.hasFeature(Feature::EmbeddedExistentials) &&
5483+
isa<TupleType>(concreteType)) {
5484+
IRGen.noteUseOfSpecializedValueMetadata(concreteType);
54365485
}
54375486

54385487
if (shouldPrespecializeGenericMetadata()) {

0 commit comments

Comments
 (0)