diff --git a/docs/WindowsBuild.md b/docs/WindowsBuild.md index 28c4e28040420..119496aa4cade 100644 --- a/docs/WindowsBuild.md +++ b/docs/WindowsBuild.md @@ -64,9 +64,9 @@ subst S: ```cmd S: -git clone https://github.com/apple/llvm-project --branch swift/master toolchain -git clone -c core.autocrlf=input -c core.symlinks=true https://github.com/apple/swift toolchain/swift -git clone https://github.com/apple/swift-cmark toolchain/cmark +git clone https://github.com/apple/llvm-project --branch swift/master llvm-project +git clone -c core.autocrlf=input -c core.symlinks=true https://github.com/apple/swift swift +git clone https://github.com/apple/swift-cmark cmark git clone https://github.com/apple/swift-corelibs-libdispatch swift-corelibs-libdispatch git clone https://github.com/apple/swift-corelibs-foundation swift-corelibs-foundation git clone https://github.com/apple/swift-corelibs-xctest swift-corelibs-xctest @@ -78,15 +78,16 @@ git clone https://github.com/compnerd/swift-build swift-build ## Acquire ICU, SQLite3, curl, libxml2 and zlib -Go to [compnerd's swift-build azure page](https://dev.azure.com/compnerd/swift-build/_build) and open [Pipelines](https://dev.azure.com/compnerd/swift-build/_build) where you'll see bots (hopefully green) for: - -- [ICU](https://dev.azure.com/compnerd/swift-build/_build?definitionId=9) -- [SQLite](https://dev.azure.com/compnerd/swift-build/_build?definitionId=12&_a=summary) -- [curl](https://dev.azure.com/compnerd/swift-build/_build?definitionId=11&_a=summary) -- [libxml2](https://dev.azure.com/compnerd/swift-build/_build?definitionId=10&_a=summary) -- [zlib](https://dev.azure.com/compnerd/swift-build/_build?definitionId=16&_a=summary) +``` +python -m pip install --user msrest azure-devops tabulate +python swift-build\utilities\swift-build.py --build-id ICU --latest-artifacts --filter windows-x64 --download +python swift-build\utilities\swift-build.py --build-id XML2 --latest-artifacts --filter windows-x64 --download +python swift-build\utilities\swift-build.py --build-id CURL --latest-artifacts --filter windows-x64 --download +python swift-build\utilities\swift-build.py --build-id zlib --latest-artifacts --filter windows-x64 --download +python swift-build\utilities\swift-build.py --build-id SQLite --latest-artifacts --filter windows-x64 --download +``` -Download each of the zip files and copy their contents into S:/Library. The directory structure should resemble: +Extract the zip files, ignoring the top level directory, into `S:/Library`. The directory structure should resemble: ``` /Library @@ -113,10 +114,10 @@ Set up the `ucrt`, `visualc`, and `WinSDK` modules by: - and setup the `visualc.apinotes` located at `swift/stdlib/public/Platform/visualc.apinotes` into `${VCToolsInstallDir}/include` as `visualc.apinotes` ```cmd -mklink "%UniversalCRTSdkDir%\Include\%UCRTVersion%\ucrt\module.modulemap" S:\toolchain\swift\stdlib\public\Platform\ucrt.modulemap -mklink "%UniversalCRTSdkDir%\Include\%UCRTVersion%\um\module.modulemap" S:\toolchain\swift\stdlib\public\Platform\winsdk.modulemap -mklink "%VCToolsInstallDir%\include\module.modulemap" S:\toolchain\swift\stdlib\public\Platform\visualc.modulemap -mklink "%VCToolsInstallDir%\include\visualc.apinotes" S:\toolchain\swift\stdlib\public\Platform\visualc.apinotes +mklink "%UniversalCRTSdkDir%\Include\%UCRTVersion%\ucrt\module.modulemap" S:\swift\stdlib\public\Platform\ucrt.modulemap +mklink "%UniversalCRTSdkDir%\Include\%UCRTVersion%\um\module.modulemap" S:\swift\stdlib\public\Platform\winsdk.modulemap +mklink "%VCToolsInstallDir%\include\module.modulemap" S:\swift\stdlib\public\Platform\visualc.modulemap +mklink "%VCToolsInstallDir%\include\visualc.apinotes" S:\swift\stdlib\public\Platform\visualc.apinotes ``` Warning: Creating the above links usually requires administrator privileges. The quick and easy way to do this is to open a second developer prompt by right clicking whatever shortcut you used to open the first one, choosing Run As Administrator, and pasting the above commands into the resulting window. You can then close the privileged prompt; this is the only step which requires elevation. @@ -124,18 +125,19 @@ Warning: Creating the above links usually requires administrator privileges. The ## Build the toolchain ```cmd -md "S:\b\toolchain" cmake -B "S:\b\toolchain" ^ -C S:\swift-build\cmake\caches\windows-x86_64.cmake ^ -C S:\swift-build\cmake\caches\org.compnerd.dt.cmake ^ -D CMAKE_BUILD_TYPE=Release ^ -D LLVM_ENABLE_ASSERTIONS=YES ^ - -D LLVM_ENABLE_PROJECTS="clang;clang-tools-extra;cmark;swift;lldb;lld" ^ + -D LLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lldb;lld" ^ -D LLVM_EXTERNAL_PROJECTS="cmark;swift" ^ -D SWIFT_PATH_TO_LIBDISPATCH_SOURCE=S:\swift-corelibs-libdispatch ^ -D LLVM_ENABLE_PDB=YES ^ -D LLVM_ENABLE_LIBEDIT=NO ^ -D LLDB_ENABLE_PYTHON=YES ^ + -D LLVM_EXTERNAL_SWIFT_SOURCE_DIR="S:/swift" ^ + -D LLVM_EXTERNAL_CMARK_SOURCE_DIR="S:/cmark" ^ -D SWIFT_WINDOWS_x86_64_ICU_UC_INCLUDE="S:/Library/icu-64/usr/include" ^ -D SWIFT_WINDOWS_x86_64_ICU_UC="S:/Library/icu-64/usr/lib/icuuc64.lib" ^ -D SWIFT_WINDOWS_x86_64_ICU_I18N_INCLUDE="S:/Library/icu-64/usr/include" ^ @@ -145,7 +147,7 @@ cmake -B "S:\b\toolchain" ^ -D SWIFT_BUILD_DYNAMIC_STDLIB=YES ^ -D SWIFT_BUILD_DYNAMIC_SDK_OVERLAY=YES ^ -G Ninja ^ - -S S:\toolchain\llvm + -S S:\llvm-project\llvm ninja -C S:\b\toolchain ``` diff --git a/include/swift/Demangling/Demangle.h b/include/swift/Demangling/Demangle.h index 4d809e7268078..61934a820e357 100644 --- a/include/swift/Demangling/Demangle.h +++ b/include/swift/Demangling/Demangle.h @@ -50,6 +50,7 @@ struct DemangleOptions { bool DisplayProtocolConformances = true; bool DisplayWhereClauses = true; bool DisplayEntityTypes = true; + bool DisplayLocalNameContexts = true; bool ShortenPartialApply = false; bool ShortenThunk = false; bool ShortenValueWitness = false; diff --git a/include/swift/Demangling/TypeDecoder.h b/include/swift/Demangling/TypeDecoder.h index fb87307e97b34..2e293989934ee 100644 --- a/include/swift/Demangling/TypeDecoder.h +++ b/include/swift/Demangling/TypeDecoder.h @@ -716,19 +716,16 @@ class TypeDecoder { // If the tuple element is labeled, add its label to 'labels'. unsigned typeChildIndex = 0; - unsigned nameIdx = 0; - if (element->getChild(nameIdx)->getKind() == NodeKind::VariadicMarker) { - variadic = true; - nameIdx = 1; - typeChildIndex = 1; + if (element->getChild(typeChildIndex)->getKind() == NodeKind::VariadicMarker) { + return BuiltType(); } - if (element->getChild(nameIdx)->getKind() == NodeKind::TupleElementName) { + if (element->getChild(typeChildIndex)->getKind() == NodeKind::TupleElementName) { // Add spaces to terminate all the previous labels if this // is the first we've seen. if (labels.empty()) labels.append(elements.size(), ' '); // Add the label and its terminator. - labels += element->getChild(0)->getText(); + labels += element->getChild(typeChildIndex)->getText(); labels += ' '; typeChildIndex++; diff --git a/include/swift/Reflection/ReflectionContext.h b/include/swift/Reflection/ReflectionContext.h index f7fe5a78398b0..82c39157df7e6 100644 --- a/include/swift/Reflection/ReflectionContext.h +++ b/include/swift/Reflection/ReflectionContext.h @@ -34,9 +34,10 @@ #include "swift/Runtime/Unreachable.h" #include -#include +#include #include #include +#include namespace { @@ -794,7 +795,7 @@ class ReflectionContext llvm::Optional iterateConformances( std::function Call) { std::string ConformancesPointerName = - "__swift_debug_protocolConformanceStatePointer"; + "_swift_debug_protocolConformanceStatePointer"; auto ConformancesAddrAddr = getReader().getSymbolAddress(ConformancesPointerName); if (!ConformancesAddrAddr) @@ -844,9 +845,9 @@ class ReflectionContext llvm::Optional iterateMetadataAllocations( std::function)> Call) { std::string IterationEnabledName = - "__swift_debug_metadataAllocationIterationEnabled"; + "_swift_debug_metadataAllocationIterationEnabled"; std::string AllocationPoolPointerName = - "__swift_debug_allocationPoolPointer"; + "_swift_debug_allocationPoolPointer"; auto IterationEnabledAddr = getReader().getSymbolAddress(IterationEnabledName); @@ -922,6 +923,50 @@ class ReflectionContext return llvm::None; } + llvm::Optional iterateMetadataAllocationBacktraces( + std::function + Call) { + std::string BacktraceListName = + "_swift_debug_metadataAllocationBacktraceList"; + + auto BacktraceListAddr = getReader().getSymbolAddress(BacktraceListName); + if (!BacktraceListAddr) + return "unable to look up debug variable " + BacktraceListName; + auto BacktraceListNextPtr = + getReader().readPointer(BacktraceListAddr, sizeof(StoredPointer)); + if (!BacktraceListNextPtr) + return llvm::None; + + auto BacktraceListNext = BacktraceListNextPtr->getResolvedAddress(); + while (BacktraceListNext) { + auto HeaderBytes = getReader().readBytes( + RemoteAddress(BacktraceListNext), + sizeof(MetadataAllocationBacktraceHeader)); + auto HeaderPtr = + reinterpret_cast *>( + HeaderBytes.get()); + if (HeaderPtr == nullptr) { + std::stringstream stream; + stream << "unable to read Next pointer 0x" << std::hex + << BacktraceListNext.getAddressData(); + return stream.str(); + } + auto BacktraceAddrPtr = + BacktraceListNext + + sizeof(MetadataAllocationBacktraceHeader); + auto BacktraceBytes = + getReader().readBytes(RemoteAddress(BacktraceAddrPtr), + HeaderPtr->Count * sizeof(StoredPointer)); + auto BacktracePtr = + reinterpret_cast(BacktraceBytes.get()); + + Call(HeaderPtr->Allocation, HeaderPtr->Count, BacktracePtr); + + BacktraceListNext = RemoteAddress(HeaderPtr->Next); + } + return llvm::None; + } + private: const TypeInfo *getClosureContextInfo(StoredPointer Context, const ClosureContextInfo &Info) { diff --git a/include/swift/Runtime/Debug.h b/include/swift/Runtime/Debug.h index 4ffc3e31174c8..86e19642e51a7 100644 --- a/include/swift/Runtime/Debug.h +++ b/include/swift/Runtime/Debug.h @@ -17,11 +17,13 @@ #ifndef SWIFT_RUNTIME_DEBUG_HELPERS_H #define SWIFT_RUNTIME_DEBUG_HELPERS_H +#include "swift/Runtime/Config.h" +#include "swift/Runtime/Unreachable.h" +#include #include #include +#include #include -#include "swift/Runtime/Config.h" -#include "swift/Runtime/Unreachable.h" #ifdef SWIFT_HAVE_CRASHREPORTERCLIENT @@ -145,6 +147,9 @@ void swift_abortDynamicReplacementDisabling(); void dumpStackTraceEntry(unsigned index, void *framePC, bool shortOutput = false); +SWIFT_RUNTIME_ATTRIBUTE_NOINLINE +bool withCurrentBacktrace(std::function call); + SWIFT_RUNTIME_ATTRIBUTE_NOINLINE void printCurrentBacktrace(unsigned framesToSkip = 1); @@ -237,6 +242,9 @@ bool _swift_debug_metadataAllocationIterationEnabled; SWIFT_RUNTIME_STDLIB_SPI const void * const _swift_debug_allocationPoolPointer; +SWIFT_RUNTIME_STDLIB_SPI +std::atomic _swift_debug_metadataAllocationBacktraceList; + SWIFT_RUNTIME_STDLIB_SPI const void * const _swift_debug_protocolConformanceStatePointer; diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h index 6f4cefcdc35ed..07fab802ee940 100644 --- a/include/swift/Runtime/Metadata.h +++ b/include/swift/Runtime/Metadata.h @@ -54,6 +54,13 @@ enum MetadataAllocatorTags : uint16_t { GenericValueMetadataTag, }; +template struct MetadataAllocationBacktraceHeader { + TargetPointer Next; + TargetPointer Allocation; + uint32_t Count; + // Count backtrace pointers immediately follow. +}; + /// The buffer used by a yield-once coroutine (such as the generalized /// accessors `read` and `modify`). struct YieldOnceBuffer { diff --git a/include/swift/SIL/SILVTable.h b/include/swift/SIL/SILVTable.h index 36beb837e70f0..405063e70cd01 100644 --- a/include/swift/SIL/SILVTable.h +++ b/include/swift/SIL/SILVTable.h @@ -39,43 +39,54 @@ enum IsSerialized_t : unsigned char; class SILFunction; class SILModule; +// TODO: Entry should include substitutions needed to invoke an overridden +// generic base class method. +class SILVTableEntry { + /// The declaration reference to the least-derived method visible through + /// the class. + SILDeclRef Method; + + /// The function which implements the method for the class and the entry kind. + llvm::PointerIntPair ImplAndKind; + +public: + enum Kind : uint8_t { + /// The vtable entry is for a method defined directly in this class. + Normal, + /// The vtable entry is for a method defined directly in this class, and is + /// never overridden by subclasses. + NormalNonOverridden, + /// The vtable entry is inherited from the superclass. + Inherited, + /// The vtable entry is inherited from the superclass, and overridden + /// in this class. + Override, + + // Please update the PointerIntPair above if you add/remove enums. + }; + + SILVTableEntry() : ImplAndKind(nullptr, Kind::Normal) {} + + SILVTableEntry(SILDeclRef Method, SILFunction *Implementation, Kind TheKind) + : Method(Method), ImplAndKind(Implementation, TheKind) {} + + SILDeclRef getMethod() const { return Method; } + + Kind getKind() const { return Kind(ImplAndKind.getInt()); } + void setKind(Kind kind) { ImplAndKind.setInt(kind); } + + SILFunction *getImplementation() const { return ImplAndKind.getPointer(); } +}; + /// A mapping from each dynamically-dispatchable method of a class to the /// SILFunction that implements the method for that class. /// Note that dead methods are completely removed from the vtable. -class SILVTable : public SILAllocated { +class SILVTable final : public SILAllocated, + llvm::TrailingObjects { + friend TrailingObjects; + public: - // TODO: Entry should include substitutions needed to invoke an overridden - // generic base class method. - struct Entry { - enum Kind : uint8_t { - /// The vtable entry is for a method defined directly in this class. - Normal, - /// The vtable entry is for a method defined directly in this class, and is never overridden - /// by subclasses. - NormalNonOverridden, - /// The vtable entry is inherited from the superclass. - Inherited, - /// The vtable entry is inherited from the superclass, and overridden - /// in this class. - Override, - }; - - Entry() - : Implementation(nullptr), TheKind(Kind::Normal) { } - - Entry(SILDeclRef Method, SILFunction *Implementation, Kind TheKind) - : Method(Method), Implementation(Implementation), TheKind(TheKind) { } - - /// The declaration reference to the least-derived method visible through - /// the class. - SILDeclRef Method; - - /// The function which implements the method for the class. - SILFunction *Implementation; - - /// The entry kind. - Kind TheKind; - }; + using Entry = SILVTableEntry; // Disallow copying into temporary objects. SILVTable(const SILVTable &other) = delete; @@ -92,9 +103,6 @@ class SILVTable : public SILAllocated { /// The number of SILVTables entries. unsigned NumEntries : 31; - /// Tail-allocated SILVTable entries. - Entry Entries[1]; - /// Private constructor. Create SILVTables by calling SILVTable::create. SILVTable(ClassDecl *c, IsSerialized_t serialized, ArrayRef entries); @@ -123,10 +131,14 @@ class SILVTable : public SILAllocated { } /// Return all of the method entries. - ArrayRef getEntries() const { return {Entries, NumEntries}; } + ArrayRef getEntries() const { + return {getTrailingObjects(), NumEntries}; + } /// Return all of the method entries mutably. - MutableArrayRef getMutableEntries() { return {Entries, NumEntries}; } + MutableArrayRef getMutableEntries() { + return {getTrailingObjects(), NumEntries}; + } /// Look up the implementation function for the given method. Optional getEntry(SILModule &M, SILDeclRef method) const; @@ -134,18 +146,19 @@ class SILVTable : public SILAllocated { /// Removes entries from the vtable. /// \p predicate Returns true if the passed entry should be removed. template void removeEntries_if(Predicate predicate) { - Entry *end = std::remove_if(Entries, Entries + NumEntries, - [&](Entry &entry) -> bool { - if (predicate(entry)) { - entry.Implementation->decrementRefCount(); - removeFromVTableCache(entry); - return true; - } - return false; - }); - NumEntries = end - Entries; + auto Entries = getMutableEntries(); + Entry *end = std::remove_if( + Entries.begin(), Entries.end(), [&](Entry &entry) -> bool { + if (predicate(entry)) { + entry.getImplementation()->decrementRefCount(); + removeFromVTableCache(entry); + return true; + } + return false; + }); + NumEntries = std::distance(Entries.begin(), end); } - + /// Verify that the vtable is well-formed for the given class. void verify(const SILModule &M) const; diff --git a/include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h b/include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h index 80a448a735f9c..01e6f43ab717f 100644 --- a/include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h +++ b/include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h @@ -331,6 +331,28 @@ swift_reflection_ptr_t swift_reflection_allocationMetadataPointer( SwiftReflectionContextRef ContextRef, swift_metadata_allocation_t Allocation); +/// Backtrace iterator callback passed to +/// swift_reflection_iterateMetadataAllocationBacktraces +typedef void (*swift_metadataAllocationIterator)( + swift_reflection_ptr_t AllocationPtr, size_t Count, + const swift_reflection_ptr_t Ptrs[], void *ContextPtr); + +/// Iterate over all recorded metadata allocation backtraces in the process. +/// +/// Calls the passed in Call function for each recorded backtrace. The function +/// is passed the number of backtrace entries and an array of those entries, as +/// pointers. The array is stored from deepest to shallowest, so main() will be +/// somewhere near the end. This array is valid only for the duration of the +/// call. +/// +/// Returns NULL on success. On error, returns a pointer to a C string +/// describing the error. This pointer remains valid until the next +/// swift_reflection call on the given context. +SWIFT_REMOTE_MIRROR_LINKAGE +const char *swift_reflection_iterateMetadataAllocationBacktraces( + SwiftReflectionContextRef ContextRef, swift_metadataAllocationIterator Call, + void *ContextPtr); + #ifdef __cplusplus } // extern "C" #endif diff --git a/lib/ClangImporter/ImportName.cpp b/lib/ClangImporter/ImportName.cpp index 8c3b90d485f09..23d49a3be21ea 100644 --- a/lib/ClangImporter/ImportName.cpp +++ b/lib/ClangImporter/ImportName.cpp @@ -1423,6 +1423,10 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D, case clang::OverloadedOperatorKind::OO_Minus: case clang::OverloadedOperatorKind::OO_Star: case clang::OverloadedOperatorKind::OO_Slash: + case clang::OverloadedOperatorKind::OO_LessLess: + case clang::OverloadedOperatorKind::OO_GreaterGreater: + case clang::OverloadedOperatorKind::OO_AmpAmp: + case clang::OverloadedOperatorKind::OO_PipePipe: if (auto FD = dyn_cast(D)) { baseName = clang::getOperatorSpelling(op); isFunction = true; diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp index ef6e5d4b9a64d..b6e120722d13c 100644 --- a/lib/Demangling/NodePrinter.cpp +++ b/lib/Demangling/NodePrinter.cpp @@ -1200,7 +1200,8 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) { /*hasName*/true); case Node::Kind::LocalDeclName: print(Node->getChild(1)); - Printer << " #" << (Node->getChild(0)->getIndex() + 1); + if (Options.DisplayLocalNameContexts) + Printer << " #" << (Node->getChild(0)->getIndex() + 1); return nullptr; case Node::Kind::PrivateDeclName: if (Node->getNumChildren() > 1) { @@ -2468,8 +2469,9 @@ printEntity(NodePointer Entity, bool asPrefixContext, TypePrinting TypePr, bool MultiWordName = ExtraName.contains(' '); // Also a local name (e.g. Mystruct #1) does not look good if its context is // printed in prefix form. - if (hasName && - Entity->getChild(1)->getKind() == Node::Kind::LocalDeclName) + bool LocalName = + hasName && Entity->getChild(1)->getKind() == Node::Kind::LocalDeclName; + if (LocalName && Options.DisplayLocalNameContexts) MultiWordName = true; if (asPrefixContext && (TypePr != TypePrinting::NoType || MultiWordName)) { @@ -2554,7 +2556,8 @@ printEntity(NodePointer Entity, bool asPrefixContext, TypePrinting TypePr, printEntityType(Entity, type, genericFunctionTypeList); } } - if (!asPrefixContext && PostfixContext) { + if (!asPrefixContext && PostfixContext && + (!LocalName || Options.DisplayLocalNameContexts)) { // Print any left over context which couldn't be printed in prefix form. if (Entity->getKind() == Node::Kind::DefaultArgumentInitializer || Entity->getKind() == Node::Kind::Initializer || diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp index 3762857f8c1fc..0487fe65f871c 100644 --- a/lib/IRGen/GenMeta.cpp +++ b/lib/IRGen/GenMeta.cpp @@ -1577,8 +1577,8 @@ namespace { descriptor.addInt(IGM.Int32Ty, flags.getIntValue()); if (auto entry = VTable->getEntry(IGM.getSILModule(), fn)) { - assert(entry->TheKind == SILVTable::Entry::Kind::Normal); - auto *implFn = IGM.getAddrOfSILFunction(entry->Implementation, + assert(entry->getKind() == SILVTable::Entry::Kind::Normal); + auto *implFn = IGM.getAddrOfSILFunction(entry->getImplementation(), NotForDefinition); descriptor.addRelativeAddress(implFn); } else { @@ -1625,8 +1625,8 @@ namespace { // The implementation of the override. if (auto entry = VTable->getEntry(IGM.getSILModule(), baseRef)) { - assert(entry->TheKind == SILVTable::Entry::Kind::Override); - auto *implFn = IGM.getAddrOfSILFunction(entry->Implementation, + assert(entry->getKind() == SILVTable::Entry::Kind::Override); + auto *implFn = IGM.getAddrOfSILFunction(entry->getImplementation(), NotForDefinition); descriptor.addRelativeAddress(implFn); } else { @@ -2981,7 +2981,7 @@ namespace { // The class is fragile. Emit a direct reference to the vtable entry. llvm::Constant *ptr; if (entry) { - ptr = IGM.getAddrOfSILFunction(entry->Implementation, + ptr = IGM.getAddrOfSILFunction(entry->getImplementation(), NotForDefinition); } else { // The method is removed by dead method elimination. diff --git a/lib/SIL/IR/Linker.cpp b/lib/SIL/IR/Linker.cpp index 245d7548cb205..358bc257d9c71 100644 --- a/lib/SIL/IR/Linker.cpp +++ b/lib/SIL/IR/Linker.cpp @@ -154,7 +154,7 @@ void SILLinkerVisitor::linkInVTable(ClassDecl *D) { for (auto P : Vtbl->getEntries()) { // Deserialize and recursively walk any vtable entries that do not have // bodies yet. - maybeAddFunctionToWorklist(P.Implementation); + maybeAddFunctionToWorklist(P.getImplementation()); } } diff --git a/lib/SIL/IR/SILModule.cpp b/lib/SIL/IR/SILModule.cpp index 5c86ac2ffd976..1c941a1076375 100644 --- a/lib/SIL/IR/SILModule.cpp +++ b/lib/SIL/IR/SILModule.cpp @@ -593,7 +593,7 @@ lookUpFunctionInVTable(ClassDecl *Class, SILDeclRef Member) { // Ok, we have a VTable. Try to lookup the SILFunction implementation from // the VTable. if (auto E = Vtbl->getEntry(*this, Member)) - return E->Implementation; + return E->getImplementation(); return nullptr; } diff --git a/lib/SIL/IR/SILPrinter.cpp b/lib/SIL/IR/SILPrinter.cpp index 29034513c01e0..a4fe67f32bc65 100644 --- a/lib/SIL/IR/SILPrinter.cpp +++ b/lib/SIL/IR/SILPrinter.cpp @@ -3106,11 +3106,11 @@ void SILVTable::print(llvm::raw_ostream &OS, bool Verbose) const { PrintOptions QualifiedSILTypeOptions = PrintOptions::printQualifiedSILType(); for (auto &entry : getEntries()) { OS << " "; - entry.Method.print(OS); + entry.getMethod().print(OS); OS << ": "; bool HasSingleImplementation = false; - switch (entry.Method.kind) { + switch (entry.getMethod().kind) { default: break; case SILDeclRef::Kind::IVarDestroyer: @@ -3122,13 +3122,13 @@ void SILVTable::print(llvm::raw_ostream &OS, bool Verbose) const { // single implementation, e.g. for destructors. if (!HasSingleImplementation) { QualifiedSILTypeOptions.CurrentModule = - entry.Method.getDecl()->getDeclContext()->getParentModule(); - entry.Method.getDecl()->getInterfaceType().print(OS, - QualifiedSILTypeOptions); + entry.getMethod().getDecl()->getDeclContext()->getParentModule(); + entry.getMethod().getDecl()->getInterfaceType().print( + OS, QualifiedSILTypeOptions); OS << " : "; } - OS << '@' << entry.Implementation->getName(); - switch (entry.TheKind) { + OS << '@' << entry.getImplementation()->getName(); + switch (entry.getKind()) { case SILVTable::Entry::Kind::Normal: break; case SILVTable::Entry::Kind::NormalNonOverridden: @@ -3141,7 +3141,7 @@ void SILVTable::print(llvm::raw_ostream &OS, bool Verbose) const { OS << " [override]"; break; } - OS << "\t// " << demangleSymbol(entry.Implementation->getName()); + OS << "\t// " << demangleSymbol(entry.getImplementation()->getName()); OS << "\n"; } OS << "}\n\n"; diff --git a/lib/SIL/IR/SILVTable.cpp b/lib/SIL/IR/SILVTable.cpp index 211e10abf9ced..b524586fd4f6b 100644 --- a/lib/SIL/IR/SILVTable.cpp +++ b/lib/SIL/IR/SILVTable.cpp @@ -26,17 +26,14 @@ using namespace swift; SILVTable *SILVTable::create(SILModule &M, ClassDecl *Class, IsSerialized_t Serialized, ArrayRef Entries) { - // SILVTable contains one element declared in Entries. We must allocate - // space for it, because its default ctor will write to it. - unsigned NumTailElements = std::max((unsigned)Entries.size(), 1U)-1; - void *buf = M.allocate(sizeof(SILVTable) + sizeof(Entry) * NumTailElements, - alignof(SILVTable)); + auto size = totalSizeToAlloc(Entries.size()); + auto buf = M.allocate(size, alignof(SILVTable)); SILVTable *vt = ::new (buf) SILVTable(Class, Serialized, Entries); M.vtables.push_back(vt); M.VTableMap[Class] = vt; // Update the Module's cache with new vtable + vtable entries: for (const Entry &entry : Entries) { - M.VTableEntryCache.insert({{vt, entry.Method}, entry}); + M.VTableEntryCache.insert({{vt, entry.getMethod()}, entry}); } return vt; } @@ -54,24 +51,25 @@ SILVTable::getEntry(SILModule &M, SILDeclRef method) const { } void SILVTable::removeFromVTableCache(Entry &entry) { - SILModule &M = entry.Implementation->getModule(); - M.VTableEntryCache.erase({this, entry.Method}); + SILModule &M = entry.getImplementation()->getModule(); + M.VTableEntryCache.erase({this, entry.getMethod()}); } SILVTable::SILVTable(ClassDecl *c, IsSerialized_t serialized, ArrayRef entries) : Class(c), Serialized(serialized), NumEntries(entries.size()) { - memcpy(Entries, entries.begin(), sizeof(Entry) * NumEntries); - + std::uninitialized_copy(entries.begin(), entries.end(), + getTrailingObjects()); + // Bump the reference count of functions referenced by this table. for (const Entry &entry : getEntries()) { - entry.Implementation->incrementRefCount(); + entry.getImplementation()->incrementRefCount(); } } SILVTable::~SILVTable() { // Drop the reference count of functions referenced by this table. for (const Entry &entry : getEntries()) { - entry.Implementation->decrementRefCount(); + entry.getImplementation()->decrementRefCount(); } } diff --git a/lib/SIL/Utils/Projection.cpp b/lib/SIL/Utils/Projection.cpp index a190c17f31213..a5575a4d336d8 100644 --- a/lib/SIL/Utils/Projection.cpp +++ b/lib/SIL/Utils/Projection.cpp @@ -549,42 +549,46 @@ ProjectionPath::removePrefix(const ProjectionPath &Path, } void Projection::print(raw_ostream &os, SILType baseType) const { - if (isNominalKind()) { + switch (getKind()) { + case ProjectionKind::Struct: + case ProjectionKind::Class: { auto *Decl = getVarDecl(baseType); os << "Field: "; Decl->print(os); - return; - } - - if (getKind() == ProjectionKind::Tuple) { - os << "Index: " << getIndex(); - return; + break; } - if (getKind() == ProjectionKind::BitwiseCast) { - os << "BitwiseCast"; - return; + case ProjectionKind::Enum: { + auto *Decl = getEnumElementDecl(baseType); + os << "Enum: "; + Decl->print(os); + break; } - if (getKind() == ProjectionKind::Index) { + case ProjectionKind::Index: + case ProjectionKind::Tuple: { os << "Index: " << getIndex(); - return; + break; + } + case ProjectionKind::Box: { + os << " Box over"; + break; } - if (getKind() == ProjectionKind::Upcast) { + case ProjectionKind::Upcast: { os << "UpCast"; - return; + break; } - if (getKind() == ProjectionKind::RefCast) { + case ProjectionKind::RefCast: { os << "RefCast"; - return; + break; } - if (getKind() == ProjectionKind::Box) { - os << " Box over"; - return; + case ProjectionKind::BitwiseCast: { + os << "BitwiseCast"; + break; } - if (getKind() == ProjectionKind::TailElems) { + case ProjectionKind::TailElems: { os << " TailElems"; - return; + break; + } } - os << ""; } raw_ostream &ProjectionPath::print(raw_ostream &os, SILModule &M, diff --git a/lib/SIL/Verifier/SILVerifier.cpp b/lib/SIL/Verifier/SILVerifier.cpp index 2a974fb82aa74..24e601367aa43 100644 --- a/lib/SIL/Verifier/SILVerifier.cpp +++ b/lib/SIL/Verifier/SILVerifier.cpp @@ -5378,10 +5378,10 @@ void SILVTable::verify(const SILModule &M) const { auto &entry = getEntries()[i]; // All vtable entries must be decls in a class context. - assert(entry.Method.hasDecl() && "vtable entry is not a decl"); - auto baseInfo = - M.Types.getConstantInfo(TypeExpansionContext::minimal(), entry.Method); - ValueDecl *decl = entry.Method.getDecl(); + assert(entry.getMethod().hasDecl() && "vtable entry is not a decl"); + auto baseInfo = M.Types.getConstantInfo(TypeExpansionContext::minimal(), + entry.getMethod()); + ValueDecl *decl = entry.getMethod().getDecl(); assert((!isa(decl) || !cast(decl)->isObservingAccessor()) @@ -5389,7 +5389,7 @@ void SILVTable::verify(const SILModule &M) const { // For ivar destroyers, the decl is the class itself. ClassDecl *theClass; - if (entry.Method.kind == SILDeclRef::Kind::IVarDestroyer) + if (entry.getMethod().kind == SILDeclRef::Kind::IVarDestroyer) theClass = dyn_cast(decl); else theClass = dyn_cast(decl->getDeclContext()); @@ -5401,29 +5401,29 @@ void SILVTable::verify(const SILModule &M) const { "vtable entry must refer to a member of the vtable's class"); // Foreign entry points shouldn't appear in vtables. - assert(!entry.Method.isForeign && "vtable entry must not be foreign"); - + assert(!entry.getMethod().isForeign && "vtable entry must not be foreign"); + // The vtable entry must be ABI-compatible with the overridden vtable slot. SmallString<32> baseName; { llvm::raw_svector_ostream os(baseName); - entry.Method.print(os); + entry.getMethod().print(os); } if (M.getStage() != SILStage::Lowered) { - SILVerifier(*entry.Implementation) + SILVerifier(*entry.getImplementation()) .requireABICompatibleFunctionTypes( baseInfo.getSILType().castTo(), - entry.Implementation->getLoweredFunctionType(), + entry.getImplementation()->getLoweredFunctionType(), "vtable entry for " + baseName + " must be ABI-compatible", - *entry.Implementation); + *entry.getImplementation()); } // Validate the entry against its superclass vtable. if (!superclass) { // Root methods should not have inherited or overridden entries. bool validKind; - switch (entry.TheKind) { + switch (entry.getKind()) { case Entry::Normal: case Entry::NormalNonOverridden: validKind = true; @@ -5441,13 +5441,14 @@ void SILVTable::verify(const SILModule &M) const { const Entry *superEntry = nullptr; for (auto &se : superVTable->getEntries()) { - if (se.Method.getOverriddenVTableEntry() == entry.Method.getOverriddenVTableEntry()) { + if (se.getMethod().getOverriddenVTableEntry() == + entry.getMethod().getOverriddenVTableEntry()) { superEntry = &se; break; } } - - switch (entry.TheKind) { + + switch (entry.getKind()) { case Entry::Normal: case Entry::NormalNonOverridden: assert(!superEntry && "non-root vtable entry must be inherited or override"); @@ -5461,8 +5462,9 @@ void SILVTable::verify(const SILModule &M) const { break; // The superclass entry must not prohibit overrides. - assert(superEntry->TheKind != Entry::NormalNonOverridden - && "vtable entry overrides an entry that claims to have no overrides"); + assert( + superEntry->getKind() != Entry::NormalNonOverridden && + "vtable entry overrides an entry that claims to have no overrides"); // TODO: Check the root vtable entry for the method too. break; } @@ -5590,9 +5592,11 @@ void SILModule::verify() const { vt->verify(*this); // Check if there is a cache entry for each vtable entry for (auto entry : vt->getEntries()) { - if (VTableEntryCache.find({vt, entry.Method}) == VTableEntryCache.end()) { + if (VTableEntryCache.find({vt, entry.getMethod()}) == + VTableEntryCache.end()) { llvm::errs() << "Vtable entry for function: " - << entry.Implementation->getName() << "not in cache!\n"; + << entry.getImplementation()->getName() + << "not in cache!\n"; assert(false && "triggering standard assertion failure routine"); } ++EntriesSZ; diff --git a/lib/SILOptimizer/Analysis/BasicCalleeAnalysis.cpp b/lib/SILOptimizer/Analysis/BasicCalleeAnalysis.cpp index 417340158fc2d..f0ef090a029c0 100644 --- a/lib/SILOptimizer/Analysis/BasicCalleeAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/BasicCalleeAnalysis.cpp @@ -129,11 +129,12 @@ void CalleeCache::computeClassMethodCallees() { // Second step: collect all implementations of a method. for (auto &VTable : M.getVTables()) { for (const SILVTable::Entry &entry : VTable->getEntries()) { - if (auto *afd = entry.Method.getAbstractFunctionDecl()) { - CalleesAndCanCallUnknown &callees = getOrCreateCalleesForMethod(entry.Method); + if (auto *afd = entry.getMethod().getAbstractFunctionDecl()) { + CalleesAndCanCallUnknown &callees = + getOrCreateCalleesForMethod(entry.getMethod()); if (unknownCallees.count(afd) != 0) callees.setInt(1); - callees.getPointer()->push_back(entry.Implementation); + callees.getPointer()->push_back(entry.getImplementation()); } } } @@ -310,9 +311,9 @@ void BasicCalleeAnalysis::print(llvm::raw_ostream &os) const { llvm::DenseSet printed; for (auto &VTable : M.getVTables()) { for (const SILVTable::Entry &entry : VTable->getEntries()) { - if (printed.insert(entry.Method).second) { - os << "callees for " << entry.Method << ":\n"; - Cache->getCalleeList(entry.Method).print(os); + if (printed.insert(entry.getMethod()).second) { + os << "callees for " << entry.getMethod() << ":\n"; + Cache->getCalleeList(entry.getMethod()).print(os); } } } diff --git a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp index 1fe9d1b5538c4..c72e35aee7817 100644 --- a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp +++ b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp @@ -444,13 +444,13 @@ class DeadFunctionElimination : FunctionLivenessComputation { for (const SILVTable::Entry &entry : vTable->getEntries()) { // We don't need to collect destructors because we mark them as alive // anyway. - if (entry.Method.kind == SILDeclRef::Kind::Deallocator || - entry.Method.kind == SILDeclRef::Kind::IVarDestroyer) { + if (entry.getMethod().kind == SILDeclRef::Kind::Deallocator || + entry.getMethod().kind == SILDeclRef::Kind::IVarDestroyer) { continue; } - SILFunction *F = entry.Implementation; - auto *fd = getBaseMethod(cast( - entry.Method.getDecl())); + SILFunction *F = entry.getImplementation(); + auto *fd = getBaseMethod( + cast(entry.getMethod().getDecl())); MethodInfo *mi = getMethodInfo(fd, /*isWitnessTable*/ false); mi->addClassMethodImpl(F, vTable->getClass()); } @@ -502,16 +502,16 @@ class DeadFunctionElimination : FunctionLivenessComputation { // Check vtable methods. for (auto &vTable : Module->getVTables()) { for (const SILVTable::Entry &entry : vTable->getEntries()) { - if (entry.Method.kind == SILDeclRef::Kind::Deallocator || - entry.Method.kind == SILDeclRef::Kind::IVarDestroyer) { + if (entry.getMethod().kind == SILDeclRef::Kind::Deallocator || + entry.getMethod().kind == SILDeclRef::Kind::IVarDestroyer) { // Destructors are alive because they are called from swift_release - ensureAlive(entry.Implementation); + ensureAlive(entry.getImplementation()); continue; } - SILFunction *F = entry.Implementation; - auto *fd = getBaseMethod(cast( - entry.Method.getDecl())); + SILFunction *F = entry.getImplementation(); + auto *fd = getBaseMethod( + cast(entry.getMethod().getDecl())); if (// We also have to check the method declaration's access level. // Needed if it's a public base method declared in another @@ -601,16 +601,17 @@ class DeadFunctionElimination : FunctionLivenessComputation { bool removeDeadEntriesFromTables() { bool changedTable = false; for (auto &vTable : Module->getVTables()) { - vTable->removeEntries_if([this, &changedTable] - (SILVTable::Entry &entry) -> bool { - if (!isAlive(entry.Implementation)) { - LLVM_DEBUG(llvm::dbgs() << " erase dead vtable method " - << entry.Implementation->getName() << "\n"); - changedTable = true; - return true; - } - return false; - }); + vTable->removeEntries_if( + [this, &changedTable](SILVTable::Entry &entry) -> bool { + if (!isAlive(entry.getImplementation())) { + LLVM_DEBUG(llvm::dbgs() + << " erase dead vtable method " + << entry.getImplementation()->getName() << "\n"); + changedTable = true; + return true; + } + return false; + }); } auto &WitnessTables = Module->getWitnessTableList(); diff --git a/lib/SILOptimizer/Transforms/PruneVTables.cpp b/lib/SILOptimizer/Transforms/PruneVTables.cpp index cbd9ce1288736..6651390abc252 100644 --- a/lib/SILOptimizer/Transforms/PruneVTables.cpp +++ b/lib/SILOptimizer/Transforms/PruneVTables.cpp @@ -29,31 +29,31 @@ class PruneVTables : public SILModuleTransform { for (auto &entry : vtable->getMutableEntries()) { // We don't need to worry about entries that are inherited, overridden, // or have already been found to have no overrides. - if (entry.TheKind != SILVTable::Entry::Normal) { + if (entry.getKind() != SILVTable::Entry::Normal) { continue; } - + // The destructor entry must remain. - if (entry.Method.kind == SILDeclRef::Kind::Deallocator) { + if (entry.getMethod().kind == SILDeclRef::Kind::Deallocator) { continue; } - - auto methodDecl = entry.Method.getAbstractFunctionDecl(); + + auto methodDecl = entry.getMethod().getAbstractFunctionDecl(); if (!methodDecl) continue; // Is the method declared final? if (!methodDecl->isFinal()) { // Are callees of this entry statically knowable? - if (!calleesAreStaticallyKnowable(*M, entry.Method)) + if (!calleesAreStaticallyKnowable(*M, entry.getMethod())) continue; // Does the method have any overrides in this module? if (methodDecl->isOverridden()) continue; } - - entry.TheKind = SILVTable::Entry::NormalNonOverridden; + + entry.setKind(SILVTable::Entry::NormalNonOverridden); } } diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp index b159a8494c566..9b6891c7452e2 100644 --- a/lib/Sema/CSBindings.cpp +++ b/lib/Sema/CSBindings.cpp @@ -1039,11 +1039,9 @@ bool TypeVarBindingProducer::computeNext() { // types, that's going to ensure that subtype relationship is // always preserved. auto *BGT = type->castTo(); - auto UGT = UnboundGenericType::get(BGT->getDecl(), BGT->getParent(), - BGT->getASTContext()); - auto dstLocator = TypeVar->getImpl().getLocator(); - auto newType = CS.openUnboundGenericType(UGT, dstLocator) + auto newType = CS.openUnboundGenericType(BGT->getDecl(), BGT->getParent(), + dstLocator) ->reconstituteSugar(/*recursive=*/false); addNewBinding(binding.withType(newType)); } diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 4574549ddda8a..6da376c1ff850 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -1420,7 +1420,7 @@ namespace { if (auto *VD = dyn_cast(E->getDecl())) { knownType = CS.getTypeIfAvailable(VD); if (!knownType) - knownType = VD->getInterfaceType(); + knownType = VD->getType(); if (knownType) { assert(!knownType->isHole()); @@ -1432,8 +1432,6 @@ namespace { } // Set the favored type for this expression to the known type. - if (knownType->hasTypeParameter()) - knownType = VD->getDeclContext()->mapTypeIntoContext(knownType); CS.setFavoredType(E, knownType.getPointer()); } diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 7b28796ae60b1..e4f8310ed326d 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -655,25 +655,19 @@ Optional> ConstraintSystem::getExprDepthAndParent( return None; } -Type -ConstraintSystem::openUnboundGenericType(UnboundGenericType *unbound, - ConstraintLocatorBuilder locator) { - auto unboundDecl = unbound->getDecl(); - auto parentTy = unbound->getParent(); +Type ConstraintSystem::openUnboundGenericType( + GenericTypeDecl *decl, Type parentTy, ConstraintLocatorBuilder locator) { if (parentTy) { parentTy = openUnboundGenericTypes(parentTy, locator); - unbound = UnboundGenericType::get(unboundDecl, parentTy, - getASTContext()); } // Open up the generic type. OpenedTypeMap replacements; - openGeneric(unboundDecl->getDeclContext(), unboundDecl->getGenericSignature(), - locator, replacements); + openGeneric(decl->getDeclContext(), decl->getGenericSignature(), locator, + replacements); if (parentTy) { - auto subs = parentTy->getContextSubstitutions( - unboundDecl->getDeclContext()); + auto subs = parentTy->getContextSubstitutions(decl->getDeclContext()); for (auto pair : subs) { auto found = replacements.find( cast(pair.first)); @@ -686,7 +680,7 @@ ConstraintSystem::openUnboundGenericType(UnboundGenericType *unbound, // Map the generic parameters to their corresponding type variables. llvm::SmallVector arguments; - for (auto gp : unboundDecl->getInnermostGenericParamTypes()) { + for (auto gp : decl->getInnermostGenericParamTypes()) { auto found = replacements.find( cast(gp->getCanonicalType())); assert(found != replacements.end() && @@ -699,8 +693,8 @@ ConstraintSystem::openUnboundGenericType(UnboundGenericType *unbound, // handle generic TypeAliases elsewhere, this can just become a // call to BoundGenericType::get(). return TypeChecker::applyUnboundGenericArguments( - unbound, unboundDecl, SourceLoc(), - TypeResolution::forContextual(DC, None), arguments); + decl, parentTy, SourceLoc(), TypeResolution::forContextual(DC, None), + arguments); } static void checkNestedTypeConstraints(ConstraintSystem &cs, Type type, @@ -791,7 +785,8 @@ Type ConstraintSystem::openUnboundGenericTypes( type = type.transform([&](Type type) -> Type { if (auto unbound = type->getAs()) { - return openUnboundGenericType(unbound, locator); + return openUnboundGenericType(unbound->getDecl(), unbound->getParent(), + locator); } return type; diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index 4c93b2ef74571..080f06cd2348a 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -3403,14 +3403,12 @@ class ConstraintSystem { /// Add implicit "load" expressions to the given expression. Expr *addImplicitLoadExpr(Expr *expr); - /// "Open" the given unbound type by introducing fresh type - /// variables for generic parameters and constructing a bound generic - /// type from these type variables. - /// - /// \param unbound The type to open. + /// "Open" the unbound generic type represented by the given declaration and + /// parent type by introducing fresh type variables for generic parameters + /// and constructing a bound generic type from these type variables. /// /// \returns The opened type. - Type openUnboundGenericType(UnboundGenericType *unbound, + Type openUnboundGenericType(GenericTypeDecl *decl, Type parentTy, ConstraintLocatorBuilder locator); /// "Open" the given type by replacing any occurrences of unbound diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 33097e7450936..6c6a1006cb0d5 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -725,9 +725,8 @@ static Type applyGenericArguments(Type type, TypeResolution resolution, // Make sure we have the right number of generic arguments. // FIXME: If we have fewer arguments than we need, that might be okay, if // we're allowed to deduce the remaining arguments from context. - auto genericDecl = cast(decl); auto genericArgs = generic->getGenericArgs(); - auto genericParams = genericDecl->getGenericParams(); + auto genericParams = decl->getGenericParams(); if (genericParams->size() != genericArgs.size()) { if (!options.contains(TypeResolutionFlags::SilenceErrors)) { diags.diagnose(loc, diag::type_parameter_count_mismatch, decl->getName(), @@ -756,10 +755,10 @@ static Type applyGenericArguments(Type type, TypeResolution resolution, } // FIXME: More principled handling of circularity. - if (!genericDecl->getGenericSignature()) { + if (!decl->getGenericSignature()) { diags.diagnose(loc, diag::recursive_decl_reference, - genericDecl->getDescriptiveKind(), genericDecl->getName()); - genericDecl->diagnose(diag::kind_declared_here, DescriptiveDeclKind::Type); + decl->getDescriptiveKind(), decl->getName()); + decl->diagnose(diag::kind_declared_here, DescriptiveDeclKind::Type); return ErrorType::get(ctx); } @@ -777,9 +776,8 @@ static Type applyGenericArguments(Type type, TypeResolution resolution, args.push_back(substTy); } - auto result = TypeChecker::applyUnboundGenericArguments( - unboundType, genericDecl, loc, - resolution, args); + const auto result = TypeChecker::applyUnboundGenericArguments( + decl, unboundType->getParent(), loc, resolution, args); const auto genericOptions = genericResolution.getOptions(); if (!genericOptions.contains(TypeResolutionFlags::AllowUnavailable)) { @@ -802,10 +800,10 @@ static Type applyGenericArguments(Type type, TypeResolution resolution, } /// Apply generic arguments to the given type. -Type TypeChecker::applyUnboundGenericArguments( - UnboundGenericType *unboundType, GenericTypeDecl *decl, - SourceLoc loc, TypeResolution resolution, - ArrayRef genericArgs) { +Type TypeChecker::applyUnboundGenericArguments(GenericTypeDecl *decl, + Type parentTy, SourceLoc loc, + TypeResolution resolution, + ArrayRef genericArgs) { assert(genericArgs.size() == decl->getGenericParams()->size() && "invalid arguments, use applyGenericArguments for diagnostic emitting"); @@ -826,20 +824,20 @@ Type TypeChecker::applyUnboundGenericArguments( // Get the substitutions for outer generic parameters from the parent // type. - if (auto parentType = unboundType->getParent()) { - if (parentType->hasUnboundGenericType()) { + if (parentTy) { + if (parentTy->hasUnboundGenericType()) { // If we're working with a nominal type declaration, just construct // a bound generic type without checking the generic arguments. if (auto *nominalDecl = dyn_cast(decl)) { - return BoundGenericType::get(nominalDecl, parentType, genericArgs); + return BoundGenericType::get(nominalDecl, parentTy, genericArgs); } assert(!resultType->hasTypeParameter()); return resultType; } - subs = parentType->getContextSubstitutions(decl->getDeclContext()); - skipRequirementsCheck |= parentType->hasTypeVariable(); + subs = parentTy->getContextSubstitutions(decl->getDeclContext()); + skipRequirementsCheck |= parentTy->hasTypeVariable(); } else if (auto genericEnv = decl->getDeclContext()->getGenericEnvironmentOfContext()) { auto genericSig = genericEnv->getGenericSignature(); @@ -876,11 +874,11 @@ Type TypeChecker::applyUnboundGenericArguments( if (!skipRequirementsCheck && resolution.getStage() > TypeResolutionStage::Structural) { - auto result = - checkGenericArguments(dc, loc, noteLoc, unboundType, - genericSig->getGenericParams(), - genericSig->getRequirements(), - QueryTypeSubstitutionMap{subs}); + auto result = checkGenericArguments( + dc, loc, noteLoc, + UnboundGenericType::get(decl, parentTy, dc->getASTContext()), + genericSig->getGenericParams(), genericSig->getRequirements(), + QueryTypeSubstitutionMap{subs}); switch (result) { case RequirementCheckResult::Failure: @@ -903,14 +901,12 @@ Type TypeChecker::applyUnboundGenericArguments( LookUpConformanceInModule(module)); // Form a sugared typealias reference. - Type parentType = unboundType->getParent(); - if (typealias && (!parentType || !parentType->isAnyExistentialType())) { + if (typealias && (!parentTy || !parentTy->isAnyExistentialType())) { auto genericSig = typealias->getGenericSignature(); auto subMap = SubstitutionMap::get(genericSig, QueryTypeSubstitutionMap{subs}, LookUpConformanceInModule(module)); - resultType = TypeAliasType::get(typealias, parentType, - subMap, resultType); + resultType = TypeAliasType::get(typealias, parentTy, subMap, resultType); } return resultType; @@ -3311,17 +3307,16 @@ Type TypeResolver::resolveDictionaryType(DictionaryTypeRepr *repr, return ErrorType::get(Context); } - auto dictDecl = Context.getDictionaryDecl(); + auto *const dictDecl = Context.getDictionaryDecl(); if (!dictDecl) { Context.Diags.diagnose(repr->getBrackets().Start, diag::sugar_type_not_found, 3); return ErrorType::get(Context); } - auto unboundTy = dictDecl->getDeclaredType()->castTo(); - Type args[] = {keyTy, valueTy}; if (!TypeChecker::applyUnboundGenericArguments( - unboundTy, dictDecl, repr->getStartLoc(), resolution, args)) { + dictDecl, nullptr, repr->getStartLoc(), resolution, + {keyTy, valueTy})) { assert(Context.Diags.hadAnyError()); return ErrorType::get(Context); } diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index 7315910400fff..282f2adae235e 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -383,25 +383,25 @@ void checkUnsupportedProtocolType(ASTContext &ctx, Type resolveTypeInContext(TypeDecl *typeDecl, DeclContext *foundDC, TypeResolution resolution, bool isSpecialized); -/// Apply generic arguments to the given type. +/// Apply generic arguments to the unbound generic type represented by the +/// given declaration and parent type. /// -/// This function requires a valid unbound generic type with the correct -/// number of generic arguments given, whereas applyGenericArguments emits -/// diagnostics in those cases. +/// This function requires the correct number of generic arguments, +/// whereas applyGenericArguments emits diagnostics in those cases. /// -/// \param unboundType The unbound generic type to which to apply arguments. -/// \param decl The declaration of the type. +/// \param decl The declaration that the resulting bound generic type +/// shall reference. +/// \param parentTy The parent type. /// \param loc The source location for diagnostic reporting. /// \param resolution The type resolution. -/// \param genericArgs The list of generic arguments to apply to the type. +/// \param genericArgs The list of generic arguments to apply. /// /// \returns A BoundGenericType bound to the given arguments, or null on /// error. /// /// \see applyGenericArguments -Type applyUnboundGenericArguments(UnboundGenericType *unboundType, - GenericTypeDecl *decl, SourceLoc loc, - TypeResolution resolution, +Type applyUnboundGenericArguments(GenericTypeDecl *decl, Type parentTy, + SourceLoc loc, TypeResolution resolution, ArrayRef genericArgs); /// Substitute the given base type into the type of the given nested type, diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp index 8eeaff83c2aff..ce262f5165ef5 100644 --- a/lib/Serialization/SerializeSIL.cpp +++ b/lib/Serialization/SerializeSIL.cpp @@ -2379,19 +2379,18 @@ void SILSerializer::writeSILVTable(const SILVTable &vt) { SmallVector ListOfValues; // Do not emit entries which are not public or serialized, unless everything // has to be serialized. - if (!ShouldSerializeAll && entry.Implementation && - !entry.Implementation->isPossiblyUsedExternally() && - !entry.Implementation->isSerialized()) + if (!ShouldSerializeAll && entry.getImplementation() && + !entry.getImplementation()->isPossiblyUsedExternally() && + !entry.getImplementation()->isSerialized()) continue; - handleSILDeclRef(S, entry.Method, ListOfValues); - addReferencedSILFunction(entry.Implementation, true); + handleSILDeclRef(S, entry.getMethod(), ListOfValues); + addReferencedSILFunction(entry.getImplementation(), true); // Each entry is a pair of SILDeclRef and SILFunction. - VTableEntryLayout::emitRecord(Out, ScratchRecord, - SILAbbrCodes[VTableEntryLayout::Code], + VTableEntryLayout::emitRecord( + Out, ScratchRecord, SILAbbrCodes[VTableEntryLayout::Code], // SILFunction name - S.addUniquedStringRef(entry.Implementation->getName()), - toStableVTableEntryKind(entry.TheKind), - ListOfValues); + S.addUniquedStringRef(entry.getImplementation()->getName()), + toStableVTableEntryKind(entry.getKind()), ListOfValues); } } diff --git a/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp b/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp index 1136473999c36..c009212d2cccd 100644 --- a/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp +++ b/stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp @@ -635,3 +635,21 @@ swift_reflection_ptr_t swift_reflection_allocationMetadataPointer( NativeAllocation.Size = Allocation.Size; return Context->allocationMetadataPointer(NativeAllocation); } + +const char *swift_reflection_iterateMetadataAllocationBacktraces( + SwiftReflectionContextRef ContextRef, swift_metadataAllocationIterator Call, + void *ContextPtr) { + auto Context = ContextRef->nativeContext; + auto Error = Context->iterateMetadataAllocationBacktraces( + [&](auto AllocationPtr, auto Count, auto Ptrs) { + // Ptrs is an array of StoredPointer, but the callback expects an array + // of swift_reflection_ptr_t. Those may are not always the same type. + // (For example, swift_reflection_ptr_t can be 64-bit on 32-bit systems, + // while StoredPointer is always the pointer size of the target system.) + // Convert the array to an array of swift_reflection_ptr_t. + std::vector ConvertedPtrs{&Ptrs[0], + &Ptrs[Count]}; + Call(AllocationPtr, Count, ConvertedPtrs.data(), ContextPtr); + }); + return convertError(ContextRef, Error); +} diff --git a/stdlib/public/runtime/EnvironmentVariables.def b/stdlib/public/runtime/EnvironmentVariables.def index 093c43f04f6fe..eca25ddea2518 100644 --- a/stdlib/public/runtime/EnvironmentVariables.def +++ b/stdlib/public/runtime/EnvironmentVariables.def @@ -26,6 +26,10 @@ VARIABLE(SWIFT_DEBUG_ENABLE_METADATA_ALLOCATION_ITERATION, bool, false, "Enable additional metadata allocation tracking for swift-inspect to " "use.") +VARIABLE(SWIFT_DEBUG_ENABLE_METADATA_BACKTRACE_LOGGING, bool, false, + "Enable logging of backtraces for each metadata allocation. Requires " + "SWIFT_DEBUG_ENABLE_METADATA_ALLOCATION_ITERATION to be enabled.") + VARIABLE(SWIFT_DEBUG_IMPLICIT_OBJC_ENTRYPOINT, uint8_t, 2, "Print warnings when using implicit @objc entrypoints. Set to " "desired reporting level, 0-3.") diff --git a/stdlib/public/runtime/Errors.cpp b/stdlib/public/runtime/Errors.cpp index efcee244d71f4..6e0dd53758bc9 100644 --- a/stdlib/public/runtime/Errors.cpp +++ b/stdlib/public/runtime/Errors.cpp @@ -223,8 +223,8 @@ static _Unwind_Reason_Code SwiftUnwindFrame(struct _Unwind_Context *context, voi } #endif -SWIFT_NOINLINE -void swift::printCurrentBacktrace(unsigned framesToSkip) { +SWIFT_ALWAYS_INLINE +static bool withCurrentBacktraceImpl(std::function call) { #if SWIFT_SUPPORTS_BACKTRACE_REPORTING constexpr unsigned maxSupportedStackDepth = 128; void *addrs[maxSupportedStackDepth]; @@ -237,14 +237,29 @@ void swift::printCurrentBacktrace(unsigned framesToSkip) { #else int symbolCount = backtrace(addrs, maxSupportedStackDepth); #endif - for (int i = framesToSkip; i < symbolCount; ++i) { - dumpStackTraceEntry(i - framesToSkip, addrs[i]); - } + call(addrs, symbolCount); + return true; #else - fprintf(stderr, "\n"); + return false; #endif } +SWIFT_NOINLINE +bool swift::withCurrentBacktrace(std::function call) { + return withCurrentBacktraceImpl(call); +} + +SWIFT_NOINLINE +void swift::printCurrentBacktrace(unsigned framesToSkip) { + bool success = withCurrentBacktraceImpl([&](void **addrs, int symbolCount) { + for (int i = framesToSkip; i < symbolCount; ++i) { + dumpStackTraceEntry(i - framesToSkip, addrs[i]); + } + }); + if (!success) + fprintf(stderr, "\n"); +} + #ifdef SWIFT_HAVE_CRASHREPORTERCLIENT #include diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp index 10f8d00f37ba1..4bcb9ef3ac7d9 100644 --- a/stdlib/public/runtime/Metadata.cpp +++ b/stdlib/public/runtime/Metadata.cpp @@ -5503,12 +5503,19 @@ AllocationPool{PoolRange{InitialAllocationPool.Pool, bool swift::_swift_debug_metadataAllocationIterationEnabled = false; const void * const swift::_swift_debug_allocationPoolPointer = &AllocationPool; +std::atomic swift::_swift_debug_metadataAllocationBacktraceList; static void checkAllocatorDebugEnvironmentVariable(void *context) { _swift_debug_metadataAllocationIterationEnabled = runtime::environment::SWIFT_DEBUG_ENABLE_METADATA_ALLOCATION_ITERATION(); - if (!_swift_debug_metadataAllocationIterationEnabled) + if (!_swift_debug_metadataAllocationIterationEnabled) { + if (runtime::environment::SWIFT_DEBUG_ENABLE_METADATA_BACKTRACE_LOGGING()) + swift::warning(RuntimeErrorFlagNone, + "Warning: SWIFT_DEBUG_ENABLE_METADATA_BACKTRACE_LOGGING " + "without SWIFT_DEBUG_ENABLE_METADATA_ALLOCATION_ITERATION " + "has no effect.\n"); return; + } // Write a PoolTrailer to the end of InitialAllocationPool and shrink // the pool accordingly. @@ -5522,6 +5529,24 @@ static void checkAllocatorDebugEnvironmentVariable(void *context) { AllocationPool.store(poolCopy, std::memory_order_relaxed); } +static void recordBacktrace(void *allocation) { + withCurrentBacktrace([&](void **addrs, int count) { + MetadataAllocationBacktraceHeader *record = + (MetadataAllocationBacktraceHeader *)malloc( + sizeof(*record) + count * sizeof(void *)); + record->Allocation = allocation; + record->Count = count; + memcpy(record + 1, addrs, count * sizeof(void *)); + + record->Next = _swift_debug_metadataAllocationBacktraceList.load( + std::memory_order_relaxed); + while (!_swift_debug_metadataAllocationBacktraceList.compare_exchange_weak( + record->Next, record, std::memory_order_release, + std::memory_order_relaxed)) + ; // empty + }); +} + void *MetadataAllocator::Allocate(size_t size, size_t alignment) { assert(Tag != 0); assert(alignment <= alignof(void*)); @@ -5581,8 +5606,14 @@ void *MetadataAllocator::Allocate(size_t size, size_t alignment) { AllocationHeader *header = (AllocationHeader *)allocation; header->Size = size; header->Tag = Tag; - - return allocation + sizeof(AllocationHeader); + + auto *returnedAllocation = allocation + sizeof(AllocationHeader); + + if (runtime::environment :: + SWIFT_DEBUG_ENABLE_METADATA_BACKTRACE_LOGGING()) + recordBacktrace(returnedAllocation); + + return returnedAllocation; } else { return allocation; } diff --git a/test/Demangle/Inputs/manglings.txt b/test/Demangle/Inputs/manglings.txt index 0102b4499a523..49120bc5410a1 100644 --- a/test/Demangle/Inputs/manglings.txt +++ b/test/Demangle/Inputs/manglings.txt @@ -351,12 +351,13 @@ $sSD5IndexVy__GD ---> $sSD5IndexVy__GD $s4test3StrCACycfC ---> {T:$s4test3StrCACycfc} test.Str.__allocating_init() -> test.Str $s18keypaths_inlinable13KeypathStructV8computedSSvpACTKq ---> key path getter for keypaths_inlinable.KeypathStruct.computed : Swift.String : keypaths_inlinable.KeypathStruct, serialized $s18resilient_protocol24ResilientDerivedProtocolPxAA0c4BaseE0Tn --> associated conformance descriptor for resilient_protocol.ResilientDerivedProtocol.A: resilient_protocol.ResilientBaseProtocol -$s3red4testyAA3ResOyxSayq_GAEs5ErrorAAq_sAFHD1__HCg_GADyxq_GsAFR_r0_lF --> red.test(red.Res) -> red.Res +$s3red4testyAA3ResOyxSayq_GAEs5ErrorAAq_sAFHD1__HCg_GADyxq_GsAFR_r0_lF ---> red.test(red.Res) -> red.Res $s3red4testyAA7OurTypeOy4them05TheirD0Vy5AssocQzGAjE0F8ProtocolAAxAA0c7DerivedH0HD1_AA0c4BaseH0HI1_AieKHA2__HCg_GxmAaLRzlF ---> red.test(A.Type) -> red.OurType> -$s17property_wrappers10WithTuplesV9fractionsSd_S2dtvpfP --> property wrapper backing initializer of property_wrappers.WithTuples.fractions : (Swift.Double, Swift.Double, Swift.Double) +$s17property_wrappers10WithTuplesV9fractionsSd_S2dtvpfP ---> property wrapper backing initializer of property_wrappers.WithTuples.fractions : (Swift.Double, Swift.Double, Swift.Double) $sSo17OS_dispatch_queueC4sync7executeyyyXE_tFTOTA ---> {T:$sSo17OS_dispatch_queueC4sync7executeyyyXE_tFTO} partial apply forwarder for @nonobjc __C.OS_dispatch_queue.sync(execute: () -> ()) -> () $sxq_Idgnr_D ---> @differentiable @callee_guaranteed (@in_guaranteed A) -> (@out B) $sxq_Ilgnr_D ---> @differentiable(linear) @callee_guaranteed (@in_guaranteed A) -> (@out B) $sS3fIedgyywd_D ---> @escaping @differentiable @callee_guaranteed (@unowned Swift.Float, @unowned @noDerivative Swift.Float) -> (@unowned Swift.Float) $sS5fIedtyyywddw_D ---> @escaping @differentiable @convention(thin) (@unowned Swift.Float, @unowned Swift.Float, @unowned @noDerivative Swift.Float) -> (@unowned Swift.Float, @unowned @noDerivative Swift.Float) $syQo ---> $syQo +$sx1td_t ---> (t: A...) diff --git a/test/Demangle/demangle-special-options.test b/test/Demangle/demangle-special-options.test index 87c54ca483780..4d3ab0b3c874e 100644 --- a/test/Demangle/demangle-special-options.test +++ b/test/Demangle/demangle-special-options.test @@ -10,3 +10,9 @@ CGRECT: {{ CGRect$}} RUN: swift-demangle -hiding-module=foo _TtC3foo3bar | %FileCheck %s --check-prefix=BAR BAR: {{ bar$}} + +RUN: swift-demangle -display-local-name-contexts=true s1a4mainyyFySRys5UInt8VGXEfU4_10ByteBufferL_aD | %FileCheck %s --check-prefix=LOCAL +LOCAL: ByteBuffer #1 in closure #6 + +RUN: swift-demangle -display-local-name-contexts=false s1a4mainyyFySRys5UInt8VGXEfU4_10ByteBufferL_aD | %FileCheck %s --check-prefix=NOLOCAL +NOLOCAL: {{ ByteBuffer$}} diff --git a/test/Interop/Cxx/operators/Inputs/non-member-inline.h b/test/Interop/Cxx/operators/Inputs/non-member-inline.h index fbe01efbe7146..7c4f28dfcd703 100644 --- a/test/Interop/Cxx/operators/Inputs/non-member-inline.h +++ b/test/Interop/Cxx/operators/Inputs/non-member-inline.h @@ -21,6 +21,26 @@ inline IntBox operator/(IntBox lhs, IntBox rhs) { return IntBox{.value = lhs.value / rhs.value}; } +inline IntBox operator<<(IntBox lhs, IntBox rhs) { + return IntBox{.value = lhs.value << rhs.value}; +} + +inline IntBox operator>>(IntBox lhs, IntBox rhs) { + return IntBox{.value = lhs.value >> rhs.value}; +} + +struct BoolBox { + bool value; +}; + +inline BoolBox operator&&(BoolBox lhs, BoolBox rhs) { + return BoolBox{.value = lhs.value && rhs.value}; +} + +inline BoolBox operator||(BoolBox lhs, BoolBox rhs) { + return BoolBox{.value = lhs.value || rhs.value}; +} + // Make sure that we don't crash on templated operators template struct S {}; template S operator+(S lhs, S rhs); diff --git a/test/Interop/Cxx/operators/non-member-inline-module-interface.swift b/test/Interop/Cxx/operators/non-member-inline-module-interface.swift index 4c800e7dac306..b056312cd4e26 100644 --- a/test/Interop/Cxx/operators/non-member-inline-module-interface.swift +++ b/test/Interop/Cxx/operators/non-member-inline-module-interface.swift @@ -4,3 +4,8 @@ // CHECK-NEXT: func - (lhs: IntBox, rhs: IntBox) -> IntBox // CHECK-NEXT: func * (lhs: IntBox, rhs: IntBox) -> IntBox // CHECK-NEXT: func / (lhs: IntBox, rhs: IntBox) -> IntBox +// CHECK-NEXT: func << (lhs: IntBox, rhs: IntBox) -> IntBox +// CHECK-NEXT: func >> (lhs: IntBox, rhs: IntBox) -> IntBox + +// CHECK: func && (lhs: BoolBox, rhs: BoolBox) -> BoolBox +// CHECK-NEXT: func || (lhs: BoolBox, rhs: BoolBox) -> BoolBox diff --git a/test/Interop/Cxx/operators/non-member-inline-typechecker.swift b/test/Interop/Cxx/operators/non-member-inline-typechecker.swift index 45bb76c892488..92a09901517be 100644 --- a/test/Interop/Cxx/operators/non-member-inline-typechecker.swift +++ b/test/Interop/Cxx/operators/non-member-inline-typechecker.swift @@ -9,3 +9,11 @@ let resultPlus = lhs + rhs let resultMinus = lhs - rhs let resultStar = lhs * rhs let resultSlash = lhs / rhs +let resultLessLess = lhs << rhs +let resultGreaterGreater = lhs >> rhs + +var lhsBool = BoolBox(value: true) +var rhsBool = BoolBox(value: false) + +let resultAmpAmp = lhsBool && rhsBool +let resultPipePipe = lhsBool && rhsBool diff --git a/test/Interop/Cxx/operators/non-member-inline.swift b/test/Interop/Cxx/operators/non-member-inline.swift index f1ce1f052f232..c383c165a980f 100644 --- a/test/Interop/Cxx/operators/non-member-inline.swift +++ b/test/Interop/Cxx/operators/non-member-inline.swift @@ -7,7 +7,7 @@ import StdlibUnittest var OperatorsTestSuite = TestSuite("Operators") -OperatorsTestSuite.test("plus") { +OperatorsTestSuite.test("plus (+)") { let lhs = IntBox(value: 42) let rhs = IntBox(value: 23) @@ -16,7 +16,7 @@ OperatorsTestSuite.test("plus") { expectEqual(65, result.value) } -OperatorsTestSuite.test("minus") { +OperatorsTestSuite.test("minus (-)") { let lhs = IntBox(value: 42) let rhs = IntBox(value: 23) @@ -25,7 +25,7 @@ OperatorsTestSuite.test("minus") { expectEqual(19, result.value) } -OperatorsTestSuite.test("star") { +OperatorsTestSuite.test("star (*)") { let lhs = IntBox(value: 42) let rhs = IntBox(value: 23) @@ -34,7 +34,7 @@ OperatorsTestSuite.test("star") { expectEqual(966, result.value) } -OperatorsTestSuite.test("slash") { +OperatorsTestSuite.test("slash (/)") { let lhs = IntBox(value: 42) let rhs = IntBox(value: 23) @@ -43,4 +43,40 @@ OperatorsTestSuite.test("slash") { expectEqual(1, result.value) } +OperatorsTestSuite.test("less less (<<)") { + let lhs = IntBox(value: 2) + let rhs = IntBox(value: 4) + + let result = lhs << rhs + + expectEqual(32, result.value) +} + +OperatorsTestSuite.test("greater greater (>>)") { + let lhs = IntBox(value: 512) + let rhs = IntBox(value: 8) + + let result = lhs >> rhs + + expectEqual(2, result.value) +} + +OperatorsTestSuite.test("amp amp (&&)") { + let lhs = BoolBox(value: true) + let rhs = BoolBox(value: false) + + let result = lhs && rhs + + expectEqual(false, result.value) +} + +OperatorsTestSuite.test("pipe pipe (||)") { + let lhs = BoolBox(value: true) + let rhs = BoolBox(value: false) + + let result = lhs || rhs + + expectEqual(true, result.value) +} + runAllTests() diff --git a/test/TypeDecoder/invalid_types.swift b/test/TypeDecoder/invalid_types.swift new file mode 100644 index 0000000000000..9f26375b875e0 --- /dev/null +++ b/test/TypeDecoder/invalid_types.swift @@ -0,0 +1,12 @@ +// RUN: %empty-directory(%t) + +// RUN: %target-build-swift -emit-executable %s -g -o %t/structural_types -emit-module +// RUN: sed -ne '/\/\/ *DEMANGLE: /s/\/\/ *DEMANGLE: *//p' < %s > %t/input +// RUN: %lldb-moduleimport-test %t/structural_types -type-from-mangled=%t/input | %FileCheck %s + + +// If this were supported, it would be `(t: τ_0_0...)` +// But tuples with a variadic 'd' marker are not actually valid Swift types, so +// the type decoder rejects them. +// DEMANGLE: $sx1td_t +// CHECK: Can't resolve type of $sx1td_t diff --git a/test/decl/protocol/req/recursion.swift b/test/decl/protocol/req/recursion.swift index 3026cb561d389..f9d9761ee5077 100644 --- a/test/decl/protocol/req/recursion.swift +++ b/test/decl/protocol/req/recursion.swift @@ -48,8 +48,7 @@ public struct S where A.T == S { // expected-error {{circular reference // expected-error@-2 {{generic struct 'S' references itself}} // expected-note@-3 {{while resolving type 'S'}} func f(a: A.T) { - g(a: id(t: a)) - // expected-error@-1 {{type of expression is ambiguous without more context}} + g(a: id(t: a)) // `a` has error type which is diagnosed as circular reference _ = A.T.self } diff --git a/test/stdlib/symbol-visibility-linux.test-sh b/test/stdlib/symbol-visibility-linux.test-sh index fd80eb8b3f3c3..b4e5a7df71e50 100644 --- a/test/stdlib/symbol-visibility-linux.test-sh +++ b/test/stdlib/symbol-visibility-linux.test-sh @@ -27,6 +27,7 @@ // RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA24_cEEEvv \ // RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA32_cEEEvv \ // RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA40_cEEEvv \ +// RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA80_cEEEvv \ // RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA88_cEEEvv \ // RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA104_cEEEvv \ // RUN: > %t/swiftCore-all.txt @@ -47,6 +48,7 @@ // RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA24_cEEEvv \ // RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA32_cEEEvv \ // RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA40_cEEEvv \ +// RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA80_cEEEvv \ // RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA88_cEEEvv \ // RUN: -e _ZSt16__once_call_implISt12_Bind_simpleIFPFvPvEPA104_cEEEvv \ // RUN: > %t/swiftRemoteMirror-all.txt diff --git a/tools/swift-demangle/swift-demangle.cpp b/tools/swift-demangle/swift-demangle.cpp index e129ce62e0de8..86a849a67e09e 100644 --- a/tools/swift-demangle/swift-demangle.cpp +++ b/tools/swift-demangle/swift-demangle.cpp @@ -76,6 +76,11 @@ Classify("classify", /// Options that are primarily used for testing. /// \{ +static llvm::cl::opt DisplayLocalNameContexts( + "display-local-name-contexts", llvm::cl::init(true), + llvm::cl::desc("Qualify local names"), + llvm::cl::Hidden); + static llvm::cl::opt DisplayStdlibModule( "display-stdlib-module", llvm::cl::init(true), llvm::cl::desc("Qualify types originating from the Swift standard library"), @@ -255,6 +260,7 @@ int main(int argc, char **argv) { options.DisplayStdlibModule = DisplayStdlibModule; options.DisplayObjCModule = DisplayObjCModule; options.HidingCurrentModule = HidingModule; + options.DisplayLocalNameContexts = DisplayLocalNameContexts; if (InputNames.empty()) { CompactMode = true; diff --git a/tools/swift-inspect/Sources/swift-inspect/Backtrace.swift b/tools/swift-inspect/Sources/swift-inspect/Backtrace.swift new file mode 100644 index 0000000000000..1ee0f052cce1e --- /dev/null +++ b/tools/swift-inspect/Sources/swift-inspect/Backtrace.swift @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import SwiftRemoteMirror + +struct Backtrace { + enum Style { + case oneLine + case long + } + + /// The pointers to the locations in the backtrace. These are stored from + /// deepest to shallowest, so main() will be somewhere near the end. + var ptrs: [swift_reflection_ptr_t] + + func symbolString( + ptr: swift_reflection_ptr_t, + inspector: Inspector + ) -> String { + let symbol = inspector.getSymbol(address: ptr) + let name = symbol.name ?? "" + let library = symbol.library ?? "" + return "\(hex: ptr) (\(library)) \(name)" + } + + func symbolicatedOneLine(inspector: Inspector) -> String { + return ptrs.reversed().map { + symbolString(ptr: $0, inspector: inspector) + }.joined(separator: " | ") + } + + func symbolicatedLong(inspector: Inspector) -> String { + return ptrs.reversed().enumerated().map { + let indent = String(repeating: " ", count: $0 + 1) + return indent + symbolString(ptr: $1, inspector: inspector) + }.joined(separator: "\n") + } + + func symbolicated(style: Style, inspector: Inspector) -> String { + switch style { + case .oneLine: + return symbolicatedOneLine(inspector: inspector) + case .long: + return symbolicatedLong(inspector: inspector) + } + } +} diff --git a/tools/swift-inspect/Sources/swift-inspect/Inspector.swift b/tools/swift-inspect/Sources/swift-inspect/Inspector.swift index a77fa6bd8cd1f..40a6b3979d504 100644 --- a/tools/swift-inspect/Sources/swift-inspect/Inspector.swift +++ b/tools/swift-inspect/Sources/swift-inspect/Inspector.swift @@ -67,11 +67,19 @@ class Inspector { } func getAddr(symbolName: String) -> swift_addr_t { - let symbol = CSSymbolOwnerGetSymbolWithMangledName(swiftCore, symbolName) + let symbol = CSSymbolOwnerGetSymbolWithMangledName(swiftCore, + "_" + symbolName) let range = CSSymbolGetRange(symbol) return swift_addr_t(range.location) } - + + func getSymbol(address: swift_addr_t) -> (name: String?, library: String?) { + let symbol = CSSymbolicatorGetSymbolWithAddressAtTime(symbolicator, address, + kCSNow) + return (CSSymbolGetName(symbol), + CSSymbolOwnerGetName(CSSymbolGetSymbolOwner(symbol))) + } + enum Callbacks { static let QueryDataLayout: @convention(c) (UnsafeMutableRawPointer?, @@ -114,12 +122,12 @@ private func QueryDataLayoutFn(context: UnsafeMutableRawPointer?, inBuffer: UnsafeMutableRawPointer?, outBuffer: UnsafeMutableRawPointer?) -> CInt { switch type { - case DLQ_GetPointerSize: - let size = UInt8(MemoryLayout.stride) - outBuffer!.storeBytes(of: size, toByteOffset: 0, as: UInt8.self) - return 1 - default: - return 0 + case DLQ_GetPointerSize: + let size = UInt8(MemoryLayout.stride) + outBuffer!.storeBytes(of: size, toByteOffset: 0, as: UInt8.self) + return 1 + default: + return 0 } } diff --git a/tools/swift-inspect/Sources/swift-inspect/RemoteMirrorExtensions.swift b/tools/swift-inspect/Sources/swift-inspect/RemoteMirrorExtensions.swift index 4467eb60ca138..9a0141e1369d8 100644 --- a/tools/swift-inspect/Sources/swift-inspect/RemoteMirrorExtensions.swift +++ b/tools/swift-inspect/Sources/swift-inspect/RemoteMirrorExtensions.swift @@ -63,6 +63,20 @@ extension SwiftReflectionContextRef { try throwError(str: errStr) } + func iterateMetadataAllocationBacktraces( + _ body: (swift_reflection_ptr_t, Int, UnsafePointer) + -> Void + ) throws { + var body = body + let errStr = swift_reflection_iterateMetadataAllocationBacktraces(self, { + let callPtr = $3!.bindMemory(to: + ((swift_reflection_ptr_t, Int, UnsafePointer) + -> Void).self, capacity: 1) + callPtr.pointee($0, $1, $2!) + }, &body) + try throwError(str: errStr) + } + func metadataPointer( allocation: swift_metadata_allocation_t ) -> swift_reflection_ptr_t { @@ -82,4 +96,13 @@ extension SwiftReflectionContextRef { } return allocations } + + var allocationBacktraces: [swift_reflection_ptr_t: Backtrace] { + var backtraces: [swift_reflection_ptr_t: Backtrace] = [:] + try! iterateMetadataAllocationBacktraces { allocation, count, ptrs in + let array = Array(UnsafeBufferPointer(start: ptrs, count: count)) + backtraces[allocation] = Backtrace(ptrs: array) + } + return backtraces + } } diff --git a/tools/swift-inspect/Sources/swift-inspect/main.swift b/tools/swift-inspect/Sources/swift-inspect/main.swift index 53301f06cd21d..0c14d546c5132 100644 --- a/tools/swift-inspect/Sources/swift-inspect/main.swift +++ b/tools/swift-inspect/Sources/swift-inspect/main.swift @@ -33,16 +33,27 @@ func dumpConformanceCache(context: SwiftReflectionContextRef) throws { } } -func dumpRawMetadata(context: SwiftReflectionContextRef) throws { +func dumpRawMetadata( + context: SwiftReflectionContextRef, + inspector: Inspector, + backtraceStyle: Backtrace.Style? +) throws { + let backtraces = backtraceStyle != nil ? context.allocationBacktraces : [:] for allocation in context.allocations { print("Metadata allocation at: \(hex: allocation.ptr) " + "size: \(allocation.size) tag: \(allocation.tag)") + printBacktrace(style: backtraceStyle, for: allocation.ptr, in: backtraces, inspector: inspector) } } -func dumpGenericMetadata(context: SwiftReflectionContextRef) throws { +func dumpGenericMetadata( + context: SwiftReflectionContextRef, + inspector: Inspector, + backtraceStyle: Backtrace.Style? +) throws { let allocations = context.allocations.sorted() let metadatas = allocations.findGenericMetadata(in: context) + let backtraces = backtraceStyle != nil ? context.allocationBacktraces : [:] print("Address","Allocation","Size","Offset","Name", separator: "\t") for metadata in metadatas { @@ -53,9 +64,26 @@ func dumpGenericMetadata(context: SwiftReflectionContextRef) throws { terminator: "\t") } else { print("???\t???\t???", terminator: "\t") - } print(metadata.name) + if let allocation = metadata.allocation { + printBacktrace(style: backtraceStyle, for: allocation.ptr, in: backtraces, inspector: inspector) + } + } +} + +func printBacktrace( + style: Backtrace.Style?, + for ptr: swift_reflection_ptr_t, + in backtraces: [swift_reflection_ptr_t: Backtrace], + inspector: Inspector +) { + if let style = style { + if let backtrace = backtraces[ptr] { + print(backtrace.symbolicated(style: style, inspector: inspector)) + } else { + print("Unknown backtrace.") + } } } @@ -86,14 +114,14 @@ func makeReflectionContext( func withReflectionContext( nameOrPid: String, - _ body: (SwiftReflectionContextRef) throws -> Void + _ body: (SwiftReflectionContextRef, Inspector) throws -> Void ) throws { let (inspector, context) = makeReflectionContext(nameOrPid: nameOrPid) defer { swift_reflection_destroyReflectionContext(context) inspector.destroyContext() } - try body(context) + try body(context, inspector) } struct SwiftInspect: ParsableCommand { @@ -114,8 +142,8 @@ struct DumpConformanceCache: ParsableCommand { var nameOrPid: String func run() throws { - try withReflectionContext(nameOrPid: nameOrPid) { - try dumpConformanceCache(context: $0) + try withReflectionContext(nameOrPid: nameOrPid) { context, _ in + try dumpConformanceCache(context: context) } } } @@ -127,23 +155,43 @@ struct DumpRawMetadata: ParsableCommand { var nameOrPid: String + @Flag(help: "Show the backtrace for each allocation") + var backtrace: Bool + + @Flag(help: "Show a long-form backtrace for each allocation") + var backtraceLong: Bool + func run() throws { + let style = backtrace ? Backtrace.Style.oneLine : + backtraceLong ? Backtrace.Style.long : + nil try withReflectionContext(nameOrPid: nameOrPid) { - try dumpRawMetadata(context: $0) + try dumpRawMetadata(context: $0, inspector: $1, backtraceStyle: style) } } } struct DumpGenericMetadata: ParsableCommand { static let configuration = CommandConfiguration( - abstract: "Print the target's metadata allocations.") - @Argument(help: "The pid or partial name of the target process") + abstract: "Print the target's generic metadata allocations.") + @Argument(help: "The pid or partial name of the target process") var nameOrPid: String + @Flag(help: "Show the backtrace for each allocation") + var backtrace: Bool + + @Flag(help: "Show a long-form backtrace for each allocation") + var backtraceLong: Bool + func run() throws { + let style = backtrace ? Backtrace.Style.oneLine : + backtraceLong ? Backtrace.Style.long : + nil try withReflectionContext(nameOrPid: nameOrPid) { - try dumpGenericMetadata(context: $0) + try dumpGenericMetadata(context: $0, + inspector: $1, + backtraceStyle: style) } } } diff --git a/tools/swift-inspect/Sources/swift-inspect/symbolication.swift b/tools/swift-inspect/Sources/swift-inspect/symbolication.swift index d1096307e59df..5da69269af7e6 100644 --- a/tools/swift-inspect/Sources/swift-inspect/symbolication.swift +++ b/tools/swift-inspect/Sources/swift-inspect/symbolication.swift @@ -46,10 +46,18 @@ enum Sym { symbol(coreSymbolicationHandle, "CSSymbolGetName") static let CSSymbolGetMangledName: @convention(c) (CSTypeRef) -> UnsafePointer? = symbol(coreSymbolicationHandle, "CSSymbolGetMangledName") + static let CSSymbolGetSymbolOwner: @convention(c) + (CSSymbolRef) -> CSSymbolOwnerRef = + symbol(coreSymbolicationHandle, "CSSymbolGetSymbolOwner") static let CSSymbolIsFunction: @convention(c) (CSTypeRef) -> CBool = symbol(coreSymbolicationHandle, "CSSymbolIsFunction") static let CSSymbolGetRange: @convention(c) (CSTypeRef) -> Range = symbol(coreSymbolicationHandle, "CSSymbolGetRange") + static let CSSymbolOwnerGetName: @convention(c) (CSSymbolOwnerRef) -> UnsafePointer? = + symbol(coreSymbolicationHandle, "CSSymbolOwnerGetName") + static let CSSymbolicatorGetSymbolWithAddressAtTime: @convention(c) + (CSSymbolicatorRef, mach_vm_address_t, CSMachineTime) -> CSSymbolRef = + symbol(coreSymbolicationHandle, "CSSymbolicatorGetSymbolWithAddressAtTime") static let task_start_peeking: @convention(c) (task_t) -> kern_return_t = symbol(symbolicationHandle, "task_start_peeking") static let task_peek: @convention(c) (task_t, mach_vm_address_t, mach_vm_size_t, @@ -66,6 +74,10 @@ enum Sym { typealias CSMachineTime = UInt64 let kCSNow = CSMachineTime(Int64.max) + 1 +typealias CSSymbolicatorRef = CSTypeRef +typealias CSSymbolRef = CSTypeRef +typealias CSSymbolOwnerRef = CSTypeRef + func pidFromHint(_ hint: String) -> pid_t? { let result = Sym.pidFromHint(hint as NSString) return result == 0 ? nil : result @@ -100,12 +112,12 @@ func CSSymbolOwnerGetSymbolWithMangledName( func CSSymbolGetName(_ sym: CSTypeRef) -> String? { let name = Sym.CSSymbolGetName(sym) - return name.map({ String(cString: $0) }) + return name.map{ String(cString: $0) } } func CSSymbolGetMangledName(_ sym: CSTypeRef) -> String? { let name = Sym.CSSymbolGetMangledName(sym) - return name.map({ String(cString: $0) }) + return name.map{ String(cString: $0) } } func CSSymbolIsFunction(_ sym: CSTypeRef) -> Bool { @@ -116,6 +128,23 @@ func CSSymbolGetRange(_ sym: CSTypeRef) -> Range { Sym.CSSymbolGetRange(sym) } +func CSSymbolGetSymbolOwner(_ sym: CSTypeRef) -> CSSymbolOwnerRef { + Sym.CSSymbolGetSymbolOwner(sym) +} + +func CSSymbolOwnerGetName(_ sym: CSTypeRef) -> String? { + Sym.CSSymbolOwnerGetName(sym) + .map(String.init(cString:)) +} + +func CSSymbolicatorGetSymbolWithAddressAtTime( + _ symbolicator: CSSymbolicatorRef, + _ address: mach_vm_address_t, + _ time: CSMachineTime +) -> CSSymbolRef { + Sym.CSSymbolicatorGetSymbolWithAddressAtTime(symbolicator, address, time) +} + func task_start_peeking(_ task: task_t) -> Bool { let result = Sym.task_start_peeking(task) if result == KERN_SUCCESS {