Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ struct Options {
}

var enableEmbeddedSwiftExistentials: Bool {
hasFeature(.EmbeddedExistentials)
hasFeature(.Embedded) && hasFeature(.EmbeddedExistentials)
}

var enableMergeableTraps: Bool {
Expand Down
2 changes: 2 additions & 0 deletions include/swift/AST/DiagnosticsFrontend.def
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,8 @@ ERROR(layout_string_instantiation_without_layout_strings,none,

ERROR(evolution_with_embedded,none,
"Library evolution cannot be enabled with embedded Swift.", ())
ERROR(embedded_existentials_without_embedded,none,
"EmbeddedExistentials requires enabling embedded Swift.", ())
ERROR(wmo_with_embedded,none,
"Whole module optimization (wmo) must be enabled with embedded Swift.", ())
ERROR(objc_with_embedded,none,
Expand Down
4 changes: 3 additions & 1 deletion include/swift/IRGen/Linking.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,10 @@ inline bool isEmbeddedWithoutEmbeddedExitentials(CanType t) {
// expect for classes (both generic and non-generic), dynamic self, and
// class-bound existentials.
inline bool isMetadataAllowedInEmbedded(CanType t) {
auto &langOpts = t->getASTContext().LangOpts;
bool embeddedExistentials =
t->getASTContext().LangOpts.hasFeature(Feature::EmbeddedExistentials);
langOpts.hasFeature(Feature::EmbeddedExistentials) &&
langOpts.hasFeature(Feature::Embedded);

if (isa<ClassType>(t) || isa<BoundGenericClassType>(t) ||
isa<DynamicSelfType>(t)) {
Expand Down
5 changes: 5 additions & 0 deletions lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1838,6 +1838,11 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
}
Opts.BypassResilienceChecks |= Args.hasArg(OPT_bypass_resilience);

if (Opts.hasFeature(Feature::EmbeddedExistentials) &&
!Opts.hasFeature(Feature::Embedded)) {
Diags.diagnose(SourceLoc(), diag::embedded_existentials_without_embedded);
HadError = true;
}
if (Opts.hasFeature(Feature::Embedded)) {
Opts.UnavailableDeclOptimizationMode = UnavailableDeclOptimization::Complete;
Opts.DisableImplicitStringProcessingModuleImport = true;
Expand Down
4 changes: 2 additions & 2 deletions lib/IRGen/ClassMetadataVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ template <class Impl> class ClassMetadataVisitor
// The regular `layout` method can be used for layout tasks for which the
// actual superclass pointer is not relevant.
void layoutEmbedded(CanType classTy) {
if (IGM.Context.LangOpts.hasFeature(Feature::EmbeddedExistentials))
if (IGM.isEmbeddedWithExistentials())
asImpl().addValueWitnessTable();
asImpl().noteAddressPoint();
asImpl().addEmbeddedSuperclass(classTy);
Expand All @@ -91,7 +91,7 @@ template <class Impl> class ClassMetadataVisitor
"Adjustment index must be synchronized with this layout");

if (IGM.Context.LangOpts.hasFeature(Feature::Embedded)) {
if (IGM.Context.LangOpts.hasFeature(Feature::EmbeddedExistentials))
if (IGM.isEmbeddedWithExistentials())
asImpl().addValueWitnessTable();
asImpl().noteAddressPoint();
asImpl().addSuperclass();
Expand Down
2 changes: 1 addition & 1 deletion lib/IRGen/GenCast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ llvm::Value *irgen::emitCheckedCast(IRGenFunction &IGF,
llvm::Value *srcMetadata = nullptr;

// Embedded swift currently only supports existential -> concrete type casts.
if (IGF.IGM.Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) {
if (IGF.IGM.isEmbeddedWithExistentials()) {
srcMetadata = llvm::ConstantPointerNull::get(IGF.IGM.TypeMetadataPtrTy);
} else {
srcMetadata = IGF.emitTypeMetadataRef(srcType);
Expand Down
7 changes: 3 additions & 4 deletions lib/IRGen/GenClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1051,18 +1051,17 @@ void IRGenModule::emitClassDecl(ClassDecl *D) {
auto &resilientLayout =
classTI.getClassLayout(*this, selfType, /*forBackwardDeployment=*/false);

auto isEmbeddedWithExistentials =
Context.LangOpts.hasFeature(Feature::EmbeddedExistentials);
auto hasEmbeddedWithExistentials = isEmbeddedWithExistentials();

// As a matter of policy, class metadata is never emitted lazily for now.
assert(isEmbeddedWithExistentials || !IRGen.hasLazyMetadata(D));
assert(hasEmbeddedWithExistentials || !IRGen.hasLazyMetadata(D));

// Emit the class metadata.
if (!D->getASTContext().LangOpts.hasFeature(Feature::Embedded)) {
emitClassMetadata(*this, D, fragileLayout, resilientLayout);
emitFieldDescriptor(D);
} else {
if (!isEmbeddedWithExistentials && !D->isGenericContext()) {
if (!hasEmbeddedWithExistentials && !D->isGenericContext()) {
emitEmbeddedClassMetadata(*this, D);
} else {
// We create all metadata lazily in embedded with existentials mode.
Expand Down
28 changes: 15 additions & 13 deletions lib/IRGen/GenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1588,8 +1588,10 @@ bool IRGenerator::hasLazyMetadata(TypeDecl *type) {
auto found = HasLazyMetadata.find(type);
if (found != HasLazyMetadata.end())
return found->second;

if (SIL.getASTContext().LangOpts.hasFeature(Feature::EmbeddedExistentials) &&
auto &langOpts = SIL.getASTContext().LangOpts;
auto isEmbeddedWithExistentials = langOpts.hasFeature(Feature::Embedded) &&
langOpts.hasFeature(Feature::EmbeddedExistentials);
if (isEmbeddedWithExistentials &&
(isa<StructDecl>(type) || isa<EnumDecl>(type))) {
bool isGeneric = cast<NominalTypeDecl>(type)->isGenericContext();
HasLazyMetadata[type] = !isGeneric;
Expand Down Expand Up @@ -5308,7 +5310,7 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(

return cast<llvm::GlobalValue>(addr);
}

bool hasEmbeddedExistentials = isEmbeddedWithExistentials();
auto entity =
(isPrespecialized &&
!irgen::isCanonicalInitializableTypeMetadataStaticallyAddressable(
Expand All @@ -5324,7 +5326,7 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(
if (Context.LangOpts.hasFeature(Feature::Embedded)) {
entity = LinkEntity::forTypeMetadata(concreteType,
TypeMetadataAddress::AddressPoint);
if (Context.LangOpts.hasFeature(Feature::EmbeddedExistentials))
if (hasEmbeddedExistentials)
entity = LinkEntity::forTypeMetadata(concreteType,
TypeMetadataAddress::FullMetadata);
}
Expand All @@ -5350,7 +5352,7 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(
markGlobalAsUsedBasedOnLinkage(*this, link, var);

if (Context.LangOpts.hasFeature(Feature::Embedded) &&
!Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) {
!hasEmbeddedExistentials) {
return var;
}

Expand All @@ -5361,14 +5363,13 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(
if (auto nominal = concreteType->getAnyNominal()) {
// Keep type metadata around for all types (except @_objcImplementation,
// since we're using ObjC metadata for that).
if (!isObjCImpl &&
!Context.LangOpts.hasFeature(Feature::EmbeddedExistentials))
if (!isObjCImpl && !hasEmbeddedExistentials)
addRuntimeResolvableType(nominal);

// Don't define the alias for foreign type metadata, prespecialized
// generic metadata, or @_objcImplementation classes, since they're not ABI.
if (requiresForeignTypeMetadata(nominal) ||
(isPrespecialized && !Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) ||
if ((requiresForeignTypeMetadata(nominal) && !hasEmbeddedExistentials) ||
(isPrespecialized && !hasEmbeddedExistentials) ||
isObjCImpl)
return var;

Expand All @@ -5382,7 +5383,7 @@ llvm::GlobalValue *IRGenModule::defineTypeMetadata(
}
}

if (Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) {
if (hasEmbeddedExistentials) {
adjustmentIndex = MetadataAdjustmentIndex::EmbeddedWithExistentials;
}

Expand Down Expand Up @@ -5427,7 +5428,8 @@ IRGenModule::getAddrOfTypeMetadata(CanType concreteType,

llvm::Type *defaultVarTy;
unsigned adjustmentIndex;
if (Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) {
auto hasEmbeddedExistentials = isEmbeddedWithExistentials();
if (hasEmbeddedExistentials) {
adjustmentIndex = 0;
defaultVarTy = EmbeddedExistentialsMetadataStructTy;
} else if (concreteType->isAny() || concreteType->isAnyObject() || concreteType->isVoid() || concreteType->is<TupleType>() || concreteType->is<BuiltinType>()) {
Expand Down Expand Up @@ -5474,15 +5476,15 @@ IRGenModule::getAddrOfTypeMetadata(CanType concreteType,
}
}

if (Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) {
if (hasEmbeddedExistentials) {
if ((isa<StructDecl>(nominal) || isa<EnumDecl>(nominal)) &&
nominal->isGenericContext()) {
IRGen.noteUseOfSpecializedValueMetadata(concreteType);
}
}
}

if (Context.LangOpts.hasFeature(Feature::EmbeddedExistentials) &&
if (hasEmbeddedExistentials &&
(isa<TupleType>(concreteType) ||
isa<FunctionType>(concreteType))) {
IRGen.noteUseOfSpecializedValueMetadata(concreteType);
Expand Down
5 changes: 2 additions & 3 deletions lib/IRGen/GenExistential.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2314,7 +2314,7 @@ Address irgen::emitAllocateBoxedOpaqueExistentialBuffer(
if (fixedTI->getFixedPacking(IGF.IGM) == FixedPacking::OffsetZero) {
return valueTI.getAddressForPointer(IGF.Builder.CreateBitCast(
existentialBuffer.getAddress(), IGF.IGM.PtrTy));
} else if (IGF.IGM.Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) {
} else if (IGF.IGM.isEmbeddedWithExistentials()) {
llvm::Value *box, *address;
auto *metadata = existLayout.loadMetadataRef(IGF, existentialContainer);
IGF.emitAllocBoxCall(metadata, box, address);
Expand Down Expand Up @@ -2897,8 +2897,7 @@ static llvm::Function *getDestroyBoxedOpaqueExistentialBufferFunction(
Builder.CreateBitCast(buffer.getAddress(), IGM.PtrTy);
auto *reference = Builder.CreateLoad(Address(
referenceAddr, IGM.RefCountedPtrTy, buffer.getAlignment()));
if (IGF.IGM.Context.LangOpts
.hasFeature(Feature::EmbeddedExistentials)) {
if (IGF.IGM.isEmbeddedWithExistentials()) {
IGF.emitReleaseBox(reference);
} else
IGF.emitNativeStrongRelease(reference, IGF.getDefaultAtomicity());
Expand Down
54 changes: 33 additions & 21 deletions lib/IRGen/GenMeta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2973,7 +2973,7 @@ void irgen::emitLazyTypeContextDescriptor(IRGenModule &IGM,
void irgen::emitLazyTypeMetadata(IRGenModule &IGM, NominalTypeDecl *type) {
// Embedded existentials emit very spares metadata records and don't have type
// context descriptors.
if (!type->getASTContext().LangOpts.hasFeature(Feature::EmbeddedExistentials))
if (!IGM.isEmbeddedWithExistentials())
eraseExistingTypeContextDescriptor(IGM, type);

if (requiresForeignTypeMetadata(type)) {
Expand Down Expand Up @@ -4270,7 +4270,7 @@ namespace {
auto type = (Target->checkAncestry(AncestryFlags::ObjC)
? IGM.Context.getAnyObjectType()
: IGM.Context.TheNativeObjectType);
if (IGM.Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) {
if (IGM.isEmbeddedWithExistentials()) {
return irgen::emitValueWitnessTable(IGM, type, false, false);
}
auto wtable = IGM.getAddrOfValueWitnessTable(type);
Expand Down Expand Up @@ -5577,9 +5577,8 @@ void irgen::emitLazyClassMetadata(IRGenModule &IGM, CanType classTy) {
// Might already be emitted, skip if that's the case.
auto entity =
LinkEntity::forTypeMetadata(classTy, TypeMetadataAddress::AddressPoint);

auto isEmbeddedWithExistentials = IGM.Context.LangOpts.hasFeature(Feature::EmbeddedExistentials);
if (isEmbeddedWithExistentials) {
auto hasEmbeddedWithExistentials = IGM.isEmbeddedWithExistentials();
if (hasEmbeddedWithExistentials) {
entity = LinkEntity::forTypeMetadata(classTy, TypeMetadataAddress::FullMetadata);
}
auto *existingVar = cast<llvm::GlobalVariable>(
Expand All @@ -5588,7 +5587,7 @@ void irgen::emitLazyClassMetadata(IRGenModule &IGM, CanType classTy) {
return;
}

if (isEmbeddedWithExistentials) {
if (hasEmbeddedWithExistentials) {
emitEmbeddedClassMetadata(IGM, classTy->getClassOrBoundGenericClass());
return;
}
Expand Down Expand Up @@ -6225,8 +6224,7 @@ void irgen::emitStructMetadata(IRGenModule &IGM, StructDecl *structDecl) {

bool isPattern;
bool canBeConstant;
bool hasEmbeddedExistentialFeature =
IGM.Context.LangOpts.hasFeature(Feature::EmbeddedExistentials);
bool hasEmbeddedExistentialFeature = IGM.isEmbeddedWithExistentials();
if (structDecl->isGenericContext()) {
assert(!hasEmbeddedExistentialFeature);
GenericStructMetadataBuilder builder(IGM, structDecl, init);
Expand Down Expand Up @@ -6268,7 +6266,7 @@ void irgen::emitSpecializedGenericStructMetadata(IRGenModule &IGM, CanType type,
bool isPattern = false;

SpecializedGenericStructMetadataBuilder builder(IGM, type, decl, init);
if (IGM.Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) {
if (IGM.isEmbeddedWithExistentials()) {
builder.embeddedLayout();
} else {
builder.layout();
Expand Down Expand Up @@ -6315,7 +6313,7 @@ class TupleMetadataBuilder : public TupleMetadataVisitor<TupleMetadataBuilder> {
};
} // end anonymous namespace
void irgen::emitLazyTupleMetadata(IRGenModule &IGM, CanType tupleTy) {
assert(IGM.Context.LangOpts.hasFeature(Feature::EmbeddedExistentials));
assert(IGM.isEmbeddedWithExistentials());
assert(isa<TupleType>(tupleTy));

Type ty = tupleTy.getPointer();
Expand Down Expand Up @@ -6374,7 +6372,7 @@ class FunctionMetadataBuilder : public FunctionMetadataVisitor<FunctionMetadataB
} // end anonymous namespace

void irgen::emitLazyFunctionMetadata(IRGenModule &IGM, CanType funTy) {
assert(IGM.Context.LangOpts.hasFeature(Feature::EmbeddedExistentials));
assert(IGM.isEmbeddedWithExistentials());
assert(isa<FunctionType>(funTy));

Type ty = funTy.getPointer();
Expand Down Expand Up @@ -6771,8 +6769,7 @@ void irgen::emitEnumMetadata(IRGenModule &IGM, EnumDecl *theEnum) {

bool isPattern;
bool canBeConstant;
bool hasEmbeddedExistentialFeature =
IGM.Context.LangOpts.hasFeature(Feature::EmbeddedExistentials);
bool hasEmbeddedExistentialFeature = IGM.isEmbeddedWithExistentials();
if (theEnum->isGenericContext()) {
assert(!hasEmbeddedExistentialFeature);
GenericEnumMetadataBuilder builder(IGM, theEnum, init);
Expand Down Expand Up @@ -6813,7 +6810,8 @@ void irgen::emitSpecializedGenericEnumMetadata(IRGenModule &IGM, CanType type,
init.setPacked(true);

SpecializedGenericEnumMetadataBuilder builder(IGM, type, decl, init);
if (IGM.Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) {

if (IGM.isEmbeddedWithExistentials()) {
builder.embeddedLayout();
} else {
builder.layout();
Expand Down Expand Up @@ -7202,46 +7200,60 @@ void irgen::emitForeignTypeMetadata(IRGenModule &IGM, NominalTypeDecl *decl) {
auto init = builder.beginStruct();
init.setPacked(true);

auto isEmbedded = IGM.isEmbeddedWithExistentials();

if (auto classDecl = dyn_cast<ClassDecl>(decl)) {
if (classDecl->isForeignReferenceType()) {
assert(!isEmbedded && "emitting foregin reference type not supported");
ForeignReferenceTypeMetadataBuilder builder(IGM, classDecl, init);
builder.layout();

IGM.defineTypeMetadata(type, /*isPattern=*/false,
builder.canBeConstant(),
init.finishAndCreateFuture());
builder.createMetadataAccessFunction();
if (!isEmbedded)
builder.createMetadataAccessFunction();
} else {
assert(classDecl->getForeignClassKind() == ClassDecl::ForeignKind::CFType);
assert(!isEmbedded && "emitting foregin cf class type not supported");

ForeignClassMetadataBuilder builder(IGM, classDecl, init);
builder.layout();

IGM.defineTypeMetadata(type, /*isPattern=*/false,
builder.canBeConstant(),
init.finishAndCreateFuture());
builder.createMetadataAccessFunction();
if (!isEmbedded)
builder.createMetadataAccessFunction();
}
} else if (auto structDecl = dyn_cast<StructDecl>(decl)) {
assert(isa<ClangModuleUnit>(structDecl->getModuleScopeContext()));

ForeignStructMetadataBuilder builder(IGM, structDecl, init);
builder.layout();
if (isEmbedded)
builder.embeddedLayout();
else
builder.layout();

IGM.defineTypeMetadata(type, /*isPattern=*/false,
builder.canBeConstant(),
init.finishAndCreateFuture());
builder.createMetadataAccessFunction();
if (!isEmbedded)
builder.createMetadataAccessFunction();
} else if (auto enumDecl = dyn_cast<EnumDecl>(decl)) {
assert(enumDecl->hasClangNode());

ForeignEnumMetadataBuilder builder(IGM, enumDecl, init);
builder.layout();
if (isEmbedded)
builder.embeddedLayout();
else
builder.layout();

IGM.defineTypeMetadata(type, /*isPattern=*/false,
builder.canBeConstant(),
init.finishAndCreateFuture());
builder.createMetadataAccessFunction();
if (!isEmbedded)
builder.createMetadataAccessFunction();
} else {
llvm_unreachable("foreign metadata for unexpected type?!");
}
Expand Down
4 changes: 2 additions & 2 deletions lib/IRGen/GenProto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1756,7 +1756,7 @@ class AccessorConformanceInfo : public ConformanceInfo {
else
typeWitness = Conformance.getTypeWitness(assocType);

if (IGM.Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) {
if (IGM.isEmbeddedWithExistentials()) {
// In Embedded Swift associated type witness point to the metadata.
llvm::Constant *witnessEntry = IGM.getAddrOfTypeMetadata(
typeWitness->getCanonicalType());
Expand Down Expand Up @@ -4558,7 +4558,7 @@ irgen::emitAssociatedTypeMetadataRef(IRGenFunction &IGF,

// Im embedded with existentials mode the type metadata is directly referenced
// by the witness table.
if (IGF.IGM.Context.LangOpts.hasFeature(Feature::EmbeddedExistentials)) {
if (IGM.isEmbeddedWithExistentials()) {
auto proto = assocType->getProtocol();
assert(!IGF.IGM.isResilient(proto, ResilienceExpansion::Maximal));
assert(!IGF.IGM.IRGen.Opts.UseRelativeProtocolWitnessTables);
Expand Down
Loading