From 80e860881f36a897b21342df2c2d5df5b01f70ea Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Fri, 14 Jun 2024 13:19:10 -0700 Subject: [PATCH 1/2] Fix an ABI break PR #74394 removed a field from `struct MetadataSections` whose layout is ABI. So restore that field as an unused padding field to preserve the layout of all the other fields in that struct. --- stdlib/public/SwiftShims/swift/shims/MetadataSections.h | 1 + 1 file changed, 1 insertion(+) diff --git a/stdlib/public/SwiftShims/swift/shims/MetadataSections.h b/stdlib/public/SwiftShims/swift/shims/MetadataSections.h index e7baba432d4bb..b9cae16c8c04a 100644 --- a/stdlib/public/SwiftShims/swift/shims/MetadataSections.h +++ b/stdlib/public/SwiftShims/swift/shims/MetadataSections.h @@ -95,6 +95,7 @@ struct MetadataSections { MetadataSectionRange swift5_replac2; MetadataSectionRange swift5_builtin; MetadataSectionRange swift5_capture; + MetadataSectionRange swift5_mpenum_unused; // No longer used MetadataSectionRange swift5_accessible_functions; MetadataSectionRange swift5_runtime_attributes; MetadataSectionRange swift5_tests; From 05c74e0d908047929940b8befd451b4cfd4775a8 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Fri, 14 Jun 2024 15:32:39 -0700 Subject: [PATCH 2/2] Revert "Merge pull request #74394 from tbkka/tbkka-remotemirror-no-more-mpe-metadata-partial" This reverts commit a1708ef8b1f69fb7d3ae8993feb66ca28e6915f4, reversing changes made to b5930625beeb2e18924f7da6e7cbd3291758b3a8. --- .../swift/RemoteInspection/DescriptorFinder.h | 28 ++-- include/swift/RemoteInspection/Records.h | 105 +++++++++++++ .../RemoteInspection/ReflectionContext.h | 27 +++- .../llvm/BinaryFormat/Swift.def | 1 + .../swift/RemoteInspection/TypeRefBuilder.h | 38 ++++- .../public/RemoteInspection/TypeLowering.cpp | 2 + .../RemoteInspection/TypeRefBuilder.cpp | 142 ++++++++++++++++++ .../SwiftRemoteMirror/SwiftRemoteMirror.cpp | 2 + .../SwiftShims/swift/shims/MetadataSections.h | 2 +- stdlib/public/runtime/SwiftRT-COFF.cpp | 2 + stdlib/public/runtime/SwiftRT-ELF-WASM.cpp | 2 + 11 files changed, 325 insertions(+), 26 deletions(-) diff --git a/include/swift/RemoteInspection/DescriptorFinder.h b/include/swift/RemoteInspection/DescriptorFinder.h index 96508c40304af..9335474be6fbb 100644 --- a/include/swift/RemoteInspection/DescriptorFinder.h +++ b/include/swift/RemoteInspection/DescriptorFinder.h @@ -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 { @@ -130,9 +125,8 @@ struct DescriptorFinder { virtual std::unique_ptr getFieldDescriptor(const TypeRef *TR) = 0; - // TODO: Delete this as soon as LLDB no longer attempts to override it virtual std::unique_ptr - getMultiPayloadEnumDescriptor(const TypeRef *TR) { abort(); }; + getMultiPayloadEnumDescriptor(const TypeRef *TR) = 0; }; } // namespace reflection diff --git a/include/swift/RemoteInspection/Records.h b/include/swift/RemoteInspection/Records.h index 1c0ceeb976257..aa08ce3ef5b6d 100644 --- a/include/swift/RemoteInspection/Records.h +++ b/include/swift/RemoteInspection/Records.h @@ -378,6 +378,111 @@ class BuiltinTypeDescriptor { } }; +class MultiPayloadEnumDescriptor { +public: + const RelativeDirectPointer 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(&contents[getPayloadSpareBitsIndex()]); + } else { + return nullptr; + } + } +}; + class CaptureTypeRecord { public: const RelativeDirectPointer MangledTypeName; diff --git a/include/swift/RemoteInspection/ReflectionContext.h b/include/swift/RemoteInspection/ReflectionContext.h index 8b0f109483251..e2384813ab4d7 100644 --- a/include/swift/RemoteInspection/ReflectionContext.h +++ b/include/swift/RemoteInspection/ReflectionContext.h @@ -335,6 +335,8 @@ 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 && @@ -342,7 +344,8 @@ class ReflectionContext 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}, @@ -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); @@ -466,6 +470,8 @@ 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 && @@ -473,7 +479,8 @@ class ReflectionContext 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}, @@ -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); } @@ -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 {}; @@ -688,7 +699,7 @@ 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}, @@ -696,6 +707,7 @@ class ReflectionContext {TypeRefMdSec.first, TypeRefMdSec.second}, {ReflStrMdSec.first, ReflStrMdSec.second}, {ConformMdSec.first, ConformMdSec.second}, + {MPEnumMdSec.first, MPEnumMdSec.second}, PotentialModuleNames}; result = this->addReflectionInfo(info); } @@ -718,13 +730,15 @@ 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}, @@ -732,6 +746,7 @@ class ReflectionContext {TypeRefMdSec.first, TypeRefMdSec.second}, {ReflStrMdSec.first, ReflStrMdSec.second}, {ConformMdSec.first, ConformMdSec.second}, + {MPEnumMdSec.first, MPEnumMdSec.second}, PotentialModuleNames}; auto rid = this->addReflectionInfo(info); if (!result) @@ -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, uint64_t>, 6> Pairs; for (auto Section : Sections) { @@ -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); } diff --git a/include/swift/RemoteInspection/RuntimeHeaders/llvm/BinaryFormat/Swift.def b/include/swift/RemoteInspection/RuntimeHeaders/llvm/BinaryFormat/Swift.def index 1ea0bc548b37e..05b60e40632cd 100644 --- a/include/swift/RemoteInspection/RuntimeHeaders/llvm/BinaryFormat/Swift.def +++ b/include/swift/RemoteInspection/RuntimeHeaders/llvm/BinaryFormat/Swift.def @@ -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") diff --git a/include/swift/RemoteInspection/TypeRefBuilder.h b/include/swift/RemoteInspection/TypeRefBuilder.h index b787b8522ded5..0a98b782d05c2 100644 --- a/include/swift/RemoteInspection/TypeRefBuilder.h +++ b/include/swift/RemoteInspection/TypeRefBuilder.h @@ -231,6 +231,21 @@ class CaptureDescriptorIterator }; using CaptureSection = ReflectionSection; +class MultiPayloadEnumDescriptorIterator + : public ReflectionSectionIteratorBase { +public: + MultiPayloadEnumDescriptorIterator(RemoteRef Cur, uint64_t Size) + : ReflectionSectionIteratorBase(Cur, Size, "MultiPayloadEnum") {} + + static uint64_t + getCurrentRecordSize(RemoteRef MPER) { + return MPER->getSizeInBytes(); + } +}; +using MultiPayloadEnumSection = + ReflectionSection; + using GenericSection = ReflectionSection; struct ReflectionInfo { @@ -241,6 +256,7 @@ struct ReflectionInfo { GenericSection TypeReference; GenericSection ReflectionString; GenericSection Conformance; + MultiPayloadEnumSection MultiPayloadEnum; llvm::SmallVector PotentialModuleNames; }; @@ -474,6 +490,10 @@ class TypeRefBuilder { /// Get the unsubstituted capture types for a closure context. ClosureContextInfo getClosureContextInfo(RemoteRef CD); + /// Get the multipayload enum projection information for a given TR + std::unique_ptr + getMultiPayloadEnumDescriptor(const TypeRef *TR) override; + const TypeRef *lookupTypeWitness(const std::string &MangledTypeName, const std::string &Member, StringRef Protocol); @@ -496,6 +516,8 @@ class TypeRefBuilder { /// Load unsubstituted field types for a nominal type. RemoteRef getFieldTypeInfo(const TypeRef *TR); + RemoteRef getMultiPayloadEnumInfo(const TypeRef *TR); + void populateFieldTypeInfoCacheWithReflectionAtIndex(size_t Index); std::optional> @@ -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 MangledName, std::ostream &stream, bool printTypeName = false); @@ -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