Skip to content

[Runtime+IRGen] Instantiate layout strings for generic multi payload … #66621

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 14, 2023
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
6 changes: 6 additions & 0 deletions include/swift/Runtime/Enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ void swift_initEnumMetadataMultiPayload(EnumMetadata *enumType,
unsigned numPayloads,
const TypeLayout * const *payloadTypes);

SWIFT_RUNTIME_EXPORT
void swift_initEnumMetadataMultiPayloadWithLayoutString(EnumMetadata *enumType,
EnumLayoutFlags flags,
unsigned numPayloads,
const Metadata * const *payloadTypes);

/// Return an integer value representing which case of a multi-payload
/// enum is inhabited.
///
Expand Down
17 changes: 16 additions & 1 deletion include/swift/Runtime/RuntimeFunctions.def
Original file line number Diff line number Diff line change
Expand Up @@ -1276,7 +1276,8 @@ FUNCTION(InitStructMetadata,
// void swift_initStructMetadataWithLayoutString(Metadata *structType,
// StructLayoutFlags flags,
// size_t numFields,
// Metadata * const *fieldTypes,
// uint8_t * const *fieldTypes,
// const uint8_t *fieldTags
// uint32_t *fieldOffsets);
FUNCTION(InitStructMetadataWithLayoutString,
swift_initStructMetadataWithLayoutString, C_CC, AlwaysAvailable,
Expand Down Expand Up @@ -1312,6 +1313,7 @@ FUNCTION(InitEnumMetadataSinglePayload,
EFFECT(MetaData))

// void swift_initEnumMetadataMultiPayload(Metadata *enumType,
// EnumLayoutFlags layoutFlags,
// size_t numPayloads,
// TypeLayout * const *payloadTypes);
FUNCTION(InitEnumMetadataMultiPayload,
Expand All @@ -1322,6 +1324,19 @@ FUNCTION(InitEnumMetadataMultiPayload,
ATTRS(NoUnwind, WillReturn),
EFFECT(MetaData))

// void
// swift_initEnumMetadataMultiPayloadWithLayoutString(Metadata *enumType,
// EnumLayoutFlags layoutFlags,
// size_t numPayloads,
// Metadata * const *payloadTypes);
FUNCTION(InitEnumMetadataMultiPayloadWithLayoutString,
swift_initEnumMetadataMultiPayloadWithLayoutString,
C_CC, AlwaysAvailable,
RETURNS(VoidTy),
ARGS(TypeMetadataPtrTy, SizeTy, SizeTy, TypeMetadataPtrPtrTy),
ATTRS(NoUnwind, WillReturn),
EFFECT(MetaData))

// int swift_getEnumCaseMultiPayload(opaque_t *obj, Metadata *enumTy);
FUNCTION(GetEnumCaseMultiPayload,
swift_getEnumCaseMultiPayload,
Expand Down
84 changes: 84 additions & 0 deletions lib/IRGen/GenEnum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,15 @@ namespace {
metadata);
}

void initializeMetadataWithLayoutString(IRGenFunction &IGF,
llvm::Value *metadata,
bool isVWTMutable,
SILType T,
MetadataDependencyCollector *collector) const override {
// Not yet supported on this type, so forward to regular method
initializeMetadata(IGF, metadata, isVWTMutable, T, collector);
}

bool mayHaveExtraInhabitants(IRGenModule &IGM) const override {
// FIXME: Hold off on registering extra inhabitants for dynamic enums
// until initializeMetadata handles them.
Expand Down Expand Up @@ -964,6 +973,15 @@ namespace {
// witness table initialization.
}

void initializeMetadataWithLayoutString(IRGenFunction &IGF,
llvm::Value *metadata,
bool isVWTMutable,
SILType T,
MetadataDependencyCollector *collector) const override {
// No-payload enums are always fixed-size so never need dynamic value
// witness table initialization.
}

/// \group Required for SingleScalarTypeInfo

llvm::Type *getScalarType() const {
Expand Down Expand Up @@ -3189,6 +3207,15 @@ namespace {
{metadata, flags, payloadLayout, emptyCasesVal});
}

void initializeMetadataWithLayoutString(IRGenFunction &IGF,
llvm::Value *metadata,
bool isVWTMutable,
SILType T,
MetadataDependencyCollector *collector) const override {
// Not yet supported on this type, so forward to regular method
initializeMetadata(IGF, metadata, isVWTMutable, T, collector);
}

/// \group Extra inhabitants

// Extra inhabitants from the payload that we didn't use for our empty cases
Expand Down Expand Up @@ -5259,6 +5286,36 @@ namespace {
return firstAddr;
}

llvm::Value *emitPayloadMetadataArray(IRGenFunction &IGF, SILType T,
MetadataDependencyCollector *collector) const {
auto numPayloads = ElementsWithPayload.size();
auto metadataBufferTy = llvm::ArrayType::get(IGM.TypeMetadataPtrTy,
numPayloads);
auto metadataBuffer = IGF.createAlloca(metadataBufferTy,
IGM.getPointerAlignment(),
"payload_types");
llvm::Value *firstAddr = nullptr;
for (unsigned i = 0; i < numPayloads; ++i) {
auto &elt = ElementsWithPayload[i];
Address eltAddr = IGF.Builder.CreateStructGEP(metadataBuffer, i,
IGM.getPointerSize() * i);
if (i == 0) firstAddr = eltAddr.getAddress();

auto payloadTy =
T.getEnumElementType(elt.decl, IGF.getSILModule(),
IGF.IGM.getMaximalTypeExpansionContext());

auto request = DynamicMetadataRequest::getNonBlocking(
MetadataState::LayoutComplete, collector);
auto metadata = IGF.emitTypeMetadataRefForLayout(payloadTy, request);

IGF.Builder.CreateStore(metadata, eltAddr);
}
assert(firstAddr && "Expected firstAddr to be assigned to");

return firstAddr;
}

void initializeMetadata(IRGenFunction &IGF,
llvm::Value *metadata,
bool isVWTMutable,
Expand All @@ -5278,6 +5335,25 @@ namespace {
{metadata, flags, numPayloadsVal, payloadLayoutArray});
}

void initializeMetadataWithLayoutString(IRGenFunction &IGF,
llvm::Value *metadata,
bool isVWTMutable,
SILType T,
MetadataDependencyCollector *collector) const override {
// Fixed-size enums don't need dynamic metadata initialization.
if (TIK >= Fixed) return;

// Ask the runtime to set up the metadata record for a dynamic enum.
auto payloadLayoutArray = emitPayloadMetadataArray(IGF, T, collector);
auto numPayloadsVal = llvm::ConstantInt::get(IGM.SizeTy,
ElementsWithPayload.size());

auto flags = emitEnumLayoutFlags(IGM, isVWTMutable);
IGF.Builder.CreateCall(
IGM.getInitEnumMetadataMultiPayloadWithLayoutStringFunctionPointer(),
{metadata, flags, numPayloadsVal, payloadLayoutArray});
}

/// \group Extra inhabitants

// If we didn't use all of the available tag bit representations, offer
Expand Down Expand Up @@ -5959,6 +6035,14 @@ namespace {
llvm_unreachable("resilient enums cannot be defined");
}

void initializeMetadataWithLayoutString(IRGenFunction &IGF,
llvm::Value *metadata,
bool isVWTMutable,
SILType T,
MetadataDependencyCollector *collector) const override {
llvm_unreachable("resilient enums cannot be defined");
}

/// \group Extra inhabitants

bool mayHaveExtraInhabitants(IRGenModule &) const override {
Expand Down
6 changes: 6 additions & 0 deletions lib/IRGen/GenEnum.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,12 @@ class EnumImplStrategy {
SILType T,
MetadataDependencyCollector *collector) const = 0;

virtual void initializeMetadataWithLayoutString(IRGenFunction &IGF,
llvm::Value *metadata,
bool isVWTMutable,
SILType T,
MetadataDependencyCollector *collector) const = 0;

virtual bool mayHaveExtraInhabitants(IRGenModule &IGM) const = 0;

// Only ever called for fixed types.
Expand Down
44 changes: 35 additions & 9 deletions lib/IRGen/GenMeta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3003,16 +3003,17 @@ static void emitInitializeValueMetadata(IRGenFunction &IGF,
MetadataDependencyCollector *collector) {
auto &IGM = IGF.IGM;
auto loweredTy = IGM.getLoweredType(nominalDecl->getDeclaredTypeInContext());
bool useLayoutStrings = IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnesses) &&
IGM.Context.LangOpts.hasFeature(
Feature::LayoutStringValueWitnessesInstantiation) &&
IGM.getOptions().EnableLayoutStringValueWitnesses &&
IGM.getOptions().EnableLayoutStringValueWitnessesInstantiation;

if (isa<StructDecl>(nominalDecl)) {
auto &fixedTI = IGM.getTypeInfo(loweredTy);
if (isa<FixedTypeInfo>(fixedTI)) return;

if (IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnesses) &&
IGM.Context.LangOpts.hasFeature(
Feature::LayoutStringValueWitnessesInstantiation) &&
IGM.getOptions().EnableLayoutStringValueWitnesses &&
IGM.getOptions().EnableLayoutStringValueWitnessesInstantiation) {
if (useLayoutStrings) {
emitInitializeFieldOffsetVectorWithLayoutString(IGF, loweredTy, metadata,
isVWTMutable, collector);
} else {
Expand All @@ -3021,9 +3022,16 @@ static void emitInitializeValueMetadata(IRGenFunction &IGF,
}
} else {
assert(isa<EnumDecl>(nominalDecl));

auto &strategy = getEnumImplStrategy(IGM, loweredTy);
strategy.initializeMetadata(IGF, metadata, isVWTMutable, loweredTy,
collector);

if (useLayoutStrings) {
strategy.initializeMetadataWithLayoutString(IGF, metadata, isVWTMutable,
loweredTy, collector);
} else {
strategy.initializeMetadata(IGF, metadata, isVWTMutable, loweredTy,
collector);
}
}
}

Expand Down Expand Up @@ -5721,10 +5729,28 @@ namespace {
return {global, offset, structSize};
}

bool hasLayoutString() {
if (!IGM.Context.LangOpts.hasFeature(
Feature::LayoutStringValueWitnesses) ||
!IGM.getOptions().EnableLayoutStringValueWitnesses) {
return false;
}

auto &strategy = getEnumImplStrategy(IGM, getLoweredType());

return !!getLayoutString() ||
(IGM.Context.LangOpts.hasFeature(
Feature::LayoutStringValueWitnessesInstantiation) &&
IGM.getOptions().EnableLayoutStringValueWitnessesInstantiation &&
(HasDependentVWT || HasDependentMetadata) &&
!isa<FixedTypeInfo>(IGM.getTypeInfo(getLoweredType())) &&
strategy.getElementsWithPayload().size() > 1);
}

llvm::Constant *emitNominalTypeDescriptor() {
return EnumContextDescriptorBuilder(
IGM, Target, RequireMetadata,
/*hasLayoutString*/ !!getLayoutString())
/*hasLayoutString*/ hasLayoutString())
.emit();
}

Expand All @@ -5746,7 +5772,7 @@ namespace {

bool hasCompletionFunction() {
return !isa<FixedTypeInfo>(IGM.getTypeInfo(getLoweredType())) ||
!!getLayoutString();
hasLayoutString();
}
};

Expand Down
3 changes: 3 additions & 0 deletions lib/IRGen/GenValueWitness.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,9 @@ bool isRuntimeInstatiatedLayoutString(IRGenModule &IGM,
IGM.Context.LangOpts.hasFeature(
Feature::LayoutStringValueWitnessesInstantiation) &&
IGM.getOptions().EnableLayoutStringValueWitnessesInstantiation) {
if (auto *enumEntry = typeLayoutEntry->getAsEnum()) {
return enumEntry->isMultiPayloadEnum();
}
return (typeLayoutEntry->isAlignedGroup() &&
!typeLayoutEntry->isFixedSize(IGM));
}
Expand Down
1 change: 1 addition & 0 deletions lib/IRGen/TypeLayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class LayoutStringBuilder {
MultiPayloadEnumFN = 0x13,
// reserved
// MultiPayloadEnumFNResolved = 0x14,
// MultiPayloadEnumGeneric = 0x15,

Skip = 0x80,
// We may use the MSB as flag that a count follows,
Expand Down
Loading