Skip to content

Fix an ABI break #74439

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 2 commits into from
Jun 15, 2024
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
28 changes: 11 additions & 17 deletions include/swift/RemoteInspection/DescriptorFinder.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,31 +93,26 @@ struct FieldDescriptorBase {
getFieldRecords() = 0;
};

// There are no longer any clients of this interface, but we
// need to keep this stubbed out until all the
// implementors have been removed. In particular, LLDB
// still implements this interface.
// TODO: Delete this after Swift 6.0 ships
struct MultiPayloadEnumDescriptorBase {
virtual ~MultiPayloadEnumDescriptorBase(){ abort(); };
virtual ~MultiPayloadEnumDescriptorBase(){};

virtual llvm::StringRef getMangledTypeName() { abort(); };
virtual llvm::StringRef getMangledTypeName() = 0;

virtual uint32_t getContentsSizeInWords() const { abort(); };
virtual uint32_t getContentsSizeInWords() const = 0;

virtual size_t getSizeInBytes() const { abort(); };
virtual size_t getSizeInBytes() const = 0;

virtual uint32_t getFlags() const { abort(); };
virtual uint32_t getFlags() const = 0;

virtual bool usesPayloadSpareBits() const { abort(); };
virtual bool usesPayloadSpareBits() const = 0;

virtual uint32_t getPayloadSpareBitMaskByteOffset() const { abort(); };
virtual uint32_t getPayloadSpareBitMaskByteOffset() const = 0;

virtual uint32_t getPayloadSpareBitMaskByteCount() const { abort(); };
virtual uint32_t getPayloadSpareBitMaskByteCount() const = 0;

virtual const uint8_t *getPayloadSpareBits() const { abort(); };
};
virtual const uint8_t *getPayloadSpareBits() const = 0;

};
/// Interface for finding type descriptors. Implementors may provide descriptors
/// that live inside or outside reflection metadata.
struct DescriptorFinder {
Expand All @@ -130,9 +125,8 @@ struct DescriptorFinder {
virtual std::unique_ptr<FieldDescriptorBase>
getFieldDescriptor(const TypeRef *TR) = 0;

// TODO: Delete this as soon as LLDB no longer attempts to override it
virtual std::unique_ptr<MultiPayloadEnumDescriptorBase>
getMultiPayloadEnumDescriptor(const TypeRef *TR) { abort(); };
getMultiPayloadEnumDescriptor(const TypeRef *TR) = 0;
};

} // namespace reflection
Expand Down
105 changes: 105 additions & 0 deletions include/swift/RemoteInspection/Records.h
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,111 @@ class BuiltinTypeDescriptor {
}
};

class MultiPayloadEnumDescriptor {
public:
const RelativeDirectPointer<const char> TypeName;

private:
// This descriptor contains a series of 32-bit words
uint32_t contents[];

// Properties are stored in `contents` at particular indexes:

// uint32_t SizeFlags;
// Upper 16 bits are the size of the contents (in 32-bit words):
// (This allows us to expand this structure in the future;
// new fields should have accessors that test whether the
// size is large enough and return "non-existent" if the
// descriptor isn't large enough to have that field.)
// Lower 16 bits are flag bits

int getSizeFlagsIndex() const { return 0; }

// uint32_t PayloadSpareBitMaskByteOffsetCount;
// Number of bytes in "payload spare bits", and
// offset of them within the payload area
// Only present if `usePayloadSpareBits()`

int getPayloadSpareBitMaskByteCountIndex() const {
return getSizeFlagsIndex() + 1;
}

// uint8_t *PayloadSpareBits;
// Variably-sized bitmask field (padded to a multiple of 4 bytes)
// Only present if `usePayloadSpareBits()`

int getPayloadSpareBitsIndex() const {
int PayloadSpareBitMaskByteCountFieldSize = usesPayloadSpareBits() ? 1 : 0;
return getPayloadSpareBitMaskByteCountIndex() + PayloadSpareBitMaskByteCountFieldSize;
}

// uint32_t foo;
// TODO: Some future field
// int getFooIndex() const {
// int PayloadSpareBitMaskFieldSize = (getPayloadSpareBitMaskByteCount() + 3) / 4;
// return getPayloadSpareBitsIndex() + PayloadSpareBitMaskFieldSize;
// }

// uint32_t getFoo() const {
// if (getFooIndex() < getContentsSizeInWords()) {
// return contents[getFooIndex()];
// } else {
// return 0; // Field isn't present
// }
// }

public:
//
// Data derived from the above...
//

uint32_t getContentsSizeInWords() const {
return contents[getSizeFlagsIndex()] >> 16;
}

size_t getSizeInBytes() const {
// assert(getContentsSizeInWords() > 0 && "Malformed MPEnum reflection record");
size_t sizeInBytes = sizeof(TypeName) + getContentsSizeInWords() * 4;
return sizeInBytes;
}

uint32_t getFlags() const {
assert(getContentsSizeInWords() > 0 && "Malformed MPEnum reflection record");
return contents[getSizeFlagsIndex()] & 0xffff;
}

bool usesPayloadSpareBits() const {
return getFlags() & 1;
}

uint32_t getPayloadSpareBitMaskByteOffset() const {
if (usesPayloadSpareBits()) {
return contents[getPayloadSpareBitMaskByteCountIndex()] >> 16;
} else {
return 0;
}
}

uint32_t getPayloadSpareBitMaskByteCount() const {
if (usesPayloadSpareBits()) {
auto byteCount = contents[getPayloadSpareBitMaskByteCountIndex()] & 0xffff;
assert(getContentsSizeInWords() >= 2 + (byteCount + 3) / 4
&& "Malformed MPEnum reflection record: mask bigger than record");
return byteCount;
} else {
return 0;
}
}

const uint8_t *getPayloadSpareBits() const {
if (usesPayloadSpareBits()) {
return reinterpret_cast<const uint8_t *>(&contents[getPayloadSpareBitsIndex()]);
} else {
return nullptr;
}
}
};

class CaptureTypeRecord {
public:
const RelativeDirectPointer<const char> MangledTypeName;
Expand Down
27 changes: 21 additions & 6 deletions include/swift/RemoteInspection/ReflectionContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,14 +335,17 @@ class ReflectionContext
ObjectFileFormat.getSectionName(ReflectionSectionKind::reflstr));
auto ConformMdSec = findMachOSectionByName(
ObjectFileFormat.getSectionName(ReflectionSectionKind::conform));
auto MPEnumMdSec = findMachOSectionByName(
ObjectFileFormat.getSectionName(ReflectionSectionKind::mpenum));

if (FieldMdSec.first == nullptr &&
AssocTySec.first == nullptr &&
BuiltinTySec.first == nullptr &&
CaptureSec.first == nullptr &&
TypeRefMdSec.first == nullptr &&
ReflStrMdSec.first == nullptr &&
ConformMdSec.first == nullptr)
ConformMdSec.first == nullptr &&
MPEnumMdSec.first == nullptr)
return {};

ReflectionInfo info = {{FieldMdSec.first, FieldMdSec.second},
Expand All @@ -352,6 +355,7 @@ class ReflectionContext
{TypeRefMdSec.first, TypeRefMdSec.second},
{ReflStrMdSec.first, ReflStrMdSec.second},
{ConformMdSec.first, ConformMdSec.second},
{MPEnumMdSec.first, MPEnumMdSec.second},
PotentialModuleNames};

auto InfoID = this->addReflectionInfo(info);
Expand Down Expand Up @@ -466,14 +470,17 @@ class ReflectionContext
ObjectFileFormat.getSectionName(ReflectionSectionKind::reflstr));
auto ConformMdSec = findCOFFSectionByName(
ObjectFileFormat.getSectionName(ReflectionSectionKind::conform));
auto MPEnumMdSec = findCOFFSectionByName(
ObjectFileFormat.getSectionName(ReflectionSectionKind::mpenum));

if (FieldMdSec.first == nullptr &&
AssocTySec.first == nullptr &&
BuiltinTySec.first == nullptr &&
CaptureSec.first == nullptr &&
TypeRefMdSec.first == nullptr &&
ReflStrMdSec.first == nullptr &&
ConformMdSec.first == nullptr)
ConformMdSec.first == nullptr &&
MPEnumMdSec.first == nullptr)
return {};

ReflectionInfo Info = {{FieldMdSec.first, FieldMdSec.second},
Expand All @@ -483,6 +490,7 @@ class ReflectionContext
{TypeRefMdSec.first, TypeRefMdSec.second},
{ReflStrMdSec.first, ReflStrMdSec.second},
{ConformMdSec.first, ConformMdSec.second},
{MPEnumMdSec.first, MPEnumMdSec.second},
PotentialModuleNames};
return this->addReflectionInfo(Info);
}
Expand Down Expand Up @@ -679,6 +687,9 @@ class ReflectionContext
ObjectFileFormat.getSectionName(ReflectionSectionKind::reflstr), true);
auto ConformMdSec = findELFSectionByName(
ObjectFileFormat.getSectionName(ReflectionSectionKind::conform), true);
auto MPEnumMdSec = findELFSectionByName(
ObjectFileFormat.getSectionName(ReflectionSectionKind::mpenum), true);

if (Error)
return {};

Expand All @@ -688,14 +699,15 @@ class ReflectionContext
// ELF executable.
if (FieldMdSec.first || AssocTySec.first || BuiltinTySec.first ||
CaptureSec.first || TypeRefMdSec.first || ReflStrMdSec.first ||
ConformMdSec.first) {
ConformMdSec.first || MPEnumMdSec.first) {
ReflectionInfo info = {{FieldMdSec.first, FieldMdSec.second},
{AssocTySec.first, AssocTySec.second},
{BuiltinTySec.first, BuiltinTySec.second},
{CaptureSec.first, CaptureSec.second},
{TypeRefMdSec.first, TypeRefMdSec.second},
{ReflStrMdSec.first, ReflStrMdSec.second},
{ConformMdSec.first, ConformMdSec.second},
{MPEnumMdSec.first, MPEnumMdSec.second},
PotentialModuleNames};
result = this->addReflectionInfo(info);
}
Expand All @@ -718,20 +730,23 @@ class ReflectionContext
ObjectFileFormat.getSectionName(ReflectionSectionKind::reflstr), false);
ConformMdSec = findELFSectionByName(
ObjectFileFormat.getSectionName(ReflectionSectionKind::conform), false);
MPEnumMdSec = findELFSectionByName(
ObjectFileFormat.getSectionName(ReflectionSectionKind::mpenum), false);

if (Error)
return {};

if (FieldMdSec.first || AssocTySec.first || BuiltinTySec.first ||
CaptureSec.first || TypeRefMdSec.first || ReflStrMdSec.first ||
ConformMdSec.first) {
ConformMdSec.first || MPEnumMdSec.first) {
ReflectionInfo info = {{FieldMdSec.first, FieldMdSec.second},
{AssocTySec.first, AssocTySec.second},
{BuiltinTySec.first, BuiltinTySec.second},
{CaptureSec.first, CaptureSec.second},
{TypeRefMdSec.first, TypeRefMdSec.second},
{ReflStrMdSec.first, ReflStrMdSec.second},
{ConformMdSec.first, ConformMdSec.second},
{MPEnumMdSec.first, MPEnumMdSec.second},
PotentialModuleNames};
auto rid = this->addReflectionInfo(info);
if (!result)
Expand Down Expand Up @@ -846,8 +861,7 @@ class ReflectionContext
ReflectionSectionKind::fieldmd, ReflectionSectionKind::assocty,
ReflectionSectionKind::builtin, ReflectionSectionKind::capture,
ReflectionSectionKind::typeref, ReflectionSectionKind::reflstr,
ReflectionSectionKind::conform
};
ReflectionSectionKind::conform, ReflectionSectionKind::mpenum};

llvm::SmallVector<std::pair<RemoteRef<void>, uint64_t>, 6> Pairs;
for (auto Section : Sections) {
Expand All @@ -873,6 +887,7 @@ class ReflectionContext
{Pairs[4].first, Pairs[4].second},
{Pairs[5].first, Pairs[5].second},
{Pairs[6].first, Pairs[6].second},
{Pairs[7].first, Pairs[7].second},
PotentialModuleNames};
return addReflectionInfo(Info);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ HANDLE_SWIFT_SECTION(protocs, "__swift5_protos", "swift5_protocols",
".sw5prt$B")
HANDLE_SWIFT_SECTION(acfuncs, "__swift5_acfuncs", "swift5_accessible_functions",
".sw5acfn$B")
HANDLE_SWIFT_SECTION(mpenum, "__swift5_mpenum", "swift5_mpenum", ".sw5mpen$B")
38 changes: 36 additions & 2 deletions include/swift/RemoteInspection/TypeRefBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,21 @@ class CaptureDescriptorIterator
};
using CaptureSection = ReflectionSection<CaptureDescriptorIterator>;

class MultiPayloadEnumDescriptorIterator
: public ReflectionSectionIteratorBase<MultiPayloadEnumDescriptorIterator,
MultiPayloadEnumDescriptor> {
public:
MultiPayloadEnumDescriptorIterator(RemoteRef<void> Cur, uint64_t Size)
: ReflectionSectionIteratorBase(Cur, Size, "MultiPayloadEnum") {}

static uint64_t
getCurrentRecordSize(RemoteRef<MultiPayloadEnumDescriptor> MPER) {
return MPER->getSizeInBytes();
}
};
using MultiPayloadEnumSection =
ReflectionSection<MultiPayloadEnumDescriptorIterator>;

using GenericSection = ReflectionSection<const void *>;

struct ReflectionInfo {
Expand All @@ -241,6 +256,7 @@ struct ReflectionInfo {
GenericSection TypeReference;
GenericSection ReflectionString;
GenericSection Conformance;
MultiPayloadEnumSection MultiPayloadEnum;
llvm::SmallVector<llvm::StringRef, 1> PotentialModuleNames;
};

Expand Down Expand Up @@ -474,6 +490,10 @@ class TypeRefBuilder {
/// Get the unsubstituted capture types for a closure context.
ClosureContextInfo getClosureContextInfo(RemoteRef<CaptureDescriptor> CD);

/// Get the multipayload enum projection information for a given TR
std::unique_ptr<MultiPayloadEnumDescriptorBase>
getMultiPayloadEnumDescriptor(const TypeRef *TR) override;

const TypeRef *lookupTypeWitness(const std::string &MangledTypeName,
const std::string &Member,
StringRef Protocol);
Expand All @@ -496,6 +516,8 @@ class TypeRefBuilder {
/// Load unsubstituted field types for a nominal type.
RemoteRef<FieldDescriptor> getFieldTypeInfo(const TypeRef *TR);

RemoteRef<MultiPayloadEnumDescriptor> getMultiPayloadEnumInfo(const TypeRef *TR);

void populateFieldTypeInfoCacheWithReflectionAtIndex(size_t Index);

std::optional<RemoteRef<FieldDescriptor>>
Expand Down Expand Up @@ -545,7 +567,8 @@ class TypeRefBuilder {

public:
///
/// Dumping typerefs, field declarations, builtin types, captures
/// Dumping typerefs, field declarations, builtin types, captures,
/// multi-payload enums
///
void dumpTypeRef(RemoteRef<char> MangledName, std::ostream &stream,
bool printTypeName = false);
Expand All @@ -554,6 +577,7 @@ class TypeRefBuilder {
void dumpFieldSection(std::ostream &stream);
void dumpBuiltinTypeSection(std::ostream &stream);
void dumpCaptureSection(std::ostream &stream);
void dumpMultiPayloadEnumSection(std::ostream &stream);

template <template <typename Runtime> class ObjCInteropKind,
unsigned PointerSize>
Expand Down Expand Up @@ -793,6 +817,10 @@ class TypeRefBuilder {
stream << "=============\n";
dumpConformanceSection<ObjCInteropKind, PointerSize>(stream);
stream << "\n";
stream << "MULTI-PAYLOAD ENUM DESCRIPTORS:\n";
stream << "===============================\n";
dumpMultiPayloadEnumSection(stream);
stream << "\n";
}
};
friend struct ReflectionTypeDescriptorFinder;
Expand Down Expand Up @@ -1549,10 +1577,17 @@ class TypeRefBuilder {
return RDF.getClosureContextInfo(CD);
}

/// Get the multipayload enum projection information for a given TR
std::unique_ptr<MultiPayloadEnumDescriptorBase>
getMultiPayloadEnumDescriptor(const TypeRef *TR);

private:
/// Get the primitive type lowering for a builtin type.
RemoteRef<BuiltinTypeDescriptor> getBuiltinTypeInfo(const TypeRef *TR);

RemoteRef<MultiPayloadEnumDescriptor>
getMultiPayloadEnumInfo(const TypeRef *TR);

std::optional<uint64_t> multiPayloadEnumPointerMask;

public:
Expand Down Expand Up @@ -1582,7 +1617,6 @@ class TypeRefBuilder {
}
return multiPayloadEnumPointerMask.value();
}

FieldTypeCollectionResult
collectFieldTypes(std::optional<std::string> forMangledTypeName) {
return RDF.collectFieldTypes(forMangledTypeName);
Expand Down
Loading