Skip to content

Commit 17447a3

Browse files
Merge pull request #85551 from aschwaighofer/wip_embedded_exit
Preliminary support for existential in embedded Swift
2 parents 4992c7a + a725de5 commit 17447a3

21 files changed

+722
-46
lines changed

include/swift/IRGen/Linking.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,18 @@ 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+
auto &langOpts = t->getASTContext().LangOpts;
94+
return langOpts.hasFeature(Feature::Embedded) &&
95+
!langOpts.hasFeature(Feature::EmbeddedExistentials);
96+
}
9397
// Metadata is not generated and not allowed to be referenced in Embedded Swift,
9498
// expect for classes (both generic and non-generic), dynamic self, and
9599
// class-bound existentials.
96100
inline bool isMetadataAllowedInEmbedded(CanType t) {
101+
bool embeddedExistentials =
102+
t->getASTContext().LangOpts.hasFeature(Feature::EmbeddedExistentials);
103+
97104
if (isa<ClassType>(t) || isa<BoundGenericClassType>(t) ||
98105
isa<DynamicSelfType>(t)) {
99106
return true;
@@ -106,6 +113,9 @@ inline bool isMetadataAllowedInEmbedded(CanType t) {
106113
if (archeTy->requiresClass())
107114
return true;
108115
}
116+
117+
if (embeddedExistentials)
118+
return true;
109119
return false;
110120
}
111121

@@ -117,6 +127,11 @@ inline bool isEmbedded(const ProtocolConformance *c) {
117127
return c->getType()->getASTContext().LangOpts.hasFeature(Feature::Embedded);
118128
}
119129

130+
inline bool isEmbeddedWithoutEmbeddedExitentials(const ProtocolConformance *c) {
131+
return isEmbedded(c) && !c->getType()->getASTContext().
132+
LangOpts.hasFeature(Feature::EmbeddedExistentials);
133+
}
134+
120135
/// A link entity is some sort of named declaration, combined with all
121136
/// the information necessary to distinguish specific implementations
122137
/// of the declaration from each other.
@@ -1098,7 +1113,7 @@ class LinkEntity {
10981113
}
10991114

11001115
static LinkEntity forValueWitnessTable(CanType type) {
1101-
assert(!isEmbedded(type));
1116+
assert(!isEmbeddedWithoutEmbeddedExitentials(type));
11021117
LinkEntity entity;
11031118
entity.setForType(Kind::ValueWitnessTable, type);
11041119
return entity;
@@ -1128,7 +1143,7 @@ class LinkEntity {
11281143
}
11291144

11301145
static LinkEntity forProtocolWitnessTable(const ProtocolConformance *C) {
1131-
if (isEmbedded(C)) {
1146+
if (isEmbeddedWithoutEmbeddedExitentials(C)) {
11321147
assert(C->getProtocol()->requiresClass());
11331148
}
11341149

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,14 @@ FUNCTION(NativeStrongReleaseDirect, Swift, swift_releaseDirect, SwiftDirectRR_CC
236236
EFFECT(RuntimeEffect::RefCounting, RuntimeEffect::Deallocating),
237237
UNKNOWN_MEMEFFECTS)
238238

239+
// void swift_releaseBox(void *ptr);
240+
FUNCTION(ReleaseBox, Swift, swift_releaseBox, C_CC, AlwaysAvailable,
241+
RETURNS(VoidTy),
242+
ARGS(RefCountedPtrTy),
243+
ATTRS(NoUnwind),
244+
EFFECT(RuntimeEffect::RefCounting, RuntimeEffect::Deallocating),
245+
UNKNOWN_MEMEFFECTS)
246+
239247
// void *swift_retain_n(void *ptr, int32_t n);
240248
FUNCTION(NativeStrongRetainN, Swift, swift_retain_n, C_CC, AlwaysAvailable,
241249
RETURNS(RefCountedPtrTy),

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: 56 additions & 7 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) {
@@ -5298,6 +5321,9 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(
52985321
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()) {

lib/IRGen/GenExistential.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2314,7 +2314,21 @@ Address irgen::emitAllocateBoxedOpaqueExistentialBuffer(
23142314
if (fixedTI->getFixedPacking(IGF.IGM) == FixedPacking::OffsetZero) {
23152315
return valueTI.getAddressForPointer(IGF.Builder.CreateBitCast(
23162316
existentialBuffer.getAddress(), IGF.IGM.PtrTy));
2317+
} else if (IGF.IGM.Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) {
2318+
llvm::Value *box, *address;
2319+
auto *metadata = existLayout.loadMetadataRef(IGF, existentialContainer);
2320+
IGF.emitAllocBoxCall(metadata, box, address);
2321+
llvm::Value *addressInBox =
2322+
IGF.Builder.CreateBitCast(address, IGF.IGM.OpaquePtrTy);
2323+
IGF.Builder.CreateStore(
2324+
box, Address(IGF.Builder.CreateBitCast(
2325+
existentialBuffer.getAddress(), IGF.IGM.PtrTy),
2326+
IGF.IGM.RefCountedPtrTy,
2327+
existLayout.getAlignment(IGF.IGM)));
2328+
2329+
return valueTI.getAddressForPointer(addressInBox);
23172330
}
2331+
23182332
// Otherwise, allocate a box with enough storage.
23192333
Address addr = emitAllocateExistentialBoxInBuffer(
23202334
IGF, valueType, existentialBuffer, genericEnv, "exist.box.addr",
@@ -2883,7 +2897,11 @@ static llvm::Function *getDestroyBoxedOpaqueExistentialBufferFunction(
28832897
Builder.CreateBitCast(buffer.getAddress(), IGM.PtrTy);
28842898
auto *reference = Builder.CreateLoad(Address(
28852899
referenceAddr, IGM.RefCountedPtrTy, buffer.getAlignment()));
2886-
IGF.emitNativeStrongRelease(reference, IGF.getDefaultAtomicity());
2900+
if (IGF.IGM.Context.LangOpts
2901+
.hasFeature(Feature::EmbeddedExistentials)) {
2902+
IGF.emitReleaseBox(reference);
2903+
} else
2904+
IGF.emitNativeStrongRelease(reference, IGF.getDefaultAtomicity());
28872905

28882906
Builder.CreateRetVoid();
28892907
}

lib/IRGen/GenHeap.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,6 +1274,12 @@ void IRGenFunction::emitNativeStrongRelease(llvm::Value *value,
12741274
emitUnaryRefCountCall(*this, function, value);
12751275
}
12761276

1277+
void IRGenFunction::emitReleaseBox(llvm::Value *value) {
1278+
if (doesNotRequireRefCounting(value))
1279+
return;
1280+
emitUnaryRefCountCall(*this, IGM.getReleaseBoxFn(), value);
1281+
}
1282+
12771283
void IRGenFunction::emitNativeSetDeallocating(llvm::Value *value) {
12781284
if (doesNotRequireRefCounting(value)) return;
12791285
emitUnaryRefCountCall(*this, IGM.getNativeSetDeallocatingFn(), value);

0 commit comments

Comments
 (0)