diff --git a/include/swift/AST/ASTScope.h b/include/swift/AST/ASTScope.h index 3411bed70fbf9..1b9e0dcdc8313 100644 --- a/include/swift/AST/ASTScope.h +++ b/include/swift/AST/ASTScope.h @@ -990,7 +990,6 @@ class ConditionalClauseInitializerScope final : public ASTScopeImpl { SourceRange getSourceRangeOfThisASTNode(bool omitAssertions = false) const override; std::string getClassName() const override; - bool ignoreInDebugInfo() const override { return true; } private: void expandAScopeThatDoesNotCreateANewInsertionPoint(ScopeCreator &); diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 891f8c1a46427..556ee0f456948 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -5317,6 +5317,16 @@ class AbstractStorageDecl : public ValueDecl { /// it. bool hasStorage() const; + /// Return true if this is a VarDecl that has init accessor associated + /// with it. + bool hasInitAccessor() const; + + /// Return true if this is a property that either has storage + /// or init accessor associated with it. + bool supportsInitialization() const { + return hasStorage() || hasInitAccessor(); + } + /// Return true if this storage has the basic accessors/capability /// to be mutated. This is generally constant after the accessors are /// installed by the parser/importer/whatever. diff --git a/include/swift/AST/DiagnosticEngine.h b/include/swift/AST/DiagnosticEngine.h index fce04b13d43b7..c8ed60a36703c 100644 --- a/include/swift/AST/DiagnosticEngine.h +++ b/include/swift/AST/DiagnosticEngine.h @@ -1458,6 +1458,22 @@ namespace swift { } }; + /// A RAII object that adds and removes a diagnostic consumer from an engine. + class DiagnosticConsumerRAII final { + DiagnosticEngine &Diags; + DiagnosticConsumer &Consumer; + + public: + DiagnosticConsumerRAII(DiagnosticEngine &diags, + DiagnosticConsumer &consumer) + : Diags(diags), Consumer(consumer) { + Diags.addConsumer(Consumer); + } + ~DiagnosticConsumerRAII() { + Diags.removeConsumer(Consumer); + } + }; + inline void DiagnosticEngine::diagnoseWithNotes(InFlightDiagnostic parentDiag, llvm::function_ref builder) { diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 63cde20ba0480..3a6606abf2a63 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -4672,7 +4672,7 @@ ERROR(unknown_case_multiple_patterns,none, ERROR(unknown_case_must_be_last,none, "'@unknown' can only be applied to the last case in a switch", ()) -WARNING(move_only_pattern_match_not_consumed,none, +ERROR(move_only_pattern_match_not_consumed,none, "noncopyable binding being pattern-matched must have the 'consume' operator applied", ()) WARNING(where_on_one_item, none, diff --git a/include/swift/AST/SearchPathOptions.h b/include/swift/AST/SearchPathOptions.h index be355091b29d6..12a96849ed722 100644 --- a/include/swift/AST/SearchPathOptions.h +++ b/include/swift/AST/SearchPathOptions.h @@ -14,8 +14,8 @@ #define SWIFT_AST_SEARCHPATHOPTIONS_H #include "swift/Basic/ArrayRefView.h" +#include "swift/Basic/ExternalUnion.h" #include "swift/Basic/PathRemapper.h" -#include "swift/Basic/TaggedUnion.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringMap.h" @@ -187,25 +187,81 @@ struct ExternalPluginSearchPathAndServerPath { std::string ServerPath; }; -namespace PluginSearchOption { -struct LoadPluginLibrary { - std::string LibraryPath; -}; -struct LoadPluginExecutable { - std::string ExecutablePath; - std::vector ModuleNames; -}; -struct PluginPath { - std::string SearchPath; -}; -struct ExternalPluginPath { - std::string SearchPath; - std::string ServerPath; -}; +class PluginSearchOption { +public: + struct LoadPluginLibrary { + std::string LibraryPath; + }; + struct LoadPluginExecutable { + std::string ExecutablePath; + std::vector ModuleNames; + }; + struct PluginPath { + std::string SearchPath; + }; + struct ExternalPluginPath { + std::string SearchPath; + std::string ServerPath; + }; + + enum class Kind : uint8_t { + LoadPluginLibrary, + LoadPluginExecutable, + PluginPath, + ExternalPluginPath, + }; -using Value = TaggedUnion; -} // namespace PluginSearchOption +private: + using Members = ExternalUnionMembers; + static Members::Index getIndexForKind(Kind kind) { + switch (kind) { + case Kind::LoadPluginLibrary: + return Members::indexOf(); + case Kind::LoadPluginExecutable: + return Members::indexOf(); + case Kind::PluginPath: + return Members::indexOf(); + case Kind::ExternalPluginPath: + return Members::indexOf(); + } + }; + using Storage = ExternalUnion; + + Kind kind; + Storage storage; + +public: + PluginSearchOption(const LoadPluginLibrary &v) + : kind(Kind::LoadPluginLibrary) { + storage.emplace(kind, v); + } + PluginSearchOption(const LoadPluginExecutable &v) + : kind(Kind::LoadPluginExecutable) { + storage.emplace(kind, v); + } + PluginSearchOption(const PluginPath &v) : kind(Kind::PluginPath) { + storage.emplace(kind, v); + } + PluginSearchOption(const ExternalPluginPath &v) + : kind(Kind::ExternalPluginPath) { + storage.emplace(kind, v); + } + + Kind getKind() const { return kind; } + + template + const T *dyn_cast() const { + if (Members::indexOf() != getIndexForKind(kind)) + return nullptr; + return &storage.get(kind); + } + + template + const T &get() const { + return storage.get(kind); + } +}; /// Options for controlling search path behavior. class SearchPathOptions { @@ -383,7 +439,7 @@ class SearchPathOptions { std::vector RuntimeLibraryPaths; /// Plugin search path options. - std::vector PluginSearchOpts; + std::vector PluginSearchOpts; /// Don't look in for compiler-provided modules. bool SkipRuntimeLibraryImportPaths = false; diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 0dd81a6b654cf..80fcb212739e1 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -4312,6 +4312,22 @@ class IsNonUserModuleRequest bool isCached() const { return true; } }; +class HasInitAccessorRequest + : public SimpleRequest { +public: + using SimpleRequest::SimpleRequest; + +private: + friend SimpleRequest; + + // Evaluation. + bool evaluate(Evaluator &evaluator, AbstractStorageDecl *decl) const; + +public: + bool isCached() const { return true; } +}; + class InitAccessorReferencedVariablesRequest : public SimpleRequest(DeclAttribute *, AccessorDecl *, diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def index e13aced855628..a7ae070b5aa99 100644 --- a/include/swift/AST/TypeCheckerTypeIDZone.def +++ b/include/swift/AST/TypeCheckerTypeIDZone.def @@ -487,6 +487,9 @@ SWIFT_REQUEST(TypeChecker, IsNonUserModuleRequest, SWIFT_REQUEST(TypeChecker, TypeCheckObjCImplementationRequest, unsigned(ExtensionDecl *), Cached, NoLocationInfo) +SWIFT_REQUEST(TypeChecker, HasInitAccessorRequest, + bool(AbstractStorageDecl *), Cached, + NoLocationInfo) SWIFT_REQUEST(TypeChecker, InitAccessorReferencedVariablesRequest, ArrayRef(DeclAttribute *, AccessorDecl *, ArrayRef), diff --git a/include/swift/Basic/FrozenMultiMap.h b/include/swift/Basic/FrozenMultiMap.h index 617fd64407266..a36f3e4704b1d 100644 --- a/include/swift/Basic/FrozenMultiMap.h +++ b/include/swift/Basic/FrozenMultiMap.h @@ -71,7 +71,7 @@ class FrozenMultiMap { // Since our array is sorted, we need to first find the first pair with our // inst as the first element. auto start = std::lower_bound( - storage.begin(), storage.end(), std::make_pair(key, Value()), + storage.begin(), storage.end(), std::make_pair(key, llvm::None), [&](const std::pair> &p1, const std::pair> &p2) { return p1.first < p2.first; diff --git a/include/swift/Driver/ToolChain.h b/include/swift/Driver/ToolChain.h index d76b0c6c99036..9655eebe6ae71 100644 --- a/include/swift/Driver/ToolChain.h +++ b/include/swift/Driver/ToolChain.h @@ -143,6 +143,11 @@ class ToolChain { const llvm::opt::ArgList &inputArgs, llvm::opt::ArgStringList &arguments) const; + virtual void addPlatformSpecificPluginFrontendArgs( + const OutputInfo &OI, + const CommandOutput &output, + const llvm::opt::ArgList &inputArgs, + llvm::opt::ArgStringList &arguments) const; virtual InvocationInfo constructInvocation(const CompileJobAction &job, const JobContext &context) const; virtual InvocationInfo constructInvocation(const InterpretJobAction &job, diff --git a/include/swift/SIL/FieldSensitivePrunedLiveness.h b/include/swift/SIL/FieldSensitivePrunedLiveness.h index 1728e0955bd3d..456ba6c387bee 100644 --- a/include/swift/SIL/FieldSensitivePrunedLiveness.h +++ b/include/swift/SIL/FieldSensitivePrunedLiveness.h @@ -358,6 +358,13 @@ struct TypeTreeLeafTypeRange { endEltOffset >= range.endEltOffset; } + /// Sets each bit in \p bits corresponding to an element of this range. + void setBits(SmallBitVector &bits) { + for (auto element : getRange()) { + bits.set(element); + } + } + IntRange getRange() const { return range(startEltOffset, endEltOffset); } @@ -666,17 +673,60 @@ class FieldSensitivePrunedLiveness { FieldSensitivePrunedLiveBlocks liveBlocks; public: + enum IsInterestingUser { NonUser, NonLifetimeEndingUse, LifetimeEndingUse }; + struct InterestingUser { - TypeTreeLeafTypeRange subEltSpan; - bool isConsuming; + SmallBitVector liveBits; + SmallBitVector consumingBits; - InterestingUser() : subEltSpan(), isConsuming(false) {} - InterestingUser(TypeTreeLeafTypeRange subEltSpan, bool isConsuming) - : subEltSpan(subEltSpan), isConsuming(isConsuming) {} + InterestingUser(unsigned bitCount) + : liveBits(bitCount), consumingBits(bitCount) {} - InterestingUser &operator&=(bool otherValue) { - isConsuming &= otherValue; - return *this; + InterestingUser(unsigned bitCount, TypeTreeLeafTypeRange range, + bool lifetimeEnding) + : liveBits(bitCount), consumingBits(bitCount) { + addUses(range, lifetimeEnding); + } + + /// Record that the instruction uses the bits of the value in \p range. + void addUses(TypeTreeLeafTypeRange range, bool lifetimeEnding) { + range.setBits(liveBits); + if (lifetimeEnding) { + range.setBits(consumingBits); + } + } + + /// Populates the provided vector with contiguous ranges of bits which are + /// users of the same sort. + void getContiguousRanges( + SmallVectorImpl> + &ranges) const { + if (liveBits.size() == 0) + return; + + assert(ranges.empty()); + Optional> current = llvm::None; + for (unsigned bit = 0, size = liveBits.size(); bit < size; ++bit) { + auto interesting = isInterestingUser(bit); + if (!current) { + current = {bit, interesting}; + continue; + } + if (current->second != interesting) { + ranges.push_back( + {TypeTreeLeafTypeRange(current->first, bit), current->second}); + current = {bit, interesting}; + } + } + ranges.push_back({TypeTreeLeafTypeRange(current->first, liveBits.size()), + current->second}); + } + + IsInterestingUser isInterestingUser(unsigned element) const { + if (!liveBits.test(element)) + return NonUser; + return consumingBits.test(element) ? LifetimeEndingUse + : NonLifetimeEndingUse; } }; @@ -758,42 +808,6 @@ class FieldSensitivePrunedLiveness { return llvm::make_range(users.begin(), users.end()); } - using LifetimeEndingUserRange = OptionalTransformRange< - UserRange, - function_ref>( - const std::pair &)>>; - LifetimeEndingUserRange getAllLifetimeEndingUses() const { - assert(isInitialized()); - function_ref>( - const std::pair &)> - op; - op = [](const std::pair &pair) - -> Optional> { - if (pair.second.isConsuming) - return {{pair.first, pair.second.subEltSpan}}; - return None; - }; - return LifetimeEndingUserRange(getAllUsers(), op); - } - - using NonLifetimeEndingUserRange = OptionalTransformRange< - UserRange, - function_ref>( - const std::pair &)>>; - NonLifetimeEndingUserRange getAllNonLifetimeEndingUses() const { - assert(isInitialized()); - function_ref>( - const std::pair &)> - op; - op = [](const std::pair &pair) - -> Optional> { - if (!pair.second.isConsuming) - return {{pair.first, pair.second.subEltSpan}}; - return None; - }; - return NonLifetimeEndingUserRange(getAllUsers(), op); - } - using UserBlockRange = TransformRange< UserRange, function_ref &)>>; @@ -848,19 +862,37 @@ class FieldSensitivePrunedLiveness { SmallBitVector &liveOutBits, SmallBitVector &deadBits) const; - enum IsInterestingUser { NonUser, NonLifetimeEndingUse, LifetimeEndingUse }; + /// If \p user has had uses recored, return a pointer to the InterestingUser + /// where they've been recorded. + InterestingUser const *getInterestingUser(SILInstruction *user) const { + auto iter = users.find(user); + if (iter == users.end()) + return nullptr; + return &iter->second; + } - /// Return a result indicating whether the given user was identified as an - /// interesting use of the current def and whether it ends the lifetime. - std::pair> - isInterestingUser(SILInstruction *user) const { + /// How \p user uses the field at \p element. + IsInterestingUser isInterestingUser(SILInstruction *user, + unsigned element) const { assert(isInitialized()); - auto useIter = users.find(user); - if (useIter == users.end()) - return {NonUser, None}; - auto isInteresting = - useIter->second.isConsuming ? LifetimeEndingUse : NonLifetimeEndingUse; - return {isInteresting, useIter->second.subEltSpan}; + auto *record = getInterestingUser(user); + if (!record) + return NonUser; + return record->isInterestingUser(element); + } + + /// Whether \p user uses the fields in \p range as indicated by \p kind. + bool isInterestingUserOfKind(SILInstruction *user, IsInterestingUser kind, + TypeTreeLeafTypeRange range) const { + auto *record = getInterestingUser(user); + if (!record) + return kind == IsInterestingUser::NonUser; + + for (auto element : range.getRange()) { + if (isInterestingUser(user, element) != kind) + return false; + } + return true; } unsigned getNumSubElements() const { return liveBlocks.getNumBitsToTrack(); } @@ -886,10 +918,11 @@ class FieldSensitivePrunedLiveness { /// argument must be copied. void addInterestingUser(SILInstruction *user, TypeTreeLeafTypeRange range, bool lifetimeEnding) { - auto iterAndSuccess = - users.insert({user, InterestingUser(range, lifetimeEnding)}); - if (!iterAndSuccess.second) - iterAndSuccess.first->second &= lifetimeEnding; + auto iter = users.find(user); + if (iter == users.end()) { + iter = users.insert({user, InterestingUser(getNumSubElements())}).first; + } + iter->second.addUses(range, lifetimeEnding); } }; diff --git a/include/swift/Sema/CSFix.h b/include/swift/Sema/CSFix.h index 4b05b20679351..0cb178fdbc733 100644 --- a/include/swift/Sema/CSFix.h +++ b/include/swift/Sema/CSFix.h @@ -306,6 +306,9 @@ enum class FixKind : uint8_t { /// This issue should already have been diagnosed elsewhere. IgnoreUnresolvedPatternVar, + /// Ignore a nested UnresolvedPatternExpr in an ExprPattern, which is invalid. + IgnoreInvalidPatternInExpr, + /// Resolve type of `nil` by providing a contextual type. SpecifyContextualTypeForNil, @@ -2963,6 +2966,33 @@ class IgnoreUnresolvedPatternVar final : public ConstraintFix { } }; +class IgnoreInvalidPatternInExpr final : public ConstraintFix { + Pattern *P; + + IgnoreInvalidPatternInExpr(ConstraintSystem &cs, Pattern *pattern, + ConstraintLocator *locator) + : ConstraintFix(cs, FixKind::IgnoreInvalidPatternInExpr, locator), + P(pattern) {} + +public: + std::string getName() const override { + return "ignore invalid Pattern nested in Expr"; + } + + bool diagnose(const Solution &solution, bool asNote = false) const override; + + bool diagnoseForAmbiguity(CommonFixesArray commonFixes) const override { + return diagnose(*commonFixes.front().first); + } + + static IgnoreInvalidPatternInExpr * + create(ConstraintSystem &cs, Pattern *pattern, ConstraintLocator *locator); + + static bool classof(const ConstraintFix *fix) { + return fix->getKind() == FixKind::IgnoreInvalidPatternInExpr; + } +}; + class SpecifyContextualTypeForNil final : public ConstraintFix { SpecifyContextualTypeForNil(ConstraintSystem &cs, ConstraintLocator *locator) diff --git a/include/swift/Serialization/SerializationOptions.h b/include/swift/Serialization/SerializationOptions.h index d3e4f49f2441d..d38467eca23d8 100644 --- a/include/swift/Serialization/SerializationOptions.h +++ b/include/swift/Serialization/SerializationOptions.h @@ -13,6 +13,7 @@ #ifndef SWIFT_SERIALIZATION_SERIALIZATIONOPTIONS_H #define SWIFT_SERIALIZATION_SERIALIZATIONOPTIONS_H +#include "swift/AST/SearchPathOptions.h" #include "swift/Basic/LLVM.h" #include "swift/Basic/PathRemapper.h" #include "llvm/Support/VersionTuple.h" @@ -43,10 +44,7 @@ namespace swift { StringRef ModuleLinkName; StringRef ModuleInterface; std::vector ExtraClangOptions; - std::vector PluginSearchPaths; - std::vector ExternalPluginSearchPaths; - std::vector CompilerPluginLibraryPaths; - std::vector CompilerPluginExecutablePaths; + std::vector PluginSearchOptions; /// Path prefixes that should be rewritten in debug info. PathRemapper DebuggingOptionsPrefixMap; diff --git a/include/swift/Serialization/Validation.h b/include/swift/Serialization/Validation.h index a82380e74963a..9ba02485ae973 100644 --- a/include/swift/Serialization/Validation.h +++ b/include/swift/Serialization/Validation.h @@ -111,10 +111,8 @@ struct ValidationInfo { class ExtendedValidationInfo { SmallVector ExtraClangImporterOpts; - SmallVector PluginSearchPaths; - SmallVector ExternalPluginSearchPaths; - SmallVector CompilerPluginLibraryPaths; - SmallVector CompilerPluginExecutablePaths; + SmallVector, 2> + PluginSearchOptions; std::string SDKPath; StringRef ModuleABIName; @@ -149,32 +147,13 @@ class ExtendedValidationInfo { ExtraClangImporterOpts.push_back(option); } - ArrayRef getPluginSearchPaths() const { - return PluginSearchPaths; + ArrayRef> + getPluginSearchOptions() const { + return PluginSearchOptions; } - void addPluginSearchPath(StringRef path) { - PluginSearchPaths.push_back(path); - } - - ArrayRef getExternalPluginSearchPaths() const { - return ExternalPluginSearchPaths; - } - void addExternalPluginSearchPath(StringRef path) { - ExternalPluginSearchPaths.push_back(path); - } - - ArrayRef getCompilerPluginLibraryPaths() const { - return CompilerPluginLibraryPaths; - } - void addCompilerPluginLibraryPath(StringRef path) { - CompilerPluginLibraryPaths.push_back(path); - } - - ArrayRef getCompilerPluginExecutablePaths() const { - return CompilerPluginExecutablePaths; - } - void addCompilerPluginExecutablePath(StringRef path) { - CompilerPluginExecutablePaths.push_back(path); + void addPluginSearchOption( + const std::pair &opt) { + PluginSearchOptions.push_back(opt); } bool isSIB() const { return Bits.IsSIB; } diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 1fd84972038b3..67f5e1946744d 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1394,6 +1394,9 @@ FuncDecl *ASTContext::getMakeInvocationEncoderOnDistributedActorSystem( FuncDecl * ASTContext::getRecordGenericSubstitutionOnDistributedInvocationEncoder( NominalTypeDecl *nominal) const { + if (!nominal) + return nullptr; + for (auto result : nominal->lookupDirect(Id_recordGenericSubstitution)) { auto *func = dyn_cast(result); if (func && @@ -1407,6 +1410,9 @@ ASTContext::getRecordGenericSubstitutionOnDistributedInvocationEncoder( AbstractFunctionDecl *ASTContext::getRecordArgumentOnDistributedInvocationEncoder( NominalTypeDecl *nominal) const { + if (!nominal) + return nullptr; + return evaluateOrDefault( nominal->getASTContext().evaluator, GetDistributedTargetInvocationEncoderRecordArgumentFunctionRequest{nominal}, @@ -1415,6 +1421,9 @@ AbstractFunctionDecl *ASTContext::getRecordArgumentOnDistributedInvocationEncode AbstractFunctionDecl *ASTContext::getRecordReturnTypeOnDistributedInvocationEncoder( NominalTypeDecl *nominal) const { + if (!nominal) + return nullptr; + return evaluateOrDefault( nominal->getASTContext().evaluator, GetDistributedTargetInvocationEncoderRecordReturnTypeFunctionRequest{nominal}, @@ -1423,6 +1432,9 @@ AbstractFunctionDecl *ASTContext::getRecordReturnTypeOnDistributedInvocationEnco AbstractFunctionDecl *ASTContext::getRecordErrorTypeOnDistributedInvocationEncoder( NominalTypeDecl *nominal) const { + if (!nominal) + return nullptr; + return evaluateOrDefault( nominal->getASTContext().evaluator, GetDistributedTargetInvocationEncoderRecordErrorTypeFunctionRequest{nominal}, @@ -1431,6 +1443,9 @@ AbstractFunctionDecl *ASTContext::getRecordErrorTypeOnDistributedInvocationEncod AbstractFunctionDecl *ASTContext::getDecodeNextArgumentOnDistributedInvocationDecoder( NominalTypeDecl *nominal) const { + if (!nominal) + return nullptr; + return evaluateOrDefault( nominal->getASTContext().evaluator, GetDistributedTargetInvocationDecoderDecodeNextArgumentFunctionRequest{nominal}, @@ -1439,6 +1454,9 @@ AbstractFunctionDecl *ASTContext::getDecodeNextArgumentOnDistributedInvocationDe AbstractFunctionDecl *ASTContext::getOnReturnOnDistributedTargetInvocationResultHandler( NominalTypeDecl *nominal) const { + if (!nominal) + return nullptr; + return evaluateOrDefault( nominal->getASTContext().evaluator, GetDistributedTargetInvocationResultHandlerOnReturnFunctionRequest{nominal}, diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 065fd1e6e352a..dd55ebe4529a1 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -6720,6 +6720,12 @@ Type AbstractStorageDecl::getValueInterfaceType() const { return cast(this)->getElementInterfaceType(); } +bool AbstractStorageDecl::hasInitAccessor() const { + return evaluateOrDefault( + getASTContext().evaluator, + HasInitAccessorRequest{const_cast(this)}, false); +} + VarDecl::VarDecl(DeclKind kind, bool isStatic, VarDecl::Introducer introducer, SourceLoc nameLoc, Identifier name, DeclContext *dc, StorageIsMutable_t supportsMutation) diff --git a/lib/AST/PluginLoader.cpp b/lib/AST/PluginLoader.cpp index 1bdfc95b1e7ef..49368dd9a0fa6 100644 --- a/lib/AST/PluginLoader.cpp +++ b/lib/AST/PluginLoader.cpp @@ -61,27 +61,31 @@ PluginLoader::lookupPluginByModuleName(Identifier moduleName) { // FIXME: Should we create a lookup table keyed by module name? for (auto &entry : Ctx.SearchPathOpts.PluginSearchOpts) { - using namespace PluginSearchOption; + switch (entry.getKind()) { // Try '-load-plugin-library'. - if (auto *val = entry.dyn_cast()) { - if (llvm::sys::path::filename(val->LibraryPath) == pluginLibBasename) { - return {val->LibraryPath, ""}; + case PluginSearchOption::Kind::LoadPluginLibrary: { + auto &val = entry.get(); + if (llvm::sys::path::filename(val.LibraryPath) == pluginLibBasename) { + return {val.LibraryPath, ""}; } continue; } // Try '-load-plugin-executable'. - if (auto *v = entry.dyn_cast()) { + case PluginSearchOption::Kind::LoadPluginExecutable: { + auto &val = entry.get(); auto found = ExecutablePluginPaths.find(moduleName); - if (found != ExecutablePluginPaths.end()) { - return {"", std::string(found->second)}; + if (found != ExecutablePluginPaths.end() && + found->second == val.ExecutablePath) { + return {"", val.ExecutablePath}; } continue; } // Try '-plugin-path'. - if (auto *v = entry.dyn_cast()) { - SmallString<128> fullPath(v->SearchPath); + case PluginSearchOption::Kind::PluginPath: { + auto &val = entry.get(); + SmallString<128> fullPath(val.SearchPath); llvm::sys::path::append(fullPath, pluginLibBasename); if (fs->exists(fullPath)) { return {std::string(fullPath), ""}; @@ -90,14 +94,16 @@ PluginLoader::lookupPluginByModuleName(Identifier moduleName) { } // Try '-external-plugin-path'. - if (auto *v = entry.dyn_cast()) { - SmallString<128> fullPath(v->SearchPath); + case PluginSearchOption::Kind::ExternalPluginPath: { + auto &val = entry.get(); + SmallString<128> fullPath(val.SearchPath); llvm::sys::path::append(fullPath, pluginLibBasename); if (fs->exists(fullPath)) { - return {std::string(fullPath), v->ServerPath}; + return {std::string(fullPath), val.ServerPath}; } continue; } + } } return {}; diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 48ef2808303fd..9019dd5ed6bf1 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -2447,15 +2447,39 @@ namespace { } if (cxxRecordDecl) { + // FIXME: Swift right now uses AddressOnly type layout + // in a way that conflates C++ types + // that need to be destroyed or copied explicitly with C++ + // types that have to be passed indirectly, because + // only AddressOnly types can be copied or destroyed using C++ + // semantics. However, in actuality these two concepts are + // separate and don't map to one notion of AddressOnly type + // layout cleanly. We should reserve the use of AddressOnly + // type layout when types have to use C++ copy/move/destroy + // operations, but allow AddressOnly types to be passed + // directly as well. This will help unify the MSVC and + // Itanium difference here, and will allow us to support + // trivial_abi C++ types as well. auto isNonTrivialForPurposeOfCalls = [](const clang::CXXRecordDecl *decl) -> bool { return decl->hasNonTrivialCopyConstructor() || decl->hasNonTrivialMoveConstructor() || !decl->hasTrivialDestructor(); }; + auto isAddressOnlySwiftStruct = + [&](const clang::CXXRecordDecl *decl) -> bool { + // MSVC ABI allows non-trivially destroyed C++ types + // to be passed in register. This is not supported, as such + // type wouldn't be destroyed in Swift correctly. Therefore, + // force AddressOnly type layout using the old heuristic. + // FIXME: Support can pass in registers for MSVC correctly. + if (Impl.SwiftContext.LangOpts.Target.isWindowsMSVCEnvironment()) + return isNonTrivialForPurposeOfCalls(decl); + return !decl->canPassInRegisters(); + }; if (auto structResult = dyn_cast(result)) structResult->setIsCxxNonTrivial( - isNonTrivialForPurposeOfCalls(cxxRecordDecl)); + isAddressOnlySwiftStruct(cxxRecordDecl)); for (auto &getterAndSetter : Impl.GetterSetterMap[result]) { auto getter = getterAndSetter.second.first; @@ -2718,6 +2742,17 @@ namespace { if (!result) return nullptr; + if (decl->hasAttr()) { + // We cannot yet represent trivial_abi C++ records in Swift. + // Clang tells us such type can be passed in registers, so + // we avoid using AddressOnly type-layout for such type, which means + // that it then does not use C++'s copy and destroy semantics from + // Swift. + Impl.markUnavailable(cast(result), + "C++ classes with `trivial_abi` Clang attribute " + "are not yet available in Swift"); + } + if (auto classDecl = dyn_cast(result)) { validateForeignReferenceType(decl, classDecl); diff --git a/lib/Driver/DarwinToolChains.cpp b/lib/Driver/DarwinToolChains.cpp index 02024e99257a5..7ec1a9a1b7eb8 100644 --- a/lib/Driver/DarwinToolChains.cpp +++ b/lib/Driver/DarwinToolChains.cpp @@ -620,6 +620,51 @@ void toolchains::Darwin::addCommonFrontendArgs( } } +/// Add the frontend arguments needed to find external plugins in standard +/// locations based on the base path. +static void addExternalPluginFrontendArgs( + StringRef basePath, const llvm::opt::ArgList &inputArgs, + llvm::opt::ArgStringList &arguments) { + // Plugin server: $BASE/usr/bin/swift-plugin-server + SmallString<128> pluginServer; + llvm::sys::path::append( + pluginServer, basePath, "usr", "bin", "swift-plugin-server"); + + SmallString<128> pluginDir; + llvm::sys::path::append(pluginDir, basePath, "usr", "lib"); + llvm::sys::path::append(pluginDir, "swift", "host", "plugins"); + arguments.push_back("-external-plugin-path"); + arguments.push_back(inputArgs.MakeArgString(pluginDir + "#" + pluginServer)); + + pluginDir.clear(); + llvm::sys::path::append(pluginDir, basePath, "usr", "local", "lib"); + llvm::sys::path::append(pluginDir, "swift", "host", "plugins"); + arguments.push_back("-external-plugin-path"); + arguments.push_back(inputArgs.MakeArgString(pluginDir + "#" + pluginServer)); +} + +void toolchains::Darwin::addPlatformSpecificPluginFrontendArgs( + const OutputInfo &OI, + const CommandOutput &output, + const llvm::opt::ArgList &inputArgs, + llvm::opt::ArgStringList &arguments) const { + // Add SDK-relative directories for plugins. + if (!OI.SDKPath.empty()) { + addExternalPluginFrontendArgs(OI.SDKPath, inputArgs, arguments); + } + + // Add platform-relative directories for plugins. + if (!OI.SDKPath.empty()) { + SmallString<128> platformPath; + llvm::sys::path::append(platformPath, OI.SDKPath); + llvm::sys::path::remove_filename(platformPath); // specific SDK + llvm::sys::path::remove_filename(platformPath); // SDKs + llvm::sys::path::remove_filename(platformPath); // Developer + llvm::sys::path::append(platformPath, "Developer"); + addExternalPluginFrontendArgs(platformPath, inputArgs, arguments); + } +} + ToolChain::InvocationInfo toolchains::Darwin::constructInvocation(const DynamicLinkJobAction &job, const JobContext &context) const { diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index c17b17f808b2d..eb1c8a0ade532 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -375,6 +375,9 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI, // Specify default plugin search path options after explicitly specified // options. inputArgs.AddAllArgs(arguments, options::OPT_plugin_search_Group); + addPlatformSpecificPluginFrontendArgs(OI, output, inputArgs, arguments); + + // Toolchain-relative plugin paths { SmallString<64> pluginPath; auto programPath = getDriver().getSwiftProgramPath(); @@ -403,6 +406,14 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI, inputArgs.AddAllArgs(arguments, options::OPT_Xcc); } +void ToolChain::addPlatformSpecificPluginFrontendArgs( + const OutputInfo &OI, + const CommandOutput &output, + const llvm::opt::ArgList &inputArgs, + llvm::opt::ArgStringList &arguments) const { + // Overridden where necessary. +} + static void addRuntimeLibraryFlags(const OutputInfo &OI, ArgStringList &Arguments) { if (!OI.RuntimeVariant) diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h index c30b04809e4f1..a91f3dd78cc29 100644 --- a/lib/Driver/ToolChains.h +++ b/lib/Driver/ToolChains.h @@ -53,6 +53,12 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain { const llvm::opt::ArgList &inputArgs, llvm::opt::ArgStringList &arguments) const override; + void addPlatformSpecificPluginFrontendArgs( + const OutputInfo &OI, + const CommandOutput &output, + const llvm::opt::ArgList &inputArgs, + llvm::opt::ArgStringList &arguments) const override; + InvocationInfo constructInvocation(const InterpretJobAction &job, const JobContext &context) const override; InvocationInfo constructInvocation(const DynamicLinkJobAction &job, diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index f96f80fc9647e..a1cfd21092870 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -209,36 +209,8 @@ SerializationOptions CompilerInvocation::computeSerializationOptions( serializationOpts.ExtraClangOptions = getClangImporterOptions().ExtraArgs; } - // FIXME: Preserve the order of these options. - for (auto &elem : getSearchPathOptions().PluginSearchOpts) { - // '-plugin-path' options. - if (auto *arg = elem.dyn_cast()) { - serializationOpts.PluginSearchPaths.push_back(arg->SearchPath); - continue; - } - - // '-external-plugin-path' options. - if (auto *arg = elem.dyn_cast()) { - serializationOpts.ExternalPluginSearchPaths.push_back( - arg->SearchPath + "#" + arg->ServerPath); - continue; - } - - // '-load-plugin-library' options. - if (auto *arg = elem.dyn_cast()) { - serializationOpts.CompilerPluginLibraryPaths.push_back(arg->LibraryPath); - continue; - } - - // '-load-plugin-executable' options. - if (auto *arg = elem.dyn_cast()) { - std::string optStr = arg->ExecutablePath + "#"; - llvm::interleave( - arg->ModuleNames, [&](auto &name) { optStr += name; }, - [&]() { optStr += ","; }); - serializationOpts.CompilerPluginExecutablePaths.push_back(optStr); - } - } + serializationOpts.PluginSearchOptions = + getSearchPathOptions().PluginSearchOpts; serializationOpts.DisableCrossModuleIncrementalInfo = opts.DisableCrossModuleIncrementalBuild; diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index 1a5296f910910..5aaaf9d90de1c 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -719,15 +719,16 @@ class ModuleInterfaceLoaderImpl { return pathStartsWith(hostPath, path); } - bool isInSystemFrameworks(StringRef path) { + bool isInSystemFrameworks(StringRef path, bool publicFramework) { StringRef sdkPath = ctx.SearchPathOpts.getSDKPath(); if (sdkPath.empty()) return false; - SmallString<128> publicFrameworksPath; - llvm::sys::path::append(publicFrameworksPath, - sdkPath, "System", "Library", "Frameworks"); + SmallString<128> frameworksPath; + llvm::sys::path::append(frameworksPath, + sdkPath, "System", "Library", + publicFramework ? "Frameworks" : "PrivateFrameworks"); - return pathStartsWith(publicFrameworksPath, path); + return pathStartsWith(frameworksPath, path); } std::pair getCompiledModuleCandidates() { @@ -738,11 +739,7 @@ class ModuleInterfaceLoaderImpl { // Don't use the adjacent swiftmodule for frameworks from the public // Frameworks folder of the SDK. - SmallString<128> publicFrameworksPath; - llvm::sys::path::append(publicFrameworksPath, - ctx.SearchPathOpts.getSDKPath(), - "System", "Library", "Frameworks"); - if (isInSystemFrameworks(modulePath)) { + if (isInSystemFrameworks(modulePath, /*publicFramework*/true)) { shouldLoadAdjacentModule = false; rebuildInfo.addIgnoredModule(modulePath, ReasonIgnored::PublicFramework); } else if (isInResourceHostDir(modulePath)) { diff --git a/lib/IRGen/TypeLayout.cpp b/lib/IRGen/TypeLayout.cpp index 5ef1e9fbd1f60..45d9b515c88eb 100644 --- a/lib/IRGen/TypeLayout.cpp +++ b/lib/IRGen/TypeLayout.cpp @@ -15,6 +15,7 @@ #include "FixedTypeInfo.h" #include "GenOpaque.h" #include "IRGen.h" +#include "GenEnum.h" #include "GenExistential.h" #include "GenericArguments.h" #include "IRGenFunction.h" @@ -510,7 +511,8 @@ llvm::Function *createFixedEnumLoadTag(IRGenModule &IGM, auto castEnumPtr = IGF.Builder.CreateBitCast(enumPtr, enumType); auto enumAddr = typeInfo->getAddressForPointer(castEnumPtr); - auto tag = entry.getEnumTag(IGF, enumAddr); + auto &strategy = getEnumImplStrategy(IGM, entry.ty); + auto tag = strategy.emitGetEnumTag(IGF, entry.ty, enumAddr); IGF.Builder.CreateRet(tag); }); diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 0091424812568..ce8131c75c479 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -1059,14 +1059,14 @@ bool Parser::isStartOfGetSetAccessor() { // The only case this can happen is if the accessor label is immediately after // a brace (possibly preceded by attributes). "get" is implicit, so it can't // be checked for. Conveniently however, get/set properties are not allowed - // to have initializers, so we don't have an ambiguity, we just have to check - // for observing accessors. + // to have initializers unless they have `init` accessor, so we don't have an + // ambiguity, we just have to check for observing accessors and init accessor. // // If we have a 'didSet' or a 'willSet' label, disambiguate immediately as // an accessor block. Token NextToken = peekToken(); if (NextToken.isContextualKeyword("didSet") || - NextToken.isContextualKeyword("willSet")) + NextToken.isContextualKeyword("willSet") || NextToken.is(tok::kw_init)) return true; // If we don't have attributes, then it cannot be an accessor block. @@ -1087,9 +1087,9 @@ bool Parser::isStartOfGetSetAccessor() { skipSingle(); } - // Check if we have 'didSet'/'willSet' after attributes. + // Check if we have 'didSet'/'willSet' or 'init' after attributes. return Tok.isContextualKeyword("didSet") || - Tok.isContextualKeyword("willSet"); + Tok.isContextualKeyword("willSet") || Tok.is(tok::kw_init); } /// Recover invalid uses of trailing closures in a situation @@ -2301,16 +2301,7 @@ ParserStatus Parser::parseFreestandingMacroExpansion( bool hasWhitespaceBeforeName = poundEndLoc != Tok.getLoc(); - // Diagnose and parse keyword right after `#`. - if (Tok.isKeyword() && !hasWhitespaceBeforeName) { - diagnose(Tok, diag::keyword_cant_be_identifier, Tok.getText()); - diagnose(Tok, diag::backticks_to_escape) - .fixItReplace(Tok.getLoc(), "`" + Tok.getText().str() + "`"); - - // Let 'parseDeclNameRef' to parse this as an identifier. - Tok.setKind(tok::identifier); - } - macroNameRef = parseDeclNameRef(macroNameLoc, diag, DeclNameOptions()); + macroNameRef = parseDeclNameRef(macroNameLoc, diag, DeclNameFlag::AllowKeywords); if (!macroNameRef) return makeParserError(); diff --git a/lib/SIL/IR/SILFunctionType.cpp b/lib/SIL/IR/SILFunctionType.cpp index cfe743ad3c3ec..78a0538a211fc 100644 --- a/lib/SIL/IR/SILFunctionType.cpp +++ b/lib/SIL/IR/SILFunctionType.cpp @@ -3212,6 +3212,12 @@ getIndirectCParameterConvention(const clang::ParmVarDecl *param) { /// /// Generally, whether the parameter is +1 is handled before this. static ParameterConvention getDirectCParameterConvention(clang::QualType type) { + if (auto *cxxRecord = type->getAsCXXRecordDecl()) { + // Directly passed non-trivially destroyed C++ record is consumed by the + // callee. + if (!cxxRecord->hasTrivialDestructor()) + return ParameterConvention::Direct_Owned; + } return ParameterConvention::Direct_Unowned; } diff --git a/lib/SIL/IR/TypeLowering.cpp b/lib/SIL/IR/TypeLowering.cpp index 8ea1c2000ef79..2697129bbfa57 100644 --- a/lib/SIL/IR/TypeLowering.cpp +++ b/lib/SIL/IR/TypeLowering.cpp @@ -2394,6 +2394,7 @@ namespace { if (D->isMoveOnly()) { properties.setNonTrivial(); + properties.setLexical(IsLexical); if (properties.isAddressOnly()) return handleMoveOnlyAddressOnly(structType, properties); return new (TC) MoveOnlyLoadableStructTypeLowering( @@ -2475,6 +2476,7 @@ namespace { if (D->isMoveOnly()) { properties.setNonTrivial(); + properties.setLexical(IsLexical); if (properties.isAddressOnly()) return handleMoveOnlyAddressOnly(enumType, properties); return new (TC) diff --git a/lib/SIL/Utils/FieldSensitivePrunedLiveness.cpp b/lib/SIL/Utils/FieldSensitivePrunedLiveness.cpp index 27cbaebc45098..e80dbac5946d0 100644 --- a/lib/SIL/Utils/FieldSensitivePrunedLiveness.cpp +++ b/lib/SIL/Utils/FieldSensitivePrunedLiveness.cpp @@ -563,6 +563,38 @@ void FieldSensitivePrunedLiveBlocks::print(llvm::raw_ostream &OS) const { void FieldSensitivePrunedLiveBlocks::dump() const { print(llvm::dbgs()); } +//===----------------------------------------------------------------------===// +// FieldSensitivePrunedLivenessBoundary +//===----------------------------------------------------------------------===// + +void FieldSensitivePrunedLivenessBoundary::print(llvm::raw_ostream &OS) const { + for (auto pair : lastUsers) { + auto *user = pair.first; + auto bits = pair.second; + OS << "last user: " << *user + << "\tat " << bits << "\n"; + } + for (auto pair : boundaryEdges) { + auto *block = pair.first; + auto bits = pair.second; + OS << "boundary edge: "; + block->printAsOperand(OS); + OS << "\n" << "\tat " << bits << "\n"; + } + if (!deadDefs.empty()) { + for (auto pair : deadDefs) { + auto *deadDef = pair.first; + auto bits = pair.second; + OS << "dead def: " << *deadDef + << "\tat " << bits << "\n"; + } + } +} + +void FieldSensitivePrunedLivenessBoundary::dump() const { + print(llvm::dbgs()); +} + //===----------------------------------------------------------------------===// // MARK: FieldSensitiveLiveness //===----------------------------------------------------------------------===// @@ -673,9 +705,7 @@ bool FieldSensitivePrunedLiveRange::isWithinBoundary( // If we are not live and have an interesting user that maps to our bit, // mark this bit as being live again. if (!isLive) { - auto interestingUser = isInterestingUser(&blockInst); - bool isInteresting = - interestingUser.first && interestingUser.second->contains(bit); + bool isInteresting = isInterestingUser(&blockInst, bit); PRUNED_LIVENESS_LOG(llvm::dbgs() << " Inst was dead... Is InterestingUser: " << (isInteresting ? "true" : "false") << '\n'); @@ -806,8 +836,7 @@ void findBoundaryInNonDefBlock(SILBasicBlock *block, unsigned bitNo, PRUNED_LIVENESS_LOG(llvm::dbgs() << "Looking for boundary in non-def block\n"); for (SILInstruction &inst : llvm::reverse(*block)) { PRUNED_LIVENESS_LOG(llvm::dbgs() << "Visiting: " << inst); - auto interestingUser = liveness.isInterestingUser(&inst); - if (interestingUser.first && interestingUser.second->contains(bitNo)) { + if (liveness.isInterestingUser(&inst, bitNo)) { PRUNED_LIVENESS_LOG(llvm::dbgs() << " Is interesting user for this bit!\n"); boundary.getLastUserBits(&inst).set(bitNo); return; @@ -837,8 +866,7 @@ void findBoundaryInSSADefBlock(SILNode *ssaDef, unsigned bitNo, boundary.getDeadDefsBits(cast(&inst)).set(bitNo); return; } - auto interestingUser = liveness.isInterestingUser(&inst); - if (interestingUser.first && interestingUser.second->contains(bitNo)) { + if (liveness.isInterestingUser(&inst, bitNo)) { PRUNED_LIVENESS_LOG(llvm::dbgs() << " Found interesting user: " << inst); boundary.getLastUserBits(&inst).set(bitNo); return; @@ -973,8 +1001,7 @@ void FieldSensitiveMultiDefPrunedLiveRange::findBoundariesInBlock( PRUNED_LIVENESS_LOG(llvm::dbgs() << " Checking if this inst is also a last user...\n"); if (!isLive) { - auto interestingUser = isInterestingUser(&inst); - if (interestingUser.first && interestingUser.second->contains(bitNo)) { + if (isInterestingUser(&inst, bitNo)) { PRUNED_LIVENESS_LOG( llvm::dbgs() << " Was interesting user! Moving from dead -> live!\n"); diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp index 4879d186e36a5..07add74e1b6ba 100644 --- a/lib/SILGen/SILGenConstructor.cpp +++ b/lib/SILGen/SILGenConstructor.cpp @@ -1474,6 +1474,13 @@ void SILGenFunction::emitMemberInitializers(DeclContext *dc, if (auto pbd = dyn_cast(member)) { if (pbd->isStatic()) continue; + // Skip properties with init accessors, they could only be used + // explicitly and in memberwise initializers. + if (auto *var = pbd->getSingleVar()) { + if (var->hasInitAccessor()) + continue; + } + for (auto i : range(pbd->getNumPatternEntries())) { auto init = pbd->getExecutableInit(i); if (!init) continue; diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp index 90d3014bd6109..1a019092f1dc4 100644 --- a/lib/SILGen/SILGenFunction.cpp +++ b/lib/SILGen/SILGenFunction.cpp @@ -55,10 +55,52 @@ SILGenFunction::SILGenFunction(SILGenModule &SGM, SILFunction &F, assert(DC && "creating SGF without a DeclContext?"); B.setInsertionPoint(createBasicBlock()); B.setCurrentDebugScope(F.getDebugScope()); + + // Populate VarDeclScopeMap. SourceLoc SLoc = F.getLocation().getSourceLoc(); if (SF && SLoc) { FnASTScope = ast_scope::ASTScopeImpl::findStartingScopeForLookup(SF, SLoc); ScopeMap.insert({{FnASTScope, nullptr}, F.getDebugScope()}); + + // Collect all variable declarations in this scope. + struct Consumer : public namelookup::AbstractASTScopeDeclConsumer { + const ast_scope::ASTScopeImpl *ASTScope; + VarDeclScopeMapTy &VarDeclScopeMap; + Consumer(const ast_scope::ASTScopeImpl *ASTScope, + VarDeclScopeMapTy &VarDeclScopeMap) + : ASTScope(ASTScope), VarDeclScopeMap(VarDeclScopeMap) {} + + bool consume(ArrayRef values, + NullablePtr baseDC) override { + LLVM_DEBUG(ASTScope->print(llvm::errs(), 0, false, false)); + for (auto &value : values) { + LLVM_DEBUG({ + if (value->hasName()) + llvm::dbgs() << "+ " << value->getBaseIdentifier() << "\n"; + }); + + // FIXME: ASTs coming out of the autodiff transformation trigger this. + // assert((VarDeclScopeMap.count(value) == 0 || + // VarDeclScopeMap[value] == ASTScope) && + // "VarDecl appears twice"); + VarDeclScopeMap.insert({value, ASTScope}); + } + return false; + } + bool lookInMembers(const DeclContext *) const override { return false; } +#ifndef NDEBUG + void startingNextLookupStep() override {} + void finishingLookup(std::string) const override {} + bool isTargetLookup() const override { return false; } +#endif + }; + const_cast(FnASTScope) + ->preOrderChildrenDo([&](ast_scope::ASTScopeImpl *ASTScope) { + if (!ASTScope->ignoreInDebugInfo()) { + Consumer consumer(ASTScope, VarDeclScopeMap); + ASTScope->lookupLocalsOrMembers(consumer); + } + }); } } @@ -202,8 +244,6 @@ const SILDebugScope *SILGenFunction::getScopeOrNull(SILLocation Loc, SourceLoc SLoc = Loc.getSourceLoc(); if (!SF || LastSourceLoc == SLoc) return nullptr; - // Prime VarDeclScopeMap. - auto Scope = getOrCreateScope(SLoc); if (ForMetaInstruction) if (ValueDecl *ValDecl = Loc.getAsASTNode()) { // The source location of a VarDecl isn't necessarily in the same scope @@ -212,7 +252,7 @@ const SILDebugScope *SILGenFunction::getScopeOrNull(SILLocation Loc, if (ValueScope != VarDeclScopeMap.end()) return getOrCreateScope(ValueScope->second, F.getDebugScope()); } - return Scope; + return getOrCreateScope(SLoc); } const SILDebugScope *SILGenFunction::getOrCreateScope(SourceLoc SLoc) { @@ -406,32 +446,6 @@ SILGenFunction::getOrCreateScope(const ast_scope::ASTScopeImpl *ASTScope, return ParentScope->InlinedCallSite != InlinedAt ? FnScope : ParentScope; } - // Collect all variable declarations in this scope. - struct Consumer : public namelookup::AbstractASTScopeDeclConsumer { - const ast_scope::ASTScopeImpl *ASTScope; - VarDeclScopeMapTy &VarDeclScopeMap; - Consumer(const ast_scope::ASTScopeImpl *ASTScope, - VarDeclScopeMapTy &VarDeclScopeMap) - : ASTScope(ASTScope), VarDeclScopeMap(VarDeclScopeMap) {} - - bool consume(ArrayRef values, - NullablePtr baseDC) override { - for (auto &value : values) { - assert(VarDeclScopeMap.count(value) == 0 && "VarDecl appears twice"); - VarDeclScopeMap.insert({value, ASTScope}); - } - return false; - } - bool lookInMembers(const DeclContext *) const override { return false; } -#ifndef NDEBUG - void startingNextLookupStep() override {} - void finishingLookup(std::string) const override {} - bool isTargetLookup() const override { return false; } -#endif - }; - Consumer consumer(ASTScope, VarDeclScopeMap); - ASTScope->lookupLocalsOrMembers(consumer); - // Collapse BraceStmtScopes whose parent is a .*BodyScope. if (auto Parent = ASTScope->getParent().getPtrOrNull()) if (Parent->getSourceRangeOfThisASTNode() == diff --git a/lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp b/lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp index 330931afa0507..1e52e99d8ae69 100644 --- a/lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp +++ b/lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp @@ -280,6 +280,12 @@ using namespace swift; using namespace swift::siloptimizer; +llvm::cl::opt DisableMoveOnlyAddressCheckerLifetimeExtension( + "move-only-address-checker-disable-lifetime-extension", + llvm::cl::init(false), + llvm::cl::desc("Disable the lifetime extension of non-consumed fields of " + "move-only values.")); + //===----------------------------------------------------------------------===// // MARK: Memory Utilities //===----------------------------------------------------------------------===// @@ -642,6 +648,15 @@ namespace { struct UseState { MarkMustCheckInst *address; + /// The number of fields in the exploded type. Set in initializeLiveness. + unsigned fieldCount = UINT_MAX; + + /// The blocks that consume fields of the value. + /// + /// A map from blocks to a bit vector recording which fields were destroyed + /// in each. + llvm::SmallMapVector consumingBlocks; + /// A map from destroy_addr to the part of the type that it destroys. llvm::SmallMapVector destroys; @@ -750,6 +765,7 @@ struct UseState { void clear() { address = nullptr; + consumingBlocks.clear(); destroys.clear(); livenessUses.clear(); borrows.clear(); @@ -806,6 +822,14 @@ struct UseState { } } + void recordConsumingBlock(SILBasicBlock *block, TypeTreeLeafTypeRange range) { + auto iter = consumingBlocks.find(block); + if (iter == consumingBlocks.end()) { + iter = consumingBlocks.insert({block, SmallBitVector(fieldCount)}).first; + } + range.setBits(iter->second); + } + void initializeLiveness(FieldSensitiveMultiDefPrunedLiveRange &prunedLiveness); @@ -907,6 +931,8 @@ struct UseState { void UseState::initializeLiveness( FieldSensitiveMultiDefPrunedLiveRange &liveness) { + fieldCount = liveness.getNumSubElements(); + // We begin by initializing all of our init uses. for (auto initInstAndValue : initInsts) { LLVM_DEBUG(llvm::dbgs() << "Found def: " << *initInstAndValue.first); @@ -1019,6 +1045,8 @@ void UseState::initializeLiveness( if (!isReinitToInitConvertibleInst(reinitInstAndValue.first)) { liveness.updateForUse(reinitInstAndValue.first, reinitInstAndValue.second, false /*lifetime ending*/); + recordConsumingBlock(reinitInstAndValue.first->getParent(), + reinitInstAndValue.second); LLVM_DEBUG(llvm::dbgs() << "Added liveness for reinit: " << *reinitInstAndValue.first; liveness.print(llvm::dbgs())); @@ -1030,6 +1058,8 @@ void UseState::initializeLiveness( for (auto takeInstAndValue : takeInsts) { liveness.updateForUse(takeInstAndValue.first, takeInstAndValue.second, true /*lifetime ending*/); + recordConsumingBlock(takeInstAndValue.first->getParent(), + takeInstAndValue.second); LLVM_DEBUG(llvm::dbgs() << "Added liveness for take: " << *takeInstAndValue.first; liveness.print(llvm::dbgs())); @@ -1037,11 +1067,18 @@ void UseState::initializeLiveness( for (auto copyInstAndValue : copyInsts) { liveness.updateForUse(copyInstAndValue.first, copyInstAndValue.second, true /*lifetime ending*/); + recordConsumingBlock(copyInstAndValue.first->getParent(), + copyInstAndValue.second); LLVM_DEBUG(llvm::dbgs() << "Added liveness for copy: " << *copyInstAndValue.first; liveness.print(llvm::dbgs())); } + for (auto destroyInstAndValue : destroys) { + recordConsumingBlock(destroyInstAndValue.first->getParent(), + destroyInstAndValue.second); + } + // Do the same for our borrow and liveness insts. for (auto livenessInstAndValue : borrows) { liveness.updateForUse(livenessInstAndValue.first, @@ -1150,9 +1187,8 @@ namespace { struct ConsumeInfo { /// Map blocks on the lifetime boundary to the last consuming instruction. - llvm::MapVector< - SILBasicBlock *, - SmallVector, 1>> + llvm::MapVector, 1>> finalBlockConsumes; bool isFrozen = false; @@ -1167,8 +1203,7 @@ struct ConsumeInfo { if (!inst) continue; os << "Inst: " << *inst; - os << "Range: "; - instRangePairVector.second.dump(); + os << "Range: " << instRangePairVector.second; os << '\n'; } } @@ -1191,13 +1226,15 @@ struct ConsumeInfo { return foundAny; } - void recordFinalConsume(SILInstruction *inst, TypeTreeLeafTypeRange span) { + void recordFinalConsume(SILInstruction *inst, SmallBitVector const &bits) { assert(!isFrozen); - auto iter = finalBlockConsumes.insert({inst->getParent(), {{inst, span}}}); - if (iter.second) - return; + auto *block = inst->getParent(); + auto iter = finalBlockConsumes.find(block); + if (iter == finalBlockConsumes.end()) { + iter = finalBlockConsumes.insert({block, {}}).first; + } LLVM_DEBUG(llvm::dbgs() << "Recorded Final Consume: " << *inst); - iter.first->second.emplace_back(inst, span); + iter->second.emplace_back(inst, bits); } void finishRecordingFinalConsumes() { @@ -1205,8 +1242,8 @@ struct ConsumeInfo { for (auto &pair : finalBlockConsumes) { llvm::stable_sort( pair.second, - [](const std::pair &lhs, - const std::pair &rhs) { + [](const std::pair &lhs, + const std::pair &rhs) { return lhs.first < rhs.first; }); } @@ -1222,7 +1259,7 @@ struct ConsumeInfo { // operands. // // Can only be used once frozen. - bool claimConsume(SILInstruction *inst, TypeTreeLeafTypeRange range) { + bool claimConsume(SILInstruction *inst, SmallBitVector const &bits) { assert(isFrozen); bool claimedConsume = false; @@ -1230,7 +1267,7 @@ struct ConsumeInfo { auto &iter = finalBlockConsumes[inst->getParent()]; for (unsigned i : indices(iter)) { auto &instRangePair = iter[i]; - if (instRangePair.first == inst && instRangePair.second == range) { + if (instRangePair.first == inst && instRangePair.second == bits) { instRangePair.first = nullptr; claimedConsume = true; LLVM_DEBUG(llvm::dbgs() << "Claimed consume: " << *inst); @@ -1321,6 +1358,44 @@ struct MoveOnlyAddressCheckerPImpl { void handleSingleBlockDestroy(SILInstruction *destroy, bool isReinit); }; +class ExtendUnconsumedLiveness { + UseState addressUseState; + FieldSensitiveMultiDefPrunedLiveRange &liveness; + FieldSensitivePrunedLivenessBoundary &boundary; + + enum class DestroyKind { + Destroy, + Take, + Reinit, + }; + using DestroysCollection = + llvm::SmallMapVector; + using ConsumingBlocksCollection = SmallPtrSetVector; + +public: + ExtendUnconsumedLiveness(UseState addressUseState, + FieldSensitiveMultiDefPrunedLiveRange &liveness, + FieldSensitivePrunedLivenessBoundary &boundary) + : addressUseState(addressUseState), liveness(liveness), + boundary(boundary) {} + + void run(); + + void runOnField(unsigned element, DestroysCollection &destroys, + ConsumingBlocksCollection &consumingBlocks); + +private: + bool hasDefAfter(SILInstruction *inst, unsigned element); + + bool + shouldAddDestroyToLiveness(SILInstruction *destroy, unsigned element, + BasicBlockSet const &consumedAtExitBlocks, + BasicBlockSetVector const &consumedAtEntryBlocks); + + void addPreviousInstructionToLiveness(SILInstruction *inst, unsigned element, + bool lifetimeEnding); +}; + } // namespace //===----------------------------------------------------------------------===// @@ -2183,9 +2258,9 @@ bool GlobalLivenessChecker::testInstVectorLiveness( // array and emit an error on those instead since it would be a better // error than using end_borrow here. { - auto pair = liveness.isInterestingUser(&*ii); - if (pair.first == FieldSensitivePrunedLiveness::NonLifetimeEndingUse && - pair.second->contains(errorSpan)) { + if (liveness.isInterestingUserOfKind( + &*ii, FieldSensitivePrunedLiveness::NonLifetimeEndingUse, + errorSpan)) { diagnosticEmitter.emitAddressDiagnostic( addressUseState.address, &*ii, errorUser, false /*is consuming*/, addressUseState.isInOutTermUser(&*ii)); @@ -2361,7 +2436,7 @@ static void insertDestroyBeforeInstruction(UseState &addressUseState, // claim that destroy instead of inserting another destroy_addr. if (auto *dai = dyn_cast(nextInstruction)) { if (dai->getOperand() == baseAddress) { - consumes.recordFinalConsume(dai, TypeTreeLeafTypeRange(0, bv.size())); + consumes.recordFinalConsume(dai, bv); return; } } @@ -2371,7 +2446,7 @@ static void insertDestroyBeforeInstruction(UseState &addressUseState, auto loc = RegularLocation::getAutoGeneratedLocation(nextInstruction->getLoc()); auto *dai = builder.createDestroyAddr(loc, baseAddress); - consumes.recordFinalConsume(dai, TypeTreeLeafTypeRange(0, bv.size())); + consumes.recordFinalConsume(dai, bv); addressUseState.destroys.insert({dai, TypeTreeLeafTypeRange(0, bv.size())}); return; } @@ -2389,7 +2464,9 @@ static void insertDestroyBeforeInstruction(UseState &addressUseState, if (pair.first->getType().isTrivial(*nextInstruction->getFunction())) continue; auto *dai = builder.createDestroyAddr(loc, pair.first); - consumes.recordFinalConsume(dai, pair.second); + SmallBitVector consumedBits(bv.size()); + pair.second.setBits(consumedBits); + consumes.recordFinalConsume(dai, consumedBits); addressUseState.destroys.insert({dai, pair.second}); } } @@ -2431,58 +2508,86 @@ void MoveOnlyAddressCheckerPImpl::insertDestroysOnBoundary( }); }; + // Control flow merge blocks used as insertion points. + llvm::DenseMap mergeBlocks; + for (auto &pair : boundary.getLastUsers()) { auto *inst = pair.first; auto &bv = pair.second; LLVM_DEBUG(llvm::dbgs() << " User: " << *inst); - auto interestingUse = liveness.isInterestingUser(inst); - switch (interestingUse.first) { - case IsInterestingUser::LifetimeEndingUse: { - LLVM_DEBUG(llvm::dbgs() - << " Lifetime ending use! Recording final consume!\n"); - // If we have a consuming use, when we stop at the consuming use we want - // the value to still be around. We only want the value to be invalidated - // once the consume operation has occured. Thus we always place the - // debug_value undef strictly after the consuming operation. - if (auto *ti = dyn_cast(inst)) { - for (auto *succBlock : ti->getSuccessorBlocks()) { - insertUndefDebugValue(&succBlock->front()); - } - } else { - insertUndefDebugValue(inst->getNextInstruction()); - } - consumes.recordFinalConsume(inst, *interestingUse.second); - continue; + auto interestingUser = liveness.getInterestingUser(inst); + SmallVector, 4> ranges; + if (interestingUser) { + interestingUser->getContiguousRanges(ranges); } - case IsInterestingUser::NonLifetimeEndingUse: - case IsInterestingUser::NonUser: - LLVM_DEBUG(llvm::dbgs() << " NoneUser or NonLifetimeEndingUse! " - "inserting destroy before instruction!\n"); - // If we are dealing with an inout parameter, we will have modeled our - // last use by treating a return inst as a last use. Since it doesn't have - // any successors, this results in us not inserting any destroy_addr. - if (isa(inst)) { - auto *block = inst->getParent(); - for (auto *succBlock : block->getSuccessorBlocks()) { - auto *insertPt = &*succBlock->begin(); - insertDestroyBeforeInstruction(addressUseState, insertPt, - liveness.getRootValue(), bv, consumes); - // We insert the debug_value undef /after/ the last use since we want - // the value to be around when we stop at the last use instruction. - insertUndefDebugValue(insertPt); + + for (auto rangePair : ranges) { + SmallBitVector bits(bv.size()); + rangePair.first.setBits(bits); + switch (rangePair.second) { + case IsInterestingUser::LifetimeEndingUse: { + LLVM_DEBUG( + llvm::dbgs() + << " Lifetime ending use! Recording final consume!\n"); + // If we have a consuming use, when we stop at the consuming use we want + // the value to still be around. We only want the value to be + // invalidated once the consume operation has occured. Thus we always + // place the debug_value undef strictly after the consuming operation. + if (auto *ti = dyn_cast(inst)) { + for (auto *succBlock : ti->getSuccessorBlocks()) { + insertUndefDebugValue(&succBlock->front()); + } + } else { + insertUndefDebugValue(inst->getNextInstruction()); } + consumes.recordFinalConsume(inst, bits); continue; } + case IsInterestingUser::NonUser: + break; + case IsInterestingUser::NonLifetimeEndingUse: + LLVM_DEBUG(llvm::dbgs() << " NonLifetimeEndingUse! " + "inserting destroy before instruction!\n"); + // If we are dealing with an inout parameter, we will have modeled our + // last use by treating a return inst as a last use. Since it doesn't + // have any successors, this results in us not inserting any + // destroy_addr. + if (isa(inst)) { + auto *block = inst->getParent(); + for (auto *succBlock : block->getSuccessorBlocks()) { + auto iter = mergeBlocks.find(succBlock); + if (iter == mergeBlocks.end()) + iter = mergeBlocks.insert({succBlock, bits}).first; + else { + SmallBitVector &alreadySetBits = iter->second; + bool hadCommon = alreadySetBits.anyCommon(bits); + alreadySetBits &= bits; + if (hadCommon) + continue; + } - auto *insertPt = inst->getNextInstruction(); - insertDestroyBeforeInstruction(addressUseState, insertPt, - liveness.getRootValue(), bv, consumes); - // We insert the debug_value undef /after/ the last use since we want - // the value to be around when we stop at the last use instruction. - insertUndefDebugValue(insertPt); - continue; + auto *insertPt = &*succBlock->begin(); + insertDestroyBeforeInstruction(addressUseState, insertPt, + liveness.getRootValue(), bits, + consumes); + // We insert the debug_value undef /after/ the last use since we + // want the value to be around when we stop at the last use + // instruction. + insertUndefDebugValue(insertPt); + } + continue; + } + + auto *insertPt = inst->getNextInstruction(); + insertDestroyBeforeInstruction(addressUseState, insertPt, + liveness.getRootValue(), bits, consumes); + // We insert the debug_value undef /after/ the last use since we want + // the value to be around when we stop at the last use instruction. + insertUndefDebugValue(insertPt); + continue; + } } } @@ -2545,8 +2650,9 @@ void MoveOnlyAddressCheckerPImpl::rewriteUses( // Process destroys for (auto destroyPair : addressUseState.destroys) { /// Is this destroy instruction a final consuming use? - bool isFinalConsume = - consumes.claimConsume(destroyPair.first, destroyPair.second); + SmallBitVector bits(liveness.getNumSubElements()); + destroyPair.second.setBits(bits); + bool isFinalConsume = consumes.claimConsume(destroyPair.first, bits); // Remove destroys that are not the final consuming use. if (!isFinalConsume) { @@ -2583,22 +2689,31 @@ void MoveOnlyAddressCheckerPImpl::rewriteUses( for (auto reinitPair : addressUseState.reinitInsts) { if (!isReinitToInitConvertibleInst(reinitPair.first)) continue; - if (!consumes.claimConsume(reinitPair.first, reinitPair.second)) + SmallBitVector bits(liveness.getNumSubElements()); + reinitPair.second.setBits(bits); + if (!consumes.claimConsume(reinitPair.first, bits)) convertMemoryReinitToInitForm(reinitPair.first, debugVar); } // Check all takes. for (auto takeInst : addressUseState.takeInsts) { - bool claimedConsume = - consumes.claimConsume(takeInst.first, takeInst.second); + SmallBitVector bits(liveness.getNumSubElements()); + takeInst.second.setBits(bits); + bool claimedConsume = consumes.claimConsume(takeInst.first, bits); (void)claimedConsume; - assert(claimedConsume && "Should claim all copies?!"); + if (!claimedConsume) { + llvm::errs() + << "Found consume that was not recorded as a 'claimed consume'!\n"; + llvm::errs() << "Unrecorded consume: " << *takeInst.first; + llvm_unreachable("Standard compiler abort?!"); + } } // Then rewrite all copy insts to be takes and claim them. for (auto copyInst : addressUseState.copyInsts) { - bool claimedConsume = - consumes.claimConsume(copyInst.first, copyInst.second); + SmallBitVector bits(liveness.getNumSubElements()); + copyInst.second.setBits(bits); + bool claimedConsume = consumes.claimConsume(copyInst.first, bits); if (!claimedConsume) { llvm::errs() << "Found consume that was not recorded as a 'claimed consume'!\n"; @@ -2744,6 +2859,240 @@ void MoveOnlyAddressCheckerPImpl::checkForReinitAfterDiscard() { } } +void ExtendUnconsumedLiveness::run() { + ConsumingBlocksCollection consumingBlocks; + DestroysCollection destroys; + for (unsigned element = 0, count = liveness.getNumSubElements(); + element < count; ++element) { + + for (auto pair : addressUseState.consumingBlocks) { + if (pair.second.test(element)) { + consumingBlocks.insert(pair.first); + } + } + + for (auto pair : addressUseState.destroys) { + if (pair.second.contains(element)) { + destroys[pair.first] = DestroyKind::Destroy; + } + } + for (auto pair : addressUseState.takeInsts) { + if (pair.second.contains(element)) { + destroys[pair.first] = DestroyKind::Take; + } + } + for (auto pair : addressUseState.reinitInsts) { + if (pair.second.contains(element)) { + destroys[pair.first] = DestroyKind::Reinit; + } + } + + runOnField(element, destroys, consumingBlocks); + + consumingBlocks.clear(); + destroys.clear(); + } +} + +/// Extend liveness of each field as far as possible within the original live +/// range as far as possible without incurring any copies. +/// +/// The strategy has two parts. +/// +/// (1) The global analysis: +/// - Collect the blocks in which the field was live before canonicalization. +/// These are the "original" live blocks (originalLiveBlocks). +/// [Color these blocks green.] +/// - From within that collection, collect the blocks which contain a _final_ +/// consuming, non-destroy use, and their iterative successors. +/// These are the "consumed" blocks (consumedAtExitBlocks). +/// [Color these blocks red.] +/// - Extend liveness down to the boundary between originalLiveBlocks and +/// consumedAtExitBlocks blocks. +/// [Extend liveness down to the boundary between green blocks and red.] +/// - In particular, in regions of originalLiveBlocks which have no boundary +/// with consumedAtExitBlocks, liveness should be extended to its original +/// extent. +/// [Extend liveness down to the boundary between green blocks and uncolored.] +/// +/// (2) The local analysis: +/// - For in-block lifetimes, extend liveness forward from non-consuming uses +/// and dead defs to the original destroy. +void ExtendUnconsumedLiveness::runOnField( + unsigned element, DestroysCollection &destroys, + ConsumingBlocksCollection &consumingBlocks) { + SILValue currentDef = addressUseState.address; + + // First, collect the blocks that were _originally_ live. We can't use + // liveness here because it doesn't include blocks that occur before a + // destroy_addr. + BasicBlockSet originalLiveBlocks(currentDef->getFunction()); + { + // Some of the work here was already done by initializeLiveness. + // Specifically, it already discovered all blocks containing (transitive) + // uses and blocks that appear between them and the def. + // + // Seed the set with what it already discovered. + for (auto *discoveredBlock : liveness.getDiscoveredBlocks()) + originalLiveBlocks.insert(discoveredBlock); + + // Start the walk from the consuming blocks (which includes destroys as well + // as the other consuming uses). + BasicBlockWorklist worklist(currentDef->getFunction()); + for (auto *consumingBlock : consumingBlocks) { + worklist.push(consumingBlock); + } + + // Walk backwards from consuming blocks. + while (auto *block = worklist.pop()) { + if (!originalLiveBlocks.insert(block)) { + continue; + } + for (auto *predecessor : block->getPredecessorBlocks()) { + // If the block was discovered by liveness, we already added it to the + // set. + if (originalLiveBlocks.contains(predecessor)) + continue; + worklist.pushIfNotVisited(predecessor); + } + } + } + + // Second, collect the blocks which occur after a consuming use. + BasicBlockSet consumedAtExitBlocks(currentDef->getFunction()); + BasicBlockSetVector consumedAtEntryBlocks(currentDef->getFunction()); + { + // Start the forward walk from blocks which contain non-destroy consumes not + // followed by defs. + // + // Because they contain a consume not followed by a def, these are + // consumed-at-exit. + BasicBlockWorklist worklist(currentDef->getFunction()); + for (auto iterator : boundary.getLastUsers()) { + if (!iterator.second.test(element)) + continue; + auto *instruction = iterator.first; + // Skip over destroys on the boundary. + auto iter = destroys.find(instruction); + if (iter != destroys.end() && iter->second != DestroyKind::Take) { + continue; + } + // Skip over non-consuming users. + auto interestingUser = liveness.isInterestingUser(instruction, element); + assert(interestingUser != + FieldSensitivePrunedLiveness::IsInterestingUser::NonUser); + if (interestingUser != + FieldSensitivePrunedLiveness::IsInterestingUser::LifetimeEndingUse) { + continue; + } + // A consume with a subsequent def doesn't cause the block to be + // consumed-at-exit. + if (hasDefAfter(instruction, element)) + continue; + worklist.push(instruction->getParent()); + } + while (auto *block = worklist.pop()) { + consumedAtExitBlocks.insert(block); + for (auto *successor : block->getSuccessorBlocks()) { + if (!originalLiveBlocks.contains(successor)) + continue; + worklist.pushIfNotVisited(successor); + consumedAtEntryBlocks.insert(successor); + } + } + } + + // Third, find the blocks on the boundary between the originally-live blocks + // and the originally-live-but-consumed blocks. Extend liveness "to the end" + // of these blocks. + for (auto *block : consumedAtEntryBlocks) { + for (auto *predecessor : block->getPredecessorBlocks()) { + if (consumedAtExitBlocks.contains(predecessor)) + continue; + // Add "the instruction(s) before the terminator" of the predecessor to + // liveness. + addPreviousInstructionToLiveness(predecessor->getTerminator(), element, + /*lifetimeEnding*/ false); + } + } + + // Finally, preserve the destroys which weren't in the consumed region in + // place: hoisting such destroys would not avoid copies. + for (auto pair : destroys) { + auto *destroy = pair.first; + if (!shouldAddDestroyToLiveness(destroy, element, consumedAtExitBlocks, + consumedAtEntryBlocks)) + continue; + addPreviousInstructionToLiveness(destroy, element, + /*lifetimeEnding*/ false); + } +} + +bool ExtendUnconsumedLiveness::shouldAddDestroyToLiveness( + SILInstruction *destroy, unsigned element, + BasicBlockSet const &consumedAtExitBlocks, + BasicBlockSetVector const &consumedAtEntryBlocks) { + auto *block = destroy->getParent(); + bool followedByDef = hasDefAfter(destroy, element); + if (!followedByDef) { + // This destroy is the last write to the field in the block. + // + // If the block is consumed-at-exit, then there is some other consuming use + // before this destroy. Liveness can't be extended. + return !consumedAtExitBlocks.contains(block); + } + for (auto *inst = destroy->getPreviousInstruction(); inst; + inst = inst->getPreviousInstruction()) { + if (liveness.isDef(inst, element)) { + // Found the corresponding def with no intervening users. Liveness + // can be extended to the destroy. + return true; + } + auto interestingUser = liveness.isInterestingUser(inst, element); + switch (interestingUser) { + case FieldSensitivePrunedLiveness::IsInterestingUser::NonUser: + break; + case FieldSensitivePrunedLiveness::IsInterestingUser::NonLifetimeEndingUse: + // The first use seen is non-consuming. Liveness can be extended to the + // destroy. + return true; + break; + case FieldSensitivePrunedLiveness::IsInterestingUser::LifetimeEndingUse: + // Found a consuming use. Liveness can't be extended to the destroy + // (without creating a copy and triggering a diagnostic). + return false; + break; + } + } + // Found no uses or defs between the destroy and the top of the block. If the + // block was not consumed at entry, liveness can be extended to the destroy. + return !consumedAtEntryBlocks.contains(block); +} + +bool ExtendUnconsumedLiveness::hasDefAfter(SILInstruction *start, + unsigned element) { + // NOTE: Start iteration at \p start, not its sequel, because + // it might be both a consuming use and a def. + for (auto *inst = start; inst; inst = inst->getNextInstruction()) { + if (liveness.isDef(inst, element)) + return true; + } + return false; +} + +void ExtendUnconsumedLiveness::addPreviousInstructionToLiveness( + SILInstruction *inst, unsigned element, bool lifetimeEnding) { + auto range = TypeTreeLeafTypeRange(element, element + 1); + if (auto *previous = inst->getPreviousInstruction()) { + liveness.updateForUse(previous, range, lifetimeEnding); + } else { + for (auto *predecessor : inst->getParent()->getPredecessorBlocks()) { + liveness.updateForUse(predecessor->getTerminator(), range, + lifetimeEnding); + } + } +} + bool MoveOnlyAddressCheckerPImpl::performSingleCheck( MarkMustCheckInst *markedAddress) { SWIFT_DEFER { diagnosticEmitter.clearUsesWithDiagnostic(); }; @@ -2838,6 +3187,12 @@ bool MoveOnlyAddressCheckerPImpl::performSingleCheck( FieldSensitivePrunedLivenessBoundary boundary(liveness.getNumSubElements()); liveness.computeBoundary(boundary); + if (!DisableMoveOnlyAddressCheckerLifetimeExtension) { + ExtendUnconsumedLiveness extension(addressUseState, liveness, boundary); + extension.run(); + } + boundary.clear(); + liveness.computeBoundary(boundary); insertDestroysOnBoundary(markedAddress, liveness, boundary); checkForReinitAfterDiscard(); rewriteUses(markedAddress, liveness, boundary); diff --git a/lib/SILOptimizer/Mandatory/MoveOnlyBorrowToDestructureUtils.cpp b/lib/SILOptimizer/Mandatory/MoveOnlyBorrowToDestructureUtils.cpp index 9f01ba50013d9..b328701d6fcbb 100644 --- a/lib/SILOptimizer/Mandatory/MoveOnlyBorrowToDestructureUtils.cpp +++ b/lib/SILOptimizer/Mandatory/MoveOnlyBorrowToDestructureUtils.cpp @@ -317,9 +317,10 @@ bool Implementation::gatherUses(SILValue value) { } LLVM_DEBUG(llvm::dbgs() << " Found non lifetime ending use!\n"); - blocksToUses.insert( - nextUse->getParentBlock(), - {nextUse, {*leafRange, false /*is lifetime ending*/}}); + blocksToUses.insert(nextUse->getParentBlock(), + {nextUse, + {liveness.getNumSubElements(), *leafRange, + false /*is lifetime ending*/}}); liveness.updateForUse(nextUse->getUser(), *leafRange, false /*is lifetime ending*/); instToInterestingOperandIndexMap.insert(nextUse->getUser(), nextUse); @@ -344,7 +345,9 @@ bool Implementation::gatherUses(SILValue value) { LLVM_DEBUG(llvm::dbgs() << " Found lifetime ending use!\n"); destructureNeedingUses.push_back(nextUse); blocksToUses.insert(nextUse->getParentBlock(), - {nextUse, {*leafRange, true /*is lifetime ending*/}}); + {nextUse, + {liveness.getNumSubElements(), *leafRange, + true /*is lifetime ending*/}}); liveness.updateForUse(nextUse->getUser(), *leafRange, true /*is lifetime ending*/); instToInterestingOperandIndexMap.insert(nextUse->getUser(), nextUse); @@ -381,9 +384,10 @@ bool Implementation::gatherUses(SILValue value) { // Otherwise, treat it as a normal use. LLVM_DEBUG(llvm::dbgs() << " Treating non-begin_borrow borrow as " "a non lifetime ending use!\n"); - blocksToUses.insert( - nextUse->getParentBlock(), - {nextUse, {*leafRange, false /*is lifetime ending*/}}); + blocksToUses.insert(nextUse->getParentBlock(), + {nextUse, + {liveness.getNumSubElements(), *leafRange, + false /*is lifetime ending*/}}); liveness.updateForUse(nextUse->getUser(), *leafRange, false /*is lifetime ending*/); instToInterestingOperandIndexMap.insert(nextUse->getUser(), nextUse); @@ -989,13 +993,13 @@ void Implementation::rewriteUses(InstructionDeleter *deleter) { if (auto operandList = blocksToUses.find(block)) { // If we do, gather up the bits that we need. for (auto operand : *operandList) { - auto &subEltSpan = operand.second.subEltSpan; + auto &liveBits = operand.second.liveBits; LLVM_DEBUG(llvm::dbgs() << " Found need operand " << operand.first->getOperandNumber() - << " of inst: " << *operand.first->getUser() - << " Needs bits: " << subEltSpan << '\n'); - bitsNeededInBlock.set(subEltSpan.startEltOffset, - subEltSpan.endEltOffset); + << " of inst: " << *operand.first->getUser()); + for (auto bit : liveBits.set_bits()) { + bitsNeededInBlock.set(bit); + } seenOperands.insert(operand.first); } } diff --git a/lib/SILOptimizer/Mandatory/MoveOnlyDiagnostics.cpp b/lib/SILOptimizer/Mandatory/MoveOnlyDiagnostics.cpp index 4375ee9631556..db5625c07130a 100644 --- a/lib/SILOptimizer/Mandatory/MoveOnlyDiagnostics.cpp +++ b/lib/SILOptimizer/Mandatory/MoveOnlyDiagnostics.cpp @@ -14,6 +14,7 @@ #include "MoveOnlyDiagnostics.h" +#include "swift/AST/Decl.h" #include "swift/AST/DiagnosticsSIL.h" #include "swift/AST/Stmt.h" #include "swift/Basic/Defer.h" @@ -226,6 +227,12 @@ void DiagnosticEmitter::emitMissingConsumeInDiscardingContext( return true; case SILLocation::RegularKind: { + Decl *decl = loc.getAsASTNode(); + if (decl && isa(decl)) { + // Having the function itself as a location results in a location at the + // first line of the function. Find another location. + return false; + } Stmt *stmt = loc.getAsASTNode(); if (!stmt) return true; // For non-statements, assume it is exiting the func. diff --git a/lib/SILOptimizer/PassManager/PassPipeline.cpp b/lib/SILOptimizer/PassManager/PassPipeline.cpp index b46ab9c304325..a1a04e038ec06 100644 --- a/lib/SILOptimizer/PassManager/PassPipeline.cpp +++ b/lib/SILOptimizer/PassManager/PassPipeline.cpp @@ -760,6 +760,9 @@ static void addLowLevelPassPipeline(SILPassPipelinePlan &P) { P.addObjectOutliner(); P.addDeadStoreElimination(); + // dead-store-elimination can expose opportunities for dead object elimination. + P.addDeadObjectElimination(); + // We've done a lot of optimizations on this function, attempt to FSO. P.addFunctionSignatureOpts(); P.addComputeEscapeEffects(); diff --git a/lib/SILOptimizer/Transforms/DestroyAddrHoisting.cpp b/lib/SILOptimizer/Transforms/DestroyAddrHoisting.cpp index 4feb70403f429..94598b56c84aa 100644 --- a/lib/SILOptimizer/Transforms/DestroyAddrHoisting.cpp +++ b/lib/SILOptimizer/Transforms/DestroyAddrHoisting.cpp @@ -870,6 +870,11 @@ bool hoistDestroys(SILValue root, bool ignoreDeinitBarriers, BasicCalleeAnalysis *calleeAnalysis) { LLVM_DEBUG(llvm::dbgs() << "Performing destroy hoisting on " << root); + // Don't canonicalize the lifetimes of addresses of move-only type. + // According to language rules, they are fixed. + if (root->getType().isMoveOnly()) + return false; + SILFunction *function = root->getFunction(); if (!function) return false; diff --git a/lib/SILOptimizer/UtilityPasses/UnitTestRunner.cpp b/lib/SILOptimizer/UtilityPasses/UnitTestRunner.cpp index d3a2808d11379..ebf9a35bdd8e6 100644 --- a/lib/SILOptimizer/UtilityPasses/UnitTestRunner.cpp +++ b/lib/SILOptimizer/UtilityPasses/UnitTestRunner.cpp @@ -89,6 +89,7 @@ #include "swift/SILOptimizer/Utils/InstructionDeleter.h" #include "swift/SILOptimizer/Utils/ParseTestSpecification.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -287,6 +288,19 @@ struct OwnershipUtilsHasPointerEscape : UnitTest { } }; +// Arguments: +// - value: whose type will be printed +// Dumps: +// - the type lowering of the type +struct PrintTypeLowering : UnitTest { + PrintTypeLowering(UnitTestRunner *pass) : UnitTest(pass) {} + void invoke(Arguments &arguments) override { + auto value = arguments.takeValue(); + auto ty = value->getType(); + getFunction()->getTypeLowering(ty).print(llvm::dbgs()); + } +}; + //===----------------------------------------------------------------------===// // MARK: OSSA Lifetime Unit Tests //===----------------------------------------------------------------------===// @@ -899,6 +913,7 @@ void UnitTestRunner::withTest(StringRef name, Doit doit) { ADD_UNIT_TEST_SUBCLASS("find-enclosing-defs", FindEnclosingDefsTest) ADD_UNIT_TEST_SUBCLASS("function-get-self-argument-index", FunctionGetSelfArgumentIndex) ADD_UNIT_TEST_SUBCLASS("has-pointer-escape", OwnershipUtilsHasPointerEscape) + ADD_UNIT_TEST_SUBCLASS("print-type-lowering", PrintTypeLowering) ADD_UNIT_TEST_SUBCLASS("interior-liveness", InteriorLivenessTest) ADD_UNIT_TEST_SUBCLASS("is-deinit-barrier", IsDeinitBarrierTest) ADD_UNIT_TEST_SUBCLASS("is-lexical", IsLexicalTest) diff --git a/lib/SILOptimizer/Utils/CanonicalizeOSSALifetime.cpp b/lib/SILOptimizer/Utils/CanonicalizeOSSALifetime.cpp index f9fda092cbea2..524e2ad5bf82b 100644 --- a/lib/SILOptimizer/Utils/CanonicalizeOSSALifetime.cpp +++ b/lib/SILOptimizer/Utils/CanonicalizeOSSALifetime.cpp @@ -558,7 +558,8 @@ void CanonicalizeOSSALifetime::extendUnconsumedLiveness( // Walk backwards from consuming blocks. while (auto *block = worklist.pop()) { - originalLiveBlocks.insert(block); + if (!originalLiveBlocks.insert(block)) + continue; for (auto *predecessor : block->getPredecessorBlocks()) { // If the block was discovered by liveness, we already added it to the // set. @@ -1156,6 +1157,12 @@ void CanonicalizeOSSALifetime::rewriteLifetimes() { bool CanonicalizeOSSALifetime::canonicalizeValueLifetime(SILValue def) { LivenessState livenessState(*this, def); + // Don't canonicalize the lifetimes of values of move-only type. According to + // language rules, they are fixed. + if (def->getType().isMoveOnly()) { + return false; + } + // Step 1: Compute liveness. if (!computeLiveness()) { LLVM_DEBUG(llvm::dbgs() << "Failed to compute liveness boundary!\n"); diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 6b246afdc5071..0958196cdfcad 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -4604,24 +4604,11 @@ namespace { Expr *visitDiscardAssignmentExpr(DiscardAssignmentExpr *expr) { return simplifyExprType(expr); } - + Expr *visitUnresolvedPatternExpr(UnresolvedPatternExpr *expr) { - // If we end up here, we should have diagnosed somewhere else - // already. - Expr *simplified = simplifyExprType(expr); - // Invalidate 'VarDecl's inside the pattern. - expr->getSubPattern()->forEachVariable([](VarDecl *VD) { - VD->setInvalid(); - }); - if (!SuppressDiagnostics - && !cs.getType(simplified)->is()) { - auto &de = cs.getASTContext().Diags; - de.diagnose(simplified->getLoc(), diag::pattern_in_expr, - expr->getSubPattern()->getDescriptiveKind()); - } - return simplified; + llvm_unreachable("Should have diagnosed"); } - + Expr *visitBindOptionalExpr(BindOptionalExpr *expr) { return simplifyExprType(expr); } diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 71b7ca6015c51..5d4d012ee2a2d 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -8295,6 +8295,32 @@ bool InvalidEmptyKeyPathFailure::diagnoseAsError() { return true; } +bool InvalidPatternInExprFailure::diagnoseAsError() { + // Check to see if we have something like 'case (let foo)', where + // has a fix associated with it. In such a case, it's more likely than not + // that the user is trying to write an EnumElementPattern, but has made some + // kind of mistake in the function expr that causes it to be treated as an + // ExprPattern. Emitting an additional error for the out of place 'let foo' is + // just noise in that case, so let's avoid diagnosing. + llvm::SmallPtrSet fixAnchors; + for (auto *fix : getSolution().Fixes) { + if (auto *anchor = getAsExpr(fix->getAnchor())) + fixAnchors.insert(anchor); + } + { + auto *E = castToExpr(getLocator()->getAnchor()); + while (auto *parent = findParentExpr(E)) { + if (auto *CE = dyn_cast(parent)) { + if (fixAnchors.contains(CE->getFn())) + return false; + } + E = parent; + } + } + emitDiagnostic(diag::pattern_in_expr, P->getDescriptiveKind()); + return true; +} + bool MissingContextualTypeForNil::diagnoseAsError() { auto *expr = castToExpr(getAnchor()); diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index 858279d586786..e3b2269cbfa3b 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -2531,6 +2531,22 @@ class InvalidEmptyKeyPathFailure final : public FailureDiagnostic { bool diagnoseAsError() override; }; +/// Diagnose an invalid Pattern node in an ExprPattern. +/// +/// \code +/// if case foo(let x) = y {} +/// \endcode +class InvalidPatternInExprFailure final : public FailureDiagnostic { + Pattern *P; + +public: + InvalidPatternInExprFailure(const Solution &solution, Pattern *pattern, + ConstraintLocator *locator) + : FailureDiagnostic(solution, locator), P(pattern) {} + + bool diagnoseAsError() override; +}; + /// Diagnose situations where there is no context to determine a /// type of `nil` literal e.g. /// diff --git a/lib/Sema/CSFix.cpp b/lib/Sema/CSFix.cpp index f4611c0b92758..f034fc341856d 100644 --- a/lib/Sema/CSFix.cpp +++ b/lib/Sema/CSFix.cpp @@ -2080,6 +2080,19 @@ IgnoreInvalidASTNode *IgnoreInvalidASTNode::create(ConstraintSystem &cs, return new (cs.getAllocator()) IgnoreInvalidASTNode(cs, locator); } +bool IgnoreInvalidPatternInExpr::diagnose(const Solution &solution, + bool asNote) const { + InvalidPatternInExprFailure failure(solution, P, getLocator()); + return failure.diagnose(asNote); +} + +IgnoreInvalidPatternInExpr * +IgnoreInvalidPatternInExpr::create(ConstraintSystem &cs, Pattern *pattern, + ConstraintLocator *locator) { + return new (cs.getAllocator()) + IgnoreInvalidPatternInExpr(cs, pattern, locator); +} + bool SpecifyContextualTypeForNil::diagnose(const Solution &solution, bool asNote) const { MissingContextualTypeForNil failure(solution, getLocator()); diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index e6d7e415a2807..e950a7bdf899c 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -3432,16 +3432,18 @@ namespace { } Type visitUnresolvedPatternExpr(UnresolvedPatternExpr *expr) { - // If there are UnresolvedPatterns floating around after pattern type - // checking, they are definitely invalid. However, we will - // diagnose that condition elsewhere; to avoid unnecessary noise errors, - // just plop an open type variable here. - - auto locator = CS.getConstraintLocator(expr); - auto typeVar = CS.createTypeVariable(locator, - TVO_CanBindToLValue | - TVO_CanBindToNoEscape); - return typeVar; + // Encountering an UnresolvedPatternExpr here means we have an invalid + // ExprPattern with a Pattern node like 'let x' nested in it. Record a + // fix, and assign ErrorTypes to any VarDecls bound. + auto *locator = CS.getConstraintLocator(expr); + auto *P = expr->getSubPattern(); + CS.recordFix(IgnoreInvalidPatternInExpr::create(CS, P, locator)); + + P->forEachVariable([&](VarDecl *VD) { + CS.setType(VD, ErrorType::get(CS.getASTContext())); + }); + + return CS.createTypeVariable(locator, TVO_CanBindToHole); } /// Get the type T? diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 49b82b210e1b1..58e2aa5d49b6c 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -14950,6 +14950,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint( case FixKind::AddExplicitExistentialCoercion: case FixKind::DestructureTupleToMatchPackExpansionParameter: case FixKind::AllowValueExpansionWithoutPackReferences: + case FixKind::IgnoreInvalidPatternInExpr: case FixKind::IgnoreMissingEachKeyword: llvm_unreachable("handled elsewhere"); } diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index c7cc86d589497..53f73bbe6354f 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -144,12 +144,6 @@ static void maybeAddMemberwiseDefaultArg(ParamDecl *arg, VarDecl *var, if (!var->getParentPattern()->getSingleVar()) return; - // FIXME: Don't attempt to synthesize default arguments for init - // accessor properties because there could be multiple properties - // with default values they are going to initialize. - if (var->getAccessor(AccessorKind::Init)) - return; - // Whether we have explicit initialization. bool isExplicitlyInitialized = false; if (auto pbd = var->getParentPatternBinding()) { diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 35e2e0736721f..0108b70e08f5e 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -5313,12 +5313,18 @@ bool ConstraintSystem::diagnoseAmbiguityWithFixes( /// provided set. static unsigned countDistinctOverloads(ArrayRef choices) { llvm::SmallPtrSet uniqueChoices; - unsigned result = 0; for (auto choice : choices) { - if (uniqueChoices.insert(choice.getOpaqueChoiceSimple()).second) - ++result; + uniqueChoices.insert(choice.getOpaqueChoiceSimple()); } - return result; + return uniqueChoices.size(); +} + +static Type getOverloadChoiceType(ConstraintLocator *overloadLoc, + const Solution &solution) { + auto selectedOverload = solution.overloadChoices.find(overloadLoc); + if (selectedOverload == solution.overloadChoices.end()) + return Type(); + return solution.simplifyType(selectedOverload->second.adjustedOpenedType); } /// Determine the name of the overload in a set of overload choices. @@ -5400,6 +5406,25 @@ bool ConstraintSystem::diagnoseAmbiguity(ArrayRef solutions) { auto &overload = diff.overloads[i]; auto *locator = overload.locator; + // If there is only one overload difference, it's the best. + if (n == 1) { + bestOverload = i; + break; + } + + // If there are multiple overload sets involved, let's pick the + // one that has choices with different types, because that is + // most likely the source of ambiguity. + { + auto overloadTy = getOverloadChoiceType(locator, solutions.front()); + if (std::all_of(solutions.begin() + 1, solutions.end(), + [&](const Solution &solution) { + return overloadTy->isEqual( + getOverloadChoiceType(locator, solution)); + })) + continue; + } + ASTNode anchor; // Simplification of member locator would produce a base expression, diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index 7b3283e5b959c..84b642e2d470f 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -2289,7 +2289,7 @@ class DeclChecker : public DeclVisitor { if (PBD->isInitialized(i)) { // Add the attribute that preserves the "has an initializer" value // across module generation, as required for TBDGen. - if (var->hasStorage() && + if (var->supportsInitialization() && !var->getAttrs().hasAttribute()) { var->getAttrs().add(new (Ctx) HasInitialValueAttr(/*IsImplicit=*/true)); diff --git a/lib/Sema/TypeCheckMacros.cpp b/lib/Sema/TypeCheckMacros.cpp index f939aeec229ef..7621a64563e49 100644 --- a/lib/Sema/TypeCheckMacros.cpp +++ b/lib/Sema/TypeCheckMacros.cpp @@ -1302,9 +1302,11 @@ Optional swift::expandAccessors( !accessorMacroOnlyIntroducesObservers(macro, roleAttr); if (foundNonObservingAccessor) { // If any non-observing accessor was added, mark the initializer as - // subsumed. + // subsumed unless it has init accessor, because the initializer in + // such cases could be used for memberwise initialization. if (auto var = dyn_cast(storage)) { - if (auto binding = var->getParentPatternBinding()) { + if (auto binding = var->getParentPatternBinding(); + !var->getAccessor(AccessorKind::Init)) { unsigned index = binding->getPatternEntryIndexForVarDecl(var); binding->setInitializerSubsumed(index); } diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index 979654b18cc1b..4e00cd1925eb5 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -301,8 +301,12 @@ StoredPropertiesAndMissingMembersRequest::evaluate(Evaluator &evaluator, return decl->getASTContext().AllocateCopy(results); } -/// Determine whether the given variable has an init accessor. -static bool hasInitAccessor(VarDecl *var) { +bool HasInitAccessorRequest::evaluate(Evaluator &evaluator, + AbstractStorageDecl *decl) const { + auto *var = dyn_cast(decl); + if (!var) + return false; + if (var->getAccessor(AccessorKind::Init)) return true; @@ -340,7 +344,7 @@ InitAccessorPropertiesRequest::evaluate(Evaluator &evaluator, SmallVector results; for (auto *member : decl->getMembers()) { auto *var = dyn_cast(member); - if (!var || var->isStatic() || !hasInitAccessor(var)) { + if (!var || var->isStatic() || !var->hasInitAccessor()) { continue; } @@ -473,6 +477,13 @@ const PatternBindingEntry *PatternBindingEntryRequest::evaluate( return &pbe; } + // Local variable packs are not allowed. + if (binding->getDeclContext()->isLocalContext() && + binding->getInit(entryNumber)->getType()->is()) { + binding->diagnose(diag::expansion_not_allowed, + binding->getInit(entryNumber)->getType()); + } + // A pattern binding at top level is not allowed to pick up another decl's // opaque result type as its type by type inference. if (!binding->getDeclContext()->isLocalContext() && @@ -3355,7 +3366,7 @@ static void finishStorageImplInfo(AbstractStorageDecl *storage, auto dc = storage->getDeclContext(); if (auto var = dyn_cast(storage)) { - if (!info.hasStorage()) { + if (!info.hasStorage() && !var->hasInitAccessor()) { if (auto *init = var->getParentExecutableInitializer()) { auto &Diags = var->getASTContext().Diags; Diags.diagnose(init->getLoc(), diag::getset_init) diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index ef53dab93a395..dec4881f9a800 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -4618,7 +4618,7 @@ NeverNullType TypeResolver::resolvePackExpansionType(PackExpansionTypeRepr *repr } // We might not allow variadic expansions here at all. - if (!options.isPackExpansionSupported(getDeclContext())) { + if (!options.isPackExpansionSupported()) { diagnose(repr->getLoc(), diag::expansion_not_allowed, result); return ErrorType::get(ctx); } diff --git a/lib/Sema/TypeCheckType.h b/lib/Sema/TypeCheckType.h index 621349220e058..483fd718ce23e 100644 --- a/lib/Sema/TypeCheckType.h +++ b/lib/Sema/TypeCheckType.h @@ -335,7 +335,7 @@ class TypeResolutionOptions { } /// Whether pack expansion types are supported in this context. - bool isPackExpansionSupported(DeclContext *dc) const { + bool isPackExpansionSupported() const { switch (context) { case Context::FunctionInput: case Context::VariadicFunctionInput: @@ -343,12 +343,7 @@ class TypeResolutionOptions { case Context::TupleElement: case Context::GenericArgument: return true; - - // Local variable packs are supported, but property packs - // are not. case Context::PatternBindingDecl: - return !dc->isTypeContext(); - case Context::None: case Context::ProtocolGenericArgument: case Context::Inherited: diff --git a/lib/Serialization/ModuleFileSharedCore.cpp b/lib/Serialization/ModuleFileSharedCore.cpp index d4c325e22c6ea..34bfe05c186e5 100644 --- a/lib/Serialization/ModuleFileSharedCore.cpp +++ b/lib/Serialization/ModuleFileSharedCore.cpp @@ -126,18 +126,27 @@ static bool readOptionsBlock(llvm::BitstreamCursor &cursor, case options_block::XCC: extendedInfo.addExtraClangImporterOption(blobData); break; - case options_block::PLUGIN_SEARCH_PATH: - extendedInfo.addPluginSearchPath(blobData); - break; - case options_block::EXTERNAL_SEARCH_PLUGIN_PATH: - extendedInfo.addExternalPluginSearchPath(blobData); - break; - case options_block::COMPILER_PLUGIN_LIBRARY_PATH: - extendedInfo.addCompilerPluginLibraryPath(blobData); - break; - case options_block::COMPILER_PLUGIN_EXECUTABLE_PATH: - extendedInfo.addCompilerPluginExecutablePath(blobData); + case options_block::PLUGIN_SEARCH_OPTION: { + unsigned kind; + options_block::ResilienceStrategyLayout::readRecord(scratch, kind); + PluginSearchOption::Kind optKind; + switch (PluginSearchOptionKind(kind)) { + case PluginSearchOptionKind::PluginPath: + optKind = PluginSearchOption::Kind::PluginPath; + break; + case PluginSearchOptionKind::ExternalPluginPath: + optKind = PluginSearchOption::Kind::ExternalPluginPath; + break; + case PluginSearchOptionKind::LoadPluginLibrary: + optKind = PluginSearchOption::Kind::LoadPluginLibrary; + break; + case PluginSearchOptionKind::LoadPluginExecutable: + optKind = PluginSearchOption::Kind::LoadPluginExecutable; + break; + } + extendedInfo.addPluginSearchOption({optKind, blobData}); break; + } case options_block::IS_SIB: bool IsSIB; options_block::IsSIBLayout::readRecord(scratch, IsSIB); diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index 12beebdf5f15a..b8ec1c1c180e9 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t SWIFTMODULE_VERSION_MINOR = 792; // removed select_value +const uint16_t SWIFTMODULE_VERSION_MINOR = 793; // PluginSearchOption /// A standard hash seed used for all string hashes in a serialized module. /// @@ -651,6 +651,16 @@ enum class MacroIntroducedDeclNameKind : uint8_t { }; using MacroIntroducedDeclNameKindField = BCFixed<4>; +// These IDs must \em not be renumbered or reordered without incrementing +// the module version. +enum class PluginSearchOptionKind : uint8_t { + PluginPath, + ExternalPluginPath, + LoadPluginLibrary, + LoadPluginExecutable, +}; +using PluginSearchOptionKindField = BCFixed<3>; + // Encodes a VersionTuple: // // Major @@ -884,10 +894,7 @@ namespace options_block { IS_CONCURRENCY_CHECKED, MODULE_PACKAGE_NAME, MODULE_EXPORT_AS_NAME, - PLUGIN_SEARCH_PATH, - EXTERNAL_SEARCH_PLUGIN_PATH, - COMPILER_PLUGIN_LIBRARY_PATH, - COMPILER_PLUGIN_EXECUTABLE_PATH, + PLUGIN_SEARCH_OPTION, HAS_CXX_INTEROPERABILITY_ENABLED, }; @@ -901,24 +908,10 @@ namespace options_block { BCBlob // -Xcc flag, as string >; - using PluginSearchPathLayout = BCRecordLayout< - PLUGIN_SEARCH_PATH, - BCBlob // -plugin-path value - >; - - using ExternalPluginSearchPathLayout = BCRecordLayout< - EXTERNAL_SEARCH_PLUGIN_PATH, - BCBlob // -external-plugin-path value - >; - - using CompilerPluginLibraryPathLayout = BCRecordLayout< - COMPILER_PLUGIN_LIBRARY_PATH, - BCBlob // -load-plugin-library value - >; - - using CompilerPluginExecutablePathLayout = BCRecordLayout< - COMPILER_PLUGIN_EXECUTABLE_PATH, - BCBlob // -load-plugin-executable value + using PluginSearchOptionLayout = BCRecordLayout< + PLUGIN_SEARCH_OPTION, + PluginSearchOptionKindField, // kind + BCBlob // option value string >; using IsSIBLayout = BCRecordLayout< diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 8f1758049b6cb..d243dc2ad0cd8 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -846,10 +846,7 @@ void Serializer::writeBlockInfoBlock() { BLOCK_RECORD(options_block, HAS_CXX_INTEROPERABILITY_ENABLED); BLOCK_RECORD(options_block, MODULE_PACKAGE_NAME); BLOCK_RECORD(options_block, MODULE_EXPORT_AS_NAME); - BLOCK_RECORD(options_block, PLUGIN_SEARCH_PATH); - BLOCK_RECORD(options_block, EXTERNAL_SEARCH_PLUGIN_PATH); - BLOCK_RECORD(options_block, COMPILER_PLUGIN_LIBRARY_PATH); - BLOCK_RECORD(options_block, COMPILER_PLUGIN_EXECUTABLE_PATH); + BLOCK_RECORD(options_block, PLUGIN_SEARCH_OPTION); BLOCK(INPUT_BLOCK); BLOCK_RECORD(input_block, IMPORTED_MODULE); @@ -1138,27 +1135,44 @@ void Serializer::writeHeader(const SerializationOptions &options) { } // Macro plugins - options_block::PluginSearchPathLayout PluginSearchPath(Out); - for (auto Arg : options.PluginSearchPaths) { - PluginSearchPath.emit(ScratchRecord, Arg); - } - - options_block::ExternalPluginSearchPathLayout - ExternalPluginSearchPath(Out); - for (auto Arg : options.ExternalPluginSearchPaths) { - ExternalPluginSearchPath.emit(ScratchRecord, Arg); - } - - options_block::CompilerPluginLibraryPathLayout - CompilerPluginLibraryPath(Out); - for (auto Arg : options.CompilerPluginLibraryPaths) { - CompilerPluginLibraryPath.emit(ScratchRecord, Arg); - } - - options_block::CompilerPluginExecutablePathLayout - CompilerPluginExecutablePath(Out); - for (auto Arg : options.CompilerPluginExecutablePaths) { - CompilerPluginExecutablePath.emit(ScratchRecord, Arg); + options_block::PluginSearchOptionLayout PluginSearchOpt(Out); + for (auto &elem : options.PluginSearchOptions) { + switch (elem.getKind()) { + case PluginSearchOption::Kind::PluginPath: { + auto &opt = elem.get(); + PluginSearchOpt.emit(ScratchRecord, + uint8_t(PluginSearchOptionKind::PluginPath), + opt.SearchPath); + continue; + } + case PluginSearchOption::Kind::ExternalPluginPath: { + auto &opt = elem.get(); + PluginSearchOpt.emit( + ScratchRecord, + uint8_t(PluginSearchOptionKind::ExternalPluginPath), + opt.SearchPath + "#" + opt.ServerPath); + continue; + } + case PluginSearchOption::Kind::LoadPluginLibrary: { + auto &opt = elem.get(); + PluginSearchOpt.emit( + ScratchRecord, + uint8_t(PluginSearchOptionKind::LoadPluginLibrary), + opt.LibraryPath); + continue; + } + case PluginSearchOption::Kind::LoadPluginExecutable: { + auto &opt = elem.get(); + std::string optStr = opt.ExecutablePath + "#"; + llvm::interleave( + opt.ModuleNames, [&](auto &name) { optStr += name; }, + [&]() { optStr += ","; }); + PluginSearchOpt.emit( + ScratchRecord, + uint8_t(PluginSearchOptionKind::LoadPluginExecutable), optStr); + continue; + } + } } } } diff --git a/test/Constraints/ambiguity_diagnostics.swift b/test/Constraints/ambiguity_diagnostics.swift new file mode 100644 index 0000000000000..b8d991529bc0e --- /dev/null +++ b/test/Constraints/ambiguity_diagnostics.swift @@ -0,0 +1,50 @@ +// RUN: %target-typecheck-verify-swift -swift-version 5 -disable-availability-checking + +protocol View { +} + +extension View { + func title(_ title: S) -> some View where S : StringProtocol { + EmptyView() + } + + func title(_ titleKey: LocalizedString) -> some View { + EmptyView() + } +} + +extension View { + func background(_: T) -> some View { + EmptyView() + } +} + +struct EmptyView : View {} + +struct Text : View { + init(_: String) {} +} + +protocol ShapeStyle { +} + +struct AnyShapeStyle : ShapeStyle {} +struct AnyGradient : ShapeStyle {} + +struct LocalizedString : ExpressibleByStringLiteral, ExpressibleByExtendedGraphemeClusterLiteral { + init(extendedGraphemeClusterLiteral value: String) {} + init(stringLiteral: String) {} +} + +func test() { + func __findValue(_: String, fallback: LocalizedString) -> LocalizedString { fatalError() } + func __findValue(_: String, fallback: T) -> T { fatalError() } + func __findValue(_: String, fallback: T) -> T { fatalError() } + + func ambiguitySource() -> AnyShapeStyle { fatalError() } // expected-note {{found this candidate}} + func ambiguitySource() -> AnyGradient { fatalError() } // expected-note {{found this candidate}} + + Text("Test") + .title(__findValue("someKey", fallback: "")) + .background(ambiguitySource()) // expected-error {{ambiguous use of 'ambiguitySource()'}} +} diff --git a/test/Constraints/issue-66553.swift b/test/Constraints/issue-66553.swift new file mode 100644 index 0000000000000..983aca34aa61d --- /dev/null +++ b/test/Constraints/issue-66553.swift @@ -0,0 +1,12 @@ +// RUN: %target-typecheck-verify-swift + +// https://github.com/apple/swift/issues/66553 + +func baz(y: [Int], z: Int) -> Int { + switch z { + case y[let z]: // expected-error {{'let' binding pattern cannot appear in an expression}} + z + default: + z + } +} diff --git a/test/Constraints/pack-expansion-expressions.swift b/test/Constraints/pack-expansion-expressions.swift index 8c09b8e167ca5..1247a21702394 100644 --- a/test/Constraints/pack-expansion-expressions.swift +++ b/test/Constraints/pack-expansion-expressions.swift @@ -36,8 +36,9 @@ func coerceExpansion(_ value: repeat each T) { func localValuePack(_ t: repeat each T) -> (repeat each T, repeat each T) { let local = repeat each t + // expected-error@-1{{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument list}} let localAnnotated: repeat each T = repeat each t - // expected-error@-1{{value pack expansion can only appear inside a function argument list or tuple element}} + // expected-error@-1{{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument list}} return (repeat each local, repeat each localAnnotated) } diff --git a/test/Constraints/rdar105782480.swift b/test/Constraints/rdar105782480.swift index 581f7b3d0db3b..aefb548622e95 100644 --- a/test/Constraints/rdar105782480.swift +++ b/test/Constraints/rdar105782480.swift @@ -12,6 +12,7 @@ func foo(value: MyEnum) { switch value { case .second(let drag).invalid: // expected-error@-1 {{value of type 'MyEnum' has no member 'invalid'}} + // expected-error@-2 {{'let' binding pattern cannot appear in an expression}} break } } diff --git a/test/Constraints/rdar106598067.swift b/test/Constraints/rdar106598067.swift index 0cacec43cf8b2..1579dc002216a 100644 --- a/test/Constraints/rdar106598067.swift +++ b/test/Constraints/rdar106598067.swift @@ -3,9 +3,10 @@ enum E: Error { case e } // rdar://106598067 – Make sure we don't crash. -// FIXME: Bad diagnostic (the issue is that it should be written 'as', not 'as?') +// FIXME: We ought to have a tailored diagnostic to change to 'as' instead of 'as?' let fn = { - // expected-error@-1 {{unable to infer closure type without a type annotation}} do {} catch let x as? E {} - // expected-warning@-1 {{'catch' block is unreachable because no errors are thrown in 'do' block}} + // expected-error@-1 {{pattern variable binding cannot appear in an expression}} + // expected-error@-2 {{expression pattern of type 'E?' cannot match values of type 'any Error'}} + // expected-warning@-3 {{'catch' block is unreachable because no errors are thrown in 'do' block}} } diff --git a/test/DebugInfo/EagerTypeMetadata.swift b/test/DebugInfo/EagerTypeMetadata.swift index d25d87b8f4918..e216d788fc7de 100644 --- a/test/DebugInfo/EagerTypeMetadata.swift +++ b/test/DebugInfo/EagerTypeMetadata.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -Onone -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -Onone -emit-ir -g -o - +// RUN: %target-swift-frontend %s -Onone -emit-ir -g -o - | %FileCheck %s public class C { @@ -7,7 +6,7 @@ public class C { // Ensure that the type metadata for T is eagerly loaded at -Onone. // CHECK: define {{.*}} @"$s17EagerTypeMetadata1CC1cyyxF" - // CHECK: %T = load %swift.type*, %swift.type** + // CHECK: %T = load ptr, ptr // CHECK-SAME: !dbg ![[LOC:[0-9]+]], !invariant.load var x = [i] } diff --git a/test/DebugInfo/LoadableByAddress-allockstack.swift b/test/DebugInfo/LoadableByAddress-allockstack.swift index d602aaf052547..0c41e463ef1f2 100644 --- a/test/DebugInfo/LoadableByAddress-allockstack.swift +++ b/test/DebugInfo/LoadableByAddress-allockstack.swift @@ -1,13 +1,9 @@ // Check we don't crash when verifying debug info. // Ideally this should print the output after loadable by address runs // but there's no way of doing this in SIL (for IRGen passes). -// RUN: %target-swift-frontend %use_no_opaque_pointers -emit-sil %s -Onone \ -// RUN: -sil-verify-all -Xllvm -verify-di-holes -emit-ir \ -// RUN: -Xllvm -sil-print-debuginfo -g -o - | %FileCheck %s - // RUN: %target-swift-frontend -emit-sil %s -Onone \ // RUN: -sil-verify-all -Xllvm -verify-di-holes -emit-ir \ -// RUN: -Xllvm -sil-print-debuginfo -g -o - +// RUN: -Xllvm -sil-print-debuginfo -g -o - | %FileCheck %s struct m { let major: Int @@ -50,4 +46,4 @@ struct h{ } } -// CHECK: define internal %swift.opaque* @"$s4main1mVwCP" +// CHECK: define internal ptr @"$s4main1mVwCP" diff --git a/test/DebugInfo/ProtocolContainer.swift b/test/DebugInfo/ProtocolContainer.swift index 5ef5ee54ad894..1057ea8c3ed12 100644 --- a/test/DebugInfo/ProtocolContainer.swift +++ b/test/DebugInfo/ProtocolContainer.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -emit-ir -g -o - +// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s func markUsed(_ t: T) {} @@ -15,7 +14,7 @@ class AClass : AProtocol { // CHECK: define hidden {{.*}}void @"$s17ProtocolContainer3foo{{[_0-9a-zA-Z]*}}F" // CHECK-NEXT: entry: // CHECK: %[[X:.*]] = alloca %T17ProtocolContainer9AProtocolP, align {{(4|8)}} -// CHECK: call void @llvm.dbg.declare(metadata %T17ProtocolContainer9AProtocolP* %[[X]], metadata ![[XMD:.*]], metadata !DIExpression()) +// CHECK: call void @llvm.dbg.declare(metadata ptr %[[X]], metadata ![[XMD:.*]], metadata !DIExpression()) // CHECK-NOT: !DILocalVariable({{.*}} name: "x" // CHECK-NOT: !DILocalVariable({{.*}} name: "x" func foo (_ x : AProtocol) { diff --git a/test/DebugInfo/WeakCapture.swift b/test/DebugInfo/WeakCapture.swift index 1a6581c38c29a..d05c73262f9db 100644 --- a/test/DebugInfo/WeakCapture.swift +++ b/test/DebugInfo/WeakCapture.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -emit-ir -g -o - +// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s class A { init(handler: (() -> ())) { } } @@ -11,9 +10,9 @@ func function() { let b = B() // Ensure that the local b and its weak copy are distinct local variables. - // CHECK: call void @llvm.dbg.{{.*}}(metadata %T11WeakCapture1BC* + // CHECK: call void @llvm.dbg.{{.*}}(metadata ptr // CHECK-SAME: metadata [[B:.*]], metadata - // CHECK: call void @llvm.dbg.{{.*}}(metadata %swift.weak* + // CHECK: call void @llvm.dbg.{{.*}}(metadata ptr // CHECK-NOT: metadata [[B]] // CHECK: call A(handler: { [weak b] in diff --git a/test/DebugInfo/any.swift b/test/DebugInfo/any.swift index fb04492286e9a..1d9f26d251717 100644 --- a/test/DebugInfo/any.swift +++ b/test/DebugInfo/any.swift @@ -1,10 +1,10 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -emit-ir -g -o - +// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s func markUsed(_ t: T) {} func main() { - // CHECK: call void @llvm.dbg.declare(metadata %Any* {{.*}}, metadata ![[S:.*]], metadata !DIExpression()), !dbg ![[DBG:.*]] + // CHECK: define hidden swiftcc void @"$s3any4mainyyF" + // CHECK: call void @llvm.dbg.declare(metadata ptr {{.*}}, metadata ![[S:.*]], metadata !DIExpression()), !dbg ![[DBG:.*]] // CHECK: ![[S]] = !DILocalVariable(name: "s", {{.*}}line: [[@LINE+2]] // CHECK: ![[DBG]] = !DILocation(line: [[@LINE+1]], column: 7, var s: Any = "hello world" diff --git a/test/DebugInfo/async-args.swift b/test/DebugInfo/async-args.swift index 5e98671f4bc77..080c479eb1a4f 100644 --- a/test/DebugInfo/async-args.swift +++ b/test/DebugInfo/async-args.swift @@ -1,10 +1,6 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o - \ -// RUN: -module-name M -disable-availability-checking \ -// RUN: -parse-as-library | %FileCheck %s - // RUN: %target-swift-frontend %s -emit-ir -g -o - \ // RUN: -module-name M -disable-availability-checking \ -// RUN: -parse-as-library +// RUN: -parse-as-library | %FileCheck %s // REQUIRES: concurrency @@ -14,14 +10,14 @@ func forceSplit() async { func withGenericArg(_ msg: T) async { // This odd debug info is part of a contract with CoroSplit/CoroFrame to fix // this up after coroutine splitting. - // CHECK-LABEL: {{^define .*}} @"$s1M14withGenericArgyyxYalF"(%swift.context* swiftasync %0 - // CHECK-DAG: call void @llvm.dbg.declare(metadata %swift.context* %0, metadata ![[MSG:[0-9]+]], metadata !DIExpression({{.*}}DW_OP_plus_uconst, {{.*}}DW_OP_deref)) - // CHECK-DAG: call void @llvm.dbg.declare(metadata %swift.context* %0, metadata ![[TAU:[0-9]+]], metadata !DIExpression({{.*}}DW_OP_plus_uconst, + // CHECK-LABEL: {{^define .*}} @"$s1M14withGenericArgyyxYalF"(ptr swiftasync %0 + // CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %0, metadata ![[MSG:[0-9]+]], metadata !DIExpression({{.*}}DW_OP_plus_uconst, {{.*}}DW_OP_deref)) + // CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %0, metadata ![[TAU:[0-9]+]], metadata !DIExpression({{.*}}DW_OP_plus_uconst, await forceSplit() - // CHECK-LABEL: {{^define .*}} @"$s1M14withGenericArgyyxYalFTQ0_"(i8* swiftasync %0) - // CHECK-DAG: call void @llvm.dbg.declare(metadata i8* %0, metadata ![[MSG_R:[0-9]+]], metadata !DIExpression({{.*}}DW_OP_plus_uconst, [[OFFSET:[0-9]+]], DW_OP_plus_uconst, {{[0-9]+}}, DW_OP_deref)) - // CHECK-DAG: call void @llvm.dbg.declare(metadata i8* %0, metadata ![[TAU_R:[0-9]+]], metadata !DIExpression({{.*}}DW_OP_deref, DW_OP_plus_uconst, [[OFFSET]], DW_OP_plus_uconst, {{[0-9]+}})) + // CHECK-LABEL: {{^define .*}} @"$s1M14withGenericArgyyxYalFTQ0_"(ptr swiftasync %0) + // CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %0, metadata ![[MSG_R:[0-9]+]], metadata !DIExpression({{.*}}DW_OP_plus_uconst, [[OFFSET:[0-9]+]], DW_OP_plus_uconst, {{[0-9]+}}, DW_OP_deref)) + // CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %0, metadata ![[TAU_R:[0-9]+]], metadata !DIExpression({{.*}}DW_OP_deref, DW_OP_plus_uconst, [[OFFSET]], DW_OP_plus_uconst, {{[0-9]+}})) use(msg) } // CHECK-LABEL: {{^define }} diff --git a/test/DebugInfo/async-let-await.swift b/test/DebugInfo/async-let-await.swift index fd408e439fb46..24bd90ef2244e 100644 --- a/test/DebugInfo/async-let-await.swift +++ b/test/DebugInfo/async-let-await.swift @@ -1,10 +1,6 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o - \ -// RUN: -module-name M -disable-availability-checking \ -// RUN: -parse-as-library | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize - // RUN: %target-swift-frontend %s -emit-ir -g -o - \ // RUN: -module-name M -disable-availability-checking \ -// RUN: -parse-as-library +// RUN: -parse-as-library | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize // REQUIRES: concurrency @@ -16,7 +12,7 @@ public func getVegetables() async -> [String] { public func chopVegetables() async throws -> [String] { let veggies = await getVegetables() // CHECK-NOT: {{^define }} - // CHECK: call void @llvm.dbg.declare(metadata i8* %0, metadata ![[V:[0-9]+]], metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, {{[0-9]+}}, DW_OP_plus_uconst, {{[0-9]+}}) + // CHECK: call void @llvm.dbg.declare(metadata ptr %0, metadata ![[V:[0-9]+]], metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, {{[0-9]+}}, DW_OP_plus_uconst, {{[0-9]+}}) // CHECK: ![[V]] = !DILocalVariable(name: "veggies" return veggies.map { "chopped \($0)" } } diff --git a/test/DebugInfo/async-let.swift b/test/DebugInfo/async-let.swift index 4c45e8ea036b2..627397b2d0259 100644 --- a/test/DebugInfo/async-let.swift +++ b/test/DebugInfo/async-let.swift @@ -1,10 +1,6 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o - \ -// RUN: -module-name M -disable-availability-checking \ -// RUN: -parse-as-library | %FileCheck %s --check-prefix=CHECK - // RUN: %target-swift-frontend %s -emit-ir -g -o - \ // RUN: -module-name M -disable-availability-checking \ -// RUN: -parse-as-library +// RUN: -parse-as-library | %FileCheck %s --check-prefix=CHECK // REQUIRES: concurrency @@ -12,16 +8,16 @@ public actor Alice { let bob = Bob() // CHECK: define {{.*}}$s1M5AliceC4callyyYaFTY0_{{.*}} !dbg ![[SCOPE0:[0-9]+]] - // CHECK: call i8* @__swift_async_resume_get_context{{.*}}!dbg ![[HOP0:[0-9]+]] + // CHECK: call ptr @__swift_async_resume_get_context{{.*}}!dbg ![[HOP0:[0-9]+]] // CHECK: define {{.*}}$s1M5AliceC4callyyYaFTY1_{{.*}} !dbg ![[SCOPE1:[0-9]+]] - // CHECK: call i8* @__swift_async_resume_get_context{{.*}}!dbg ![[HOP1:[0-9]+]] + // CHECK: call ptr @__swift_async_resume_get_context{{.*}}!dbg ![[HOP1:[0-9]+]] // CHECK: define {{.*}}$s1M5AliceC4callyyYaFSiyYaYbcfu_TY0_{{.*}} !dbg ![[LET_SCOPE0:[0-9]+]] - // CHECK: call i8* @__swift_async_resume_get_context{{.*}}!dbg ![[LET_HOP0:[0-9]+]] + // CHECK: call ptr @__swift_async_resume_get_context{{.*}}!dbg ![[LET_HOP0:[0-9]+]] // CHECK: define {{.*}}$s1M5AliceC4callyyYaFSiyYaYbcfu_TY2_{{.*}} !dbg ![[LET_SCOPE1:[0-9]+]] - // CHECK: call i8* @__swift_async_resume_get_context{{.*}}!dbg ![[LET_HOP1:[0-9]+]] + // CHECK: call ptr @__swift_async_resume_get_context{{.*}}!dbg ![[LET_HOP1:[0-9]+]] public func call() async { // CHECK: ![[SCOPE0]] = distinct !DISubprogram({{.*}}line: [[@LINE-1]] // CHECK: ![[HOP0]] = !DILocation(line: [[@LINE-2]], column: 15 diff --git a/test/DebugInfo/basic.swift b/test/DebugInfo/basic.swift index a63dee7403dd0..86aca41b4171d 100644 --- a/test/DebugInfo/basic.swift +++ b/test/DebugInfo/basic.swift @@ -20,23 +20,19 @@ // CHECK-LINETABLES-NOT: DIBasicType // -------------------------------------------------------------------- // Now check that we do generate line+scope info with -g. -// RUN: %target-swift-frontend %use_no_opaque_pointers %/s -emit-ir -g -o - \ +// RUN: %target-swift-frontend %/s -emit-ir -g -o - \ // RUN: | %FileCheck %s --check-prefixes CHECK,DWARF-CHECK -// RUN: %target-swift-frontend %/s -emit-ir -g -o - // -------------------------------------------------------------------- // Currently -gdwarf-types should give the same results as -g. -// RUN: %target-swift-frontend %use_no_opaque_pointers %/s -emit-ir -gdwarf-types -o - \ +// RUN: %target-swift-frontend %/s -emit-ir -gdwarf-types -o - \ // RUN: | %FileCheck %s --check-prefixes CHECK,DWARF-CHECK -// RUN: %target-swift-frontend %/s -emit-ir -gdwarf-types -o - // -------------------------------------------------------------------- // Verify that -g -debug-info-format=dwarf gives the same results as -g. -// RUN: %target-swift-frontend %use_no_opaque_pointers %/s -emit-ir -g -debug-info-format=dwarf -o - \ +// RUN: %target-swift-frontend %/s -emit-ir -g -debug-info-format=dwarf -o - \ // RUN: | %FileCheck %s --check-prefixes CHECK,DWARF-CHECK -// RUN: %target-swift-frontend %/s -emit-ir -g -debug-info-format=dwarf -o - // -------------------------------------------------------------------- -// RUN: %target-swift-frontend %use_no_opaque_pointers %/s -emit-ir -g -debug-info-format=codeview -o - \ +// RUN: %target-swift-frontend %/s -emit-ir -g -debug-info-format=codeview -o - \ // RUN: | %FileCheck %s --check-prefixes CHECK,CV-CHECK -// RUN: %target-swift-frontend %/s -emit-ir -g -debug-info-format=codeview -o - // -------------------------------------------------------------------- // // CHECK: foo @@ -48,12 +44,12 @@ func foo(_ a: Int64, _ b: Int64) -> Int64 { var b = b // CHECK-DAG: ![[ALOC:.*]] = !DILocation(line: [[@LINE-3]],{{.*}} scope: ![[FOO]]) // Check that a is the first and b is the second argument. - // CHECK-DAG: store i64 %0, i64* [[AADDR:.*]], align - // CHECK-DAG: store i64 %1, i64* [[BADDR:.*]], align + // CHECK-DAG: store i64 %0, ptr [[AADDR:.*]], align + // CHECK-DAG: store i64 %1, ptr [[BADDR:.*]], align // CHECK-DAG: [[AVAL:%.*]] = getelementptr inbounds {{.*}}, [[AMEM:.*]], i32 0, i32 0 // CHECK-DAG: [[BVAL:%.*]] = getelementptr inbounds {{.*}}, [[BMEM:.*]], i32 0, i32 0 - // CHECK-DAG: call void @llvm.dbg.declare(metadata i64* [[AADDR]], metadata ![[AARG:.*]], metadata !DIExpression()), !dbg ![[ALOC]] - // CHECK-DAG: call void @llvm.dbg.declare(metadata i64* [[BADDR]], metadata ![[BARG:.*]], metadata !DIExpression()) + // CHECK-DAG: call void @llvm.dbg.declare(metadata ptr [[AADDR]], metadata ![[AARG:.*]], metadata !DIExpression()), !dbg ![[ALOC]] + // CHECK-DAG: call void @llvm.dbg.declare(metadata ptr [[BADDR]], metadata ![[BARG:.*]], metadata !DIExpression()) // CHECK-DAG: ![[AARG]] = !DILocalVariable(name: "a", arg: 1 // CHECK-DAG: ![[BARG]] = !DILocalVariable(name: "b", arg: 2 if b != 0 { diff --git a/test/DebugInfo/byref-capture.swift b/test/DebugInfo/byref-capture.swift index 3816a0754ed2e..34e072719599a 100644 --- a/test/DebugInfo/byref-capture.swift +++ b/test/DebugInfo/byref-capture.swift @@ -1,12 +1,11 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -emit-ir -g -o - +// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s func makeIncrementor(_ inc : Int64) -> () -> Int64 { var sum : Int64 = 0 // CHECK: define {{.*}}5inner func inner() -> Int64 { - // CHECK: call void @llvm.dbg.declare(metadata %Ts5Int64V** + // CHECK: call void @llvm.dbg.declare(metadata ptr // CHECK-SAME: metadata ![[SUM_CAPTURE:[0-9]+]], // CHECK-SAME: metadata !DIExpression(DW_OP_deref)) // CHECK: ![[INOUTTY:[0-9]+]] = !DICompositeType({{.*}}identifier: "$ss5Int64VD" diff --git a/test/DebugInfo/case-scope2.swift b/test/DebugInfo/case-scope2.swift index 3ae29af43d817..ca96e9ad59245 100644 --- a/test/DebugInfo/case-scope2.swift +++ b/test/DebugInfo/case-scope2.swift @@ -9,10 +9,10 @@ func consume(_ t: T) {} public func f(_ s1: Set?, _ s2: Set?) { switch (s1, s2) { case (nil, let a), (let a, nil): - // CHECK: debug_value {{.*}} $Optional>, let, name "a", {{.*}}:[[@LINE-1]]:18, scope [[S1]] + // CHECK: debug_value {{.*}} $Optional>, let, name "a", {{.*}}:11:18, scope [[S2]] consume(a) case (let a?, _): - // CHECK: debug_value {{.*}} $Set, let, name "a", {{.*}}:[[@LINE-1]]:13, scope [[S3]] + // CHECK: debug_value {{.*}} $Set, let, name "a", {{.*}}:14:13, scope [[S3]] consume((a)) } } diff --git a/test/DebugInfo/case-scope3.swift b/test/DebugInfo/case-scope3.swift new file mode 100644 index 0000000000000..293e9ea3b0ce6 --- /dev/null +++ b/test/DebugInfo/case-scope3.swift @@ -0,0 +1,22 @@ +// RUN: %target-swift-frontend -module-name a -parse-as-library -emit-sil -g %s | %FileCheck %s + +enum E { +case integerValue(Int?) +} + +func getE() -> E? { return .integerValue(0) } + +func f() -> Int { + if case .integerValue(let nextValue) = getE(), let nextValue = nextValue { +// CHECK: sil_scope [[F:[0-9]+]] { loc "{{.*}}":9:6 parent @$s1a1fSiyF +// CHECK: sil_scope [[S0:[0-9]+]] { loc "{{.*}}":10:5 parent [[F]] } +// CHECK: sil_scope [[S1:[0-9]+]] { loc "{{.*}}":10:44 parent [[S0]] } +// CHECK: sil_scope [[S2:[0-9]+]] { loc "{{.*}}":10:44 parent [[S0]] } +// CHECK: sil_scope [[S3:[0-9]+]] { loc "{{.*}}":10:68 parent [[S2]] } +// CHECK: sil_scope [[S4:[0-9]+]] { loc "{{.*}}":10:78 parent [[S3]] } +// CHECK: debug_value {{.*}}: $Optional, let, name "nextValue", {{.*}}:10:31, scope [[S2]] +// CHECK: debug_value {{.*}}: $Int, let, name "nextValue", {{.*}}:10:56, scope [[S3]] + return nextValue + } + return 0 +} diff --git a/test/DebugInfo/catch_let.swift b/test/DebugInfo/catch_let.swift index 4f260d767ebcb..1fc704687b56a 100644 --- a/test/DebugInfo/catch_let.swift +++ b/test/DebugInfo/catch_let.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -emit-ir -g -o - +// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s enum MyError : Error { case Yikes @@ -17,7 +16,7 @@ public func explicitBinding() { try throwing() } catch let error { - // CHECK: call void @llvm.dbg.declare(metadata %swift.error** %{{.*}}, metadata ![[EXPLICIT_ERROR:[0-9]+]], + // CHECK: call void @llvm.dbg.declare(metadata ptr %{{.*}}, metadata ![[EXPLICIT_ERROR:[0-9]+]], use(error) } } @@ -29,7 +28,7 @@ public func implicitBinding() { try throwing() } catch { - // CHECK: call void @llvm.dbg.declare(metadata %swift.error** %{{.*}}, metadata ![[IMPLICIT_ERROR:[0-9]+]], + // CHECK: call void @llvm.dbg.declare(metadata ptr %{{.*}}, metadata ![[IMPLICIT_ERROR:[0-9]+]], use(error) } } @@ -41,8 +40,8 @@ public func multiBinding() { try throwing() } catch let error as MyError, let error as MyError { - // CHECK: call void @llvm.dbg.declare(metadata %swift.error** %{{.*}}, metadata ![[MULTI_BINDING_ERROR:[0-9]+]], - // CHECK-NOT: call void @llvm.dbg.declare(metadata %swift.error** %{{.*}} + // CHECK: call void @llvm.dbg.declare(metadata ptr %{{.*}}, metadata ![[MULTI_BINDING_ERROR:[0-9]+]], + // CHECK-NOT: call void @llvm.dbg.declare(metadata ptr %{{.*}} use(error) } catch { use(error) diff --git a/test/DebugInfo/closure-args.swift b/test/DebugInfo/closure-args.swift index 19c3f837031de..cc15b45004eb7 100644 --- a/test/DebugInfo/closure-args.swift +++ b/test/DebugInfo/closure-args.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -emit-ir -g -o - +// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s import Swift @@ -12,20 +11,20 @@ func main() -> Void var backward_ptr = // CHECK: define internal {{.*}} i1 @"$s4mainAAyyFSbSS_SStcfU_"( - // CHECK: %[[RANDOM_STR_ADDR:.*]] = alloca %TSS*, align {{(4|8)}} + // CHECK: %[[RANDOM_STR_ADDR:.*]] = alloca ptr, align {{(4|8)}} // FIXME(TODO: JIRA): i386 String is temporarily larger, and that causes the // value to be by-address. When that is fixed, remove the optional // DW_OP_deref below. // - // CHECK-NEXT: call void @llvm.dbg.declare(metadata %TSS** %[[RANDOM_STR_ADDR]], metadata !{{.*}}, metadata !DIExpression({{(DW_OP_deref)?}})), !dbg + // CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr %[[RANDOM_STR_ADDR]], metadata !{{.*}}, metadata !DIExpression({{(DW_OP_deref)?}})), !dbg - // CHECK: store %TSS* %{{.*}}, %TSS** %[[RANDOM_STR_ADDR]], align {{(4|8)}} + // CHECK: store ptr %{{.*}}, ptr %[[RANDOM_STR_ADDR]], align {{(4|8)}} // CHECK-DAG: !DILocalVariable(name: "lhs",{{.*}} line: [[@LINE+5]], // CHECK-DAG: !DILocalVariable(name: "rhs",{{.*}} line: [[@LINE+4]], - // CHECK-DAG: !DILocalVariable(name: "random_string",{{.*}} line: 9, - // CHECK-DAG: !DILocalVariable(name: "random_int",{{.*}} line: 10, - // CHECK-DAG: !DILocalVariable(name: "out_only",{{.*}} line: 11, + // CHECK-DAG: !DILocalVariable(name: "random_string",{{.*}} line: 8, + // CHECK-DAG: !DILocalVariable(name: "random_int",{{.*}} line: 9, + // CHECK-DAG: !DILocalVariable(name: "out_only",{{.*}} line: 10, { (lhs : String, rhs : String) -> Bool in if rhs == random_string || rhs.unicodeScalars.count == random_int diff --git a/test/DebugInfo/dbgvalue-insertpt.swift b/test/DebugInfo/dbgvalue-insertpt.swift index c5afa4bfaba0b..b5612ec8ea7c3 100644 --- a/test/DebugInfo/dbgvalue-insertpt.swift +++ b/test/DebugInfo/dbgvalue-insertpt.swift @@ -1,11 +1,10 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers -g -emit-ir -Xllvm '-sil-inline-never-functions=next' %s | %FileCheck %s -// RUN: %target-swift-frontend -g -emit-ir -Xllvm '-sil-inline-never-functions=next' %s +// RUN: %target-swift-frontend -g -emit-ir -Xllvm '-sil-inline-never-functions=next' %s | %FileCheck %s // FIXME: This test should be testing a non-shadow-copied value instead. for i in 0 ..< 3 { // CHECK: %[[ALLOCA:[0-9]+]] = alloca %TSiSg // CHECK: %i.debug = alloca i{{32|64}} - // CHECK-NEXT: call void @llvm.dbg.declare(metadata i{{32|64}}* %i.debug, + // CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr %i.debug, // CHECK-SAME: metadata ![[I:[0-9]+]], // CHECK: ![[I]] = !DILocalVariable(name: "i", } diff --git a/test/DebugInfo/debug_info_expression.sil b/test/DebugInfo/debug_info_expression.sil index 185b15c2297be..3957fcda09483 100644 --- a/test/DebugInfo/debug_info_expression.sil +++ b/test/DebugInfo/debug_info_expression.sil @@ -1,6 +1,5 @@ // RUN: %target-swift-frontend %s -sil-verify-all -g -emit-sil -o - | %FileCheck --check-prefix=CHECK-SIL %s -// RUN: %target-swift-frontend %use_no_opaque_pointers -disable-debugger-shadow-copies -primary-file %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend -disable-debugger-shadow-copies -primary-file %s -emit-ir -g -o - +// RUN: %target-swift-frontend -disable-debugger-shadow-copies -primary-file %s -emit-ir -g -o - | %FileCheck %s import Builtin import Swift @@ -20,9 +19,9 @@ sil hidden @test_fragment : $@convention(thin) () -> () { bb0: %2 = alloc_stack $MyStruct, var, name "my_struct", loc "file.swift":8:9, scope 1 // CHECK: %[[MY_STRUCT:.+]] = alloca %{{.*}}MyStruct - // CHECK: llvm.dbg.declare(metadata {{.*}}* %[[MY_STRUCT]], metadata ![[VAR_DECL_MD:[0-9]+]] + // CHECK: llvm.dbg.declare(metadata {{.*}} %[[MY_STRUCT]], metadata ![[VAR_DECL_MD:[0-9]+]] // CHECK: %[[SMALL_STRUCT:.+]] = alloca %{{.*}}SmallStruct - // CHECK: llvm.dbg.declare(metadata {{.*}}* %[[SMALL_STRUCT]], metadata ![[SMALL_VAR_DECL_MD:[0-9]+]] + // CHECK: llvm.dbg.declare(metadata {{.*}} %[[SMALL_STRUCT]], metadata ![[SMALL_VAR_DECL_MD:[0-9]+]] %3 = struct_element_addr %2 : $*MyStruct, #MyStruct.x, loc "file.swift":9:17, scope 1 // CHECK: %[[FIELD_X:.*]] = getelementptr {{.*}} %[[MY_STRUCT]] // CHECK-SIL: debug_value %{{[0-9]+}} : $*Builtin.Int64 @@ -50,13 +49,13 @@ sil hidden @test_alloc_stack : $@convention(thin) () -> () { bb0: %my_struct = alloc_stack $MyStruct, var, name "my_struct", loc "file.swift":15:9, scope 2 // CHECK: %[[MY_STRUCT:.+]] = alloca %{{.*}}MyStruct - // CHECK: llvm.dbg.declare(metadata {{.*}}* %[[MY_STRUCT]], metadata ![[VAR_DECL_MD:[0-9]+]] + // CHECK: llvm.dbg.declare(metadata ptr %[[MY_STRUCT]], metadata ![[VAR_DECL_MD:[0-9]+]] // CHECK-SIL: alloc_stack $Int, var // CHECK-SIL-SAME: (name "my_struct", loc "file.swift":15:9, scope {{[0-9]+}}) // CHECK-SIL-SAME: type $MyStruct, expr op_fragment:#MyStruct.x %field_x = alloc_stack $Int, var, (name "my_struct", loc "file.swift":15:9, scope 2), type $MyStruct, expr op_fragment:#MyStruct.x, loc "file.swift":16:17, scope 2 // CHECK: %[[FIELD_X:.+]] = alloca %TSi - // CHECK: llvm.dbg.declare(metadata %TSi* %[[FIELD_X]], metadata ![[VAR_DECL_MD]] + // CHECK: llvm.dbg.declare(metadata ptr %[[FIELD_X]], metadata ![[VAR_DECL_MD]] // CHECK-SAME: !DIExpression(DW_OP_LLVM_fragment, 0, 64) dealloc_stack %field_x : $*Int dealloc_stack %my_struct: $*MyStruct diff --git a/test/DebugInfo/debug_value_addr.swift b/test/DebugInfo/debug_value_addr.swift index 0152b8a4d7fb4..e104dcd35a005 100644 --- a/test/DebugInfo/debug_value_addr.swift +++ b/test/DebugInfo/debug_value_addr.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers -primary-file %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -o - +// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -o - | %FileCheck %s // RUN: %target-swift-frontend %s -emit-sil -g -o - | %FileCheck -check-prefix=CHECK-SIL %s // Verify that -Onone shadow copies are emitted for debug_value_addr @@ -12,7 +11,7 @@ // CHECK: entry: // CHECK-NEXT: %[[TADDR:.*]] = alloca // CHECK-NEXT: call void @llvm.dbg.declare({{.*}}%[[TADDR]] -// CHECK: store %swift.opaque* %0, %swift.opaque** %[[TADDR:.*]], align +// CHECK: store ptr %0, ptr %[[TADDR:.*]], align struct S { var a : T diff --git a/test/DebugInfo/debug_variable.sil b/test/DebugInfo/debug_variable.sil index ca2cbc7bee896..b6070b5a810ee 100644 --- a/test/DebugInfo/debug_variable.sil +++ b/test/DebugInfo/debug_variable.sil @@ -1,5 +1,4 @@ -// RUN: %target-swiftc_driver %use_no_opaque_pointers -g -emit-ir %s | %FileCheck %s -// RUN: %target-swiftc_driver -g -emit-ir %s +// RUN: %target-swiftc_driver -g -emit-ir %s | %FileCheck %s sil_stage canonical import Builtin @@ -14,7 +13,7 @@ sil_scope 2 { loc "simple.swift":1:2 parent @test_debug_value : $@convention(thi // CHECK-SAME: !dbg ![[FUNC_DI:[0-9]+]] sil hidden @test_debug_value : $@convention(thin) (Int) -> () { bb0(%0 : $Int): - // CHECK: @llvm.dbg.declare(metadata i{{[0-9]+}}* + // CHECK: @llvm.dbg.declare(metadata ptr // CHECK-SAME: metadata ![[VAR_DI:[0-9]+]] // CHECK-SAME: ), !dbg ![[LOC_DI:[0-9]+]] debug_value %0 : $Int, let, name "x", argno 1, loc "simple.swift":3:4, scope 2 diff --git a/test/DebugInfo/dynamic_layout.swift b/test/DebugInfo/dynamic_layout.swift index ff37b293b4acb..dafd0bce55cde 100644 --- a/test/DebugInfo/dynamic_layout.swift +++ b/test/DebugInfo/dynamic_layout.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -emit-ir -g -o - +// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s func markUsed(_ t: T) {} @@ -10,11 +9,11 @@ class Class { // Verify that the mangling of the type U is correct. // CHECK: define {{.*}}3foo - // CHECK: %[[U1:.*]] = alloca %swift.type* - // CHECK: call void @llvm.dbg.declare(metadata %swift.type** %[[U1]], + // CHECK: %[[U1:.*]] = alloca ptr + // CHECK: call void @llvm.dbg.declare(metadata ptr %[[U1]], // CHECK-SAME: metadata ![[U:[0-9]+]] - // CHECK: %[[T2:.*]] = alloca %swift.type* - // CHECK: call void @llvm.dbg.declare(metadata %swift.type** %[[T2]], + // CHECK: %[[T2:.*]] = alloca ptr + // CHECK: call void @llvm.dbg.declare(metadata ptr %[[T2]], // CHECK-SAME: metadata ![[T:[0-9]+]] // CHECK: ![[U]] = !DILocalVariable(name: "$\CF\84_1_0" // CHECK: ![[T]] = !DILocalVariable(name: "$\CF\84_0_0" diff --git a/test/DebugInfo/for-scope.swift b/test/DebugInfo/for-scope.swift index 3b7c3997636f6..2ad423d3d9714 100644 --- a/test/DebugInfo/for-scope.swift +++ b/test/DebugInfo/for-scope.swift @@ -15,7 +15,7 @@ public func f(_ xs: [String?]) { // CHECK: sil_scope [[S5:[0-9]+]] { loc "{{.*}}":7:13 parent [[S4]] } // CHECK: sil_scope [[S6:[0-9]+]] { loc "{{.*}}":7:9 parent [[S4]] } -// CHECK: debug_value %[[X:.*]] : $Optional, let, name "x", {{.*}}, scope [[S3]] +// CHECK: debug_value %[[X:.*]] : $Optional, let, name "x", {{.*}}, scope [[S4]] // CHECK: retain_value %[[X]] : $Optional, {{.*}}, scope [[S5]] // CHECK: debug_value %[[X1:[0-9]+]] : $String, let, name "x", {{.*}}, scope [[S6]] // CHECK: release_value %[[X1]] : $String, {{.*}}, scope [[S6]] diff --git a/test/DebugInfo/generic_arg.swift b/test/DebugInfo/generic_arg.swift index f09763da4a3ec..00acddb3fc2e1 100644 --- a/test/DebugInfo/generic_arg.swift +++ b/test/DebugInfo/generic_arg.swift @@ -1,18 +1,17 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -emit-ir -g -o - +// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s import StdlibUnittest func foo(_ x: T) -> () { // CHECK: define {{.*}} @"$s11generic_arg3fooyyxlF" - // CHECK: %[[T:.*]] = alloca %swift.type* - // CHECK: call void @llvm.dbg.declare(metadata %swift.type** %[[T]], + // CHECK: %[[T:.*]] = alloca ptr + // CHECK: call void @llvm.dbg.declare(metadata ptr %[[T]], // CHECK-SAME: metadata ![[T1:.*]], metadata !DIExpression()) - // CHECK: %[[X:.*]] = alloca %swift.opaque* - // CHECK: call void @llvm.dbg.declare(metadata %swift.opaque** %[[X]], + // CHECK: %[[X:.*]] = alloca ptr + // CHECK: call void @llvm.dbg.declare(metadata ptr %[[X]], // CHECK-SAME: metadata ![[X1:.*]], metadata !DIExpression(DW_OP_deref)) - // CHECK: store %swift.type* %T, %swift.type** %[[T]], - // CHECK: store %swift.opaque* %0, %swift.opaque** %[[X]], + // CHECK: store ptr %T, ptr %[[T]], + // CHECK: store ptr %0, ptr %[[X]], // CHECK-DAG: ![[T1]] = !DILocalVariable(name: "$\CF\84_0_0",{{.*}}flags: DIFlagArtificial) - // CHECK-DAG: ![[X1]] = !DILocalVariable(name: "x", arg: 1,{{.*}}line: 4, type: ![[LET_TY2:[0-9]+]]) + // CHECK-DAG: ![[X1]] = !DILocalVariable(name: "x", arg: 1,{{.*}}line: 3, type: ![[LET_TY2:[0-9]+]]) // CHECK-DAG: ![[LET_TY2]] = !DIDerivedType(tag: DW_TAG_const_type,{{.*}}baseType: ![[TY2:[0-9]+]]) // CHECK-DAG: ![[TY2]] = !DICompositeType({{.*}}name: "$sxD" _blackHole(x) diff --git a/test/DebugInfo/generic_arg2.swift b/test/DebugInfo/generic_arg2.swift index 43d72a5b96da8..8876a76a38496 100644 --- a/test/DebugInfo/generic_arg2.swift +++ b/test/DebugInfo/generic_arg2.swift @@ -1,8 +1,7 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -emit-ir -g -o - +// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s -// CHECK: define hidden swiftcc void @"$s12generic_arg25ClassC3foo{{.*}}, %swift.type* %U -// CHECK: call void @llvm.dbg.declare(metadata %swift.opaque** %y.debug, metadata ![[U:.*]], metadata !DIExpression(DW_OP_deref)) +// CHECK: define hidden swiftcc void @"$s12generic_arg25ClassC3foo{{.*}}, ptr %U +// CHECK: call void @llvm.dbg.declare(metadata ptr %y.debug, metadata ![[U:.*]], metadata !DIExpression(DW_OP_deref)) // Make sure there is no conflicting dbg.value for this variable.x // CHECK-NOT: dbg.value{{.*}}metadata ![[U]] class Class { diff --git a/test/DebugInfo/generic_arg3.swift b/test/DebugInfo/generic_arg3.swift index 93b5bc85d2d68..2844bcedf4201 100644 --- a/test/DebugInfo/generic_arg3.swift +++ b/test/DebugInfo/generic_arg3.swift @@ -1,14 +1,12 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -emit-ir -g -o - +// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s func apply(_ T : Type, fn: (Type) -> Type) -> Type { return fn(T) } public func f(_ value : Type) { // CHECK: define {{.*}}$s12generic_arg31fyyxlFxxXEfU_ - // CHECK: call void @llvm.dbg.declare(metadata %swift.opaque** %[[ALLOCA:[^,]+]], - // CHECK-SAME: metadata ![[ARG:.*]], metadata !DIExpression(DW_OP_deref)) - // CHECK: store %swift.opaque* %1, %swift.opaque** %[[ALLOCA]], align + // CHECK: call void @llvm.dbg.declare(metadata ptr %[[ALLOCA:.*]], metadata ![[ARG:.*]], metadata !DIExpression(DW_OP_deref)) + // CHECK: store ptr %1, ptr %[[ALLOCA]], align // No deref here. // CHECK-DAG: ![[TY:.*]] = !DICompositeType({{.*}}name: "$sxD", file // CHECK-DAG: ![[LET_TY:[0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type,{{.*}}baseType: ![[TY]]) diff --git a/test/DebugInfo/generic_arg4.swift b/test/DebugInfo/generic_arg4.swift index fe2f1158631ec..707209f0513c2 100644 --- a/test/DebugInfo/generic_arg4.swift +++ b/test/DebugInfo/generic_arg4.swift @@ -1,14 +1,13 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -emit-ir -g -o - +// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s // REQUIRES: objc_interop public struct Q { let x: T } // CHECK: define {{.*}}$s12generic_arg43fooyySayAA1QVyxGGlF // CHECK: call void @llvm.dbg.declare -// CHECK: call void @llvm.dbg.declare(metadata %[[TY:.*]]** %[[ALLOCA:[^,]+]], +// CHECK: call void @llvm.dbg.declare(metadata ptr %[[ALLOCA:[^,]+]], // CHECK-SAME: metadata ![[ARG:.*]], metadata !DIExpression()) -// CHECK: store %[[TY]]* %0, %[[TY]]** %[[ALLOCA]], align +// CHECK: store ptr %0, ptr %[[ALLOCA]], align // No deref here: the array argument is passed by value. // CHECK: ![[DITY:.*]] = !DICompositeType({{.*}}name: "$sSay12generic_arg41QVyxGGD" public func foo(_ arg: [Q]) { diff --git a/test/DebugInfo/generic_arg5.swift b/test/DebugInfo/generic_arg5.swift index 80538d9d234ef..9cc609045998f 100644 --- a/test/DebugInfo/generic_arg5.swift +++ b/test/DebugInfo/generic_arg5.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -emit-ir -g -o - +// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s public struct S { let value : Type @@ -9,10 +8,10 @@ public func foo(_ values : [S]) { // CHECK: define {{.*}}$s12generic_arg53fooyySayAA1SVyxGGlFAESgAEXEfU_ // CHECK: call void @llvm.dbg.declare - // CHECK: call void @llvm.dbg.declare(metadata %[[TY:.*]]** %[[ALLOCA:[^,]+]], + // CHECK: call void @llvm.dbg.declare(metadata ptr %[[ALLOCA:[^,]+]], // CHECK-SAME: metadata ![[ARG:[0-9]+]], // CHECK-SAME: metadata !DIExpression(DW_OP_deref)) - // CHECK: store %[[TY]]* %1, %[[TY]]** %[[ALLOCA]], align + // CHECK: store ptr %1, ptr %[[ALLOCA]], align // CHECK: ![[TYP:[0-9]+]] = !DICompositeType({{.*}}, name: "$s12generic_arg51SVyxGD" // The argument is a by-ref struct and thus needs to be dereferenced. // CHECK: ![[ARG]] = !DILocalVariable(name: "arg", arg: 1, diff --git a/test/DebugInfo/generic_enum_closure.swift b/test/DebugInfo/generic_enum_closure.swift index c99a01cd5e9a5..e95c1463b3926 100644 --- a/test/DebugInfo/generic_enum_closure.swift +++ b/test/DebugInfo/generic_enum_closure.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers -primary-file %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -o - +// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -o - | %FileCheck %s struct __CurrentErrno {} struct CErrorOr @@ -12,9 +11,9 @@ struct CErrorOr // CHECK: call void @llvm.dbg.declare // Self is in a dynamic alloca, hence the shadow copy. // CHECK: call void @llvm.dbg.declare( - // CHECK-SAME: metadata i8** %[[SHADOW:.*]], metadata ![[SELF:.*]], meta + // CHECK-SAME: metadata ptr %[[SHADOW:.*]], metadata ![[SELF:.*]], meta // CHECK-SAME: !DIExpression(DW_OP_deref)) - // CHECK-DAG: store i8* %[[DYN:.*]], i8** %[[SHADOW]] + // CHECK-DAG: store ptr %[[DYN:.*]], ptr %[[SHADOW]] // CHECK-DAG: %[[DYN]] = alloca i8, i{{32|64}} % // CHECK-DAG: ![[SELF]] = !DILocalVariable(name: "self", scope:{{.*}}, type: ![[TY_CONTAINER:.*]]) // CHECK-DAG: ![[TY_CONTAINER]] = !DICompositeType({{.*}}elements: ![[TY_ELTS:[0-9]+]] diff --git a/test/DebugInfo/guard-let-scope.swift b/test/DebugInfo/guard-let-scope.swift index 797f08f0b97f6..644d581c0a11c 100644 --- a/test/DebugInfo/guard-let-scope.swift +++ b/test/DebugInfo/guard-let-scope.swift @@ -10,12 +10,14 @@ func f(c: AnyObject??) { // CHECK: sil_scope [[S5:[0-9]+]] { {{.*}} parent [[S3]] } // CHECK: sil_scope [[S6:[0-9]+]] { loc "{{.*}}":7:3 parent [[S5]] } // CHECK: sil_scope [[S7:[0-9]+]] { loc "{{.*}}":7:17 parent [[S6]] } - // CHECK: sil_scope [[S8:[0-9]+]] { loc "{{.*}}":7:28 parent [[S7]] } + // CHECK: sil_scope [[S8:[0-9]+]] { loc "{{.*}}":7:17 parent [[S6]] } + // CHECK: sil_scope [[S9:[0-9]+]] { loc "{{.*}}":7:28 parent [[S8]] } + // CHECK: sil_scope [[S10:[0-9]+]] { loc "{{.*}}":7:28 parent [[S8]] } // CHECK: debug_value %{{.*}} : $Optional>, let, name "x"{{.*}} scope [[S5]] - // CHECK: debug_value %{{.*}} : $Optional, let, name "x", {{.*}} scope [[S7]] - // CHECK: debug_value %{{.*}} : $AnyObject, let, name "x", {{.*}} scope [[S8]] + // CHECK: debug_value %{{.*}} : $Optional, let, name "x", {{.*}} scope [[S8]] + // CHECK: debug_value %{{.*}} : $AnyObject, let, name "x", {{.*}} scope [[S10]] fatalError() } - // CHECK: function_ref {{.*3use.*}} scope [[S8]] + // CHECK: function_ref {{.*3use.*}} scope [[S10]] use(x) } diff --git a/test/DebugInfo/guard-let-scope2.swift b/test/DebugInfo/guard-let-scope2.swift index ab85c650cf5c7..20c455df897ad 100644 --- a/test/DebugInfo/guard-let-scope2.swift +++ b/test/DebugInfo/guard-let-scope2.swift @@ -16,11 +16,12 @@ public func f(x: String?) throws { s = SomeObject() return s != nil } - // CHECK: sil_scope [[S1:[0-9]+]] { {{.*}} parent @{{.*}}1f - // CHECK: sil_scope [[S2:[0-9]+]] { {{.*}} parent [[S1]] } - // CHECK: sil_scope [[S3:[0-9]+]] { {{.*}} parent [[S1]] } - // CHECK: sil_scope [[S4:[0-9]+]] { {{.*}} parent [[S2]] } - // CHECK: alloc_stack {{.*}} $SomeObject, let, name "s", {{.*}} scope [[S4]] + // CHECK: sil_scope [[S1:[0-9]+]] { {{.*}}:13:13 parent @{{.*}}1f + // CHECK: sil_scope [[S2:[0-9]+]] { {{.*}}:14:7 parent [[S1]] } + // CHECK: sil_scope [[S3:[0-9]+]] { {{.*}}:14:26 parent [[S1]] } + // CHECK: sil_scope [[S4:[0-9]+]] { {{.*}}:25:3 parent [[S2]] } + // CHECK: sil_scope [[S5:[0-9]+]] { {{.*}}:25:17 parent [[S4]] } + // CHECK: alloc_stack {{.*}} $SomeObject, let, name "s", {{.*}} scope [[S5]] guard let s = s else { assert(false) return diff --git a/test/DebugInfo/guard-let-scope3.swift b/test/DebugInfo/guard-let-scope3.swift index f023a3901c069..d97db8f2f69a5 100644 --- a/test/DebugInfo/guard-let-scope3.swift +++ b/test/DebugInfo/guard-let-scope3.swift @@ -7,13 +7,15 @@ public class S { private var c = [Int : C?]() public func f(_ i: Int) throws -> C { guard let x = c[i], let x else { - // CHECK: sil_scope [[P:[0-9]+]] { loc "{{.*}}":[[@LINE-1]]:5 - // CHECK: sil_scope [[X1:[0-9]+]] { loc "{{.*}}":[[@LINE-2]]:19 parent [[P]] - // CHECK: sil_scope [[X2:[0-9]+]] { loc "{{.*}}":[[@LINE-3]]:29 parent [[X1]] - // CHECK: sil_scope [[GUARD:[0-9]+]] { loc "{{.*}}":[[@LINE-4]]:36 parent [[P]] + // CHECK: sil_scope [[P:[0-9]+]] { loc "{{.*}}":9:5 + // CHECK: sil_scope [[X1_RHS:[0-9]+]] { loc "{{.*}}":9:19 parent [[P]] + // CHECK: sil_scope [[X1:[0-9]+]] { loc "{{.*}}":9:19 parent [[P]] + // CHECK: sil_scope [[X2:[0-9]+]] { loc "{{.*}}":9:29 parent [[X1]] + // CHECK: sil_scope [[GUARD:[0-9]+]] { loc "{{.*}}":9:36 parent [[P]] // CHECK: debug_value {{.*}} : $Optional, let, name "x", {{.*}}, scope [[X1]] // CHECK: debug_value {{.*}} : $C, let, name "x", {{.*}}, scope [[X2]] - // CHECK-NEXT: scope [[X2]] + // FIXME: This source location is a little wild. + // CHECK-NEXT: strong_retain{{.*}}:[[@LINE+4]]:12, scope [[X2]] throw MyError() // CHECK: function_ref {{.*}}MyError{{.*}}:[[@LINE-1]]:13, scope [[GUARD]] } diff --git a/test/DebugInfo/guard-let-scope4.swift b/test/DebugInfo/guard-let-scope4.swift new file mode 100644 index 0000000000000..ba84a006d7422 --- /dev/null +++ b/test/DebugInfo/guard-let-scope4.swift @@ -0,0 +1,18 @@ +// RUN: %target-swift-frontend -g -emit-sil %s -parse-as-library -module-name a | %FileCheck %s +open class C { + public func fun() {} + + public func run() { + { [weak self] in + guard let self else { fatalError("cannot happen") } + // CHECK: sil_scope [[LAMBDA:[0-9]+]] { loc "{{.*}}":6:5 + // CHECK: sil_scope [[BODY:[0-9]+]] { loc "{{.*}}":6:19 parent [[LAMBDA]] + // CHECK: sil_scope [[LET:[0-9]+]] { loc "{{.*}}":7:7 parent [[BODY]] + // CHECK: sil_scope [[GUARD:[0-9]+]] { loc "{{.*}}":7:17 parent [[LET]] + // CHECK: debug_value {{.*}} : $C, let, name "self", {{.*}}, scope [[GUARD]] + // CHECK: function_ref {{.*}}3fun{{.*}}, scope [[GUARD]] + // CHECK-NEXT: apply {{.*}}, scope [[GUARD]] + self.fun() + }() + } +} diff --git a/test/DebugInfo/guard-let.swift b/test/DebugInfo/guard-let.swift index aca098d4b0e4c..6ac87a636b981 100644 --- a/test/DebugInfo/guard-let.swift +++ b/test/DebugInfo/guard-let.swift @@ -1,10 +1,9 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -c -emit-ir -g -o - | \ +// RUN: %target-swift-frontend %s -c -emit-ir -g -o - | \ // RUN: %FileCheck %s --check-prefix=CHECK1 -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -c -emit-ir -g -o - | \ +// RUN: %target-swift-frontend %s -c -emit-ir -g -o - | \ // RUN: %FileCheck %s --check-prefix=CHECK2 -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -c -emit-ir -g -o - | \ +// RUN: %target-swift-frontend %s -c -emit-ir -g -o - | \ // RUN: %FileCheck %s --check-prefix=CHECK3 -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -c -emit-ir -g -o - // UNSUPPORTED: OS=watchos @@ -21,12 +20,11 @@ func use(_ t: T) {} public func f(_ i : Int?) { // CHECK1-LABEL: define {{.*}}@"$s4main1fyySiSgF" - // CHECK1: %i.debug = alloca %TSiSg - // CHECK1: @llvm.dbg.declare(metadata %TSiSg* %i.debug - // CHECK1: %[[BITCAST:.*]] = bitcast %TSiSg* %i.debug to i8* - // CHECK1: call void @llvm.memset{{.*}}(i8* align {{(4|8)}} %[[BITCAST]], + // CHECK1: %[[alloca:.*]] = alloca %TSiSg + // CHECK1: @llvm.dbg.declare(metadata ptr %i.debug + // CHECK1: call void @llvm.memset{{.*}}(ptr align {{(4|8)}} %[[alloca]], // CHECK1-SAME: i8 0, i64 {{(5|9)}}, i1 false){{$}} - // CHECK1: @llvm.dbg.declare(metadata {{(i32|i64)}}* %val.debug, + // CHECK1: @llvm.dbg.declare(metadata ptr %val.debug, // CHECK1-SAME: !dbg ![[DBG0:.*]] // CHECK1-LABEL: define {{.*}}@"$s4main1gyySSSgF" // CHECK1: ![[F:.*]] = distinct !DISubprogram(name: "f", @@ -39,12 +37,11 @@ public func f(_ i : Int?) public func g(_ s : String?) { // CHECK2: define {{.*}}@"$s4main1gyySSSgF" - // CHECK2: %s.debug = alloca %TSSSg - // CHECK2: @llvm.dbg.declare(metadata %TSSSg* + // CHECK2: %[[alloca:.*]] = alloca %TSSSg + // CHECK2: @llvm.dbg.declare(metadata ptr // CHECK2: %val.debug = alloca %TSS - // CHECK2: @llvm.dbg.declare(metadata %TSS* - // CHECK2: %[[BITCAST:.*]] = bitcast %TSS* %val.debug to i8*{{$}} - // CHECK2: call void @llvm.memset.{{.*}}(i8* align {{(4|8)}} %[[BITCAST]], i8 0 + // CHECK2: @llvm.dbg.declare(metadata ptr + // CHECK2: call void @llvm.memset.{{.*}}(ptr align {{(4|8)}} %[[alloca]], i8 0 // CHECK2: ![[G:.*]] = distinct !DISubprogram(name: "g" guard let val = s else { return } use(val) @@ -54,11 +51,10 @@ public func h(_ s : String?) { // CHECK3: define {{.*}}@"$s4main1hyySSSgF" // CHECK3: %s.debug = alloca %TSSSg - // CHECK3: @llvm.dbg.declare(metadata %TSSSg* - // CHECK3: %s.debug1 = alloca %TSS - // CHECK3: @llvm.dbg.declare(metadata %TSS* - // CHECK3: %[[BITCAST:.*]] = bitcast %TSS* %s.debug1 to i8*{{$}} - // CHECK3: call void @llvm.memset.{{.*}}(i8* align {{(4|8)}} %[[BITCAST]], i8 0 + // CHECK3: @llvm.dbg.declare(metadata ptr + // CHECK3: %[[alloca:.*]] = alloca %TSS + // CHECK3: @llvm.dbg.declare(metadata ptr + // CHECK3: call void @llvm.memset.{{.*}}(ptr align {{(4|8)}} %[[alloca]], i8 0 // CHECK3: ![[G:.*]] = distinct !DISubprogram(name: "h" guard let s = s else { return } use(s) diff --git a/test/DebugInfo/if-let-scope.swift b/test/DebugInfo/if-let-scope.swift index 452464b1a9f18..74fd72a198eac 100644 --- a/test/DebugInfo/if-let-scope.swift +++ b/test/DebugInfo/if-let-scope.swift @@ -1,13 +1,16 @@ // RUN: %target-swift-frontend -g -emit-sil %s -parse-as-library -module-name a | %FileCheck %s func use(_ t: T) {} public func f(value: String?) { - // CHECK: sil_scope [[S0:[0-9]+]] { loc "{{.*}}":[[@LINE-1]]:13 + // CHECK: sil_scope [[S0:[0-9]+]] { loc "{{.*}}":3:13 if let value, let value = Int(value) { - // CHECK: sil_scope [[S1:[0-9]+]] { loc "{{.*}}":[[@LINE-1]]:10 - // CHECK: sil_scope [[S2:[0-9]+]] { loc "{{.*}}":[[@LINE-2]]:29 parent [[S1]] } + // CHECK: sil_scope [[S1:[0-9]+]] { loc "{{.*}}":5:3 + // CHECK: sil_scope [[S2:[0-9]+]] { loc "{{.*}}":5:10 + // CHECK: sil_scope [[S3:[0-9]+]] { loc "{{.*}}":5:29 parent [[S2]] } + // CHECK: sil_scope [[S4:[0-9]+]] { loc "{{.*}}":5:29 parent [[S2]] } + // CHECK: sil_scope [[S5:[0-9]+]] { loc "{{.*}}":5:40 parent [[S4]] } // CHECK: debug_value {{.*}} : $Optional, let, name "value", {{.*}}, scope [[S0]] - // CHECK: debug_value {{.*}} : $String, let, name "value", {{.*}}, scope [[S1]] - // CHECK: debug_value {{.*}} : $Int, let, name "value", {{.*}}, scope [[S2]] + // CHECK: debug_value {{.*}} : $String, let, name "value", {{.*}}, scope [[S2]] + // CHECK: debug_value {{.*}} : $Int, let, name "value", {{.*}}, scope [[S4]] use((value)) } } diff --git a/test/DebugInfo/initializer.swift b/test/DebugInfo/initializer.swift index 4c0457f5ae4d0..8bf7051315b16 100644 --- a/test/DebugInfo/initializer.swift +++ b/test/DebugInfo/initializer.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -import-objc-header %S/Inputs/serialized-objc-header.h -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -import-objc-header %S/Inputs/serialized-objc-header.h -emit-ir -g -o - +// RUN: %target-swift-frontend %s -import-objc-header %S/Inputs/serialized-objc-header.h -emit-ir -g -o - | %FileCheck %s // REQUIRES: objc_interop @@ -8,11 +7,11 @@ protocol Named { } // initializer.Person.__allocating_init (initializer.Person.Type)() -> initializer.Person -// CHECK: define hidden {{.*}}%T11initializer6PersonC* @"$s11initializer6PersonCACycfC"(%swift.type*{{.*}}) {{.*}} { -// CHECK: call {{.*}}%T11initializer6PersonC* @"$s11initializer6PersonCACycfc"(%T11initializer6PersonC* {{.*}}), !dbg ![[ALLOCATING_INIT:.*]] +// CHECK: define hidden {{.*}}ptr @"$s11initializer6PersonCACycfC"(ptr{{.*}}) {{.*}} { +// CHECK: call {{.*}}ptr @"$s11initializer6PersonCACycfc"(ptr {{.*}}), !dbg ![[ALLOCATING_INIT:.*]] // initializer.Person.init (initializer.Person.Type)() -> initializer.Person -// CHECK: define hidden {{.*}}%T11initializer6PersonC* @"$s11initializer6PersonCACycfc"(%T11initializer6PersonC*{{.*}}) {{.*}} { +// CHECK: define hidden {{.*}}ptr @"$s11initializer6PersonCACycfc"(ptr{{.*}}) {{.*}} { // CHECK-DAG: ![[ALLOCATING_INIT]] = !DILocation(line: 0, scope class Person : Named { diff --git a/test/DebugInfo/inlined-generics-basic.swift b/test/DebugInfo/inlined-generics-basic.swift index a396583521239..f1e4c48605df3 100644 --- a/test/DebugInfo/inlined-generics-basic.swift +++ b/test/DebugInfo/inlined-generics-basic.swift @@ -3,7 +3,7 @@ // RUN: -Xllvm -sil-print-debuginfo %s -g -O -o - -emit-sil \ // RUN: | %FileCheck %s --check-prefix=SIL // IR. -// RUN: %target-swift-frontend %use_no_opaque_pointers -parse-as-library -module-name A \ +// RUN: %target-swift-frontend -parse-as-library -module-name A \ // RUN: %s -g -O -o - -emit-ir \ // RUN: | %FileCheck %s --check-prefix=IR @@ -50,12 +50,12 @@ public class C { // SIL: debug_value %0 : $*S, let, name "s", argno 1, expr op_deref, {{.*}} scope [[F]] // SIL: function_ref {{.*}}yes{{.*}} scope [[F1G1]] // SIL: function_ref {{.*}}use{{.*}} scope [[F1G3H]] - // IR: dbg.value(metadata %swift.type* %[[ARG_S]], metadata ![[MD_1_0:[0-9]+]] + // IR: dbg.value(metadata ptr %[[ARG_S]], metadata ![[MD_1_0:[0-9]+]] // IR: %[[RS_PAIR:.*]] = alloca i8, i64 % - // IR: dbg.declare({{.*}} %[[RS_PAIR]], metadata ![[GRS_T:[0-9]+]], - // IR: dbg.value(metadata %swift.opaque* %[[ARG_0]], metadata ![[S:[0-9]+]] - // IR: dbg.value(metadata %swift.opaque* %[[ARG_0]], metadata ![[GS_T:[0-9]+]] - // IR: dbg.value(metadata %swift.opaque* %[[ARG_0]], metadata ![[GS_U:[0-9]+]] + // IR: dbg.declare(metadata ptr %[[RS_PAIR]], metadata ![[GRS_T:[0-9]+]], + // IR: dbg.value(metadata ptr %[[ARG_0]], metadata ![[S:[0-9]+]] + // IR: dbg.value(metadata ptr %[[ARG_0]], metadata ![[GS_T:[0-9]+]] + // IR: dbg.value(metadata ptr %[[ARG_0]], metadata ![[GS_U:[0-9]+]] // IR: call {{.*}}3use #sourceLocation(file: "f.swift", line: 2) g(s) diff --git a/test/DebugInfo/inlined-generics.swift b/test/DebugInfo/inlined-generics.swift index bacb5b7dac860..3efba82d3428f 100644 --- a/test/DebugInfo/inlined-generics.swift +++ b/test/DebugInfo/inlined-generics.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers -Xllvm -sil-inline-generics=true %s -O -g -o - -emit-ir | %FileCheck %s -// RUN: %target-swift-frontend -Xllvm -sil-inline-generics=true %s -O -g -o - -emit-ir +// RUN: %target-swift-frontend -Xllvm -sil-inline-generics=true %s -O -g -o - -emit-ir | %FileCheck %s public protocol P { associatedtype DT1 func getDT() -> DT1 @@ -13,7 +12,7 @@ func foo1(_ t: T, _ dt: T.DT1) -> T.DT1 { // CHECK: define {{.*}}@"$s4main4foo2yyxAA1PRzlF" public func foo2(_ s: S) { - // CHECK: call void @llvm.dbg.value(metadata %swift.type* %S, + // CHECK: call void @llvm.dbg.value(metadata ptr %S, // CHECK-SAME: metadata ![[META:[0-9]+]] foo1(s, s.getDT()) // T should get substituted with S diff --git a/test/DebugInfo/inout.swift b/test/DebugInfo/inout.swift index e75cf70a98b33..090c9654c2c2a 100644 --- a/test/DebugInfo/inout.swift +++ b/test/DebugInfo/inout.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -module-name inout -o %t.ll -// RUN: %target-swift-frontend %s -emit-ir -g -module-name inout +// RUN: %target-swift-frontend %s -emit-ir -g -module-name inout -o %t.ll // RUN: cat %t.ll | %FileCheck %s // RUN: cat %t.ll | %FileCheck %s --check-prefix=PROMO-CHECK // RUN: cat %t.ll | %FileCheck %s --check-prefix=FOO-CHECK @@ -10,13 +9,13 @@ func Close(_ fn: () -> Int64) { fn() } typealias MyFloat = Float // CHECK: define hidden swiftcc void @"$s5inout13modifyFooHeap{{[_0-9a-zA-Z]*}}F" -// CHECK: %[[ALLOCA:.*]] = alloca %Ts5Int64V* +// CHECK: %[[ALLOCA:.*]] = alloca ptr // CHECK: call void @llvm.dbg.declare(metadata // CHECK-SAME: %[[ALLOCA]], metadata ![[A:[0-9]+]] // Closure with promoted capture. // PROMO-CHECK: define {{.*}}@"$s5inout13modifyFooHeapyys5Int64Vz_SftFADyXEfU_" -// PROMO-CHECK: call void @llvm.dbg.declare(metadata %Ts5Int64V** % +// PROMO-CHECK: call void @llvm.dbg.declare(metadata ptr % // PROMO-CHECK-SAME: metadata ![[A1:[0-9]+]], metadata !DIExpression(DW_OP_deref)) // PROMO-CHECK: ![[INT:.*]] = !DICompositeType({{.*}}identifier: "$ss5Int64VD" @@ -37,7 +36,7 @@ func modifyFooHeap(_ a: inout Int64, // Inout reference type. // FOO-CHECK: define {{.*}}@"$s5inout9modifyFooyys5Int64Vz_SftF" -// FOO-CHECK: call void @llvm.dbg.declare(metadata %Ts5Int64V** % +// FOO-CHECK: call void @llvm.dbg.declare(metadata ptr % // FOO-CHECK-SAME: metadata ![[U:[0-9]+]], metadata !DIExpression(DW_OP_deref)) func modifyFoo(_ u: inout Int64, // FOO-CHECK-DAG: !DILocalVariable(name: "v", arg: 2{{.*}} line: [[@LINE+3]],{{.*}} type: ![[LET_MYFLOAT:[0-9]+]] diff --git a/test/DebugInfo/iuo_arg.swift b/test/DebugInfo/iuo_arg.swift index 8b6518646caee..701e1138a94d2 100644 --- a/test/DebugInfo/iuo_arg.swift +++ b/test/DebugInfo/iuo_arg.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -emit-ir -g -o - +// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s class CGImageRef {} class UIImage { @@ -14,12 +13,12 @@ class CIFilter { } class MyClass { - // CHECK: define hidden {{.*}} %T7iuo_arg7UIImageC* @"$s7iuo_arg7MyClassC11filterImageyAA7UIImageCAFSg_SbtF" + // CHECK: define hidden {{.*}} ptr @"$s7iuo_arg7MyClassC11filterImageyAA7UIImageCAFSg_SbtF" func filterImage(_ image: UIImage!, _ doSomething:Bool) -> UIImage { // Test that image is in an alloca, but not an indirect location. - // CHECK: call void @llvm.dbg.declare(metadata {{(i32|i64)}}* %[[ALLOCA:.*]], metadata ![[IMAGE:.*]], metadata !DIExpression()) - // CHECK: store {{(i32|i64)}} %0, {{(i32|i64)}}* %[[ALLOCA]], align + // CHECK: call void @llvm.dbg.declare(metadata ptr %[[ALLOCA:.*]], metadata ![[IMAGE:.*]], metadata !DIExpression()) + // CHECK: store {{(i32|i64)}} %0, ptr %[[ALLOCA]], align // CHECK: ![[IMAGE]] = !DILocalVariable(name: "image", arg: 1 // CHECK-NOT: flags: // CHECK-SAME: line: [[@LINE-7]] diff --git a/test/DebugInfo/let.swift b/test/DebugInfo/let.swift index cb99ad707d97c..7527526cc4e76 100644 --- a/test/DebugInfo/let.swift +++ b/test/DebugInfo/let.swift @@ -1,12 +1,11 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers -primary-file %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -o - +// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -o - | %FileCheck %s class DeepThought { func query() -> Int64 { return 42 } } func foo() -> Int64 { - // CHECK: call void @llvm.dbg.declare(metadata %T3let11DeepThoughtC** {{.*}}, metadata ![[A:.*]], metadata !DIExpression()) + // CHECK: call void @llvm.dbg.declare(metadata ptr {{.*}}, metadata ![[A:.*]], metadata !DIExpression()) // CHECK-DAG: !DILocalVariable(name: "machine",{{.*}}line: [[@LINE+1]], type: !{{[0-9]+}}) let machine = DeepThought() // CHECK-DAG: !DILocalVariable(name: "a", {{.*}}line: [[@LINE+1]], diff --git a/test/DebugInfo/linetable-cleanups.swift b/test/DebugInfo/linetable-cleanups.swift index eafe989923982..02e04142c6c22 100644 --- a/test/DebugInfo/linetable-cleanups.swift +++ b/test/DebugInfo/linetable-cleanups.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -emit-ir -g -o - +// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s // TODO: check why this is failing on linux // REQUIRES: OS=macosx @@ -21,15 +20,14 @@ func main() { // CHECK: call {{.*}}void @"$s4main8markUsedyyxlF" // CHECK: br label // CHECK: {{[0-9]+}}: -// CHECK: call %Ts16IndexingIteratorVySaySiGG* @"$ss16IndexingIteratorVySaySiGGWOh"(%Ts16IndexingIteratorVySaySiGG* %{{.*}}), !dbg ![[LOOPHEADER_LOC:.*]] +// CHECK: call ptr @"$ss16IndexingIteratorVySaySiGGWOh"(ptr %{{.*}}), !dbg ![[LOOPHEADER_LOC:.*]] // CHECK: call {{.*}}void @"$s4main8markUsedyyxlF" // The cleanups should share the line number with the ret stmt. -// CHECK: call %TSa* @"$sSaySiGWOh"(%TSa* %{{.*}}), !dbg ![[CLEANUPS:.*]] -// CHECK-NEXT: !dbg ![[CLEANUPS]] +// CHECK: call ptr @"$sSaySiGWOh"(ptr %{{.*}}), !dbg ![[CLEANUPS:.*]] // CHECK-NEXT: llvm.lifetime.end +// CHECK-SAME: !dbg ![[CLEANUPS]] // CHECK-NEXT: load // CHECK-NEXT: swift_release -// CHECK-NEXT: bitcast // CHECK-NEXT: llvm.lifetime.end // CHECK-NEXT: ret void, !dbg ![[CLEANUPS]] // CHECK: ![[CLEANUPS]] = !DILocation(line: [[@LINE+1]], column: 1, diff --git a/test/DebugInfo/linetable-codeview.swift b/test/DebugInfo/linetable-codeview.swift index c3ba2aaf56650..1bae78e54340a 100644 --- a/test/DebugInfo/linetable-codeview.swift +++ b/test/DebugInfo/linetable-codeview.swift @@ -1,4 +1,4 @@ -// RUN: %swiftc_driver %use_no_opaque_pointers %s -g -debug-info-format=codeview -emit-ir -o - | %FileCheck %s +// RUN: %swiftc_driver %s -g -debug-info-format=codeview -emit-ir -o - | %FileCheck %s // REQUIRES: optimized_stdlib func markUsed(_ t: T) {} @@ -49,12 +49,12 @@ func foo() { // NOTE: The point of this test is to trigger IRGenSIL::emitShadowCopy() // and IRGenSIL::emitShadowCopyIfNeeded(). It may be worthwhile to // simplify this testcase. - // CHECK: store float %0, float* %myArg.debug, {{.*}}, !dbg ![[PROLOGUE:[0-9]+]] - // CHECK: store float {{.*}}, float* %self.debug.myVal1._value, {{.*}}, !dbg ![[PROLOGUE]] + // CHECK: store float %0, ptr %myArg.debug, {{.*}}, !dbg ![[PROLOGUE:[0-9]+]] + // CHECK: store float {{.*}}, ptr %self.debug.myVal1._value, {{.*}}, !dbg ![[PROLOGUE]] // func myLoop() { // CHECK: define {{.*}} @"$s4main6myLoopyyF" - // CHECK: call void @llvm.dbg.declare(metadata i64* %index.debug, {{.*}}), !dbg ![[FORLOOP:[0-9]+]] + // CHECK: call void @llvm.dbg.declare(metadata ptr %index.debug, {{.*}}), !dbg ![[FORLOOP:[0-9]+]] // CHECK: phi i64 [ %{{.[0-9]+}}, %{{.[0-9]+}} ], !dbg ![[FORLOOP]] // CHECK: call {{.*}} @"$s4main8markUsedyyxlF"{{.*}}, !dbg ![[FORBODY:[0-9]+]] // CHECK: ret void @@ -70,7 +70,7 @@ func foo() { // func foo() // CHECK: define {{.*}} @"$s4main3fooyyF" // CHECK: %[[MYARRAY:.*]] = alloca - // CHECK: call void @llvm.dbg.declare(metadata %TSa* %[[MYARRAY]], + // CHECK: call void @llvm.dbg.declare(metadata ptr %[[MYARRAY]], // CHECK-SAME: !dbg ![[ARRAY:[0-9]+]] // CHECK: call swiftcc { {{.*}} } @"${{.*}}_allocateUninitializedArray{{.*}}" // CHECK-SAME: !dbg ![[ARRAY_ALLOC:[0-9]+]] diff --git a/test/DebugInfo/move_function_dbginfo.swift b/test/DebugInfo/move_function_dbginfo.swift index 38a7a88fcca72..02ff1d2a3c49b 100644 --- a/test/DebugInfo/move_function_dbginfo.swift +++ b/test/DebugInfo/move_function_dbginfo.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend %use_no_opaque_pointers -parse-as-library -g -emit-ir -o - %s | %FileCheck %s -// RUN: %target-swift-frontend %use_no_opaque_pointers -parse-as-library -g -c %s -o %t/out.o +// RUN: %target-swift-frontend -parse-as-library -g -emit-ir -o - %s | %FileCheck %s +// RUN: %target-swift-frontend -parse-as-library -g -c %s -o %t/out.o // RUN: %llvm-dwarfdump --show-children %t/out.o | %FileCheck -check-prefix=DWARF %s // This test checks that: @@ -38,17 +38,17 @@ public var falseValue: Bool { false } // CHECK-LABEL: define swiftcc void @"$s21move_function_dbginfo17copyableValueTestyyF"() // // In contrast, we should have a dbg.declare for m since we aren't -// CHECK: call void @llvm.dbg.declare(metadata {{.*}}** %m.debug, metadata ![[M_COPYABLE_VALUE_TEST:[0-9]*]], +// CHECK: call void @llvm.dbg.declare(metadata ptr %m.debug, metadata ![[M_COPYABLE_VALUE_TEST:[0-9]*]], // // We should have a llvm.dbg.addr for k since we moved it. -// CHECK: call void @llvm.dbg.addr(metadata {{.*}}** %k.debug, metadata ![[K_COPYABLE_VALUE_METADATA:[0-9]*]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]*]] +// CHECK: call void @llvm.dbg.addr(metadata ptr %k.debug, metadata ![[K_COPYABLE_VALUE_METADATA:[0-9]*]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]*]] // CHECK-NEXT: br // // Our undef should be an llvm.dbg.value. Counter-intuitively this works for // both llvm.dbg.addr /and/ llvm.dbg.value. Importantly though its metadata // should be for k since that is the variable that we are telling the debugger // is no longer defined. -// CHECK: call void @llvm.dbg.value(metadata %T21move_function_dbginfo5KlassC* undef, metadata ![[K_COPYABLE_VALUE_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[K_COPYABLE_VALUE_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] // CHECK-NOT: br label // // CHECK: ret void @@ -84,20 +84,20 @@ public func copyableValueTest() { m.doSomething() } -// CHECK-LABEL: define swiftcc void @"$s21move_function_dbginfo15copyableArgTestyyAA5KlassCnF"(%T21move_function_dbginfo5KlassC* %0) +// CHECK-LABEL: define swiftcc void @"$s21move_function_dbginfo15copyableArgTestyyAA5KlassCnF"(ptr %0) // // In contrast, we should have a dbg.declare for m since we aren't -// CHECK: call void @llvm.dbg.declare(metadata {{.*}}** %m.debug, metadata ![[M_COPYABLE_VALUE_TEST:[0-9]*]], +// CHECK: call void @llvm.dbg.declare(metadata ptr %m.debug, metadata ![[M_COPYABLE_VALUE_TEST:[0-9]*]], // // We should have a llvm.dbg.addr for k since we moved it. -// CHECK: call void @llvm.dbg.addr(metadata {{.*}}** %k.debug, metadata ![[K_COPYABLE_VALUE_METADATA:[0-9]*]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]*]] +// CHECK: call void @llvm.dbg.addr(metadata ptr %k.debug, metadata ![[K_COPYABLE_VALUE_METADATA:[0-9]*]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]*]] // CHECK-NEXT: br // // Our undef should be an llvm.dbg.value. Counter-intuitively this works for // both llvm.dbg.addr /and/ llvm.dbg.value. Importantly though its metadata // should be for k since that is the variable that we are telling the debugger // is no longer defined. -// CHECK: call void @llvm.dbg.value(metadata %T21move_function_dbginfo5KlassC* undef, metadata ![[K_COPYABLE_VALUE_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[K_COPYABLE_VALUE_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] // CHECK-NOT: br label // // CHECK: ret void @@ -131,12 +131,12 @@ public func copyableArgTest(_ k: __owned Klass) { } // CHECK-LABEL: define swiftcc void @"$s21move_function_dbginfo15copyableVarTestyyF"() -// CHECK: call void @llvm.dbg.declare(metadata %T21move_function_dbginfo5KlassC** %m.debug, -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo5KlassC** [[VAR:%.*]], metadata ![[K_COPYABLE_VAR_METADATA:[0-9]+]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]*]] +// CHECK: call void @llvm.dbg.declare(metadata ptr %m.debug, +// CHECK: call void @llvm.dbg.addr(metadata ptr [[VAR:%.*]], metadata ![[K_COPYABLE_VAR_METADATA:[0-9]+]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]*]] // CHECK-NEXT: br -// CHECK: call void @llvm.dbg.value(metadata %T21move_function_dbginfo5KlassC** undef, metadata ![[K_COPYABLE_VAR_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[K_COPYABLE_VAR_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] // TODO: Should this be a deref like the original? -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo5KlassC** [[VAR]], metadata ![[K_COPYABLE_VAR_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.addr(metadata ptr [[VAR]], metadata ![[K_COPYABLE_VAR_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] // CHECK-NEXT: br // CHECK: ret void // CHECK-NEXT: } @@ -176,12 +176,12 @@ public func copyableVarTest() { } // CHECK-LABEL: define swiftcc void @"$s21move_function_dbginfo18copyableVarArgTestyyAA5KlassCzF"( -// CHECK: call void @llvm.dbg.declare(metadata %T21move_function_dbginfo5KlassC** %m.debug, -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo5KlassC*** [[VAR:%.*]], metadata ![[K_COPYABLE_VAR_METADATA:[0-9]+]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]*]] +// CHECK: call void @llvm.dbg.declare(metadata ptr %m.debug, +// CHECK: call void @llvm.dbg.addr(metadata ptr [[VAR:%.*]], metadata ![[K_COPYABLE_VAR_METADATA:[0-9]+]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]*]] // CHECK-NEXT: br -// CHECK: call void @llvm.dbg.value(metadata %T21move_function_dbginfo5KlassC** undef, metadata ![[K_COPYABLE_VAR_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[K_COPYABLE_VAR_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] // TODO: Should this be a deref like the original? -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo5KlassC*** [[VAR]], metadata ![[K_COPYABLE_VAR_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.addr(metadata ptr [[VAR]], metadata ![[K_COPYABLE_VAR_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] // CHECK-NEXT: br // CHECK: ret void // CHECK-NEXT: } @@ -218,10 +218,10 @@ public func copyableVarArgTest(_ k: inout Klass) { k.doSomething() } -// CHECK-LABEL: define swiftcc void @"$s21move_function_dbginfo20addressOnlyValueTestyyxAA1PRzlF"(%swift.opaque* noalias nocapture %0, %swift.type* %T, i8** %T.P) -// CHECK: @llvm.dbg.addr(metadata %swift.opaque** %k.debug, metadata ![[K_ADDR_LET_METADATA:[0-9]+]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]*]] +// CHECK-LABEL: define swiftcc void @"$s21move_function_dbginfo20addressOnlyValueTestyyxAA1PRzlF"(ptr noalias nocapture %0, ptr %T, ptr %T.P) +// CHECK: @llvm.dbg.addr(metadata ptr %{{.*}}, metadata ![[K_ADDR_LET_METADATA:[0-9]+]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]*]] // CHECK-NEXT: br -// CHECK: @llvm.dbg.value(metadata %swift.opaque* undef, metadata ![[K_ADDR_LET_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] +// CHECK: @llvm.dbg.value(metadata ptr undef, metadata ![[K_ADDR_LET_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] // CHECK: ret void // CHECK-NEXT: } // @@ -267,11 +267,11 @@ public func addressOnlyValueTest(_ x: T) { } // CHECK-LABEL: define swiftcc void @"$s21move_function_dbginfo23addressOnlyValueArgTestyyxnAA1PRzlF"( -// CHECK: @llvm.dbg.declare(metadata %swift.type** %T1, -// CHECK: @llvm.dbg.declare(metadata i8** %m.debug, -// CHECK: @llvm.dbg.addr(metadata %swift.opaque** %k.debug, metadata ![[K_ADDR_LET_METADATA:[0-9]+]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]*]] +// CHECK: @llvm.dbg.declare(metadata ptr %T1, +// CHECK: @llvm.dbg.declare(metadata ptr %m.debug, +// CHECK: @llvm.dbg.addr(metadata ptr %k.debug, metadata ![[K_ADDR_LET_METADATA:[0-9]+]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]*]] // CHECK-NEXT: br -// CHECK: @llvm.dbg.value(metadata %swift.opaque* undef, metadata ![[K_ADDR_LET_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: @llvm.dbg.value(metadata ptr undef, metadata ![[K_ADDR_LET_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] // CHECK: ret void // CHECK-NEXT: } // @@ -308,11 +308,11 @@ public func addressOnlyValueArgTest(_ k: __owned T) { m.doSomething() } -// CHECK-LABEL: define swiftcc void @"$s21move_function_dbginfo18addressOnlyVarTestyyxAA1PRzlF"(%swift.opaque* noalias nocapture %0, %swift.type* %T, i8** %T.P) -// CHECK: @llvm.dbg.addr(metadata %swift.opaque** %k.debug, metadata ![[K_ADDRONLY_VAR_METADATA:[0-9]+]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]*]] +// CHECK-LABEL: define swiftcc void @"$s21move_function_dbginfo18addressOnlyVarTestyyxAA1PRzlF"(ptr noalias nocapture %0, ptr %T, ptr %T.P) +// CHECK: @llvm.dbg.addr(metadata ptr %{{.*}}, metadata ![[K_ADDRONLY_VAR_METADATA:[0-9]+]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]*]] // CHECK-NEXT: br -// CHECK: @llvm.dbg.value(metadata %swift.opaque* undef, metadata ![[K_ADDRONLY_VAR_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] -// CHECK: @llvm.dbg.addr(metadata %swift.opaque** %k.debug, metadata ![[K_ADDRONLY_VAR_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] +// CHECK: @llvm.dbg.value(metadata ptr undef, metadata ![[K_ADDRONLY_VAR_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] +// CHECK: @llvm.dbg.addr(metadata ptr %{{.*}}, metadata ![[K_ADDRONLY_VAR_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] // CHECK-NEXT: br // CHECK: ret void // CHECK-NEXT: } @@ -347,7 +347,7 @@ public func addressOnlyValueArgTest(_ k: __owned T) { // DWARF-NEXT: DW_AT_decl_line ( // DWARF-NEXT: DW_AT_type ( public func addressOnlyVarTest(_ x: T) { - var k = x + var k = x // << this k.doSomething() let m = consume k m.doSomething() @@ -356,10 +356,10 @@ public func addressOnlyVarTest(_ x: T) { } // CHECK-LABEL: define swiftcc void @"$s21move_function_dbginfo21addressOnlyVarArgTestyyxz_xtAA1PRzlF"( -// CHECK: call void @llvm.dbg.addr(metadata %swift.opaque** %k.debug, metadata ![[K_ADDRONLY_VAR_METADATA:[0-9]+]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]*]] +// CHECK: call void @llvm.dbg.addr(metadata ptr %k.debug, metadata ![[K_ADDRONLY_VAR_METADATA:[0-9]+]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]*]] // CHECK-NEXT: br -// CHECK: @llvm.dbg.value(metadata %swift.opaque* undef, metadata ![[K_ADDRONLY_VAR_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] -// CHECK: @llvm.dbg.addr(metadata %swift.opaque** %k.debug, metadata ![[K_ADDRONLY_VAR_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: @llvm.dbg.value(metadata ptr undef, metadata ![[K_ADDRONLY_VAR_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: @llvm.dbg.addr(metadata ptr %k.debug, metadata ![[K_ADDRONLY_VAR_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] // CHECK-NEXT: br // CHECK: ret void // CHECK-NEXT: } @@ -405,14 +405,14 @@ public func addressOnlyVarArgTest(_ k: inout T, _ x: T) { /////////////////////// // CHECK-LABEL: define swiftcc void @"$s21move_function_dbginfo23copyableValueCCFlowTestyyF"( -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo5KlassC** %k.debug, metadata ![[K_COPYABLE_LET_CCFLOW_METADATA:[0-9]+]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]+]] +// CHECK: call void @llvm.dbg.addr(metadata ptr %k.debug, metadata ![[K_COPYABLE_LET_CCFLOW_METADATA:[0-9]+]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]+]] // CHECK-NEXT: br label %[[NEXT_BB:[a-z\.0-9]+]], // // CHECK: [[NEXT_BB]]: // CHECK: br i1 {{%[0-9]+}}, label %[[LHS:[0-9]+]], label %[[RHS:[0-9]+]], // // CHECK: [[LHS]]: -// CHECK: call void @llvm.dbg.value(metadata %T21move_function_dbginfo5KlassC* undef, metadata ![[K_COPYABLE_LET_CCFLOW_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[K_COPYABLE_LET_CCFLOW_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] public func copyableValueCCFlowTest() { let k = Klass() k.doSomething() @@ -423,14 +423,14 @@ public func copyableValueCCFlowTest() { } // CHECK-LABEL: define swiftcc void @"$s21move_function_dbginfo26copyableValueArgCCFlowTestyyAA5KlassCnF"( -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo5KlassC** %k.debug, metadata ![[K_COPYABLE_LET_CCFLOW_METADATA:[0-9]+]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]+]] +// CHECK: call void @llvm.dbg.addr(metadata ptr %k.debug, metadata ![[K_COPYABLE_LET_CCFLOW_METADATA:[0-9]+]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]+]] // CHECK-NEXT: br label %[[NEXT_BB:[a-z\.0-9]+]], // // CHECK: [[NEXT_BB]]: // CHECK: br i1 {{%[0-9]+}}, label %[[LHS:[0-9]+]], label %[[RHS:[0-9]+]], // // CHECK: [[LHS]]: -// CHECK: call void @llvm.dbg.value(metadata %T21move_function_dbginfo5KlassC* undef, metadata ![[K_COPYABLE_LET_CCFLOW_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[K_COPYABLE_LET_CCFLOW_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] public func copyableValueArgCCFlowTest(_ k: __owned Klass) { k.doSomething() if trueValue { @@ -440,15 +440,15 @@ public func copyableValueArgCCFlowTest(_ k: __owned Klass) { } // CHECK-LABEL: define swiftcc void @"$s21move_function_dbginfo037copyableVarTestCCFlowReinitOutOfBlockF0yyF"( -// CHECK: call void @llvm.dbg.declare(metadata %T21move_function_dbginfo5KlassC** %m.debug, -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo5KlassC** [[VAR:%.*]], metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA:[0-9]+]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]*]] +// CHECK: call void @llvm.dbg.declare(metadata ptr %m.debug, +// CHECK: call void @llvm.dbg.addr(metadata ptr [[VAR:%.*]], metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA:[0-9]+]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]*]] // CHECK-NEXT: br label %[[BB_NEXT:[a-z0-9\.]+]], // // CHECK: [[BB_NEXT]]: // CHECK: br i1 %{{[0-9]+}}, label %[[LHS:[0-9]+]], label %[[RHS:[0-9]+]], // // CHECK: [[LHS]]: -// CHECK: call void @llvm.dbg.value(metadata %T21move_function_dbginfo5KlassC** undef, metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] // CHECK: br label %[[CONT_BB:[0-9]+]], // // CHECK: [[RHS]]: @@ -456,7 +456,7 @@ public func copyableValueArgCCFlowTest(_ k: __owned Klass) { // // CHECK: [[CONT_BB]]: // TODO: Should this be a deref like the original? -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo5KlassC** [[VAR]], metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.addr(metadata ptr [[VAR]], metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] // CHECK-NEXT: br // CHECK: ret void // CHECK-NEXT: } @@ -472,22 +472,22 @@ public func copyableVarTestCCFlowReinitOutOfBlockTest() { } // CHECK-LABEL: define swiftcc void @"$s21move_function_dbginfo040copyableVarArgTestCCFlowReinitOutOfBlockG0yyAA5KlassCzF"( -// CHECK: call void @llvm.dbg.declare(metadata %T21move_function_dbginfo5KlassC** %m.debug, -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo5KlassC*** [[VAR:%.*]], metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA:[0-9]+]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]*]] +// CHECK: call void @llvm.dbg.declare(metadata ptr %m.debug, +// CHECK: call void @llvm.dbg.addr(metadata ptr [[VAR:%.*]], metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA:[0-9]+]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]*]] // CHECK-NEXT: br label %[[BB_NEXT:[a-z0-9\.]+]], // // CHECK: [[BB_NEXT]]: // CHECK: br i1 %{{[0-9]+}}, label %[[LHS:[0-9]+]], label %[[RHS:[0-9]+]], // // CHECK: [[LHS]]: -// CHECK: call void @llvm.dbg.value(metadata %T21move_function_dbginfo5KlassC** undef, metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] // CHECK: br label %[[CONT_BB:[0-9]+]], // // CHECK: [[RHS]]: // CHECK: br label %[[CONT_BB]], // // CHECK: [[CONT_BB]]: -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo5KlassC*** [[VAR]], metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.addr(metadata ptr [[VAR]], metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] // CHECK-NEXT: br // CHECK: ret void // CHECK-NEXT: } @@ -503,17 +503,17 @@ public func copyableVarArgTestCCFlowReinitOutOfBlockTest(_ k: inout Klass) { // CHECK-LABEL: define swiftcc void @"$s21move_function_dbginfo034copyableVarTestCCFlowReinitInBlockF0yyF"( // CHECK: entry: -// CHECK: call void @llvm.dbg.declare(metadata %T21move_function_dbginfo5KlassC** %m.debug, -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo5KlassC** [[VAR:%.*]], metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA:[0-9]+]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]*]] +// CHECK: call void @llvm.dbg.declare(metadata ptr %m.debug, +// CHECK: call void @llvm.dbg.addr(metadata ptr [[VAR:%.*]], metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA:[0-9]+]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]*]] // CHECK-NEXT: br label %[[BB_NEXT:[a-z0-9\.]+]], // // CHECK: [[BB_NEXT]]: // CHECK: br i1 %{{[0-9]+}}, label %[[LHS:[0-9]+]], label %[[RHS:[0-9]+]], // // CHECK: [[LHS]]: -// CHECK: call void @llvm.dbg.value(metadata %T21move_function_dbginfo5KlassC** undef, metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] // TODO: Should this be a deref like the original? -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo5KlassC** [[VAR]], metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.addr(metadata ptr [[VAR]], metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] // CHECK-NEXT: br label %[[BB_NEXT_2:[a-z\.0-9]+]], // // CHECK: [[BB_NEXT_2]]: @@ -538,17 +538,17 @@ public func copyableVarTestCCFlowReinitInBlockTest() { // CHECK-LABEL: define swiftcc void @"$s21move_function_dbginfo037copyableVarArgTestCCFlowReinitInBlockG0yyAA5KlassCzF"( // CHECK: entry: -// CHECK: call void @llvm.dbg.declare(metadata %T21move_function_dbginfo5KlassC** %m.debug, -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo5KlassC*** [[VAR:%.*]], metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA:[0-9]+]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]*]] +// CHECK: call void @llvm.dbg.declare(metadata ptr %m.debug, +// CHECK: call void @llvm.dbg.addr(metadata ptr [[VAR:%.*]], metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA:[0-9]+]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]*]] // CHECK-NEXT: br label %[[BB_NEXT:[a-z0-9\.]+]], // // CHECK: [[BB_NEXT]]: // CHECK: br i1 %{{[0-9]+}}, label %[[LHS:[0-9]+]], label %[[RHS:[0-9]+]], // // CHECK: [[LHS]]: -// CHECK: call void @llvm.dbg.value(metadata %T21move_function_dbginfo5KlassC** undef, metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] // TODO: Should this be a deref like the original? -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo5KlassC*** [[VAR]], metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.addr(metadata ptr [[VAR]], metadata ![[K_COPYABLE_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] // CHECK-NEXT: br label %[[BB_NEXT_2:[a-z\.0-9]+]], // // CHECK: [[BB_NEXT_2]]: @@ -572,14 +572,14 @@ public func copyableVarArgTestCCFlowReinitInBlockTest(_ k: inout Klass) { // CHECK-LABEL: define swiftcc void @"$s21move_function_dbginfo040addressOnlyVarTestCCFlowReinitOutOfBlockG0yyxmAA1PRzlF"( // CHECK: entry: -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo1PP* [[VAR:%.*]], metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA:[0-9]+]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]*]] +// CHECK: call void @llvm.dbg.addr(metadata ptr [[VAR:%.*]], metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA:[0-9]+]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]*]] // CHECK-NEXT: br label %[[BB_NEXT:[a-z0-9\.]+]], // // CHECK: [[BB_NEXT]]: // CHECK: br i1 %{{[0-9]+}}, label %[[LHS:[0-9]+]], label %[[RHS:[0-9]+]], // // CHECK: [[LHS]]: -// CHECK: call void @llvm.dbg.value(metadata %T21move_function_dbginfo1PP* undef, metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] // CHECK: br label %[[CONT_BB:[a-z\.0-9]+]], // // CHECK: [[RHS]]: @@ -587,7 +587,7 @@ public func copyableVarArgTestCCFlowReinitInBlockTest(_ k: inout Klass) { // // CHECK: [[CONT_BB]]: // TODO: Should this be a deref like the original? -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo1PP* [[VAR]], metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.addr(metadata ptr [[VAR]], metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] // CHECK-NEXT: br // CHECK: ret void // CHECK-NEXT: } @@ -604,14 +604,14 @@ public func addressOnlyVarTestCCFlowReinitOutOfBlockTest(_ x: T.Type) { // CHECK-LABEL: define swiftcc void @"$s21move_function_dbginfo043addressOnlyVarArgTestCCFlowReinitOutOfBlockH0yyAA1P_pz_xmtAaCRzlF"( // CHECK: entry: -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo1PP** [[VAR:%.*]], metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA:[0-9]+]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]*]] +// CHECK: call void @llvm.dbg.addr(metadata ptr [[VAR:%.*]], metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA:[0-9]+]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]*]] // CHECK-NEXT: br label %[[BB_NEXT:[a-z0-9\.]+]], // // CHECK: [[BB_NEXT]]: // CHECK: br i1 %{{[0-9]+}}, label %[[LHS:[0-9]+]], label %[[RHS:[0-9]+]], // // CHECK: [[LHS]]: -// CHECK: call void @llvm.dbg.value(metadata %T21move_function_dbginfo1PP* undef, metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] // CHECK: br label %[[CONT_BB:[a-z\.0-9]+]], // // CHECK: [[RHS]]: @@ -619,7 +619,7 @@ public func addressOnlyVarTestCCFlowReinitOutOfBlockTest(_ x: T.Type) { // // CHECK: [[CONT_BB]]: // TODO: Should this be a deref like the original? -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo1PP** [[VAR]], metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.addr(metadata ptr [[VAR]], metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_OUT_BLOCK_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] // CHECK-NEXT: br // CHECK: ret void // CHECK-NEXT: } @@ -635,16 +635,16 @@ public func addressOnlyVarArgTestCCFlowReinitOutOfBlockTest(_ k: inout (a // CHECK-LABEL: define swiftcc void @"$s21move_function_dbginfo037addressOnlyVarTestCCFlowReinitInBlockG0yyxmAA1PRzlF"( // CHECK: entry: -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo1PP* [[VAR:%.*]], metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA:[0-9]+]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]*]] +// CHECK: call void @llvm.dbg.addr(metadata ptr [[VAR:%.*]], metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA:[0-9]+]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]*]] // CHECK-NEXT: br label %[[BB_NEXT:[a-z0-9\.]+]], // // CHECK: [[BB_NEXT]]: // CHECK: br i1 %{{[0-9]+}}, label %[[LHS:[0-9]+]], label %[[RHS:[0-9]+]], // // CHECK: [[LHS]]: -// CHECK: call void @llvm.dbg.value(metadata %T21move_function_dbginfo1PP* undef, metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] // TODO: Should this be a deref like the original? -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo1PP* [[VAR]], metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.addr(metadata ptr [[VAR]], metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] // CHECK-NEXT: br label %[[BB_NEXT_2:[a-z\.0-9]+]], // // CHECK: [[BB_NEXT_2]]: @@ -669,16 +669,16 @@ public func addressOnlyVarTestCCFlowReinitInBlockTest(_ x: T.Type) { // CHECK-LABEL: define swiftcc void @"$s21move_function_dbginfo040addressOnlyVarArgTestCCFlowReinitInBlockH0yyAA1P_pz_xmtAaCRzlF"( // CHECK: entry: -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo1PP** [[VAR:%.*]], metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA:[0-9]+]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]*]] +// CHECK: call void @llvm.dbg.addr(metadata ptr [[VAR:%.*]], metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA:[0-9]+]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]*]] // CHECK-NEXT: br label %[[BB_NEXT:[a-z0-9\.]+]], // // CHECK: [[BB_NEXT]]: // CHECK: br i1 %{{[0-9]+}}, label %[[LHS:[0-9]+]], label %[[RHS:[0-9]+]], // // CHECK: [[LHS]]: -// CHECK: call void @llvm.dbg.value(metadata %T21move_function_dbginfo1PP* undef, metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] // TODO: Should this be a deref like the original? -// CHECK: call void @llvm.dbg.addr(metadata %T21move_function_dbginfo1PP** [[VAR]], metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.addr(metadata ptr [[VAR]], metadata ![[K_ADDRESSONLY_VAR_CCFLOW_REINIT_IN_BLOCK_METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] // CHECK-NEXT: br label %[[BB_NEXT_2:[a-z\.0-9]+]], // // CHECK: [[BB_NEXT_2]]: diff --git a/test/DebugInfo/move_function_dbginfo_async.swift b/test/DebugInfo/move_function_dbginfo_async.swift index 03185937b7e18..2a27a90da07df 100644 --- a/test/DebugInfo/move_function_dbginfo_async.swift +++ b/test/DebugInfo/move_function_dbginfo_async.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) // RUN: %target-swift-frontend -parse-as-library -disable-availability-checking -g -emit-sil -o - %s | %FileCheck -check-prefix=SIL %s -// RUN: %target-swift-frontend %use_no_opaque_pointers -parse-as-library -disable-availability-checking -g -emit-ir -o - %s | %FileCheck %s +// RUN: %target-swift-frontend -parse-as-library -disable-availability-checking -g -emit-ir -o - %s | %FileCheck %s // RUN: %target-swift-frontend -parse-as-library -disable-availability-checking -g -c %s -o %t/out.o // This test checks that: @@ -43,22 +43,22 @@ public func forceSplit5() async {} // Tests // /////////// -// CHECK-LABEL: define swifttailcc void @"$s27move_function_dbginfo_async13letSimpleTestyyxnYalF"(%swift.context* swiftasync %0, %swift.opaque* noalias %1, %swift.type* %T) +// CHECK-LABEL: define swifttailcc void @"$s27move_function_dbginfo_async13letSimpleTestyyxnYalF"(ptr swiftasync %0, ptr noalias %1, ptr %T) // CHECK: entry: -// CHECK: call void @llvm.dbg.addr(metadata %swift.context* %{{[0-9]+}}, metadata ![[SIMPLE_TEST_METADATA:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]+]] +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata ![[SIMPLE_TEST_METADATA:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]+]] // CHECK: musttail call swifttailcc void // CHECK-NEXT: ret void -// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async13letSimpleTestyyxnYalFTQ0_"(i8* swiftasync %0) +// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async13letSimpleTestyyxnYalFTQ0_"(ptr swiftasync %0) // CHECK: entryresume.0: -// CHECK: call void @llvm.dbg.addr(metadata i8* %{{[0-9]+}}, metadata ![[SIMPLE_TEST_METADATA_2:[0-9]+]], metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)), +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata ![[SIMPLE_TEST_METADATA_2:[0-9]+]], metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)), // CHECK: musttail call swifttailcc void // CHECK-NEXT: ret void // -// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async13letSimpleTestyyxnYalFTY1_"(i8* swiftasync %0) +// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async13letSimpleTestyyxnYalFTY1_"(ptr swiftasync %0) // CHECK: entryresume.1: -// CHECK: call void @llvm.dbg.addr(metadata i8* %{{[0-9]+}}, metadata ![[SIMPLE_TEST_METADATA_3:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]+]] -// CHECK: call void @llvm.dbg.value(metadata %swift.opaque* undef, metadata ![[SIMPLE_TEST_METADATA_3]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata ![[SIMPLE_TEST_METADATA_3:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]+]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[SIMPLE_TEST_METADATA_3]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] // CHECK: musttail call swifttailcc void // CHECK-NEXT: ret void @@ -88,35 +88,35 @@ public func letSimpleTest(_ msg: __owned T) async { use(consume msg) } -// CHECK-LABEL: define swifttailcc void @"$s27move_function_dbginfo_async13varSimpleTestyyxz_xtYalF"(%swift.context* swiftasync %0, %swift.opaque* %1, %swift.opaque* noalias %2, %swift.type* %T) -// CHECK: call void @llvm.dbg.addr(metadata %swift.context* %{{[0-9]+}}, metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)) -// CHECK: musttail call swifttailcc void @"$s27move_function_dbginfo_async10forceSplityyYaF"(%swift.context* swiftasync %{{[0-9]+}}) +// CHECK-LABEL: define swifttailcc void @"$s27move_function_dbginfo_async13varSimpleTestyyxz_xtYalF"(ptr swiftasync %0, ptr %1, ptr noalias %2, ptr %T) +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)) +// CHECK: musttail call swifttailcc void @"$s27move_function_dbginfo_async10forceSplityyYaF"(ptr swiftasync %{{[0-9]+}}) // CHECK-NEXT: ret void // CHECK-NEXT: } // -// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async13varSimpleTestyyxz_xtYalFTQ0_"(i8* swiftasync %0) +// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async13varSimpleTestyyxz_xtYalFTQ0_"(ptr swiftasync %0) // CHECK: entryresume.0: -// CHECK: call void @llvm.dbg.addr(metadata i8* %{{[0-9]+}}, metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)) -// CHECK: musttail call swifttailcc void @swift_task_switch(%swift.context* swiftasync %{{[0-9]+}}, i8* bitcast (void (i8*)* @"$s27move_function_dbginfo_async13varSimpleTestyyxz_xtYalFTY1_" to i8*), i64 0, i64 0) +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)) +// CHECK: musttail call swifttailcc void @swift_task_switch(ptr swiftasync %{{[0-9]+}}, ptr @"$s27move_function_dbginfo_async13varSimpleTestyyxz_xtYalFTY1_", i64 0, i64 0) // CHECK-NEXT: ret void // CHECK-NEXT: } // -// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async13varSimpleTestyyxz_xtYalFTY1_"(i8* swiftasync %0) +// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async13varSimpleTestyyxz_xtYalFTY1_"(ptr swiftasync %0) // CHECK: entryresume.1: -// CHECK: call void @llvm.dbg.addr(metadata i8* %{{[0-9]+}}, metadata ![[METADATA:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]+]] -// CHECK: call void @llvm.dbg.value(metadata %swift.opaque* undef, metadata ![[METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] -// CHECK: musttail call swifttailcc void @"$s27move_function_dbginfo_async10forceSplityyYaF"(%swift.context* swiftasync +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata ![[METADATA:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]+]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: musttail call swifttailcc void @"$s27move_function_dbginfo_async10forceSplityyYaF"(ptr swiftasync // CHECK-NEXT: ret void // CHECK-NEXT: } // -// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async13varSimpleTestyyxz_xtYalFTQ2_"(i8* swiftasync %0) +// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async13varSimpleTestyyxz_xtYalFTQ2_"(ptr swiftasync %0) // CHECK: entryresume.2: -// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async13varSimpleTestyyxz_xtYalFTY3_"(i8* swiftasync %0) +// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async13varSimpleTestyyxz_xtYalFTY3_"(ptr swiftasync %0) // CHECK: entryresume.3: -// CHECK: call void @llvm.dbg.addr(metadata i8* %{{[0-9]+}}, metadata ![[METADATA:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]+]] -// CHECK: call void @llvm.dbg.value(metadata %swift.opaque* undef, metadata ![[METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] -// CHECK: call void @llvm.dbg.addr(metadata i8* %{{[0-9]+}}, metadata ![[METADATA]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata ![[METADATA:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]+]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata ![[METADATA]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)), !dbg ![[ADDR_LOC]] // CHECK: musttail call swifttailcc void @"$s27move_function_dbginfo_async10forceSplityyYaF"( // CHECK-NEXT: ret void // CHECK-NEXT: } @@ -201,31 +201,31 @@ public func varSimpleTest(_ msg: inout T, _ msg2: T) async { // We don't have an argument here, so we shouldn't have an llvm.dbg.addr in the // initial function. // -// CHECK-LABEL: define swifttailcc void @"$s27move_function_dbginfo_async16varSimpleTestVaryyYaF"(%swift.context* swiftasync %0) +// CHECK-LABEL: define swifttailcc void @"$s27move_function_dbginfo_async16varSimpleTestVaryyYaF"(ptr swiftasync %0) // CHECK-NOT: llvm.dbg.addr // -// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async16varSimpleTestVaryyYaFTY0_"(i8* swiftasync %0) -// CHECK: call void @llvm.dbg.addr(metadata i8* %{{[0-9]+}}, metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8)) +// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async16varSimpleTestVaryyYaFTY0_"(ptr swiftasync %0) +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8)) // -// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async16varSimpleTestVaryyYaFTQ1_"(i8* swiftasync %0) -// CHECK: call void @llvm.dbg.addr(metadata i8* %{{[0-9]+}}, metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8)) +// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async16varSimpleTestVaryyYaFTQ1_"(ptr swiftasync %0) +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8)) -// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async16varSimpleTestVaryyYaFTY2_"(i8* swiftasync %0) -// CHECK: call void @llvm.dbg.addr(metadata i8* %{{[0-9]+}}, metadata ![[METADATA:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8)), !dbg ![[ADDR_LOC:[0-9]+]] -// CHECK: call void @llvm.dbg.value(metadata %T27move_function_dbginfo_async5KlassC** undef, metadata ![[METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] +// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async16varSimpleTestVaryyYaFTY2_"(ptr swiftasync %0) +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata ![[METADATA:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8)), !dbg ![[ADDR_LOC:[0-9]+]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[METADATA]], metadata !DIExpression()), !dbg ![[ADDR_LOC]] -// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async16varSimpleTestVaryyYaFTQ3_"(i8* swiftasync %0) +// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async16varSimpleTestVaryyYaFTQ3_"(ptr swiftasync %0) // We should only see an llvm.dbg.value here. // CHECK-NOT: llvm.dbg.addr -// CHECK: call void @llvm.dbg.value(metadata %T27move_function_dbginfo_async5KlassC** undef, +// CHECK: call void @llvm.dbg.value(metadata ptr undef, // CHECK-NOT: llvm.dbg.addr // // We should see first a llvm.dbg.value to undef the value until we reinit. Then // we should see a llvm.dbg.addr to reinit. // -// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async16varSimpleTestVaryyYaFTY4_"(i8* swiftasync %0) -// CHECK: call void @llvm.dbg.value(metadata %T27move_function_dbginfo_async5KlassC** undef, metadata ![[METADATA:[0-9]+]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]+]] -// CHECK: call void @llvm.dbg.addr(metadata i8* %{{[0-9]+}}, metadata ![[METADATA]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8)), !dbg ![[ADDR_LOC]] +// CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async16varSimpleTestVaryyYaFTY4_"(ptr swiftasync %0) +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[METADATA:[0-9]+]], metadata !DIExpression()), !dbg ![[ADDR_LOC:[0-9]+]] +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata ![[METADATA]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8)), !dbg ![[ADDR_LOC]] // We are not an argument, so no problem here. // @@ -312,20 +312,20 @@ public func varSimpleTestVar() async { // CHECK-NEXT: } // CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async20letArgCCFlowTrueTestyyxnYalFTQ0_"( -// CHECK: call void @llvm.dbg.addr(metadata i8* %{{[0-9]+}}, metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)), -// CHECK: musttail call swifttailcc void @swift_task_switch(%swift.context* swiftasync %{{[0-9]+}}, i8* bitcast (void (i8*)* @"$s27move_function_dbginfo_async20letArgCCFlowTrueTestyyxnYalFTY1_" to i8*), i64 0, i64 0) +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)), +// CHECK: musttail call swifttailcc void @swift_task_switch(ptr swiftasync %{{[0-9]+}}, ptr @"$s27move_function_dbginfo_async20letArgCCFlowTrueTestyyxnYalFTY1_", i64 0, i64 0) // CHECK-NEXT: ret void // CHECK-NEXT: } // CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async20letArgCCFlowTrueTestyyxnYalFTY1_"( -// CHECK: call void @llvm.dbg.addr(metadata i8* %{{[0-9]+}}, metadata ![[METADATA:[0-9]*]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]*]] +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata ![[METADATA:[0-9]*]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]*]] // CHECK-NEXT: br label %[[BLOCK:[a-zA-Z\.0-9]*]], // // CHECK: [[BLOCK]]: // CHECK: br i1 %{{[0-9]}}, label %[[LHS_BLOCK:[a-zA-Z\.0-9]*]], label %[[RHS_BLOCK:[a-zA-Z\.0-9]*]], // // CHECK: [[LHS_BLOCK]]: -// CHECK: call void @llvm.dbg.value(metadata %swift.opaque* undef, metadata ![[METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] // CHECK: musttail call swifttailcc void @"$s27move_function_dbginfo_async11forceSplit2yyYaF"( // CHECK-NEXT: ret void // @@ -341,22 +341,22 @@ public func varSimpleTestVar() async { // _move. // // CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async20letArgCCFlowTrueTestyyxnYalFTQ2_"( -// CHECK: call void @llvm.dbg.value(metadata %swift.opaque* undef, metadata ![[METADATA:[0-9]*]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]*]] -// CHECK: call void @llvm.dbg.value(metadata %swift.opaque* undef, metadata ![[METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[METADATA:[0-9]*]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]*]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] // CHECK: musttail call swifttailcc void @"$s27move_function_dbginfo_async11forceSplit4yyYaF"( // CHECK-NEXT: ret void // // This is the false branch. // // CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async20letArgCCFlowTrueTestyyxnYalFTQ3_"( -// CHECK: call void @llvm.dbg.addr(metadata i8* %{{[0-9]+}}, metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)) +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 8, DW_OP_deref)) // CHECK: musttail call swifttailcc void @"$s27move_function_dbginfo_async11forceSplit4yyYaF"( // CHECK-NEXT: ret void, // CHECK-NEXT: } // // This is the continuation block // CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async20letArgCCFlowTrueTestyyxnYalFTQ4_"( -// CHECK: call void @llvm.dbg.value(metadata %swift.opaque* undef, metadata !{{.*}}, metadata !DIExpression(DW_OP_deref)), +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata !{{.*}}, metadata !DIExpression(DW_OP_deref)), // RUN: %llvm-dwarfdump -c --name='$s3out20letArgCCFlowTrueTestyyxnYalF' %t/out.o | %FileCheck -check-prefix=DWARF17 %s // DWARF17: DW_TAG_subprogram @@ -451,18 +451,18 @@ public func letArgCCFlowTrueTest(_ msg: __owned T) async { // SIL: } // end sil function '$s27move_function_dbginfo_async20varArgCCFlowTrueTestyyxzYaAA1PRzlF' // CHECK-LABEL: define swifttailcc void @"$s27move_function_dbginfo_async20varArgCCFlowTrueTestyyxzYaAA1PRzlF"( -// CHECK: call void @llvm.dbg.addr(metadata %swift.context* %{{[0-9]+}}, metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 48, DW_OP_deref)), +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 48, DW_OP_deref)), // CHECK: musttail call swifttailcc void @"$s27move_function_dbginfo_async11forceSplit1yyYaF"( // CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async20varArgCCFlowTrueTestyyxzYaAA1PRzlFTQ0_"( -// CHECK: call void @llvm.dbg.addr(metadata i8* %{{[0-9]+}}, metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 48, DW_OP_deref)), +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 48, DW_OP_deref)), // CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async20varArgCCFlowTrueTestyyxzYaAA1PRzlFTY1_"( -// CHECK: call void @llvm.dbg.addr(metadata i8* %{{[0-9]+}}, metadata ![[METADATA:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 48, DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]+]] +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata ![[METADATA:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 48, DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]+]] // CHECK: br i1 %{{[0-9]+}}, label %[[LHS_BLOCK:[a-zA-Z0-9]+]], label %[[RHS_BLOCK:[a-zA-Z0-9]+]] // CHECK: [[LHS_BLOCK]]: -// CHECK: call void @llvm.dbg.value(metadata %swift.opaque* undef, metadata ![[METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] // CHECK: musttail call swifttailcc void @"$s27move_function_dbginfo_async11forceSplit2yyYaF"( // CHECK: [[RHS_BLOCK]]: @@ -471,34 +471,34 @@ public func letArgCCFlowTrueTest(_ msg: __owned T) async { // CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async20varArgCCFlowTrueTestyyxzYaAA1PRzlFTQ2_"( // CHECK-NOT: @llvm.dbg.addr -// CHECK: call void @llvm.dbg.value(metadata %swift.opaque* undef, metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_deref)), +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_deref)), // CHECK-NOT: @llvm.dbg.addr -// CHECK: musttail call swifttailcc void @swift_task_switch(%swift.context* swiftasync %{{[0-9]+}}, i8* bitcast (void (i8*)* @"$s27move_function_dbginfo_async20varArgCCFlowTrueTestyyxzYaAA1PRzlFTY3_" to i8*), i64 0, i64 0) +// CHECK: musttail call swifttailcc void @swift_task_switch(ptr swiftasync %{{[0-9]+}}, ptr @"$s27move_function_dbginfo_async20varArgCCFlowTrueTestyyxzYaAA1PRzlFTY3_", i64 0, i64 0) // CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async20varArgCCFlowTrueTestyyxzYaAA1PRzlFTY3_"( // CHECK-NOT: @llvm.dbg.addr -// CHECK: call void @llvm.dbg.value(metadata %swift.opaque* undef, metadata ![[METADATA:[0-9]+]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]+]] -// CHECK: call void @llvm.dbg.value(metadata %swift.opaque* undef, metadata ![[METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] -// CHECK: call void @llvm.dbg.addr(metadata i8* %{{[0-9]+}}, metadata ![[METADATA]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 48, DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[METADATA:[0-9]+]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]+]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata ![[METADATA]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 48, DW_OP_deref)), !dbg ![[ADDR_LOC]] // CHECK: musttail call swifttailcc void @"$s27move_function_dbginfo_async11forceSplit4yyYaF"( // CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async20varArgCCFlowTrueTestyyxzYaAA1PRzlFTQ4_"( // CHECK-NOT: @llvm.dbg.value -// CHECK: call void @llvm.dbg.addr(metadata i8* %{{[0-9]+}}, metadata ![[METADATA:[0-9]+]], metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 48, DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]+]] -// CHECK: call void @llvm.dbg.value(metadata %swift.opaque* undef, metadata ![[METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] -// CHECK: musttail call swifttailcc void @swift_task_switch(%swift.context* swiftasync %{{[0-9]+}}, i8* bitcast (void (i8*)* @"$s27move_function_dbginfo_async20varArgCCFlowTrueTestyyxzYaAA1PRzlFTY5_" to i8*), +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata ![[METADATA:[0-9]+]], metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 48, DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]+]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: musttail call swifttailcc void @swift_task_switch(ptr swiftasync %{{[0-9]+}}, ptr @"$s27move_function_dbginfo_async20varArgCCFlowTrueTestyyxzYaAA1PRzlFTY5_", // CHECK: define internal swifttailcc void @"$s27move_function_dbginfo_async20varArgCCFlowTrueTestyyxzYaAA1PRzlFTY5_"( -// CHECK: call void @llvm.dbg.value(metadata %swift.opaque* undef, metadata ![[METADATA:[0-9]+]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]+]] -// CHECK: call void @llvm.dbg.value(metadata %swift.opaque* undef, metadata ![[METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] -// CHECK: call void @llvm.dbg.addr(metadata i8* %{{[0-9]+}}, metadata ![[METADATA]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 48, DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[METADATA:[0-9]+]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC:[0-9]+]] +// CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata ![[METADATA]], metadata !DIExpression(DW_OP_deref)), !dbg ![[ADDR_LOC]] +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata ![[METADATA]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 48, DW_OP_deref)), !dbg ![[ADDR_LOC]] // CHECK: musttail call swifttailcc void @"$s27move_function_dbginfo_async11forceSplit4yyYaF"( // CHECK-LABEL: define internal swifttailcc void @"$s27move_function_dbginfo_async20varArgCCFlowTrueTestyyxzYaAA1PRzlFTQ6_"( // CHECK-NOT: @llvm.dbg.value( -// CHECK: call void @llvm.dbg.addr(metadata i8* %{{[0-9]+}}, metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 48, DW_OP_deref)), +// CHECK: call void @llvm.dbg.addr(metadata ptr %{{[0-9]+}}, metadata !{{[0-9]+}}, metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16, DW_OP_plus_uconst, 48, DW_OP_deref)), // CHECK-NOT: @llvm.dbg.value( -// CHECK: musttail call swifttailcc void %{{[0-9]+}}(%swift.context* swiftasync +// CHECK: musttail call swifttailcc void %{{[0-9]+}}(ptr swiftasync // CHECK-NEXT: ret void, // CHECK-NEXT: } diff --git a/test/DebugInfo/nostorage.swift b/test/DebugInfo/nostorage.swift index 21267c6de1421..9b3741cc53238 100644 --- a/test/DebugInfo/nostorage.swift +++ b/test/DebugInfo/nostorage.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o %t -// RUN: %target-swift-frontend %s -emit-ir -g +// RUN: %target-swift-frontend %s -emit-ir -g -o %t // RUN: cat %t | %FileCheck %s --check-prefix=CHECK1 // RUN: cat %t | %FileCheck %s --check-prefix=CHECK2 // RUN: cat %t | %FileCheck %s --check-prefix=CHECK3 @@ -29,7 +28,7 @@ struct AStruct {} // CHECK2: define{{.*}}app public func app() { // No members? No storage! - // CHECK2: call void @llvm.dbg.value(metadata {{.*}}* undef, + // CHECK2: call void @llvm.dbg.value(metadata ptr undef, // CHECK2-SAME: metadata ![[AT:.*]], metadata // CHECK2: ![[AT]] = !DILocalVariable(name: "at",{{.*}}line: [[@LINE+1]] var at = AStruct() diff --git a/test/DebugInfo/protocol-extension.swift b/test/DebugInfo/protocol-extension.swift index 30788b2354444..aace6d8336245 100644 --- a/test/DebugInfo/protocol-extension.swift +++ b/test/DebugInfo/protocol-extension.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers -primary-file %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -o - +// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -o - | %FileCheck %s public protocol P { var v : Int32 { get }; @@ -9,8 +8,8 @@ public extension P { // CHECK: define {{.*}}swiftcc i32 @"$s4main1PPAAE1fs5Int32VyF" public func f() -> Int32 { // CHECK-NEXT: entry: - // CHECK-NEXT: %[[ALLOCA:.*]] = alloca %swift.type*, - // CHECK-NEXT: @llvm.dbg.declare(metadata %swift.type** %[[ALLOCA]], + // CHECK-NEXT: %[[ALLOCA:.*]] = alloca ptr, + // CHECK-NEXT: @llvm.dbg.declare(metadata ptr %[[ALLOCA]], // CHECK-SAME: metadata ![[SELFMETA:.*]], metadata !DIExpression()) return v } diff --git a/test/DebugInfo/protocolarg.swift b/test/DebugInfo/protocolarg.swift index 3dcaf60722808..999def8e3680b 100644 --- a/test/DebugInfo/protocolarg.swift +++ b/test/DebugInfo/protocolarg.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -emit-ir -g -o - +// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s func markUsed(_ t: T) {} func use(_ t: inout T) {} @@ -9,10 +8,10 @@ public protocol IGiveOutInts { } // CHECK: define {{.*}}@"$s11protocolarg16printSomeNumbersyyAA12IGiveOutInts_pF" -// CHECK: @llvm.dbg.declare(metadata %T11protocolarg12IGiveOutIntsP** % +// CHECK: @llvm.dbg.declare(metadata ptr % // CHECK-SAME: metadata ![[ARG:[0-9]+]], // CHECK-SAME: metadata !DIExpression(DW_OP_deref)) -// CHECK: @llvm.dbg.declare(metadata %T11protocolarg12IGiveOutIntsP* % +// CHECK: @llvm.dbg.declare(metadata ptr % // CHECK-SAME: metadata ![[VAR:.*]], metadata !DIExpression()) public func printSomeNumbers(_ gen: IGiveOutInts) { diff --git a/test/DebugInfo/resilient_debug_value.sil b/test/DebugInfo/resilient_debug_value.sil index 25e44b6834aa3..73054d0df6ed3 100644 --- a/test/DebugInfo/resilient_debug_value.sil +++ b/test/DebugInfo/resilient_debug_value.sil @@ -5,8 +5,7 @@ // RUN: -emit-module-path=%t/resilient_struct.swiftmodule \ // RUN: -module-name=resilient_struct %S/../Inputs/resilient_struct.swift // -// RUN: %target-swift-frontend %use_no_opaque_pointers -g -I %t -emit-ir %s -o - | %FileCheck %s -// RUN: %target-swift-frontend -g -I %t -emit-ir %s -o - +// RUN: %target-swift-frontend -g -I %t -emit-ir %s -o - | %FileCheck %s // REQUIRES: CPU=arm64 || CPU=x86_64 @@ -23,6 +22,6 @@ bb0: return %1 : $() } // CHECK: define{{.*}} swiftcc void @test_debug_value_resilient() -// CHECK: [[ASSERTIONSDBG:%.*]] = alloca i8* +// CHECK: [[ASSERTIONSDBG:%.*]] = alloca ptr // CHECK: [[ASSERTIONS:%.*]] = alloca i8, i64 %size -// CHECK: store i8* [[ASSERTIONS]], i8** [[ASSERTIONSDBG]] +// CHECK: store ptr [[ASSERTIONS]], ptr [[ASSERTIONSDBG]] diff --git a/test/DebugInfo/return.swift b/test/DebugInfo/return.swift index 65ac0407e357d..e42fd3210b637 100644 --- a/test/DebugInfo/return.swift +++ b/test/DebugInfo/return.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -g -emit-ir -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -g -emit-ir -o - +// RUN: %target-swift-frontend %s -g -emit-ir -o - | %FileCheck %s class X { init (i : Int64) { x = i } @@ -9,20 +8,20 @@ class X { // CHECK: define {{.*}}ifelseexpr public func ifelseexpr() -> Int64 { var x = X(i:0) - // CHECK: [[ALLOCA:%.*]] = alloca %T6return1XC* + // CHECK: [[ALLOCA:%.*]] = alloca ptr // CHECK: [[TMP:%.*]] = call swiftcc %swift.metadata_response @"$s6return1XCMa"( // CHECK: [[META:%.*]] = extractvalue %swift.metadata_response [[TMP]], 0 - // CHECK: [[X:%.*]] = call {{.*}}%T6return1XC* @"$s6return1XC1iACs5Int64V_tcfC"( - // CHECK-SAME: i64 0, %swift.type* swiftself [[META]]) - // CHECK: store %T6return1XC* [[X]], %T6return1XC** [[ALLOCA]] - // CHECK: @swift_release to void (%T6return1XC*)*)(%T6return1XC* [[X]]) + // CHECK: [[X:%.*]] = call {{.*}}ptr @"$s6return1XC1iACs5Int64V_tcfC"( + // CHECK-SAME: i64 0, ptr swiftself [[META]]) + // CHECK: store ptr [[X]], ptr [[ALLOCA]] + // CHECK: @swift_release if true { x.x += 1 } else { x.x -= 1 } - // CHECK: [[L:%.*]] = load %T6return1XC*, %T6return1XC** [[ALLOCA]] - // CHECK: @swift_release to void (%T6return1XC*)*)(%T6return1XC* [[L]]) + // CHECK: [[L:%.*]] = load ptr, ptr [[ALLOCA]] + // CHECK: @swift_release // CHECK-SAME: , !dbg ![[RELEASE:.*]] // The ret instruction should be in the same scope as the return expression. // CHECK: ret{{.*}}, !dbg ![[RELEASE]] diff --git a/test/DebugInfo/self.swift b/test/DebugInfo/self.swift index e46c369ef1fa4..3cd5cae576a5f 100644 --- a/test/DebugInfo/self.swift +++ b/test/DebugInfo/self.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers -primary-file %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -o - +// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -o - | %FileCheck %s public struct stuffStruct { var a: Int64 = 6 @@ -17,7 +16,7 @@ public func f() { // CHECK: define {{.*}} @"$s4self11stuffStructVACycfC"( // CHECK-NEXT: entry: // CHECK: %[[ALLOCA:.*]] = alloca %T4self11stuffStructV, align {{(4|8)}} -// CHECK: call void @llvm.dbg.declare(metadata %T4self11stuffStructV* %[[ALLOCA]], +// CHECK: call void @llvm.dbg.declare(metadata ptr %[[ALLOCA]], // CHECK-SAME: metadata ![[SELF:.*]], metadata !DIExpression()), !dbg // CHECK: ![[STUFFSTRUCT:.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "stuffStruct", scope:{{.*}}identifier // CHECK: ![[SELF]] = !DILocalVariable(name: "self", scope diff --git a/test/DebugInfo/shadow_copies.swift b/test/DebugInfo/shadow_copies.swift index 4d3a7af891fa8..c3e9bdd4dfaed 100644 --- a/test/DebugInfo/shadow_copies.swift +++ b/test/DebugInfo/shadow_copies.swift @@ -1,9 +1,6 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -Onone -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -Onone -emit-ir -g -o - -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -Onone -emit-ir -g -o - \ -// RUN: -disable-debugger-shadow-copies | %FileCheck %s --check-prefix=NOCOPY +// RUN: %target-swift-frontend %s -Onone -emit-ir -g -o - | %FileCheck %s // RUN: %target-swift-frontend %s -Onone -emit-ir -g -o - \ -// RUN: -disable-debugger-shadow-copies +// RUN: -disable-debugger-shadow-copies | %FileCheck %s --check-prefix=NOCOPY class ClassA { var x : Int64 @@ -22,15 +19,15 @@ class ClassB : ClassA { // CHECK: @"$s{{.*}}6ClassBCyACs5Int64Vcfc" // NOCOPY: @"$s{{.*}}6ClassBCyACs5Int64Vcfc" - // CHECK: alloca {{.*}}ClassBC* - // NOCOPY: alloca {{.*}}ClassBC* + // CHECK: alloca ptr + // NOCOPY: alloca ptr // CHECK: alloca i64 // CHECK-NOT: alloca // NOCOPY-NOT: alloca - // CHECK: ret {{.*}}ClassBC - // NOCOPY: ret {{.*}}ClassBC + // CHECK: ret ptr + // NOCOPY: ret ptr super.init (input) } } @@ -45,7 +42,7 @@ class ClassC // NOCOPY: define {{.*}}@"$s13shadow_copies6ClassCCACycfc" init () { - // CHECK: alloca %T13shadow_copies6ClassCC* + // CHECK: alloca ptr // CHECK-NOT: alloca // NOCOPY-NOT: alloca diff --git a/test/DebugInfo/shadowcopy-linetable.swift b/test/DebugInfo/shadowcopy-linetable.swift index 521ebf7ee043c..777cf88248a77 100644 --- a/test/DebugInfo/shadowcopy-linetable.swift +++ b/test/DebugInfo/shadowcopy-linetable.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -emit-ir -g -o - +// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s func markUsed(_ t: T) {} @@ -7,13 +6,13 @@ func foo(_ x: inout Int64) { // Make sure the shadow copy is being made in the prologue or (at // line 0), but the code to load the value from the inout storage is // not. - // CHECK: %[[X:.*]] = alloca %Ts5Int64V*, align {{(4|8)}} + // CHECK: define hidden swiftcc void @"$s4main3fooyys5Int64VzF" + // CHECK: %[[X:.*]] = alloca ptr, align {{(4|8)}} // CHECK-NEXT: call void @llvm.dbg.declare - // CHECK-NEXT: %[[ZEROED:[0-9]+]] = bitcast %Ts5Int64V** %[[X]] to i8*{{$}} - // CHECK-NEXT: call void @llvm.memset.{{.*}}(i8* align {{(4|8)}} %[[ZEROED]], i8 0 - // CHECK: store %Ts5Int64V* %0, %Ts5Int64V** %[[X]], align {{(4|8)}} + // CHECK-NEXT: call void @llvm.memset.{{.*}}(ptr align {{(4|8)}} %[[X]], i8 0 + // CHECK: store ptr %0, ptr %[[X]], align {{(4|8)}} // CHECK-SAME: !dbg ![[LOC0:.*]] - // CHECK-NEXT: getelementptr inbounds %Ts5Int64V, %Ts5Int64V* %0, i32 0, i32 0, + // CHECK-NEXT: getelementptr inbounds %Ts5Int64V, ptr %0, i32 0, i32 0, // CHECK-SAME: !dbg ![[LOC0]] // CHECK: ![[LOC0]] = !DILocation(line: 0, // CHECK: !DILocation(line: [[@LINE+1]], diff --git a/test/DebugInfo/sil_combine.sil b/test/DebugInfo/sil_combine.sil index a8ede98677bf3..ee38762a5b5cc 100644 --- a/test/DebugInfo/sil_combine.sil +++ b/test/DebugInfo/sil_combine.sil @@ -1,6 +1,5 @@ // RUN: %target-sil-opt -sil-verify-all -sil-combine %s | %FileCheck %s -// RUN: %target-swift-frontend %use_no_opaque_pointers -g -O -emit-ir -primary-file %s | %FileCheck --check-prefix=CHECK-IR %s -// RUN: %target-swift-frontend -g -O -emit-ir -primary-file %s +// RUN: %target-swift-frontend -g -O -emit-ir -primary-file %s | %FileCheck --check-prefix=CHECK-IR %s sil_stage canonical @@ -18,7 +17,7 @@ bb0(%0 : $Builtin.RawPointer): %addr1 = index_addr %addr : $*UInt8, %offset1 : $Builtin.Word // CHECK: debug_value %[[ADDR]] : $*UInt8, let, name "hello" // CHECK-SAME: expr op_constu:3:op_plus:op_deref - // CHECK-IR: call void @llvm.dbg.value(metadata i8* %0, metadata ![[DBG_VAR:[0-9]+]], + // CHECK-IR: call void @llvm.dbg.value(metadata ptr %0, metadata ![[DBG_VAR:[0-9]+]], // CHECK-IR-SAME: !DIExpression(DW_OP_constu, 3, DW_OP_plus, DW_OP_deref) debug_value %addr1 : $*UInt8, let, name "hello", expr op_deref %addr2 = index_addr %addr1 : $*UInt8, %offset2 : $Builtin.Word diff --git a/test/DebugInfo/struct_resilience.swift b/test/DebugInfo/struct_resilience.swift index 96cdbddf1b3d5..d3f5a2fcc0c69 100644 --- a/test/DebugInfo/struct_resilience.swift +++ b/test/DebugInfo/struct_resilience.swift @@ -6,15 +6,13 @@ // RUN: -emit-module-path=%t/resilient_struct.swiftmodule \ // RUN: -module-name=resilient_struct %S/../Inputs/resilient_struct.swift // -// RUN: %target-swift-frontend %use_no_opaque_pointers -g -I %t -emit-ir -enable-library-evolution %s \ -// RUN: -o - | %FileCheck %s // RUN: %target-swift-frontend -g -I %t -emit-ir -enable-library-evolution %s \ -// RUN: -o - +// RUN: -o - | %FileCheck %s // import resilient_struct -// CHECK-LABEL: define{{.*}} swiftcc void @"$s17struct_resilience9takesSizeyy010resilient_A00D0VF"(%swift.opaque* noalias nocapture %0) -// CHECK-LLDB-LABEL: define{{.*}} swiftcc void @"$s17struct_resilience9takesSizeyy010resilient_A00D0VF"(%T16resilient_struct4SizeV* noalias nocapture dereferenceable({{8|16}}) %0) +// CHECK-LABEL: define{{.*}} swiftcc void @"$s17struct_resilience9takesSizeyy010resilient_A00D0VF"(ptr noalias nocapture %0) +// CHECK-LLDB-LABEL: define{{.*}} swiftcc void @"$s17struct_resilience9takesSizeyy010resilient_A00D0VF"(ptr noalias nocapture dereferenceable({{8|16}}) %0) public func takesSize(_ s: Size) {} @@ -23,12 +21,12 @@ public func takesSize(_ s: Size) {} func f() { let s1 = Size(w: 1, h: 2) takesSize(s1) - // CHECK: %[[ADDR:.*]] = alloca i8* - // CHECK: call void @llvm.dbg.declare(metadata i8** %[[ADDR]], + // CHECK: %[[ADDR:.*]] = alloca ptr + // CHECK: call void @llvm.dbg.declare(metadata ptr %[[ADDR]], // CHECK-SAME: metadata ![[V1:[0-9]+]], // CHECK-SAME: metadata !DIExpression(DW_OP_deref)) // CHECK: %[[S1:.*]] = alloca i8, - // CHECK: store i8* %[[S1]], i8** %[[ADDR]] + // CHECK: store ptr %[[S1]], ptr %[[ADDR]] } f() diff --git a/test/DebugInfo/structs.swift b/test/DebugInfo/structs.swift index 00321ff86397a..4a951f9c21df9 100644 --- a/test/DebugInfo/structs.swift +++ b/test/DebugInfo/structs.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers -primary-file %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -o - +// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -o - | %FileCheck %s // Capture the pointer size from type Int // CHECK: %TSi = type <{ i[[PTRSIZE:[0-9]+]] }> @@ -13,7 +12,7 @@ func test(_ x : A) { } // CHECK: define hidden {{.*}}void @"$s7structs4test{{[_0-9a-zA-Z]*}}F" // CHECK: [[X_DBG:%.*]] = alloca -// CHECK: call void @llvm.dbg.declare(metadata {{.*}}* [[X_DBG]], metadata [[X_MD:!.*]], metadata +// CHECK: call void @llvm.dbg.declare(metadata ptr [[X_DBG]], metadata [[X_MD:!.*]], metadata // A class is represented by a pointer, so B's total size should be PTRSIZE. // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "B",{{.*}}size: [[PTRSIZE]] diff --git a/test/DebugInfo/typearg.swift b/test/DebugInfo/typearg.swift index 4e471cb51ffbd..1d9e640049dc6 100644 --- a/test/DebugInfo/typearg.swift +++ b/test/DebugInfo/typearg.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -emit-ir -g -o - +// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s protocol AProtocol { func f() -> String @@ -9,7 +8,7 @@ class AClass : AProtocol { } // CHECK: define hidden {{.*}}void @{{.*}}aFunction -// CHECK: call void @llvm.dbg.declare(metadata %swift.type** %{{.*}}, metadata ![[TYPEARG:.*]], metadata !DIExpression()), +// CHECK: call void @llvm.dbg.declare(metadata ptr %{{.*}}, metadata ![[TYPEARG:.*]], metadata !DIExpression()), // CHECK: ![[TYPEARG]] = !DILocalVariable(name: "$\CF\84_0_0" // CHECK-SAME: type: ![[SWIFTMETATYPE:[^,)]+]] // CHECK-SAME: flags: DIFlagArtificial diff --git a/test/DebugInfo/uninitialized.swift b/test/DebugInfo/uninitialized.swift index 55e828153f7b0..3664dfbb4bcfd 100644 --- a/test/DebugInfo/uninitialized.swift +++ b/test/DebugInfo/uninitialized.swift @@ -1,17 +1,14 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -c -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -c -emit-ir -g -o - -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -O -c -emit-ir -g -o - | %FileCheck %s --check-prefix=OPT -// RUN: %target-swift-frontend %s -O -c -emit-ir -g -o - +// RUN: %target-swift-frontend %s -c -emit-ir -g -o - | %FileCheck %s +// RUN: %target-swift-frontend %s -O -c -emit-ir -g -o - | %FileCheck %s --check-prefix=OPT class MyClass {} // CHECK-LABEL: define {{.*}} @"$s13uninitialized1fyyF" // OPT-LABEL: define {{.*}} @"$s13uninitialized1fyyF" public func f() { var object: MyClass - // CHECK: %[[OBJ:.*]] = alloca %[[T1:.*]]*, align - // CHECK: call void @llvm.dbg.declare(metadata %[[T1]]** %[[OBJ]], - // CHECK: %[[BC1:.*]] = bitcast %[[T1]]** %[[OBJ]] to i8*{{$}} - // CHECK: void @llvm.memset.{{.*}}(i8* align {{(4|8)}} %[[BC1]], i8 0, + // CHECK: %[[OBJ:.*]] = alloca ptr, align + // CHECK: call void @llvm.dbg.declare(metadata ptr %[[OBJ]], + // CHECK: void @llvm.memset.{{.*}}(ptr align {{(4|8)}} %[[OBJ]], i8 0, // CHECK-SAME: ){{$}} // OPT-NOT: @llvm.memset // OPT: ret @@ -21,10 +18,9 @@ public func f() { // OPT-LABEL: define {{.*}} @"$s13uninitialized1gyyF" public func g() { var dict: Dictionary - // CHECK: %[[DICT:.*]] = alloca %[[T2:.*]], align - // CHECK: call void @llvm.dbg.declare(metadata %[[T2]]* %[[DICT]], - // CHECK: %[[BC2:.*]] = bitcast %[[T2]]* %[[DICT]] to i8* - // CHECK: void @llvm.memset.{{.*}}(i8* align {{(4|8)}} %[[BC2]], i8 0, + // CHECK: %[[DICT:.*]] = alloca + // CHECK: call void @llvm.dbg.declare(metadata ptr %[[DICT]], + // CHECK: void @llvm.memset.{{.*}}(ptr align {{(4|8)}} %[[DICT]], i8 0, // CHECK-SAME: ){{$}} // OPT-NOT: @llvm.memset // OPT: ret diff --git a/test/DebugInfo/variadic-generics-count.swift b/test/DebugInfo/variadic-generics-count.swift index 0f4cb79db204b..45cddba6b6410 100644 --- a/test/DebugInfo/variadic-generics-count.swift +++ b/test/DebugInfo/variadic-generics-count.swift @@ -1,34 +1,32 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers -emit-ir %s -g -o - \ -// RUN: -parse-as-library -module-name a -disable-availability-checking | %FileCheck %s // RUN: %target-swift-frontend -emit-ir %s -g -o - \ -// RUN: -parse-as-library -module-name a -disable-availability-checking +// RUN: -parse-as-library -module-name a -disable-availability-checking | %FileCheck %s public func f1(ts: repeat each T) { - // CHECK: define {{.*}} @"$s1a2f12tsyxxQp_tRvzlF"(%swift.opaque** {{.*}}, i{{32|64}} [[COUNT1_1:.*]], %swift.type** {{.*}}) - // CHECK-DAG: store i{{32|64}} [[COUNT1_1]], i{{32|64}}* %[[COUNT1_1_A:.*]], align + // CHECK: define {{.*}} @"$s1a2f12tsyxxQp_tRvzlF"(ptr {{.*}}, i{{32|64}} [[COUNT1_1:.*]], ptr {{.*}}) + // CHECK-DAG: store i{{32|64}} [[COUNT1_1]], ptr %[[COUNT1_1_A:.*]], align // CHECK-DAG: call void @llvm.dbg.declare({{.*}}[[COUNT1_1_A]], metadata ![[COUNT1_1_VAR:[0-9]+]], metadata !DIExpression()) // CHECK-LABEL: ret void } public func f2(us: repeat each U, vs: repeat each V) { - // CHECK: define {{.*}} @"$s1a2f22us2vsyxxQp_q_q_QptRvzRv_r0_lF"(%swift.opaque** {{.*}}, %swift.opaque** {{.*}}, i{{32|64}} [[COUNT2_1:.*]], i{{32|64}} [[COUNT2_2:.*]], %swift.type** {{.*}}, %swift.type** {{.*}}) - // CHECK-DAG: store i{{32|64}} [[COUNT2_1]], i{{32|64}}* %[[COUNT2_1_A:.*]], align - // CHECK-DAG: store i{{32|64}} [[COUNT2_2]], i{{32|64}}* %[[COUNT2_2_A:.*]], align + // CHECK: define {{.*}} @"$s1a2f22us2vsyxxQp_q_q_QptRvzRv_r0_lF"(ptr {{.*}}, ptr {{.*}}, i{{32|64}} [[COUNT2_1:.*]], i{{32|64}} [[COUNT2_2:.*]], ptr {{.*}}, ptr {{.*}}) + // CHECK-DAG: store i{{32|64}} [[COUNT2_1]], ptr %[[COUNT2_1_A:.*]], align + // CHECK-DAG: store i{{32|64}} [[COUNT2_2]], ptr %[[COUNT2_2_A:.*]], align // CHECK-DAG: call void @llvm.dbg.declare({{.*}}[[COUNT2_1_A]], metadata ![[COUNT2_1_VAR:[0-9]+]], metadata !DIExpression()) // CHECK-DAG: call void @llvm.dbg.declare({{.*}}[[COUNT2_2_A]], metadata ![[COUNT2_2_VAR:[0-9]+]], metadata !DIExpression()) // CHECK-LABEL: ret void } public func f3(ts: repeat each T, more_ts: repeat each T) { - // CHECK: define {{.*}} @"$s1a2f32ts05more_B0yxxQp_xxQptRvzlF"(%swift.opaque** {{.*}}, %swift.opaque** {{.*}}, i{{32|64}} [[COUNT3_1:.*]], %swift.type** {{.*}}) - // CHECK-DAG: store i{{32|64}} [[COUNT3_1]], i{{32|64}}* %[[COUNT3_1_A:.*]], align + // CHECK: define {{.*}} @"$s1a2f32ts05more_B0yxxQp_xxQptRvzlF"(ptr {{.*}}, ptr {{.*}}, i{{32|64}} [[COUNT3_1:.*]], ptr {{.*}}) + // CHECK-DAG: store i{{32|64}} [[COUNT3_1]], ptr %[[COUNT3_1_A:.*]], align // CHECK-DAG: call void @llvm.dbg.declare({{.*}}[[COUNT3_1_A]], metadata ![[COUNT3_1_VAR:[0-9]+]], metadata !DIExpression()) // CHECK-LABEL: ret void } public func f4(us: repeat (each U, each V)) { - // CHECK: define {{.*}} @"$s1a2f42usyx_q_txQp_tRvzRv_q_Rhzr0_lF"(%swift.opaque** {{.*}}, i{{32|64}} [[COUNT4_1:.*]], %swift.type** {{.*}}, %swift.type** {{.*}}) - // CHECK-DAG: store i{{32|64}} [[COUNT4_1]], i{{32|64}}* %[[COUNT4_1_A:.*]], align + // CHECK: define {{.*}} @"$s1a2f42usyx_q_txQp_tRvzRv_q_Rhzr0_lF"(ptr {{.*}}, i{{32|64}} [[COUNT4_1:.*]], ptr {{.*}}, ptr {{.*}}) + // CHECK-DAG: store i{{32|64}} [[COUNT4_1]], ptr %[[COUNT4_1_A:.*]], align // CHECK-DAG: call void @llvm.dbg.declare({{.*}}[[COUNT4_1_A]], metadata ![[COUNT4_1_VAR:[0-9]+]], metadata !DIExpression()) // CHECK-LABEL: ret void } @@ -37,13 +35,13 @@ public struct S { let vals: (repeat each T) public func f5() { - // CHECK: define {{.*}} @"$s1a1SV2f5yyF"(%swift.type* {{.*}}, %T1a1SV* {{.*}} %0) + // CHECK: define {{.*}} @"$s1a1SV2f5yyF"(ptr {{.*}}, ptr {{.*}} %0) } } public func f6(s: S) { - // CHECK: define {{.*}} @"$s1a2f61syAA1SVyxxQp_QPG_tRvzlF"(%T1a1SV* {{.*}}, i{{32|64}} [[COUNT6_1:.*]], %swift.type** {{.*}}) - // CHECK-DAG: store i{{32|64}} [[COUNT6_1]], i{{32|64}}* %[[COUNT6_1_A:.*]], align + // CHECK: define {{.*}} @"$s1a2f61syAA1SVyxxQp_QPG_tRvzlF"(ptr {{.*}}, i{{32|64}} [[COUNT6_1:.*]], ptr {{.*}}) + // CHECK-DAG: store i{{32|64}} [[COUNT6_1]], ptr %[[COUNT6_1_A:.*]], align // CHECK-DAG: call void @llvm.dbg.declare({{.*}}[[COUNT6_1_A]], metadata ![[COUNT6_1_VAR:[0-9]+]], metadata !DIExpression()) } diff --git a/test/DebugInfo/variadic-generics.swift b/test/DebugInfo/variadic-generics.swift index ba4b3c3325e36..041537ae70d1e 100644 --- a/test/DebugInfo/variadic-generics.swift +++ b/test/DebugInfo/variadic-generics.swift @@ -1,21 +1,20 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers -emit-ir %s -g -o - \ -// RUN: -parse-as-library -module-name a | %IRGenFileCheck %s // RUN: %target-swift-frontend -emit-ir %s -g -o - \ -// RUN: -parse-as-library -module-name a +// RUN: -parse-as-library -module-name a | %IRGenFileCheck %s public func foo(args: repeat each T) { // CHECK: define {{.*}} @"$s1a3foo4argsyxxQp_tRvzlF" - // CHECK-SAME: %swift.type** %[[TYPE_PACK_ARG:.*]]) - // CHECK: %[[TYPE_PACK_ALLOCA:.*]] = alloca %swift.type** - // CHECK: call void @llvm.dbg.declare(metadata %swift.type*** %[[TYPE_PACK_ALLOCA]], metadata ![[TYPE_PACK_VAR:[0-9]+]], metadata !DIExpression()) - // CHECK: %[[ARGS_ALLOCA:.*]] = alloca %swift.opaque** - // CHECK-DAG: call void @llvm.dbg.declare(metadata %swift.opaque*** %[[ARGS_ALLOCA]], metadata ![[ARGS_VAR:[0-9]+]], metadata !DIExpression(DW_OP_deref)) - // CHECK-DAG: %[[TYPE_PACK_ARG_INT:[^,]+]] = ptrtoint %swift.type** %[[TYPE_PACK_ARG]] to [[INT]] + // CHECK-SAME: ptr {{.*}} %[[ARG_0:.*]], i64 %{{.*}}, + // CHECK-SAME: ptr %[[TYPE_PACK_ARG:.*]]) + // CHECK: %[[TYPE_PACK_ALLOCA:.*]] = alloca ptr + // CHECK: call void @llvm.dbg.declare(metadata ptr %[[TYPE_PACK_ALLOCA]], metadata ![[TYPE_PACK_VAR:[0-9]+]], metadata !DIExpression()) + // CHECK: %[[ARGS_ALLOCA:.*]] = alloca ptr + // CHECK-DAG: call void @llvm.dbg.declare(metadata ptr %[[ARGS_ALLOCA]], metadata ![[ARGS_VAR:[0-9]+]], metadata !DIExpression(DW_OP_deref)) + // CHECK-DAG: %[[TYPE_PACK_ARG_INT:[^,]+]] = ptrtoint ptr %[[TYPE_PACK_ARG]] to [[INT]] // CHECK-DAG: %[[TYPE_PACK_ARG_MASKED_INT:[^,]+]] = and [[INT]] %[[TYPE_PACK_ARG_INT]], -2 - // CHECK-DAG: %[[TYPE_PACK_ARG_MASKED:[^,]+]] = inttoptr [[INT]] %[[TYPE_PACK_ARG_MASKED_INT]] to %swift.type** - // CHECK-DAG: store %swift.type** %[[TYPE_PACK_ARG_MASKED]], %swift.type*** %[[TYPE_PACK_ALLOCA]] - // CHECK-DAG: store %swift.opaque** %0, %swift.opaque*** %[[ARGS_ALLOCA]] - // CHECK-DAG: ![[ARGS_VAR]] = !DILocalVariable(name: "args", arg: 1, {{.*}}line: [[@LINE-12]], type: ![[ARGS_LET_TY:[0-9]+]]) + // CHECK-DAG: %[[TYPE_PACK_ARG_MASKED:[^,]+]] = inttoptr [[INT]] %[[TYPE_PACK_ARG_MASKED_INT]] to ptr + // CHECK-DAG: store ptr %[[TYPE_PACK_ARG_MASKED]], ptr %[[TYPE_PACK_ALLOCA]] + // CHECK-DAG: store ptr %[[ARG_0]], ptr %[[ARGS_ALLOCA]] + // CHECK-DAG: ![[ARGS_VAR]] = !DILocalVariable(name: "args", arg: 1, {{.*}}line: [[@LINE-13]], type: ![[ARGS_LET_TY:[0-9]+]]) // CHECK-DAG: ![[ARGS_LET_TY]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[ARGS_TY:[0-9]+]]) // CHECK-DAG: ![[ARGS_TY]] = !DICompositeType({{.*}}identifier: "$sxxQp_QSiD") // CHECK-DAG: ![[TYPE_PACK_VAR]] = !DILocalVariable(name: "$\CF\84_0_0", {{.*}}type: ![[TYPE_PACK_TYD:[0-9]+]], flags: DIFlagArtificial) diff --git a/test/DebugInfo/weak-self-capture.swift b/test/DebugInfo/weak-self-capture.swift index 6c5235eb5b875..676a1482e3a6f 100644 --- a/test/DebugInfo/weak-self-capture.swift +++ b/test/DebugInfo/weak-self-capture.swift @@ -1,5 +1,4 @@ -// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -g -o - | %FileCheck %s -// RUN: %target-swift-frontend %s -emit-ir -g -o - +// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s public class ClosureMaker { var a : Int @@ -17,4 +16,4 @@ public class ClosureMaker { } // CHECK: define {{.*}} @"$s4main12ClosureMakerC03getB0SiycyFSiycfU_" -// CHECK: call void @llvm.dbg.declare(metadata %swift.weak** %{{.*}} !DIExpression(DW_OP_deref)), +// CHECK: call void @llvm.dbg.declare(metadata ptr %{{.*}} !DIExpression(DW_OP_deref)), diff --git a/test/Distributed/distributed_imcomplete_system_dont_crash.swift b/test/Distributed/distributed_imcomplete_system_dont_crash.swift index a2cc7d2ca3772..e4f5d3e7f9dce 100644 --- a/test/Distributed/distributed_imcomplete_system_dont_crash.swift +++ b/test/Distributed/distributed_imcomplete_system_dont_crash.swift @@ -36,4 +36,12 @@ public final class CompletelyHollowActorSystem: DistributedActorSystem { // expected-error@-1{{type 'CompletelyHollowActorSystem.ResultHandler' does not conform to protocol 'DistributedTargetInvocationResultHandler'}} } +} + +public final class CompletelyHollowActorSystem_NotEvenTypes: DistributedActorSystem { + // expected-error@-1{{type 'CompletelyHollowActorSystem_NotEvenTypes' does not conform to protocol 'DistributedActorSystem'}} + // expected-error@-2{{class 'CompletelyHollowActorSystem_NotEvenTypes' is missing witness for protocol requirement 'remoteCallVoid'}} + // expected-error@-3{{class 'CompletelyHollowActorSystem_NotEvenTypes' is missing witness for protocol requirement 'remoteCall'}} + // expected-note@-4{{protocol 'DistributedActorSystem' requires function 'remoteCall' with signature:}} + // expected-note@-5{{protocol 'DistributedActorSystem' requires function 'remoteCallVoid' with signature:}} } \ No newline at end of file diff --git a/test/Driver/compiler_plugin_path_macosx.swift b/test/Driver/compiler_plugin_path_macosx.swift new file mode 100644 index 0000000000000..556dcf21579a6 --- /dev/null +++ b/test/Driver/compiler_plugin_path_macosx.swift @@ -0,0 +1,24 @@ +// RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.9 %s 2>^1 | %FileCheck %s +// REQUIRES: OS=macosx + +// CHECK: -external-plugin-path +// CHECK-SAME: .sdk/usr/lib/swift/host/plugins# +// CHECK-SAME: .sdk/usr/bin/swift-plugin-server + +// CHECK-SAME: -external-plugin-path +// CHECK-SAME: .sdk/usr/local/lib/swift/host/plugins# +// CHECK-SAME: .sdk/usr/bin/swift-plugin-server + +// CHECK-SAME: -external-plugin-path +// CHECK-SAME: MacOSX.platform/Developer/usr/lib/swift/host/plugins# +// CHECK-SAME: MacOSX.platform/Developer/usr/bin/swift-plugin-server + +// CHECK-SAME: -external-plugin-path +// CHECK-SAME: MacOSX.platform/Developer/usr/local/lib/swift/host/plugins# +// CHECK-SAME: MacOSX.platform/Developer/usr/bin/swift-plugin-server + +// CHECK-SAME: -plugin-path +// CHECK-SAME: {{(/|\\\\)}}lib{{(/|\\\\)}}swift{{(/|\\\\)}}host{{(/|\\\\)}}plugins + +// CHECK-SAME: -plugin-path +// CHECK-SAME: {{(/|\\\\)}}local{{(/|\\\\)}}lib{{(/|\\\\)}}swift{{(/|\\\\)}}host{{(/|\\\\)}}plugins diff --git a/test/Driver/driver-compile.swift b/test/Driver/driver-compile.swift index 920bd127e199c..5910b4f1b794e 100644 --- a/test/Driver/driver-compile.swift +++ b/test/Driver/driver-compile.swift @@ -75,7 +75,7 @@ // COMPLEX: bin{{/|\\\\}}swift // COMPLEX: -c // COMPLEX: Driver{{/|\\\\}}driver-compile.swift -// COMPLEX-DAG: -sdk {{.*}}/Inputs/clang-importer-sdk +// COMPLEX-DAG: -sdk // COMPLEX-DAG: -foo -bar // COMPLEX-DAG: -Xllvm -baz // COMPLEX-DAG: -Xcc -garply diff --git a/test/Driver/merge-module.swift b/test/Driver/merge-module.swift index b8cf77ba0ee13..9a2e934661bcc 100644 --- a/test/Driver/merge-module.swift +++ b/test/Driver/merge-module.swift @@ -36,15 +36,16 @@ // SIMPLE: -o main.swiftmodule -// COMPLEX: {{bin(/|\\\\)swift(-frontend|c)?(\.exe)?"?}} -frontend +// COMPLEX: -frontend // COMPLEX: -emit-module // COMPLEX-DAG: -emit-module-doc-path {{[^ ]*[/\\]}}merge-module-{{[^ ]*}}.swiftdoc -// COMPLEX-DAG: -sdk {{.*}}/Inputs/clang-importer-sdk +// COMPLEX-DAG: -sdk +// COMPLEX-DAG /Inputs/clang-importer-sdk // COMPLEX-DAG: -foo -bar // COMPLEX-DAG: -F /path/to/frameworks -F /path/to/more/frameworks // COMPLEX-DAG: -I /path/to/headers -I path/to/more/headers // COMPLEX-DAG: -module-cache-path /tmp/modules -// COMPLEX: {{bin(/|\\\\)swift(-frontend|c)?(\.exe)?"?}} -frontend +// COMPLEX-DAG: -frontend // COMPLEX: -emit-module // COMPLEX-DAG: -F /path/to/frameworks -F /path/to/more/frameworks // COMPLEX-DAG: -I /path/to/headers -I path/to/more/headers diff --git a/test/Driver/sdk.swift b/test/Driver/sdk.swift index 8aba6e15f51f3..6ec138bd8fbc1 100644 --- a/test/Driver/sdk.swift +++ b/test/Driver/sdk.swift @@ -12,7 +12,7 @@ // OSX: bin{{/|\\\\}}swift // OSX: Driver{{/|\\\\}}sdk.swift // OSX: -sdk {{.*}}/Inputs/clang-importer-sdk -// OSX-NEXT: bin{{/|\\\\}}swift +// OSX: bin{{/|\\\\}}swift // OSX: -sdk {{.*}}/Inputs/clang-importer-sdk // OSX: {{.*}}.o{{[ "]}} // OSX: {{-syslibroot|--sysroot}} {{[^ ]*}}/Inputs/clang-importer-sdk diff --git a/test/IRGen/protocol_metadata.swift b/test/IRGen/protocol_metadata.swift index 8149c2ec19723..6c06734bc65a8 100644 --- a/test/IRGen/protocol_metadata.swift +++ b/test/IRGen/protocol_metadata.swift @@ -1,7 +1,7 @@ // RUN: %target-swift-frontend %use_no_opaque_pointers -primary-file %s -emit-ir -disable-objc-attr-requires-foundation-module -enable-objc-interop | %FileCheck %s -DINT=i%target-ptrsize // RUN: %target-swift-frontend -primary-file %s -emit-ir -disable-objc-attr-requires-foundation-module -enable-objc-interop -// REQUIRES: CPU=x86_64 +// REQUIRES: PTRSIZE=64 protocol A { func a() } protocol B { func b() } diff --git a/test/IRGen/ptrauth-blocks.sil b/test/IRGen/ptrauth-blocks.sil index a95d3f372db15..85ac4231e05b0 100644 --- a/test/IRGen/ptrauth-blocks.sil +++ b/test/IRGen/ptrauth-blocks.sil @@ -1,4 +1,5 @@ -// RUN: %swift -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls | %FileCheck %s --check-prefix=CHECK +// RUN: %swift %use_no_opaque_pointers -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls | %FileCheck %s --check-prefix=CHECK +// RUN: %swift -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls // REQUIRES: CPU=arm64e // REQUIRES: OS=ios diff --git a/test/IRGen/ptrauth-class-methods.sil b/test/IRGen/ptrauth-class-methods.sil index 697e535a5050f..da61de7fb4037 100644 --- a/test/IRGen/ptrauth-class-methods.sil +++ b/test/IRGen/ptrauth-class-methods.sil @@ -1,4 +1,5 @@ -// RUN: %swift -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls | %FileCheck %s --check-prefix=CHECK +// RUN: %swift %use_no_opaque_pointers -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls | %FileCheck %s --check-prefix=CHECK +// RUN: %swift -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls // REQUIRES: CPU=arm64e // REQUIRES: OS=ios diff --git a/test/IRGen/ptrauth-classes.sil b/test/IRGen/ptrauth-classes.sil index d4ce0bbeb2876..92ab0086b1135 100644 --- a/test/IRGen/ptrauth-classes.sil +++ b/test/IRGen/ptrauth-classes.sil @@ -1,4 +1,5 @@ -// RUN: %swift -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls | %FileCheck %s --check-prefix=CHECK +// RUN: %swift %use_no_opaque_pointers -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls | %FileCheck %s --check-prefix=CHECK +// RUN: %swift -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls // REQUIRES: CPU=arm64e // REQUIRES: OS=ios diff --git a/test/IRGen/ptrauth-dynamic_replaceable.sil b/test/IRGen/ptrauth-dynamic_replaceable.sil index 7e21c444eb6ff..02c8d88dc9c11 100644 --- a/test/IRGen/ptrauth-dynamic_replaceable.sil +++ b/test/IRGen/ptrauth-dynamic_replaceable.sil @@ -1,4 +1,5 @@ -// RUN: %target-swift-frontend %s -emit-ir -disable-objc-interop -module-name A | %FileCheck %s +// RUN: %target-swift-frontend %use_no_opaque_pointers %s -emit-ir -disable-objc-interop -module-name A | %FileCheck %s +// RUN: %target-swift-frontend %s -emit-ir -disable-objc-interop -module-name A // REQUIRES: objc_interop // REQUIRES: CPU=arm64e diff --git a/test/IRGen/ptrauth-dynamic_replaceable_opaque_return.swift b/test/IRGen/ptrauth-dynamic_replaceable_opaque_return.swift index 1e32842cac907..9064959d589fc 100644 --- a/test/IRGen/ptrauth-dynamic_replaceable_opaque_return.swift +++ b/test/IRGen/ptrauth-dynamic_replaceable_opaque_return.swift @@ -1,4 +1,5 @@ -// RUN: %target-swift-frontend -disable-availability-checking -module-name A -swift-version 5 -primary-file %s -emit-ir | %FileCheck %s +// RUN: %target-swift-frontend %use_no_opaque_pointers -disable-availability-checking -module-name A -swift-version 5 -primary-file %s -emit-ir | %FileCheck %s +// RUN: %target-swift-frontend -disable-availability-checking -module-name A -swift-version 5 -primary-file %s -emit-ir // REQUIRES: CPU=arm64e diff --git a/test/IRGen/ptrauth-functions.sil b/test/IRGen/ptrauth-functions.sil index 80f9e43227584..91ea06859dace 100644 --- a/test/IRGen/ptrauth-functions.sil +++ b/test/IRGen/ptrauth-functions.sil @@ -1,4 +1,5 @@ -// RUN: %swift -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls | %FileCheck %s --check-prefix=CHECK +// RUN: %swift %use_no_opaque_pointers -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls | %FileCheck %s --check-prefix=CHECK +// RUN: %swift -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls // REQUIRES: CPU=arm64e // REQUIRES: OS=ios diff --git a/test/IRGen/ptrauth-global.swift b/test/IRGen/ptrauth-global.swift index ad4f7a415a810..55319713e27ef 100644 --- a/test/IRGen/ptrauth-global.swift +++ b/test/IRGen/ptrauth-global.swift @@ -1,5 +1,7 @@ -// RUN: %swift-frontend -swift-version 4 -target arm64e-apple-ios12.0 -primary-file %s -emit-ir -module-name A | %FileCheck %s --check-prefix=CHECK -// RUN: %swift-frontend -swift-version 4 -target arm64e-apple-ios12.0 %s -primary-file %S/Inputs/ptrauth-global-2.swift -emit-ir -module-name A | %FileCheck %s --check-prefix=CHECK2 +// RUN: %swift-frontend %use_no_opaque_pointers -swift-version 4 -target arm64e-apple-ios12.0 -primary-file %s -emit-ir -module-name A | %FileCheck %s --check-prefix=CHECK +// RUN: %swift-frontend %use_no_opaque_pointers -swift-version 4 -target arm64e-apple-ios12.0 %s -primary-file %S/Inputs/ptrauth-global-2.swift -emit-ir -module-name A | %FileCheck %s --check-prefix=CHECK2 +// RUN: %swift-frontend -swift-version 4 -target arm64e-apple-ios12.0 -primary-file %s -emit-ir -module-name A +// RUN: %swift-frontend -swift-version 4 -target arm64e-apple-ios12.0 %s -primary-file %S/Inputs/ptrauth-global-2.swift -emit-ir -module-name A // REQUIRES: CPU=arm64e // REQUIRES: OS=ios diff --git a/test/IRGen/ptrauth-objc-partial-apply.sil b/test/IRGen/ptrauth-objc-partial-apply.sil index da742d2ffb859..4c96ef548b0e8 100644 --- a/test/IRGen/ptrauth-objc-partial-apply.sil +++ b/test/IRGen/ptrauth-objc-partial-apply.sil @@ -1,4 +1,5 @@ -// RUN: %swift -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls | %FileCheck %s --check-prefix=CHECK +// RUN: %swift %use_no_opaque_pointers -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls | %FileCheck %s --check-prefix=CHECK +// RUN: %swift -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls // REQUIRES: objc_interop // REQUIRES: CPU=arm64e diff --git a/test/IRGen/ptrauth-objc.swift b/test/IRGen/ptrauth-objc.swift index 8393be7bd9fb5..573a73fa4b2e7 100644 --- a/test/IRGen/ptrauth-objc.swift +++ b/test/IRGen/ptrauth-objc.swift @@ -1,4 +1,5 @@ -// RUN: %swift -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls | %FileCheck %s --check-prefix=CHECK +// RUN: %swift %use_no_opaque_pointers -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls | %FileCheck %s --check-prefix=CHECK +// RUN: %swift -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls // REQUIRES: CPU=arm64e // REQUIRES: OS=ios diff --git a/test/IRGen/ptrauth-partial-apply.sil b/test/IRGen/ptrauth-partial-apply.sil index 3f1db37f783e6..cc4ccba7dc76f 100644 --- a/test/IRGen/ptrauth-partial-apply.sil +++ b/test/IRGen/ptrauth-partial-apply.sil @@ -1,4 +1,5 @@ -// RUN: %swift -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls | %FileCheck %s --check-prefix=CHECK +// RUN: %swift %use_no_opaque_pointers -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls | %FileCheck %s --check-prefix=CHECK +// RUN: %swift -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls // REQUIRES: CPU=arm64e // REQUIRES: OS=ios diff --git a/test/IRGen/ptrauth-protocols.sil b/test/IRGen/ptrauth-protocols.sil index c697dc99f5827..088cd54a98a56 100644 --- a/test/IRGen/ptrauth-protocols.sil +++ b/test/IRGen/ptrauth-protocols.sil @@ -1,4 +1,5 @@ -// RUN: %swift -swift-version 5 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls | %FileCheck %s --check-prefix=CHECK +// RUN: %swift %use_no_opaque_pointers -swift-version 5 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls | %FileCheck %s --check-prefix=CHECK +// RUN: %swift -swift-version 5 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls // REQUIRES: CPU=arm64e // REQUIRES: OS=ios diff --git a/test/IRGen/ptrauth-runtime.sil b/test/IRGen/ptrauth-runtime.sil index cb8faa64e5fc4..15be05ee8f683 100644 --- a/test/IRGen/ptrauth-runtime.sil +++ b/test/IRGen/ptrauth-runtime.sil @@ -1,4 +1,5 @@ -// RUN: %swift -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test | %FileCheck %s --check-prefix=CHECK +// RUN: %swift %use_no_opaque_pointers -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test | %FileCheck %s --check-prefix=CHECK +// RUN: %swift -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test // REQUIRES: CPU=arm64e // REQUIRES: OS=ios diff --git a/test/IRGen/ptrauth-value-witnesses.sil b/test/IRGen/ptrauth-value-witnesses.sil index 3ad86a8793815..85f7940751274 100644 --- a/test/IRGen/ptrauth-value-witnesses.sil +++ b/test/IRGen/ptrauth-value-witnesses.sil @@ -1,4 +1,5 @@ -// RUN: %swift -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls | %FileCheck %s --check-prefix=CHECK +// RUN: %swift %use_no_opaque_pointers -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls | %FileCheck %s --check-prefix=CHECK +// RUN: %swift %use_no_opaque_pointers -swift-version 4 -target arm64e-apple-ios12.0 -parse-stdlib -parse-as-library %s -emit-ir -module-name test -Xcc -Xclang -Xcc -fptrauth-calls // REQUIRES: CPU=arm64e // REQUIRES: OS=ios diff --git a/test/IRGen/ptrauth_field_fptr_import.swift b/test/IRGen/ptrauth_field_fptr_import.swift index d435ce53292e6..2f8d9fdcff5ae 100644 --- a/test/IRGen/ptrauth_field_fptr_import.swift +++ b/test/IRGen/ptrauth_field_fptr_import.swift @@ -1,4 +1,5 @@ -// RUN: %swift-frontend %s -enable-import-ptrauth-field-function-pointers -emit-ir -target arm64e-apple-ios13.0 -I %S/Inputs/ -validate-tbd-against-ir=none -Xllvm -sil-disable-pass=OnoneSimplification | %FileCheck %s +// RUN: %swift-frontend %use_no_opaque_pointers %s -enable-import-ptrauth-field-function-pointers -emit-ir -target arm64e-apple-ios13.0 -I %S/Inputs/ -validate-tbd-against-ir=none -Xllvm -sil-disable-pass=OnoneSimplification | %FileCheck %s +// RUN: %swift-frontend %s -enable-import-ptrauth-field-function-pointers -emit-ir -target arm64e-apple-ios13.0 -I %S/Inputs/ -validate-tbd-against-ir=none -Xllvm -sil-disable-pass=OnoneSimplification // REQUIRES: CPU=arm64e // REQUIRES: OS=ios diff --git a/test/Interop/Cxx/class/clang-trivial-abi.swift b/test/Interop/Cxx/class/clang-trivial-abi.swift new file mode 100644 index 0000000000000..f9415365b4a41 --- /dev/null +++ b/test/Interop/Cxx/class/clang-trivial-abi.swift @@ -0,0 +1,33 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t + +// RUN: %target-swift-ide-test -print-module -module-to-print=Test -I %t/Inputs -source-filename=x -enable-experimental-cxx-interop | %FileCheck %s +// RUN: %target-swift-frontend -typecheck -I %t/Inputs %t/test.swift -enable-experimental-cxx-interop -verify + +//--- Inputs/module.modulemap +module Test { + header "test.h" + requires cplusplus +} + +//--- Inputs/test.h + +class TrivialABIRecord { + int x = 0; +public: + TrivialABIRecord() {} + ~TrivialABIRecord() { + } +} +__attribute__((trivial_abi)); + +// CHECK: @available(*, unavailable, message: "C++ classes with `trivial_abi` Clang attribute are not yet available in Swift") +// CHECK-NEXT: struct TrivialABIRecord { + +//--- test.swift + +import Test + +func test() { + let _ = TrivialABIRecord() // expected-error{{'TrivialABIRecord' is unavailable: C++ classes with `trivial_abi` Clang attribute are not yet available in Swift}} +} diff --git a/test/Interop/Cxx/objc-correctness/Inputs/cxx-class-with-arc-fields-ctor.h b/test/Interop/Cxx/objc-correctness/Inputs/cxx-class-with-arc-fields-ctor.h index bb702daa8910c..706de84cdb7d5 100644 --- a/test/Interop/Cxx/objc-correctness/Inputs/cxx-class-with-arc-fields-ctor.h +++ b/test/Interop/Cxx/objc-correctness/Inputs/cxx-class-with-arc-fields-ctor.h @@ -5,6 +5,10 @@ struct S { NSString *_Nullable B; NSString *_Nullable C; +#ifdef S_NONTRIVIAL_DESTRUCTOR + ~S() {} +#endif + void dump() const { printf("%s\n", [A UTF8String]); printf("%s\n", [B UTF8String]); @@ -12,3 +16,30 @@ struct S { } }; +inline void takeSFunc(S s) { + s.dump(); +} + +struct NonTrivialLogDestructor { + int x = 0; + + ~NonTrivialLogDestructor() { + printf("~NonTrivialLogDestructor %d\n", x); + } +}; + +@interface ClassWithNonTrivialDestructorIvar: NSObject + +- (ClassWithNonTrivialDestructorIvar * _Nonnull)init; + +- (void)takesS:(S)s; + +@end + +struct ReferenceStructToClassWithNonTrivialLogDestructorIvar { + ClassWithNonTrivialDestructorIvar *_Nonnull x; + +#ifdef S_NONTRIVIAL_DESTRUCTOR + ~ReferenceStructToClassWithNonTrivialLogDestructorIvar() {} +#endif +}; diff --git a/test/Interop/Cxx/objc-correctness/Inputs/objc-class-with-non-trivial-cxx-record.mm b/test/Interop/Cxx/objc-correctness/Inputs/objc-class-with-non-trivial-cxx-record.mm new file mode 100644 index 0000000000000..c274eeba63c8b --- /dev/null +++ b/test/Interop/Cxx/objc-correctness/Inputs/objc-class-with-non-trivial-cxx-record.mm @@ -0,0 +1,18 @@ +#import +#import "cxx-class-with-arc-fields-ctor.h" + +@implementation ClassWithNonTrivialDestructorIvar { + NonTrivialLogDestructor value; +}; + +- (ClassWithNonTrivialDestructorIvar *)init { + self->value.x = 21; + return self; +} + +- (void)takesS:(S)s { + printf("takesS!\n"); + s.dump(); +} + +@end diff --git a/test/Interop/Cxx/objc-correctness/call-to-generated-init-with-nsstring.swift b/test/Interop/Cxx/objc-correctness/call-to-generated-init-with-nsstring.swift index eb4abc01ed32e..3d39ec2d35b0f 100644 --- a/test/Interop/Cxx/objc-correctness/call-to-generated-init-with-nsstring.swift +++ b/test/Interop/Cxx/objc-correctness/call-to-generated-init-with-nsstring.swift @@ -1,6 +1,8 @@ // RUN: %target-swift-ide-test -print-module -module-to-print=CxxClassWithNSStringInit -I %S/Inputs -source-filename=x -enable-experimental-cxx-interop -enable-objc-interop | %FileCheck -check-prefix=CHECK-IDE-TEST %s -// RUN: %target-swift-frontend -I %S/Inputs -enable-experimental-cxx-interop -emit-ir %s -Xcc -fignore-exceptions | %FileCheck %s - +// RUN: %target-swift-frontend -I %S/Inputs -enable-experimental-cxx-interop -emit-sil %s -Xcc -fignore-exceptions | %FileCheck --check-prefix=SIL-TRIVIAL %s +// RUN: %target-swift-frontend -I %S/Inputs -enable-experimental-cxx-interop -emit-sil %s -Xcc -fignore-exceptions -Xcc -DS_NONTRIVIAL_DESTRUCTOR | %FileCheck --check-prefix=SIL-NONTRIVIAL %s +// RUN: %target-swift-frontend -I %S/Inputs -enable-experimental-cxx-interop -emit-ir %s -Xcc -fignore-exceptions | %FileCheck --check-prefix=IR-TRIVIAL %s +// RUN: %target-swift-frontend -I %S/Inputs -enable-experimental-cxx-interop -emit-ir %s -Xcc -fignore-exceptions -Xcc -DS_NONTRIVIAL_DESTRUCTOR | %FileCheck --check-prefix=IR-NONTRIVIAL %s // REQUIRES: objc_interop @@ -15,11 +17,45 @@ import CxxClassWithNSStringInit // CHECK-IDE-TEST: var C: NSString? // CHECK-IDE-TEST: } -var foo: NSString? = "foo" -var bar: NSString? = "bar" -var baz: NSString? = "baz" -var s = S(A: foo, B: bar, C: baz) -s.dump() +func testSdump() { + var foo: NSString? = "foo" + var bar: NSString? = "bar" + var baz: NSString? = "baz" + var s = S(A: foo, B: bar, C: baz) + s.dump() + ClassWithNonTrivialDestructorIvar().takesS(s) + takeSFunc(s) +} + +testSdump() + +// SIL-TRIVIAL: function_ref @_ZNK1S4dumpEv : $@convention(cxx_method) (@in_guaranteed S) -> () +// SIL-TRIVIAL-NEXT: apply %{{.*}}(%{{.*}}) : $@convention(cxx_method) (@in_guaranteed S) -> () +// SIL-TRIVIAL: $@convention(objc_method) (@owned S, ClassWithNonTrivialDestructorIvar) -> () +// SIL-TRIVIAL-NEXT: apply %{{.*}}(%{{.*}}) : $@convention(objc_method) (@owned S, ClassWithNonTrivialDestructorIvar) -> () +// SIL-TRIVIAL: function_ref @_Z9takeSFunc : $@convention(c) (@owned S) -> () +// SIL-TRIVIAL-NEXT: apply %{{.*}}(%{{.*}}) : $@convention(c) (@owned S) -> () + +// SIL-NONTRIVIAL: function_ref @_ZNK1S4dumpEv : $@convention(cxx_method) (@in_guaranteed S) -> () +// SIL-NONTRIVIAL-NEXT: apply %{{.*}}(%{{.*}}) : $@convention(cxx_method) (@in_guaranteed S) -> () +// SIL-NONTRIVIAL: $@convention(objc_method) (@in S, ClassWithNonTrivialDestructorIvar) -> () +// SIL-NONTRIVIAL-NEXT: apply %{{.*}}(%{{.*}}) : $@convention(objc_method) (@in S, ClassWithNonTrivialDestructorIvar) -> () +// SIL-NONTRIVIAL: function_ref @_Z9takeSFunc : $@convention(c) (@in S) -> () +// SIL-NONTRIVIAL-NEXT: apply %{{.*}}(%{{.*}}) : $@convention(c) (@in S) -> () + + +// IR-TRIVIAL-LABEL: define {{.*}} swiftcc void @"$s4main9testSdumpyyF"() +// IR-TRIVIAL-NOT: @_ZN1SC1ERKS_ +// IR-TRIVIAL: call {{.*}} @_ZNK1S4dumpEv +// IR-TRIVIAL: call {{.*}} @"$sSo1SVWOh" + +// IR-TRIVIAL-LABEL: define linkonce_odr {{.*}} @"$sSo1SVWOh"( +// IR-TRIVIAL: @llvm.objc.release +// IR-TRIVIAL: @llvm.objc.release +// IR-TRIVIAL: @llvm.objc.release +// IR-TRIVIAL: } -// CHECK: call {{.*}} @_ZN1SC1ERKS_ -// CHECK: call {{.*}} @_ZNK1S4dumpEv +// IR-NONTRIVIAL-LABEL: define {{.*}} swiftcc void @"$s4main9testSdumpyyF"() +// IR-NONTRIVIAL: call {{.*}} @_ZN1SC1ERKS_ +// IR-NONTRIVIAL: call {{.*}} @_ZNK1S4dumpEv +// IR-NONTRIVIAL: call {{.*}} @_ZN1SD1Ev diff --git a/test/Interop/Cxx/objc-correctness/objcxx-arc-field-in-struct-type-layout-execution.swift b/test/Interop/Cxx/objc-correctness/objcxx-arc-field-in-struct-type-layout-execution.swift new file mode 100644 index 0000000000000..572fe16bad4d8 --- /dev/null +++ b/test/Interop/Cxx/objc-correctness/objcxx-arc-field-in-struct-type-layout-execution.swift @@ -0,0 +1,64 @@ +// RUN: %empty-directory(%t2) + +// RUN: %target-interop-build-clangxx -c %S/Inputs/objc-class-with-non-trivial-cxx-record.mm -o %t2/objc-class-impl.o -fobjc-arc + +// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-experimental-cxx-interop -Xcc -fignore-exceptions -Xlinker %t2/objc-class-impl.o) | %FileCheck %s +// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-experimental-cxx-interop -Xcc -fignore-exceptions -O -Xlinker %t2/objc-class-impl.o) | %FileCheck %s + +// RUN: %target-interop-build-clangxx -c %S/Inputs/objc-class-with-non-trivial-cxx-record.mm -o %t2/objc-class-impl-non-trivial.o -fobjc-arc -DS_NONTRIVIAL_DESTRUCTOR +// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-experimental-cxx-interop -Xcc -fignore-exceptions -Xcc -DS_NONTRIVIAL_DESTRUCTOR -Xlinker %t2/objc-class-impl-non-trivial.o) | %FileCheck %s +// +// REQUIRES: executable_test +// REQUIRES: objc_interop + +import Foundation +import CxxClassWithNSStringInit + +func testS() { + let copy: S + do { + let foo: NSString? = "super long string actually allocated" + let bar: NSString? = "bar" + let baz: NSString? = "baz" + var s = S(A: foo, B: bar, C: baz) + s.dump() + copy = s + } + print("after scope") + copy.dump() + print("takeSFunc") + takeSFunc(copy) +} + +@inline(never) +func blackHole(_ x: T) { + +} + +func testReferenceStructToClassWithNonTrivialLogDestructorIvar() { + print("testReferenceStructToClassWithNonTrivialLogDestructorIvar") + let m = ReferenceStructToClassWithNonTrivialLogDestructorIvar(x: ClassWithNonTrivialDestructorIvar()) + m.x.takesS(S(A: "hello world two", B: "bar", C: "baz")) + blackHole(m) +} + +testS() +testReferenceStructToClassWithNonTrivialLogDestructorIvar() + +// CHECK: super long string actually allocated +// CHECK-NEXT: bar +// CHECK-NEXT: baz +// CHECK-NEXT: after scope +// CHECK-NEXT: super long string actually allocated +// CHECK-NEXT: bar +// CHECK-NEXT: baz +// CHECK-NEXT: takeSFunc +// CHECK-NEXT: super long string actually allocated +// CHECK-NEXT: bar +// CHECK-NEXT: baz +// CHECK-NEXT: testReferenceStructToClassWithNonTrivialLogDestructorIvar +// CHECK-NEXT: takesS! +// CHECK-NEXT: hello world two +// CHECK-NEXT: bar +// CHECK-NEXT: baz +// CHECK-NEXT: ~NonTrivialLogDestructor 21 diff --git a/test/Interpreter/Inputs/layout_string_witnesses_types.swift b/test/Interpreter/Inputs/layout_string_witnesses_types.swift index 1eb45df5b93d2..0be7f7c54ca90 100644 --- a/test/Interpreter/Inputs/layout_string_witnesses_types.swift +++ b/test/Interpreter/Inputs/layout_string_witnesses_types.swift @@ -454,7 +454,7 @@ public enum SinglePayloadEnumManyXI { case empty4 case empty5 case empty6 - case nonEmpty(Builtin.Int127, SimpleClass) + case nonEmpty(Builtin.Int63, SimpleClass) } public struct PrespecializedStruct { diff --git a/test/Interpreter/init_accessors.swift b/test/Interpreter/init_accessors.swift index df8be55a75d2f..ff8ba32daa435 100644 --- a/test/Interpreter/init_accessors.swift +++ b/test/Interpreter/init_accessors.swift @@ -393,3 +393,72 @@ test_memberwise_ordering() // CHECK: test-memberwise-ordering-1: Test1(_a: 0, _b: 42) // CHECK-NEXT: test-memberwise-ordering-2: Test2(_a: -1, _b: -2) // CHECK-NEXT: test-memberwise-ordering-3: Test3(_a: 1, _b: 2, _c: 3) + +func test_memberwise_with_default_args() { + struct TestWithoutDefault { + var _a: Int + var _b: Int + + var pair: (Int, Int) = (-1, 42) { + init(initialValue) initializes(_a, _b) { + _a = initialValue.0 + _b = initialValue.1 + } + + get { (0, 42) } + set { } + } + } + + let test1 = TestWithoutDefault() + print("test-memberwise_with_default-1: \(test1)") + + let test2 = TestWithoutDefault(pair: (42, -1)) + print("test-memberwise_with_default-2: \(test2)") + + struct TestDefaulted { + var _a: Int = 0 + var _b: Int = 0 + + var pair: (Int, Int) = (1, 2) { + init(initialValue) initializes(_a, _b) { + _a = initialValue.0 + _b = initialValue.1 + } + + get { (_a, _b) } + set { } + } + } + + let test3 = TestDefaulted() + print("test-defaulted-1: \(test3)") + + let test4 = TestDefaulted(pair: (3, 4)) + print("test-defaulted-2: \(test4)") + + class TestClass { + var _q: String = "<>" + var _a: Int = 1 + + var pair: (String, Int) = ("", 42) { + init(initialValue) initializes(_q, _a) { + _q = initialValue.0 + _a = initialValue.1 + } + + get { (_q, _a) } + set { } + } + } + + let test5 = TestClass() + print("test-defaulted-class: \(test5.pair)") +} + +test_memberwise_with_default_args() +// CHECK: test-memberwise_with_default-1: TestWithoutDefault(_a: -1, _b: 42) +// CHECK-NEXT: test-memberwise_with_default-2: TestWithoutDefault(_a: 42, _b: -1) +// CHECK-NEXT: test-defaulted-1: TestDefaulted(_a: 0, _b: 0) +// CHECK-NEXT: test-defaulted-2: TestDefaulted(_a: 3, _b: 4) +// CHECK-NEXT: test-defaulted-class: ("<>", 1) diff --git a/test/Interpreter/layout_string_witnesses_static.swift b/test/Interpreter/layout_string_witnesses_static.swift index b90a89623334a..c612445152503 100644 --- a/test/Interpreter/layout_string_witnesses_static.swift +++ b/test/Interpreter/layout_string_witnesses_static.swift @@ -1,8 +1,8 @@ // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend -enable-experimental-feature LayoutStringValueWitnesses -enable-layout-string-value-witnesses -enable-type-layout -parse-stdlib -emit-module -emit-module-path=%t/layout_string_witnesses_types.swiftmodule %S/Inputs/layout_string_witnesses_types.swift +// RUN: %target-swift-frontend -enable-experimental-feature LayoutStringValueWitnesses -enable-layout-string-value-witnesses -parse-stdlib -emit-module -emit-module-path=%t/layout_string_witnesses_types.swiftmodule %S/Inputs/layout_string_witnesses_types.swift // NOTE: We have to build this as dylib to turn private external symbols into local symbols, so we can observe potential issues with linkage -// RUN: %target-build-swift-dylib(%t/%target-library-name(layout_string_witnesses_types)) -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-layout-string-value-witnesses -Xfrontend -enable-type-layout -Xfrontend -parse-stdlib -parse-as-library %S/Inputs/layout_string_witnesses_types.swift +// RUN: %target-build-swift-dylib(%t/%target-library-name(layout_string_witnesses_types)) -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-layout-string-value-witnesses -Xfrontend -parse-stdlib -parse-as-library %S/Inputs/layout_string_witnesses_types.swift // RUN: %target-codesign %t/%target-library-name(layout_string_witnesses_types) // RUN: %target-swift-frontend -enable-experimental-feature LayoutStringValueWitnesses -enable-layout-string-value-witnesses -enable-library-evolution -emit-module -emit-module-path=%t/layout_string_witnesses_types_resilient.swiftmodule %S/Inputs/layout_string_witnesses_types_resilient.swift // RUN: %target-build-swift -g -Xfrontend -enable-experimental-feature -Xfrontend LayoutStringValueWitnesses -Xfrontend -enable-layout-string-value-witnesses -Xfrontend -enable-library-evolution -c -parse-as-library -o %t/layout_string_witnesses_types_resilient.o %S/Inputs/layout_string_witnesses_types_resilient.swift diff --git a/test/Interpreter/moveonly_address_maximize.swift b/test/Interpreter/moveonly_address_maximize.swift new file mode 100644 index 0000000000000..8ec5548ba3738 --- /dev/null +++ b/test/Interpreter/moveonly_address_maximize.swift @@ -0,0 +1,307 @@ +// RUN: %target-run-simple-swift(-Xfrontend -sil-verify-all) | %FileCheck %s +// RUN: %target-run-simple-swift(-O -Xfrontend -sil-verify-all) | %FileCheck %s + +struct S : ~Copyable { + let s: String + init(_ s: String) { self.s = s } + deinit { + print("destroying \(s)") + } +} +struct S2 : ~Copyable { + var s1: S + var s2: S + init(_ s: String) { + self.s1 = S("\(s).s1") + self.s2 = S("\(s).s2") + } +} +struct S3 : ~Copyable { + var s1: S + var s2: S + var s3: S + init(_ s: String) { + self.s1 = S("\(s).s1") + self.s2 = S("\(s).s2") + self.s3 = S("\(s).s3") + } +} + +func consumeVal(_ s: consuming S) {} +func consumeVal(_ s: consuming S2) {} +func borrowVal(_ s: borrowing S) {} +func borrowVal(_ s: borrowing S2) {} + +func marker(_ s: String) { + print("\(#function): \(s)") +} + +// Simple test that makes sure that we still after we consume have the lifetime +// of s be completely consumed by consumeVal. +// CHECK: destroying simpleTestVar().first.s1 +// CHECK: destroying simpleTestVar().first.s2 +// CHECK: destroying simpleTestVar().second.s1 +// CHECK: destroying simpleTestVar().second.s2 +// CHECK: marker(_:): simpleTestVar().1 +@_silgen_name("simpleTestVar") +func simpleTestVar() { + var s = S2("\(#function).first") + s = S2("\(#function).second") + consumeVal(s) // Lifetime of s should end here before end of scope. + marker("\(#function).1") +} + +// Simple test that proves that we can maximize lifetimes in a field sensitive +// manner. Since we only consume s.s1, s.s2's lifetime should still be maximized +// and be at end of scope. +// CHECK: destroying simpleTestVar2().first.s1 +// CHECK: destroying simpleTestVar2().first.s2 +// CHECK: destroying simpleTestVar2().second.s1 +// CHECK: marker(_:): simpleTestVar2().1 +// CHECK: destroying simpleTestVar2().second.s2 +func simpleTestVar2() { + var s = S2("\(#function).first") + s = S2("\(#function).second") + consumeVal(s.s1) // Lifetime of s1 should end here. + marker("\(#function).1") + // Lifetime of s2 should end at end of scope after marker. +} + +// In this case, we consume all of s by consuming s.s1 and s.s2 separately, so +// all lifetimes should be done before marker. +// CHECK: destroying simpleTestVar3().first.s1 +// CHECK: destroying simpleTestVar3().first.s2 +// CHECK: destroying simpleTestVar3().second.s1 +// CHECK: destroying simpleTestVar3().second.s2 +// CHECK: marker(_:): simpleTestVar3().1 +func simpleTestVar3() { + var s = S2("\(#function).first") + s = S2("\(#function).second") + consumeVal(s.s1) + consumeVal(s.s2) + marker("\(#function).1") // Lifetimes should end before marker. +} + +// In this case, we completely consume s and then reinitialize s implying we +// need to deal with two disjoint lifetimes. The second lifetime of s should end +// after marker. +// CHECK: destroying simpleTestVar3a().first.s1 +// CHECK: destroying simpleTestVar3a().first.s2 +// CHECK: destroying simpleTestVar3a().second.s1 +// CHECK: destroying simpleTestVar3a().second.s2 +// CHECK: marker(_:): simpleTestVar3a().1 +// CHECK: marker(_:): simpleTestVar3a().2 +// CHECK: destroying simpleTestVar3a().third.s1 +// CHECK: destroying simpleTestVar3a().third.s2 +func simpleTestVar3a() { + var s = S2("\(#function).first") + s = S2("\(#function).second") + consumeVal(s.s1) + consumeVal(s.s2) + + marker("\(#function).1") + + s = S2("\(#function).third") + marker("\(#function).2") +} + +// In this case, we have another borrowVal of s.s2. That should still let s.s2's +// lifetime end after marker. +// CHECK: destroying simpleTestVar3b().first.s1 +// CHECK: destroying simpleTestVar3b().first.s2 +// CHECK: destroying simpleTestVar3b().second.s1 +// CHECK: marker(_:): simpleTestVar3b().1 +// CHECK: destroying simpleTestVar3b().second.s2 +func simpleTestVar3b() { + var s = S2("\(#function).first") + s = S2("\(#function).second") + consumeVal(s.s1) + borrowVal(s.s2) + marker("\(#function).1") // s2 should end its lifetime after marker. +} + +// In this case, we are testing reinitialization and making sure that we can +// handle two initializations properly. We also are testing conditional merge +// logic. Since in both cases below s is completely consumed in b, s's lifetime +// would end at marker. + +// CHECK: destroying simpleTestVar4(_:_:)[false, false)].first.s1 +// CHECK: destroying simpleTestVar4(_:_:)[false, false)].first.s2 +// CHECK: marker(_:): simpleTestVar4(_:_:)[false, false)].1 +// CHECK: destroying simpleTestVar4(_:_:)[false, false)].second.s1 +// CHECK: destroying simpleTestVar4(_:_:)[false, false)].second.s2 +// CHECK: destroying simpleTestVar4(_:_:)[false, false)].third.s1 +// CHECK: destroying simpleTestVar4(_:_:)[false, false)].third.s2 +// CHECK: marker(_:): simpleTestVar4(_:_:)[false, false)].2 + +// CHECK: destroying simpleTestVar4(_:_:)[false, true)].first.s1 +// CHECK: destroying simpleTestVar4(_:_:)[false, true)].first.s2 +// CHECK: marker(_:): simpleTestVar4(_:_:)[false, true)].1 +// CHECK: destroying simpleTestVar4(_:_:)[false, true)].second.s1 +// CHECK: destroying simpleTestVar4(_:_:)[false, true)].second.s2 +// CHECK: destroying simpleTestVar4(_:_:)[false, true)].third.s1 +// CHECK: destroying simpleTestVar4(_:_:)[false, true)].third.s2 + +// CHECK: destroying simpleTestVar4(_:_:)[true, false)].first.s1 +// CHECK: destroying simpleTestVar4(_:_:)[true, false)].first.s2 +// CHECK: destroying simpleTestVar4(_:_:)[true, false)].second.s1 +// CHECK: destroying simpleTestVar4(_:_:)[true, false)].second.s2 +// CHECK: destroying simpleTestVar4(_:_:)[true, false)].third.s1 +// CHECK: destroying simpleTestVar4(_:_:)[true, false)].third.s2 +// CHECK: marker(_:): simpleTestVar4(_:_:)[true, false)].2 + +// CHECK: destroying simpleTestVar4(_:_:)[true, true)].first.s1 +// CHECK: destroying simpleTestVar4(_:_:)[true, true)].first.s2 +// CHECK: destroying simpleTestVar4(_:_:)[true, true)].second.s1 +// CHECK: destroying simpleTestVar4(_:_:)[true, true)].second.s2 +// CHECK: destroying simpleTestVar4(_:_:)[true, true)].third.s1 +// CHECK: destroying simpleTestVar4(_:_:)[true, true)].third.s2 +func simpleTestVar4(_ b1: Bool, _ b2: Bool) { + var s = S2("\(#function)[\(b1), \(b2))].first") + s = S2("\(#function)[\(b1), \(b2))].second") + + if b1 { + consumeVal(s) + } else { + marker("\(#function)[\(b1), \(b2))].1") + // S's lifetime should end after marker in this block. + } + + s = S2("\(#function)[\(b1), \(b2))].third") + + if b2 { + consumeVal(s) + } else { + marker("\(#function)[\(b1), \(b2))].2") + // S's 2nd lifetime should end after marker in this block. + } +} + +// This test is similar to the previous, except we are consuming different +// values along the if/else branch that completely covers the value. As a result +// of this, we need to end the lifetime of s in the branches. +// CHECK: destroying simpleTestVar6(_:)[false].first.s1 +// CHECK: destroying simpleTestVar6(_:)[false].first.s2 +// CHECK: destroying simpleTestVar6(_:)[false].second.s2 +// CHECK: marker(_:): simpleTestVar6(_:)[false].2 +// CHECK: destroying simpleTestVar6(_:)[false].second.s1 +// CHECK: destroying simpleTestVar6(_:)[false].third.s1 +// CHECK: destroying simpleTestVar6(_:)[false].third.s2 + +// CHECK: destroying simpleTestVar6(_:)[true].first.s1 +// CHECK: destroying simpleTestVar6(_:)[true].first.s2 +// CHECK: destroying simpleTestVar6(_:)[true].second.s1 +// CHECK: marker(_:): simpleTestVar6(_:)[true].1 +// CHECK: destroying simpleTestVar6(_:)[true].second.s2 +// CHECK: destroying simpleTestVar6(_:)[true].third.s1 +// CHECK: destroying simpleTestVar6(_:)[true].third.s2 +func simpleTestVar6(_ b: Bool) { + var s = S2("\(#function)[\(b)].first") + s = S2("\(#function)[\(b)].second") + + if b { + consumeVal(s.s1) // end of s.s1's lifetime. + marker("\(#function)[\(b)].1") + // s.s2 should end here. + } else { + consumeVal(s.s2) // end of s.s2's lifetime + marker("\(#function)[\(b)].2") + // end of s.s1's lifetime should end after marker. + } + + s = S2("\(#function)[\(b)].third") +} + +// In this case, we are using S3 implying we have three fields. So despite the +// fact that we are deleting these two values in the if-else branches, s3's +// lifetime needs to end at end of scope. +// CHECK: destroying simpleTestVar6a(_:)[false].first.s1 +// CHECK: destroying simpleTestVar6a(_:)[false].first.s2 +// CHECK: destroying simpleTestVar6a(_:)[false].first.s3 +// CHECK: destroying simpleTestVar6a(_:)[false].second.s2 +// CHECK: marker(_:): simpleTestVar6a(_:)[false].2 +// CHECK: destroying simpleTestVar6a(_:)[false].second.s1 +// CHECK: marker(_:): simpleTestVar6a(_:)[false].3 +// CHECK: destroying simpleTestVar6a(_:)[false].second.s3 + +// CHECK: destroying simpleTestVar6a(_:)[true].first.s1 +// CHECK: destroying simpleTestVar6a(_:)[true].first.s2 +// CHECK: destroying simpleTestVar6a(_:)[true].first.s3 +// CHECK: destroying simpleTestVar6a(_:)[true].second.s1 +// CHECK: marker(_:): simpleTestVar6a(_:)[true].1 +// CHECK: destroying simpleTestVar6a(_:)[true].second.s2 +// CHECK: marker(_:): simpleTestVar6a(_:)[true].3 +// CHECK: destroying simpleTestVar6a(_:)[true].second.s3 +func simpleTestVar6a(_ b: Bool) { + var s = S3("\(#function)[\(b)].first") + s = S3("\(#function)[\(b)].second") + + if b { + consumeVal(s.s1) // end of s.s1's lifetime. + marker("\(#function)[\(b)].1") + // s.s2 should end here. + } else { + consumeVal(s.s2) // end of s.s2's lifetime + marker("\(#function)[\(b)].2") + // end of s.s1's lifetime should end after marker. + } + + marker("\(#function)[\(b)].3") + // s.s3's lifetime should end here. +} + +// In this case, we are using S3, but we are consuming two disjoint parts of S +// in the if statement so we cover again completely. +// CHECK: destroying simpleTestVar6b(_:)[false].first.s1 +// CHECK: destroying simpleTestVar6b(_:)[false].first.s2 +// CHECK: destroying simpleTestVar6b(_:)[false].first.s3 +// CHECK: destroying simpleTestVar6b(_:)[false].second.s2 +// CHECK: marker(_:): simpleTestVar6b(_:)[false].2 +// CHECK: destroying simpleTestVar6b(_:)[false].second.s3 +// CHECK: destroying simpleTestVar6b(_:)[false].second.s1 +// CHECK: marker(_:): simpleTestVar6b(_:)[false].3 + +// CHECK: destroying simpleTestVar6b(_:)[true].first.s1 +// CHECK: destroying simpleTestVar6b(_:)[true].first.s2 +// CHECK: destroying simpleTestVar6b(_:)[true].first.s3 +// CHECK: destroying simpleTestVar6b(_:)[true].second.s1 +// CHECK: destroying simpleTestVar6b(_:)[true].second.s3 +// CHECK: marker(_:): simpleTestVar6b(_:)[true].1 +// CHECK: destroying simpleTestVar6b(_:)[true].second.s2 +// CHECK: marker(_:): simpleTestVar6b(_:)[true].3 +func simpleTestVar6b(_ b: Bool) { + var s = S3("\(#function)[\(b)].first") + s = S3("\(#function)[\(b)].second") + + if b { + consumeVal(s.s1) // end of s.s1's lifetime. + consumeVal(s.s3) // end of s.s3's lifetime + marker("\(#function)[\(b)].1") + // s.s2 should end here. + } else { + consumeVal(s.s2) // end of s.s2's lifetime + marker("\(#function)[\(b)].2") + // end of s.s1's lifetime should end after marker. + // end of s.s3's lifetime should end after marker. + } + + marker("\(#function)[\(b)].3") +} + + +simpleTestVar() +simpleTestVar2() +simpleTestVar3() +simpleTestVar3a() +simpleTestVar3b() +simpleTestVar4(false, false) +simpleTestVar4(false, true) +simpleTestVar4(true, false) +simpleTestVar4(true, true) +simpleTestVar6(false) +simpleTestVar6(true) +simpleTestVar6a(false) +simpleTestVar6a(true) +simpleTestVar6b(false) +simpleTestVar6b(true) + diff --git a/test/Interpreter/moveonly_maximize.swift b/test/Interpreter/moveonly_maximize.swift new file mode 100644 index 0000000000000..d313c5d501a19 --- /dev/null +++ b/test/Interpreter/moveonly_maximize.swift @@ -0,0 +1,33 @@ +// RUN: %target-run-simple-swift(-Xfrontend -sil-verify-all) | %FileCheck %s +// RUN: %target-run-simple-swift(-O -Xfrontend -sil-verify-all) | %FileCheck %s + +// REQUIRES: executable_test +struct Alice: ~Copyable { + var age: Int + + init(age: Int) { + print("INIT"); + self.age = age + } + + deinit { print("DEINIT") } +} + +func eatMe(_ alice: consuming Alice) { + print(" start") + print(" age:", alice.age) + print(" end") +} + +func doit() { + let alice = Alice(age: 10) + eatMe(alice) +} + +doit() + +// CHECK: INIT +// CHECK: start +// CHECK: age: 10 +// CHECK: end +// CHECK: DEINIT diff --git a/test/Macros/macro_keywordname.swift b/test/Macros/macro_keywordname.swift index 3a302538b312e..2e8b94b8d33a8 100644 --- a/test/Macros/macro_keywordname.swift +++ b/test/Macros/macro_keywordname.swift @@ -53,7 +53,7 @@ import MacroLib @freestanding(expression) public macro `class`() -> Int = #externalMacro(module: "MacroDefinition", type: "OneMacro") func test() { - let _: Int = #public() // expected-error {{keyword 'public' cannot be used as an identifier here}} expected-note {{if this name is unavoidable, use backticks to escape it}} + let _: Int = #public() let _: Int = #`public`() let _: Int = #escaped() let _: Int = #`class`() diff --git a/test/Macros/macro_self.swift b/test/Macros/macro_self.swift index 4e8b39b0fc173..47b278568314c 100644 --- a/test/Macros/macro_self.swift +++ b/test/Macros/macro_self.swift @@ -9,11 +9,11 @@ func sync() {} macro Self() = #externalMacro(module: "MacroDefinition", type: "InvalidMacro") func testSelfAsFreestandingMacro() { - _ = #self // expected-error {{keyword 'self' cannot be used as an identifier here}} expected-note {{use backticks to escape it}} + _ = #self } func testCapitalSelfAsFreestandingMacro() { - _ = #Self // expected-error {{keyword 'Self' cannot be used as an identifier here}} expected-note {{use backticks to escape it}} + _ = #Self } func testSelfAsAttachedMacro() { diff --git a/test/Macros/serialize_plugin_search_paths.swift b/test/Macros/serialize_plugin_search_paths.swift index ef9c5c8d7ee88..cd4b53fc4725f 100644 --- a/test/Macros/serialize_plugin_search_paths.swift +++ b/test/Macros/serialize_plugin_search_paths.swift @@ -11,10 +11,10 @@ // RUN: -load-plugin-executable %t/mock-plugin#TestPlugin // RUN: %lldb-moduleimport-test -verbose -dump-module %t/a.out | %FileCheck %s -// CHECK: - Macro Search Paths: -// CHECK: -plugin-path: {{.*}}plugins -// CHECK: -plugin-path: {{.*}}plugins -// CHECK: -plugin-path: {{.*}}plugins -// CHECK: -external-plugin-path: {{.*}}plugins#{{.*}}swift-plugin-server -// CHECK: -load-plugin-library: {{.*}}MacroDefinition.{{dylib|so|dll}} -// CHECK: -load-plugin-executable: {{.*}}mock-plugin#TestPlugin +// CHECK: - Plugin Search Options: +// CHECK: -plugin-path {{.*}}plugins +// CHECK: -external-plugin-path {{.*}}plugins#{{.*}}swift-plugin-server +// CHECK: -load-plugin-library {{.*}}MacroDefinition.{{dylib|so|dll}} +// CHECK: -load-plugin-executable {{.*}}mock-plugin#TestPlugin +// CHECK: -plugin-path {{.*}}plugins +// CHECK: -plugin-path {{.*}}plugins diff --git a/test/Parse/macro_decl.swift b/test/Parse/macro_decl.swift index 3fc66878c1f8d..53f4afd5e5b66 100644 --- a/test/Parse/macro_decl.swift +++ b/test/Parse/macro_decl.swift @@ -51,6 +51,6 @@ public # someFunc // expected-error {{extraneous whitespace between '#' and macr struct S { # someFunc // expected-error {{extraneous whitespace between '#' and macro name is not permitted}} {{4-5=}} - #class // expected-error {{keyword 'class' cannot be used as an identifier here}} expected-note {{if this name is unavoidable, use backticks to escape it}} {{4-9=`class`}} + #class # struct Inner {} // expected-error {{expected a macro identifier for a pound literal declaration}} expected-error {{consecutive declarations on a line}} } diff --git a/test/Parse/macro_expr.swift b/test/Parse/macro_expr.swift index 3e9a6d061931a..16928aaa5d478 100644 --- a/test/Parse/macro_expr.swift +++ b/test/Parse/macro_expr.swift @@ -44,7 +44,7 @@ do { _ = # macro() // expected-error {{extraneous whitespace between '#' and macro name is not permitted}} {{8-9=}} } do { - _ = #public() // expected-error {{keyword 'public' cannot be used as an identifier here}} expected-note {{if this name is unavoidable, use backticks to escape it}} {{8-14=`public`}} + _ = #public() } do { _ = # public() // expected-error {{expected a macro identifier for a pound literal expression}} diff --git a/test/SIL/type_lowering_unit.sil b/test/SIL/type_lowering_unit.sil new file mode 100644 index 0000000000000..23e1ba35bbf64 --- /dev/null +++ b/test/SIL/type_lowering_unit.sil @@ -0,0 +1,18 @@ +// RUN: %target-sil-opt -unit-test-runner %s -o /dev/null 2>&1 | %FileCheck %s + +sil_stage raw + +import Builtin + +struct S : ~Copyable {} + +// CHECK-LABEL: begin {{.*}} print-type-lowering with: @argument[0] +// CHECK: isLexical: true +// CHECK-LABEL: end {{.*}} print-type-lowering with: @argument[0] +sil [ossa] @move_only_argument : $@convention(thin) (@owned S) -> () { +bb0(%0 : @owned $S): + test_specification "print-type-lowering @argument[0]" + destroy_value %0 : $S + %retval = tuple () + return %retval : $() +} diff --git a/test/SILGen/discard.swift b/test/SILGen/discard.swift index abb4ba5d8a5ad..17a2e5a17360a 100644 --- a/test/SILGen/discard.swift +++ b/test/SILGen/discard.swift @@ -89,7 +89,8 @@ func invokedDeinit() {} // CHECK-LABEL: sil hidden [ossa] @$s4test11PointerTreeV10tryDestroy9doDiscardySb_tKF : $@convention(method) (Bool, @owned PointerTree) -> @error any Error { // CHECK: bb0{{.*}}: // CHECK: [[SELF_BOX:%.*]] = alloc_box ${ var PointerTree }, var, name "self" -// CHECK: [[SELF_PTR:%.*]] = project_box [[SELF_BOX]] : ${ var PointerTree }, 0 +// CHECK: [[SELF_BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[SELF_BOX]] +// CHECK: [[SELF_PTR:%.*]] = project_box [[SELF_BOX_LIFETIME]] : ${ var PointerTree }, 0 // .. skip to the conditional test .. // CHECK: [[SHOULD_FORGET:%.*]] = struct_extract {{.*}} : $Bool, #Bool._value // CHECK: cond_br [[SHOULD_FORGET]], bb1, bb2 @@ -107,6 +108,7 @@ func invokedDeinit() {} // CHECK: br bb3 // // CHECK: bb3: +// CHECK: end_borrow [[SELF_BOX_LIFETIME]] // CHECK: destroy_value [[SELF_BOX]] : ${ var PointerTree } // CHECK: throw // CHECK: } // end sil function diff --git a/test/SILGen/moveonly.swift b/test/SILGen/moveonly.swift index e25375482eb4e..e6166fe94a8f7 100644 --- a/test/SILGen/moveonly.swift +++ b/test/SILGen/moveonly.swift @@ -131,7 +131,7 @@ public func useNonTrivialOwnedStruct(_ s: __owned NonTrivialStruct) { public func useNonTrivialEnum(_ s: borrowing NonTrivialEnum) { borrowVal(s) let s2 = s - switch s { + switch consume s { case _: break } @@ -149,7 +149,7 @@ public func useNonTrivialEnum(_ s: borrowing NonTrivialEnum) { public func useNonTrivialOwnedEnum(_ s: __owned NonTrivialEnum) { borrowVal(s) let s2 = s - switch s { + switch consume s { case _: break } @@ -705,7 +705,13 @@ var booleanGuard2: Bool { false } // CHECK-LABEL: sil hidden [ossa] @$s8moveonly15enumSwitchTest1yyAA04EnumC5TestsO1EOF : $@convention(thin) (@guaranteed EnumSwitchTests.E) -> () { // CHECK: bb0([[ARG:%.*]] : @guaranteed // CHECK: [[COPY_ARG:%.*]] = copy_value [[ARG]] -// CHECK: [[MARKED_VALUE:%.*]] = mark_must_check [no_consume_or_assign] [[COPY_ARG]] +// CHECK: [[ARG_MARKED_VALUE:%.*]] = mark_must_check [no_consume_or_assign] [[COPY_ARG]] +// -- code corresponding to the consume x -- +// CHECK: [[BORROW_ARG_MARKED_VALUE:%.*]] = begin_borrow [[ARG_MARKED_VALUE]] +// CHECK: [[COPY_COPY_ARG:%.*]] = copy_value [[BORROW_ARG_MARKED_VALUE]] +// CHECK: [[MOVE_COPY_COPY_ARG:%.*]] = move_value [allows_diagnostics] [[COPY_COPY_ARG]] +// CHECK: [[MARKED_VALUE:%.*]] = mark_must_check [consumable_and_assignable] [[MOVE_COPY_COPY_ARG]] +// -- now switching on the `consume x` -- // CHECK: [[BORROWED_VALUE:%.*]] = begin_borrow [[MARKED_VALUE]] // CHECK: switch_enum [[BORROWED_VALUE]] : $EnumSwitchTests.E, case #EnumSwitchTests.E.first!enumelt: [[BB_E_1:bb[0-9]+]], case #EnumSwitchTests.E.second!enumelt: [[BB_E_2:bb[0-9]+]], case #EnumSwitchTests.E.third!enumelt: [[BB_E_3:bb[0-9]+]], case #EnumSwitchTests.E.fourth!enumelt: [[BB_E_4:bb[0-9]+]] // @@ -758,10 +764,10 @@ var booleanGuard2: Bool { false } // CHECK: br [[BB_CONT]] // // CHECK: [[BB_CONT]]: -// CHECK: destroy_value [[MARKED_VALUE]] +// CHECK: destroy_value [[ARG_MARKED_VALUE]] // CHECK: } // end sil function '$s8moveonly15enumSwitchTest1yyAA04EnumC5TestsO1EOF' func enumSwitchTest1(_ e: borrowing EnumSwitchTests.E) { - switch e { + switch consume e { case .first: break case .second(let x): @@ -933,7 +939,8 @@ struct EmptyStruct { // CHECK-LABEL: sil hidden [ossa] @$s8moveonly11EmptyStructVACycfC : $@convention(method) (@thin EmptyStruct.Type) -> @owned EmptyStruct { // CHECK: [[BOX:%.*]] = alloc_box ${ var EmptyStruct }, var, name "self" // CHECK: [[MARKED_UNINIT:%.*]] = mark_uninitialized [rootself] [[BOX]] - // CHECK: [[PROJECT:%.*]] = project_box [[MARKED_UNINIT]] + // CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[MARKED_UNINIT]] + // CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // CHECK: [[STRUCT:%.*]] = struct $EmptyStruct () // CHECK: store [[STRUCT]] to [init] [[PROJECT]] // CHECK: [[MV_CHECK:%.*]] = mark_must_check [assignable_but_not_consumable] [[PROJECT]] @@ -1039,7 +1046,8 @@ public struct LoadableSubscriptGetOnlyTester : ~Copyable { // CHECK-LABEL: sil [ossa] @$s8moveonly047testSubscriptGetOnly_BaseLoadable_ResultAddressE4_VaryyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box $ -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // // The get call // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]] @@ -1077,7 +1085,8 @@ public func testSubscriptGetOnly_BaseLoadable_ResultAddressOnly_Var() { // CHECK-LABEL: sil [ossa] @$s8moveonly047testSubscriptGetOnly_BaseLoadable_ResultAddressE4_LetyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box $ -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // // The get call // CHECK: [[MARK:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] @@ -1140,7 +1149,8 @@ public struct LoadableSubscriptGetOnlyTesterNonCopyableStructParent : ~Copyable // CHECK-LABEL: sil [ossa] @$s8moveonly077testSubscriptGetOnlyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressE4_VaryyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box $ -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // // The first get call // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]] @@ -1181,7 +1191,8 @@ public func testSubscriptGetOnlyThroughNonCopyableParentStruct_BaseLoadable_Resu // CHECK-LABEL: sil [ossa] @$s8moveonly077testSubscriptGetOnlyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressE4_LetyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box ${ let L -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // // CHECK: [[MARK:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] // CHECK: [[LOAD:%.*]] = load_borrow [[MARK]] @@ -1350,7 +1361,8 @@ public struct LoadableSubscriptGetSetTester : ~Copyable { // CHECK-LABEL: sil [ossa] @$s8moveonly54testSubscriptGetSet_BaseLoadable_ResultAddressOnly_VaryyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box $ -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // // The get call // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]] @@ -1396,7 +1408,8 @@ public func testSubscriptGetSet_BaseLoadable_ResultAddressOnly_Var() { // CHECK-LABEL: sil [ossa] @$s8moveonly54testSubscriptGetSet_BaseLoadable_ResultAddressOnly_LetyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box $ -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // // The get call // CHECK: [[MARK:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] @@ -1507,7 +1520,8 @@ public struct LoadableSubscriptGetSetTesterNonCopyableStructParent : ~Copyable { // CHECK-LABEL: sil [ossa] @$s8moveonly84testSubscriptGetSetThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_VaryyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box $ -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // // The first get call // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]] @@ -1561,7 +1575,8 @@ public func testSubscriptGetSetThroughNonCopyableParentStruct_BaseLoadable_Resul // CHECK-LABEL: sil [ossa] @$s8moveonly84testSubscriptGetSetThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_LetyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box ${ let L -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // // CHECK: [[MARK:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] // CHECK: [[LOAD:%.*]] = load_borrow [[MARK]] @@ -1819,7 +1834,8 @@ public struct LoadableSubscriptReadSetTester : ~Copyable { // CHECK-LABEL: sil [ossa] @$s8moveonly55testSubscriptReadSet_BaseLoadable_ResultAddressOnly_VaryyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box $ -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // // The read call // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]] @@ -1865,7 +1881,8 @@ public func testSubscriptReadSet_BaseLoadable_ResultAddressOnly_Var() { // CHECK-LABEL: sil [ossa] @$s8moveonly55testSubscriptReadSet_BaseLoadable_ResultAddressOnly_LetyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box $ -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // // The get call // CHECK: [[MARK:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] @@ -1979,7 +1996,8 @@ public struct LoadableSubscriptReadSetTesterNonCopyableStructParent : ~Copyable // CHECK-LABEL: sil [ossa] @$s8moveonly85testSubscriptReadSetThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_VaryyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box $ -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // // The first get call // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]] @@ -2031,7 +2049,8 @@ public func testSubscriptReadSetThroughNonCopyableParentStruct_BaseLoadable_Resu // CHECK-LABEL: sil [ossa] @$s8moveonly85testSubscriptReadSetThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_LetyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box ${ let L -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // // CHECK: [[MARK:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] // CHECK: [[LOAD:%.*]] = load_borrow [[MARK]] @@ -2285,7 +2304,8 @@ public struct LoadableSubscriptReadModifyTester : ~Copyable { // CHECK-LABEL: sil [ossa] @$s8moveonly58testSubscriptReadModify_BaseLoadable_ResultAddressOnly_VaryyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box $ -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // // The read call // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]] @@ -2328,7 +2348,8 @@ public func testSubscriptReadModify_BaseLoadable_ResultAddressOnly_Var() { // CHECK-LABEL: sil [ossa] @$s8moveonly58testSubscriptReadModify_BaseLoadable_ResultAddressOnly_LetyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box $ -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // // The get call // CHECK: [[MARK:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] @@ -2431,7 +2452,8 @@ public struct LoadableSubscriptReadModifyTesterNonCopyableStructParent : ~Copyab // CHECK-LABEL: sil [ossa] @$s8moveonly88testSubscriptReadModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_VaryyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box $ -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // // The first get call // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]] @@ -2477,7 +2499,8 @@ public func testSubscriptReadModifyThroughNonCopyableParentStruct_BaseLoadable_R // CHECK-LABEL: sil [ossa] @$s8moveonly88testSubscriptReadModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_LetyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box ${ let L -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // // CHECK: [[MARK:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] // CHECK: [[LOAD:%.*]] = load_borrow [[MARK]] @@ -2699,7 +2722,8 @@ public struct LoadableSubscriptGetModifyTester : ~Copyable { // CHECK-LABEL: sil [ossa] @$s8moveonly57testSubscriptGetModify_BaseLoadable_ResultAddressOnly_VaryyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box $ -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // // The get call // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]] @@ -2743,7 +2767,8 @@ public func testSubscriptGetModify_BaseLoadable_ResultAddressOnly_Var() { // CHECK-LABEL: sil [ossa] @$s8moveonly57testSubscriptGetModify_BaseLoadable_ResultAddressOnly_LetyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box $ -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // // The get call // CHECK: [[MARK:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] @@ -2850,7 +2875,8 @@ public struct LoadableSubscriptGetModifyTesterNonCopyableStructParent : ~Copyabl // CHECK-LABEL: sil [ossa] @$s8moveonly87testSubscriptGetModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_VaryyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box $ -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // // The first get call // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]] @@ -2900,7 +2926,8 @@ public func testSubscriptGetModifyThroughNonCopyableParentStruct_BaseLoadable_Re // CHECK-LABEL: sil [ossa] @$s8moveonly87testSubscriptGetModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_LetyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box ${ let L -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // // CHECK: [[MARK:%.*]] = mark_must_check [no_consume_or_assign] [[PROJECT]] // CHECK: [[LOAD:%.*]] = load_borrow [[MARK]] diff --git a/test/SILGen/moveonly_deinits.swift b/test/SILGen/moveonly_deinits.swift index 73a7353966af0..88a6fd778ef20 100644 --- a/test/SILGen/moveonly_deinits.swift +++ b/test/SILGen/moveonly_deinits.swift @@ -83,7 +83,8 @@ var value: Bool { false } // SILGEN-LABEL: sil [ossa] @$s16moveonly_deinits24testIntPairWithoutDeinityyF : $@convention(thin) () -> () { // SILGEN: [[BOX:%.*]] = alloc_box -// SILGEN: [[PROJECT:%.*]] = project_box [[BOX]] +// SILGEN: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// SILGEN: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // SILGEN: cond_br {{%.*}}, bb1, bb2 // // SILGEN: bb1: @@ -132,7 +133,8 @@ public func testIntPairWithoutDeinit() { // SILGEN-LABEL: sil [ossa] @$s16moveonly_deinits21testIntPairWithDeinityyF : $@convention(thin) () -> () { // SILGEN: [[BOX:%.*]] = alloc_box -// SILGEN: [[PROJECT:%.*]] = project_box [[BOX]] +// SILGEN: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// SILGEN: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // SILGEN: cond_br {{%.*}}, bb1, bb2 // // SILGEN: bb1: @@ -343,7 +345,8 @@ func consumeKlassEnumPairWithDeinit(_ x: __owned KlassEnumPairWithDeinit) { } // SILGEN-LABEL: sil [ossa] @$s16moveonly_deinits28testIntEnumPairWithoutDeinityyF : $@convention(thin) () -> () { // SILGEN: [[BOX:%.*]] = alloc_box -// SILGEN: [[PROJECT:%.*]] = project_box [[BOX]] +// SILGEN: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// SILGEN: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // SILGEN: cond_br {{%.*}}, bb1, bb2 // // SILGEN: bb1: @@ -391,7 +394,8 @@ public func testIntEnumPairWithoutDeinit() { // SILGEN-LABEL: sil [ossa] @$s16moveonly_deinits25testIntEnumPairWithDeinityyF : $@convention(thin) () -> () { // SILGEN: [[BOX:%.*]] = alloc_box -// SILGEN: [[PROJECT:%.*]] = project_box [[BOX]] +// SILGEN: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// SILGEN: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // SILGEN: cond_br {{%.*}}, bb1, bb2 // // SILGEN: bb1: diff --git a/test/SILGen/moveonly_enum_literal.swift b/test/SILGen/moveonly_enum_literal.swift index 4d566835f4b83..13555bce43a40 100644 --- a/test/SILGen/moveonly_enum_literal.swift +++ b/test/SILGen/moveonly_enum_literal.swift @@ -16,7 +16,8 @@ var value: Bool { false } // CHECK-LABEL: sil hidden [ossa] @$s21moveonly_enum_literal4testyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // CHECK: [[VALUE:%.*]] = enum $MoveOnlyIntPair, #MoveOnlyIntPair.lhs!enumelt, // CHECK: store [[VALUE]] to [init] [[PROJECT]] // diff --git a/test/SILGen/moveonly_escaping_closure.swift b/test/SILGen/moveonly_escaping_closure.swift index 1b20481e0147e..3977658feebb9 100644 --- a/test/SILGen/moveonly_escaping_closure.swift +++ b/test/SILGen/moveonly_escaping_closure.swift @@ -24,9 +24,10 @@ func borrowConsumeVal(_ x: borrowing SingleElt, _ y: consuming SingleElt) {} // CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure27testGlobalClosureCaptureVaryyF : $@convention(thin) () -> () { // CHECK: [[GLOBAL:%.*]] = global_addr @$s16moveonly_closure23globalClosureCaptureVaryycvp // CHECK: [[BOX:%.*]] = alloc_box ${ var SingleElt } -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // CHECK: [[CLOSURE:%.*]] = function_ref @$s16moveonly_closure27testGlobalClosureCaptureVaryyFyycfU_ : $@convention(thin) (@guaranteed { var SingleElt }) -> () -// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX]] +// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX_LIFETIME]] // CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE]]([[BOX_COPY]]) // CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[GLOBAL]] // CHECK: assign [[PAI]] to [[ACCESS]] @@ -84,8 +85,9 @@ func testGlobalClosureCaptureVar() { // CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure29testLocalLetClosureCaptureVaryyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] -// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] +// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX_LIFETIME]] // CHECK: mark_function_escape [[PROJECT]] // CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[BOX_COPY]]) // CHECK: [[BORROW_PAI:%.*]] = begin_borrow [lexical] [[PAI]] @@ -151,8 +153,9 @@ func testLocalLetClosureCaptureVar() { // CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure026testLocalVarClosureCaptureE0yyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] -// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] +// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX_LIFETIME]] // CHECK: mark_function_escape [[PROJECT]] // CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[BOX_COPY]]) // CHECK: } // end sil function '$s16moveonly_closure026testLocalVarClosureCaptureE0yyF' @@ -209,9 +212,10 @@ func testLocalVarClosureCaptureVar() { // CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure026testInOutVarClosureCaptureF0yyyyczF : $@convention(thin) (@inout @callee_guaranteed () -> ()) -> () { // CHECK: bb0([[F:%.*]] : $*@callee_guaranteed () -> ()): // CHECK: [[BOX:%.*]] = alloc_box ${ var SingleElt } -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // CHECK: [[CLOSURE:%.*]] = function_ref @$s16moveonly_closure026testInOutVarClosureCaptureF0yyyyczFyycfU_ : $@convention(thin) (@guaranteed { var SingleElt }) -> () -// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX]] +// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX_LIFETIME]] // CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE]]([[BOX_COPY]]) // CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[F]] // CHECK: assign [[PAI]] to [[ACCESS]] @@ -275,9 +279,10 @@ func testInOutVarClosureCaptureVar(_ f: inout () -> ()) { // CHECK: store [[ARG]] to [init] [[UNWRAP]] // // CHECK: [[BOX:%.*]] = alloc_box ${ var SingleElt } -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // CHECK: [[CLOSURE:%.*]] = function_ref @$s16moveonly_closure36testConsumingEscapeClosureCaptureVaryyyycnFyycfU_ : $@convention(thin) (@guaranteed { var SingleElt }) -// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX]] +// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX_LIFETIME]] // CHECK: mark_function_escape [[PROJECT]] // CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE]]([[BOX_COPY]]) // CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[FUNC_PROJECT]] @@ -342,9 +347,10 @@ func testConsumingEscapeClosureCaptureVar(_ f: consuming @escaping () -> ()) { // CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure27testGlobalClosureCaptureLetyyF : $@convention(thin) () -> () { // CHECK: [[GLOBAL:%.*]] = global_addr @$s16moveonly_closure23globalClosureCaptureLetyycvp // CHECK: [[BOX:%.*]] = alloc_box ${ let SingleElt } -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // CHECK: [[CLOSURE:%.*]] = function_ref @$s16moveonly_closure27testGlobalClosureCaptureLetyyFyycfU_ : $@convention(thin) (@guaranteed { let SingleElt }) -> () -// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX]] +// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX_LIFETIME]] // CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE]]([[BOX_COPY]]) // CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[GLOBAL]] // CHECK: assign [[PAI]] to [[ACCESS]] @@ -388,8 +394,9 @@ func testGlobalClosureCaptureLet() { // CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure026testLocalLetClosureCaptureE0yyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] -// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] +// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX_LIFETIME]] // CHECK: mark_function_escape [[PROJECT]] // CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[BOX_COPY]]) // CHECK: [[BORROW_PAI:%.*]] = begin_borrow [lexical] [[PAI]] @@ -437,8 +444,9 @@ func testLocalLetClosureCaptureLet() { // CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure29testLocalVarClosureCaptureLetyyF : $@convention(thin) () -> () { // CHECK: [[BOX:%.*]] = alloc_box -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] -// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] +// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX_LIFETIME]] // CHECK: mark_function_escape [[PROJECT]] // CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[BOX_COPY]]) // CHECK: } // end sil function '$s16moveonly_closure29testLocalVarClosureCaptureLetyyF' @@ -482,9 +490,10 @@ func testLocalVarClosureCaptureLet() { // CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure29testInOutVarClosureCaptureLetyyyyczF : $@convention(thin) (@inout @callee_guaranteed () -> ()) -> () { // CHECK: bb0([[F:%.*]] : $*@callee_guaranteed () -> ()): // CHECK: [[BOX:%.*]] = alloc_box ${ let SingleElt } -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // CHECK: [[CLOSURE:%.*]] = function_ref @$s16moveonly_closure29testInOutVarClosureCaptureLetyyyyczFyycfU_ : $@convention(thin) (@guaranteed { let SingleElt }) -> () -// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX]] +// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX_LIFETIME]] // CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE]]([[BOX_COPY]]) // CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[F]] // CHECK: assign [[PAI]] to [[ACCESS]] @@ -530,14 +539,15 @@ func testInOutVarClosureCaptureLet(_ f: inout () -> ()) { // CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure36testConsumingEscapeClosureCaptureLetyyyycnF : $@convention(thin) (@owned @callee_guaranteed () -> ()) -> () { // CHECK: bb0([[ARG:%.*]] : @noImplicitCopy @_eagerMove @owned // CHECK: [[FUNC_BOX:%.*]] = alloc_box ${ var @moveOnly @callee_guaranteed () -> () } -// CHECK: [[FUNC_PROJECT:%.*]] = project_box [[FUNC_BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[FUNC_BOX]] // CHECK: [[UNWRAP:%.*]] = moveonlywrapper_to_copyable_addr [[FUNC_PROJECT]] // CHECK: store [[ARG]] to [init] [[UNWRAP]] // // CHECK: [[BOX:%.*]] = alloc_box ${ let SingleElt } -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // CHECK: [[CLOSURE:%.*]] = function_ref @$s16moveonly_closure36testConsumingEscapeClosureCaptureLetyyyycnFyycfU_ : $@convention(thin) (@guaranteed { let SingleElt }) -// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX]] +// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX_LIFETIME]] // CHECK: mark_function_escape [[PROJECT]] // CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE]]([[BOX_COPY]]) // CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[FUNC_PROJECT]] @@ -840,9 +850,10 @@ func testConsumingEscapeClosureCaptureInOut(_ f: consuming @escaping () -> (), _ // CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure33testGlobalClosureCaptureConsumingyyAA9SingleEltVnF : $@convention(thin) (@owned SingleElt) -> () { // CHECK: [[GLOBAL:%.*]] = global_addr @$s16moveonly_closure29globalClosureCaptureConsumingyycvp // CHECK: [[BOX:%.*]] = alloc_box ${ var SingleElt } -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // CHECK: [[CLOSURE:%.*]] = function_ref @$s16moveonly_closure33testGlobalClosureCaptureConsumingyyAA9SingleEltVnFyycfU_ : $@convention(thin) (@guaranteed { var SingleElt }) -> () -// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX]] +// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX_LIFETIME]] // CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE]]([[BOX_COPY]]) // CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[GLOBAL]] // CHECK: assign [[PAI]] to [[ACCESS]] @@ -898,8 +909,9 @@ func testGlobalClosureCaptureConsuming(_ x: consuming SingleElt) { // CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure35testLocalLetClosureCaptureConsumingyyAA9SingleEltVnF : $@convention(thin) (@owned SingleElt) -> () { // CHECK: [[BOX:%.*]] = alloc_box -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] -// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] +// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX_LIFETIME]] // CHECK: mark_function_escape [[PROJECT]] // CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[BOX_COPY]]) // CHECK: [[BORROW_PAI:%.*]] = begin_borrow [lexical] [[PAI]] @@ -976,8 +988,9 @@ func testLocalLetClosureCaptureConsuming2(_ x: consuming SingleElt) -> (() -> () // CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure35testLocalVarClosureCaptureConsumingyyAA9SingleEltVnF : $@convention(thin) (@owned SingleElt) -> () { // CHECK: [[BOX:%.*]] = alloc_box -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] -// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] +// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX_LIFETIME]] // CHECK: mark_function_escape [[PROJECT]] // CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[BOX_COPY]]) // CHECK: } // end sil function '$s16moveonly_closure35testLocalVarClosureCaptureConsumingyyAA9SingleEltVnF' @@ -1038,9 +1051,10 @@ func testLocalVarClosureCaptureConsuming(_ x: consuming SingleElt) { // CHECK: store [[ARG]] to [init] [[UNWRAP]] // // CHECK: [[BOX:%.*]] = alloc_box ${ var SingleElt } -// CHECK: [[PROJECT:%.*]] = project_box [[BOX]] +// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [[BOX]] +// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]] // CHECK: [[CLOSURE:%.*]] = function_ref @$s16moveonly_closure033testConsumingEscapeClosureCaptureD0yyyycn_AA9SingleEltVntFyycfU_ : $@convention(thin) (@guaranteed { var SingleElt }) -> () -// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX]] +// CHECK: [[BOX_COPY:%.*]] = copy_value [[BOX_LIFETIME]] // CHECK: mark_function_escape [[PROJECT]] // CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE]]([[BOX_COPY]]) // CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[FUNC_PROJECT]] diff --git a/test/SILGen/switch-case-debug-descriptions.swift b/test/SILGen/switch-case-debug-descriptions.swift index acf2d46451726..68b118406653a 100644 --- a/test/SILGen/switch-case-debug-descriptions.swift +++ b/test/SILGen/switch-case-debug-descriptions.swift @@ -9,7 +9,7 @@ enum E { func test1(_ e: E) { switch e { // SCOPE: sil_scope [[test1_switch:[0-9]+]] {{.*}}:[[@LINE]]:3 case .one(let payload), .two(let payload): // SCOPE-NEXT: sil_scope [[test1_case1:[0-9]+]] {{.*}}:[[@LINE]]:3 parent [[test1_switch]] - print(payload) + print(payload) // SCOPE-NEXT: sil_scope {{.*}}:[[@LINE]]:5 parent [[test1_case1]] case .three(let payload): // SCOPE-NEXT: sil_scope [[test1_case2:[0-9]+]] {{.*}}:[[@LINE]]:3 parent [[test1_switch]] print(payload) } @@ -43,7 +43,7 @@ func test4(_ e: E) { print(x) // SCOPE-NEXT: sil_scope {{.*}}:[[@LINE]]:5 parent [[test4_case1]] fallthrough case .two(let x): // SCOPE-NEXT: sil_scope [[test4_case2:[0-9]+]] {{.*}}:[[@LINE]]:3 parent [[test4_switch]] - print(x) + print(x) // SCOPE-NEXT: {{.*}}:[[@LINE]]:5 parent [[test4_case2]] fallthrough default: // SCOPE-NEXT: sil_scope [[test4_default:[0-9]+]] {{.*}}:[[@LINE]]:3 parent [[test4_switch]] print("default") // SCOPE: sil_scope [[test4_default1:[0-9]+]] {{.*}}:[[@LINE]]:5 diff --git a/test/SILOptimizer/canonicalize_ossa_lifetime_unit.sil b/test/SILOptimizer/canonicalize_ossa_lifetime_unit.sil index 2f36344f108d6..7d2f7425b1f25 100644 --- a/test/SILOptimizer/canonicalize_ossa_lifetime_unit.sil +++ b/test/SILOptimizer/canonicalize_ossa_lifetime_unit.sil @@ -5,6 +5,9 @@ sil @getOwned : $@convention(thin) () -> @owned C sil @barrier : $@convention(thin) () -> () struct S {} +@_moveOnly struct MoS {} +@_moveOnly struct MoE {} + // When access scopes are respected, the lifetime which previously extended // beyond the access scope still extends beyond it. // CHECK-LABEL: begin running test 1 of 2 on retract_value_lifetime_into_access_scope_when_access_scopes_not_respected: canonicalize-ossa-lifetime with: true, false, true, @trace @@ -134,3 +137,46 @@ exit(%phi : @owned $C, %typhi : $S): %retval = tuple () return %retval : $() } + +sil @empty : $@convention(thin) () -> () { +[global: ] +bb0: + %0 = tuple () + return %0 : $() +} + +// Even though the apply of %empty is not a deinit barrier, verify that the +// destroy is not hoisted, because MoS is move-only. +// CHECK-LABEL: begin running test {{.*}} on dont_move_destroy_value_of_moveonly_struct: canonicalize-ossa-lifetime with: true, false, true, @argument +// CHECK-LABEL: sil [ossa] @dont_move_destroy_value_of_moveonly_struct : {{.*}} { +// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : +// CHECK: apply +// CHECK: destroy_value [[INSTANCE]] +// CHECK-LABEL: } // end sil function 'dont_move_destroy_value_of_moveonly_struct' +// CHECK-LABEL: end running test {{.*}} on dont_move_destroy_value_of_moveonly_struct: canonicalize-ossa-lifetime with: true, false, true, @argument +sil [ossa] @dont_move_destroy_value_of_moveonly_struct : $@convention(thin) (@owned MoS) -> () { +entry(%instance : @owned $MoS): + test_specification "canonicalize-ossa-lifetime true false true @argument" + %empty = function_ref @empty : $@convention(thin) () -> () + apply %empty() : $@convention(thin) () -> () + destroy_value %instance : $MoS + %retval = tuple () + return %retval : $() +} + +// CHECK-LABEL: begin running test {{.*}} on dont_move_destroy_value_of_moveonly_enum: canonicalize-ossa-lifetime with: true, false, true, @argument +// CHECK-LABEL: sil [ossa] @dont_move_destroy_value_of_moveonly_enum : {{.*}} { +// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : +// CHECK: apply +// CHECK: destroy_value [[INSTANCE]] +// CHECK-LABEL: } // end sil function 'dont_move_destroy_value_of_moveonly_enum' +// CHECK-LABEL: end running test {{.*}} on dont_move_destroy_value_of_moveonly_enum: canonicalize-ossa-lifetime with: true, false, true, @argument +sil [ossa] @dont_move_destroy_value_of_moveonly_enum : $@convention(thin) (@owned MoE) -> () { +entry(%instance : @owned $MoE): + test_specification "canonicalize-ossa-lifetime true false true @argument" + %empty = function_ref @empty : $@convention(thin) () -> () + apply %empty() : $@convention(thin) () -> () + destroy_value %instance : $MoE + %retval = tuple () + return %retval : $() +} diff --git a/test/SILOptimizer/dead_alloc.swift b/test/SILOptimizer/dead_alloc.swift new file mode 100644 index 0000000000000..3c435ec9e58b2 --- /dev/null +++ b/test/SILOptimizer/dead_alloc.swift @@ -0,0 +1,47 @@ +// RUN: %target-swift-frontend -O -emit-sil -parse-as-library %s | %FileCheck %s + +// REQUIRES: swift_stdlib_no_asserts,optimized_stdlib +// REQUIRES: swift_in_compiler + +protocol E { + func f() -> Bool +} + +protocol P { + associatedtype A = Int +} + +public struct X : P, E { + func f() -> Bool { return true } +} + +func g(_ x : T) -> Bool { + if let y = x as? E { return y.f() } + return false +} + +// Check that this function can be completely constant folded and no alloc_stack remains. + +// CHECK-LABEL: sil @$s10dead_alloc0A10AllocStackySbAA1XVF : +// CHECK: bb0({{.*}}): +// CHECK-NEXT: debug_value +// CHECK-NEXT: integer_literal +// CHECK-NEXT: struct +// CHECK-NEXT: return +// CHECK-NEXT: } // end sil function '$s10dead_alloc0A10AllocStackySbAA1XVF' +public func deadAllocStack(_ x: X) -> Bool { + return g(x) +} + +public class C { + let x: String = "123" +} + +// CHECK-LABEL: sil @$s10dead_alloc0A13ClassInstanceyyF : +// CHECK: bb0: +// CHECK-NEXT: tuple +// CHECK-NEXT: return +// CHECK-NEXT: } // end sil function '$s10dead_alloc0A13ClassInstanceyyF' +public func deadClassInstance() { + let _ = C() +} diff --git a/test/SILOptimizer/dead_alloc_stack.swift b/test/SILOptimizer/dead_alloc_stack.swift deleted file mode 100644 index 457253f8a3a34..0000000000000 --- a/test/SILOptimizer/dead_alloc_stack.swift +++ /dev/null @@ -1,32 +0,0 @@ -// RUN: %target-swift-frontend -O -emit-sil -parse-as-library %s | %FileCheck %s - -protocol E { - func f() -> Bool -} - -protocol P { - associatedtype A = Int -} - -public struct X : P, E { - func f() -> Bool { return true } -} - -func g(_ x : T) -> Bool { - if let y = x as? E { return y.f() } - return false -} - -// Check that this function can be completely constant folded and no alloc_stack remains. - -// CHECK-LABEL: sil @$s16dead_alloc_stack6testitySbAA1XVF -// CHECK: bb0({{.*}}): -// CHECK-NEXT: debug_value -// CHECK-NEXT: integer_literal -// CHECK-NEXT: struct -// CHECK-NEXT: return -// CHECK-NEXT: } // end sil function '$s16dead_alloc_stack6testitySbAA1XVF' -public func testit(_ x: X) -> Bool { - return g(x) -} - diff --git a/test/SILOptimizer/discard_checking.swift b/test/SILOptimizer/discard_checking.swift index 322c1eb66487c..69334b6283c36 100644 --- a/test/SILOptimizer/discard_checking.swift +++ b/test/SILOptimizer/discard_checking.swift @@ -125,8 +125,8 @@ struct Basics: ~Copyable { if case .red = c { discard self // expected-note {{discarded self here}} } else { - mutator() // expected-error {{must consume 'self' before exiting method that discards self}} - throw E.someError // <- better spot + mutator() + throw E.someError // expected-error {{must consume 'self' before exiting method that discards self}} } } @@ -212,10 +212,10 @@ struct Basics: ~Copyable { return } catch { print("hi") - return // <- better spot!! + return // expected-error {{must consume 'self' before exiting method that discards self}} } _ = consume self // expected-warning {{will never be executed}} - } // expected-error {{must consume 'self' before exiting method that discards self}} + } consuming func test9_fixed(_ c: Color) throws { if case .red = c { @@ -238,16 +238,16 @@ struct Basics: ~Copyable { consuming func test10(_ c: Color) throws { if case .red = c { - discard self // expected-note {{discarded self here}} + discard self // expected-note 2{{discarded self here}} return } do { - throw E.someError // expected-error {{must consume 'self' before exiting method that discards self}} + throw E.someError } catch E.someError { - return // <- better spot + return // expected-error {{must consume 'self' before exiting method that discards self}} } catch { - return // <- ok spot + return // expected-error {{must consume 'self' before exiting method that discards self}} } } @@ -263,8 +263,8 @@ struct Basics: ~Copyable { borrower() let x = self self = x - mutator() // expected-error {{must consume 'self' before exiting method that discards self}} - } + mutator() + } // expected-error {{must consume 'self' before exiting method that discards self}} consuming func test11_fixed(_ c: Color) { guard case .red = c else { @@ -328,13 +328,13 @@ struct Basics: ~Copyable { _ = consume self } - consuming func test13(_ c: Color) async { // expected-error {{must consume 'self' before exiting method that discards self}} + consuming func test13(_ c: Color) async { guard case .red = c else { discard self // expected-note {{discarded self here}} return } await asyncer() - } // <- better spot + } // expected-error {{must consume 'self' before exiting method that discards self}} consuming func test13_fixed(_ c: Color) async { guard case .red = c else { @@ -350,11 +350,11 @@ struct Basics: ~Copyable { discard self // expected-note {{discarded self here}} return } - await withCheckedContinuation { cont in // expected-error {{must consume 'self' before exiting method that discards self}} + await withCheckedContinuation { cont in cont.resume() } print("back!") - } // <- better spot + } // expected-error {{must consume 'self' before exiting method that discards self}} consuming func test14_fixed(_ c: Color) async { guard case .red = c else { @@ -402,7 +402,7 @@ struct Basics: ~Copyable { case 0: fallthrough case 1: - throw E.someError // expected-error 2{{must consume 'self' before exiting method that discards self}} + throw E.someError // expected-error {{must consume 'self' before exiting method that discards self}} case 2: return // expected-error {{must consume 'self' before exiting method that discards self}} case 3: @@ -410,22 +410,21 @@ struct Basics: ~Copyable { case 4: globalConsumingFn(self) default: - discard self // expected-note 4{{discarded self here}} + discard self // expected-note 3{{discarded self here}} } } consuming func loopyExit_bad(_ i: Int) { if i < 0 { - discard self // expected-note 2{{discarded self here}} + discard self // expected-note {{discarded self here}} return } - // TODO: rdar://110239087 (avoid duplicate consume-before-exit diagnostics for loop in discarding method) - for _ in 0.. () sil @use_S : $@convention(thin) (@in_guaranteed S) -> () @@ -1145,3 +1148,34 @@ entry(%addr : $*X): %retval = tuple () return %retval : $() } + +// Even though the apply of %empty is not a deinit barrier (c.f. +// hoist_over_apply_of_non_barrier_fn), verify that the destroy_addr is not +// hoisted, because MoS is move-only. +// CHECK-LABEL: sil [ossa] @dont_move_destroy_addr_of_moveonly_struct : {{.*}} { +// CHECK: {{bb[0-9]+}}([[ADDR:%[^,]+]] : +// CHECK: apply +// CHECK: destroy_addr [[ADDR]] +// CHECK-LABEL: } // end sil function 'dont_move_destroy_addr_of_moveonly_struct' +sil [ossa] @dont_move_destroy_addr_of_moveonly_struct : $@convention(thin) (@in MoS) -> () { +entry(%addr : $*MoS): + %empty = function_ref @empty : $@convention(thin) () -> () + apply %empty() : $@convention(thin) () -> () + destroy_addr %addr : $*MoS + %retval = tuple () + return %retval : $() +} + +// CHECK-LABEL: sil [ossa] @dont_move_destroy_addr_of_moveonly_enum : {{.*}} { +// CHECK: {{bb[0-9]+}}([[ADDR:%[^,]+]] : +// CHECK: apply +// CHECK: destroy_addr [[ADDR]] +// CHECK-LABEL: } // end sil function 'dont_move_destroy_addr_of_moveonly_enum' +sil [ossa] @dont_move_destroy_addr_of_moveonly_enum : $@convention(thin) (@in MoE) -> () { +entry(%addr : $*MoE): + %empty = function_ref @empty : $@convention(thin) () -> () + apply %empty() : $@convention(thin) () -> () + destroy_addr %addr : $*MoE + %retval = tuple () + return %retval : $() +} diff --git a/test/SILOptimizer/moveonly_addresschecker.sil b/test/SILOptimizer/moveonly_addresschecker.sil index 65b098e7c3418..e03a8a420790f 100644 --- a/test/SILOptimizer/moveonly_addresschecker.sil +++ b/test/SILOptimizer/moveonly_addresschecker.sil @@ -100,12 +100,12 @@ bb0(%arg1 : @owned $NonTrivialStruct, %arg2 : @owned $NonTrivialStruct): // CHECK: bb0([[ARG:%.*]] : @owned $NonTrivialStruct): // CHECK-NEXT: [[ALLOC_STACK:%.*]] = alloc_stack [lexical] // CHECK-NEXT: store [[ARG]] to [init] [[ALLOC_STACK]] +// CHECK-NEXT: [[GEP_3:%.*]] = struct_element_addr [[ALLOC_STACK]] : $*NonTrivialStruct, #NonTrivialStruct.k +// CHECK-NEXT: [[RESULT:%.*]] = load [take] [[GEP_3]] // CHECK-NEXT: [[GEP_1:%.*]] = struct_element_addr [[ALLOC_STACK]] : $*NonTrivialStruct, #NonTrivialStruct.copyableK // CHECK-NEXT: [[GEP_2:%.*]] = struct_element_addr [[ALLOC_STACK]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialStruct2 // CHECK-NEXT: destroy_addr [[GEP_1]] // CHECK-NEXT: destroy_addr [[GEP_2]] -// CHECK-NEXT: [[GEP_3:%.*]] = struct_element_addr [[ALLOC_STACK]] : $*NonTrivialStruct, #NonTrivialStruct.k -// CHECK-NEXT: [[RESULT:%.*]] = load [take] [[GEP_3]] // CHECK-NEXT: dealloc_stack [[ALLOC_STACK]] // CHECK-NEXT: return [[RESULT]] // CHECK: } // end sil function 'simpleInitReturnMoveOnlyField' @@ -125,10 +125,6 @@ bb0(%0 : @owned $NonTrivialStruct): // CHECK: bb0([[ARG:%.*]] : @owned $NonTrivialStruct): // CHECK-NEXT: [[ALLOC_STACK:%.*]] = alloc_stack [lexical] // CHECK-NEXT: store [[ARG]] to [init] [[ALLOC_STACK]] -// CHECK-NEXT: [[GEP_1:%.*]] = struct_element_addr [[ALLOC_STACK]] : $*NonTrivialStruct, #NonTrivialStruct.copyableK -// CHECK-NEXT: [[GEP_2:%.*]] = struct_element_addr [[ALLOC_STACK]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialStruct2 -// CHECK-NEXT: destroy_addr [[GEP_1]] -// CHECK-NEXT: destroy_addr [[GEP_2]] // CHECK-NEXT: cond_br undef, bb1, bb2 // // CHECK: bb1: @@ -142,6 +138,10 @@ bb0(%0 : @owned $NonTrivialStruct): // CHECK-NEXT: br bb3([[RESULT]] : // CHECK: bb3([[RESULT:%.*]] : +// CHECK-NEXT: [[GEP_1:%.*]] = struct_element_addr [[ALLOC_STACK]] : $*NonTrivialStruct, #NonTrivialStruct.copyableK +// CHECK-NEXT: [[GEP_2:%.*]] = struct_element_addr [[ALLOC_STACK]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialStruct2 +// CHECK-NEXT: destroy_addr [[GEP_1]] +// CHECK-NEXT: destroy_addr [[GEP_2]] // CHECK-NEXT: dealloc_stack [[ALLOC_STACK]] // CHECK-NEXT: return [[RESULT]] // CHECK: } // end sil function 'simpleInitReturnMoveOnlyFieldMultiBlock' @@ -172,18 +172,14 @@ bb3(%5 : @owned $Klass): // CHECK: bb0([[ARG:%.*]] : @owned $NonTrivialStruct): // CHECK-NEXT: [[ALLOC_STACK:%.*]] = alloc_stack [lexical] // CHECK-NEXT: store [[ARG]] to [init] [[ALLOC_STACK]] -// CHECK-NEXT: [[GEP_1:%.*]] = struct_element_addr [[ALLOC_STACK]] : $*NonTrivialStruct, #NonTrivialStruct.copyableK -// CHECK-NEXT: [[GEP_2:%.*]] = struct_element_addr [[ALLOC_STACK]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialStruct2 -// CHECK-NEXT: destroy_addr [[GEP_1]] -// CHECK-NEXT: destroy_addr [[GEP_2]] // CHECK-NEXT: cond_br undef, bb1, bb2 // // CHECK: bb1: -// CHECK-NEXT: [[GEP:%.*]] = struct_element_addr [[ALLOC_STACK]] -// CHECK-NEXT: destroy_addr [[GEP]] // CHECK-NEXT: function_ref get_klass // CHECK-NEXT: [[FUNC:%.*]] = function_ref @get_klass : // CHECK-NEXT: [[RESULT:%.*]] = apply [[FUNC]]() +// CHECK-NEXT: [[GEP:%.*]] = struct_element_addr [[ALLOC_STACK]] +// CHECK-NEXT: destroy_addr [[GEP]] // CHECK-NEXT: br bb3([[RESULT]] : // // CHECK: bb2: @@ -192,6 +188,10 @@ bb3(%5 : @owned $Klass): // CHECK-NEXT: br bb3([[RESULT]] : // CHECK: bb3([[RESULT:%.*]] : +// CHECK-NEXT: [[GEP_1:%.*]] = struct_element_addr [[ALLOC_STACK]] : $*NonTrivialStruct, #NonTrivialStruct.copyableK +// CHECK-NEXT: [[GEP_2:%.*]] = struct_element_addr [[ALLOC_STACK]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialStruct2 +// CHECK-NEXT: destroy_addr [[GEP_1]] +// CHECK-NEXT: destroy_addr [[GEP_2]] // CHECK-NEXT: dealloc_stack [[ALLOC_STACK]] // CHECK-NEXT: return [[RESULT]] // CHECK: } // end sil function 'simpleInitReturnMoveOnlyFieldMultiBlock2' @@ -222,19 +222,15 @@ bb3(%5 : @owned $Klass): // CHECK: bb0([[ARG:%.*]] : @owned $NonTrivialStruct): // CHECK-NEXT: [[ALLOC_STACK:%.*]] = alloc_stack [lexical] // CHECK-NEXT: store [[ARG]] to [init] [[ALLOC_STACK]] -// CHECK-NEXT: [[GEP_1:%.*]] = struct_element_addr [[ALLOC_STACK]] : $*NonTrivialStruct, #NonTrivialStruct.copyableK -// CHECK-NEXT: [[GEP_2:%.*]] = struct_element_addr [[ALLOC_STACK]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialStruct2 -// CHECK-NEXT: destroy_addr [[GEP_1]] -// CHECK-NEXT: destroy_addr [[GEP_2]] // CHECK-NEXT: cond_br undef, bb1, bb2 // // CHECK: bb1: -// CHECK-NEXT: [[GEP:%.*]] = struct_element_addr [[ALLOC_STACK]] -// CHECK-NEXT: destroy_addr [[GEP]] // CHECK-NEXT: function_ref get_klass // CHECK-NEXT: [[FUNC:%.*]] = function_ref @get_klass : // CHECK-NEXT: [[RESULT:%.*]] = apply [[FUNC]]() // CHECK-NEXT: [[GEP:%.*]] = struct_element_addr [[ALLOC_STACK]] +// CHECK-NEXT: [[GEPP:%.*]] = struct_element_addr [[ALLOC_STACK]] +// CHECK-NEXT: destroy_addr [[GEPP]] // CHECK-NEXT: store [[RESULT]] to [init] [[GEP]] // CHECK-NEXT: [[RESULT:%.*]] = load [take] [[GEP]] // CHECK-NEXT: br bb3([[RESULT]] : @@ -245,6 +241,10 @@ bb3(%5 : @owned $Klass): // CHECK-NEXT: br bb3([[RESULT]] : // // CHECK: bb3([[RESULT:%.*]] : +// CHECK-NEXT: [[GEP_1:%.*]] = struct_element_addr [[ALLOC_STACK]] : $*NonTrivialStruct, #NonTrivialStruct.copyableK +// CHECK-NEXT: [[GEP_2:%.*]] = struct_element_addr [[ALLOC_STACK]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialStruct2 +// CHECK-NEXT: destroy_addr [[GEP_1]] +// CHECK-NEXT: destroy_addr [[GEP_2]] // CHECK-NEXT: dealloc_stack [[ALLOC_STACK]] // CHECK-NEXT: return [[RESULT]] // CHECK: } // end sil function 'simpleInitReturnMoveOnlyFieldMultiBlock3' @@ -310,8 +310,8 @@ bb0(%arg : @owned $Klass): // CHECK-LABEL: sil [ossa] @classSimpleNonConsumingUseTest : $@convention(thin) (@owned Klass, @owned Klass) -> () { // CHECK: [[STACK:%.*]] = alloc_stack [lexical] $Klass, var, name "x2" // CHECK: store {{%.*}} to [init] [[STACK]] -// CHECK: destroy_addr [[STACK]] // CHECK: [[ACCESS:%.*]] = begin_access [modify] [static] [[STACK]] +// CHECK: destroy_addr [[STACK]] // CHECK: store {{%.*}} to [init] [[ACCESS]] // CHECK: end_access [[ACCESS]] // CHECK: [[ACCESS:%.*]] = begin_access [read] [static] [[STACK]] @@ -575,3 +575,120 @@ bb0(%0 : @owned $NonTrivialStruct): %9999 = tuple() return %9999 : $() } + +@_moveOnly +struct M { + deinit {} +} +@_moveOnly +struct M2 { + let s1: M + let s2: M +} + +sil @get_M2 : $@convention(thin) () -> @owned M2 +sil @end_addr_see_addr : $@convention(thin) (@in M, @in_guaranteed M) -> () + +/// A single instruction, apply @end_addr_see_addr, consumes one field and +/// borrows another. + +/// Varify that the consumed value isn't destroyed twice and that the borrowed +/// value isn't destroyed before it's used. +/// +/// Note: This test case doesn't have valid SIL (#M2.s1 is consumed twice), but +/// the invalidity wasn't the cause of the miscompile. With the fix, this +/// is transformed into valid SIL. +/// +/// Once verification is enabled, feel free to modify this test case to +/// have a destroy_addr of %second_addr instead, though not that this will +/// no longer verify the fix. +// CHECK-LABEL: sil [ossa] @rdar110909290 : {{.*}} { +// CHECK: [[STACK:%[^,]+]] = alloc_stack $M2 +// CHECK: [[GET_M2:%[^,]+]] = function_ref @get_M2 +// CHECK: [[M2:%[^,]+]] = apply [[GET_M2]]() +// CHECK: store [[M2]] to [init] [[STACK]] : $*M2 +// CHECK-NOT: destroy_addr +// CHECK: [[S1_ADDR:%[^,]+]] = struct_element_addr [[STACK]] : $*M2, #M2.s1 +// CHECK: [[S2_ADDR:%[^,]+]] = struct_element_addr [[STACK]] : $*M2, #M2.s2 +// CHECK: [[END_ADDR_SEE_ADDR:%[^,]+]] = function_ref @end_addr_see_addr +// CHECK: apply [[END_ADDR_SEE_ADDR]]([[S1_ADDR]], [[S2_ADDR]]) +// CHECK-NOT: struct_element_addr [[STACK]] : $*M2, #M2.s1 +// CHECK: [[S2_ADDR_2:%[^,]+]] = struct_element_addr [[STACK]] : $*M2, #M2.s2 +// CHECK: destroy_addr [[S2_ADDR_2]] : $*M +// CHECK-LABEL: } // end sil function 'rdar110909290' +sil [ossa] @rdar110909290 : $@convention(thin) () -> () { +bb0: + %0 = alloc_stack $M2 + %1 = mark_must_check [consumable_and_assignable] %0 : $*M2 + %3 = function_ref @get_M2 : $@convention(thin) () -> @owned M2 + %4 = apply %3() : $@convention(thin) () -> @owned M2 + store %4 to [init] %1 : $*M2 + %first_addr = struct_element_addr %1 : $*M2, #M2.s1 + %second_addr = struct_element_addr %1 : $*M2, #M2.s2 + %end_addr_see_addr = function_ref @end_addr_see_addr : $@convention(thin) (@in M, @in_guaranteed M) -> () + apply %end_addr_see_addr(%first_addr, %second_addr) : $@convention(thin) (@in M, @in_guaranteed M) -> () + destroy_addr %1 : $*M2 + dealloc_stack %0 : $*M2 + %22 = tuple () + return %22 : $() +} + +@_moveOnly +struct M4 { + let s1: M + let s2: M + let s3: M + let s4: M +} + +sil @get_M4 : $@convention(thin) () -> @owned M4 +sil @end_2 : $@convention(thin) (@owned M, @owned M) -> () +sil @see_addr_2 : $@convention(thin) (@in_guaranteed M, @in_guaranteed M) -> () + + +/// Two non-contiguous fields (#M4.s2, #M4.s4) are borrowed by @see_addr_2. +/// Two non-contiguous fields (#M4.s1, #M$.s3) are consumed by @end_2. +/// +/// Verify that #M4.s2 and #M4.s4 both survive past the apply of @see_addr_2. +// CHECK-LABEL: sil [ossa] @rdar110676577 : {{.*}} { +// CHECK: [[STACK:%[^,]+]] = alloc_stack $M4 +// CHECK: [[GET_M4:%[^,]+]] = function_ref @get_M4 +// CHECK: [[M4:%[^,]+]] = apply [[GET_M4]]() : $@convention(thin) () -> @owned M4 +// CHECK: store [[M4]] to [init] [[STACK]] : $*M4 +// CHECK: [[M4_S2_ADDR:%[^,]+]] = struct_element_addr [[STACK]] : $*M4, #M4.s2 +// CHECK: [[M4_S4_ADDR:%[^,]+]] = struct_element_addr [[STACK]] : $*M4, #M4.s4 +// CHECK: [[SEE_ADDR_2:%[^,]+]] = function_ref @see_addr_2 +// CHECK: apply [[SEE_ADDR_2]]([[M4_S2_ADDR]], [[M4_S4_ADDR]]) +// CHECK: [[M4_S1_ADDR:%[^,]+]] = struct_element_addr [[STACK]] : $*M4, #M4.s1 +// CHECK: [[M4_S1:%[^,]+]] = load [take] [[M4_S1_ADDR]] : $*M +// CHECK: [[M4_S3_ADDR:%[^,]+]] = struct_element_addr [[STACK]] : $*M4, #M4.s3 +// CHECK: [[M4_S3:%[^,]+]] = load [take] [[M4_S3_ADDR]] : $*M +// CHECK: [[END_2:%[^,]+]] = function_ref @end_2 +// CHECK: apply [[END_2]]([[M4_S1]], [[M4_S3]]) +// CHECK: [[M4_S4_ADDR_2:%[^,]+]] = struct_element_addr [[STACK]] : $*M4, #M4.s4 +// CHECK: destroy_addr [[M4_S4_ADDR_2]] +// CHECK: [[M4_S2_ADDR_2:%[^,]+]] = struct_element_addr [[STACK]] : $*M4, #M4.s2 +// CHECK: destroy_addr [[M4_S2_ADDR_2]] +// CHECK-LABEL: } // end sil function 'rdar110676577' +sil [ossa] @rdar110676577 : $@convention(thin) () -> () { +bb0: + %0 = alloc_stack $M4 + %1 = mark_must_check [consumable_and_assignable] %0 : $*M4 + %3 = function_ref @get_M4 : $@convention(thin) () -> @owned M4 + %4 = apply %3() : $@convention(thin) () -> @owned M4 + store %4 to [init] %1 : $*M4 + %6 = struct_element_addr %1 : $*M4, #M4.s2 + %6a = struct_element_addr %1 : $*M4, #M4.s4 + %see_addr_2 = function_ref @see_addr_2 : $@convention(thin) (@in_guaranteed M, @in_guaranteed M) -> () + apply %see_addr_2(%6, %6a) : $@convention(thin) (@in_guaranteed M, @in_guaranteed M) -> () + %12 = struct_element_addr %1 : $*M4, #M4.s1 + %13 = load [copy] %12 : $*M + %14 = struct_element_addr %1 : $*M4, #M4.s3 + %15 = load [copy] %14 : $*M + %16 = function_ref @end_2 : $@convention(thin) (@owned M, @owned M) -> () + %17 = apply %16(%13, %15) : $@convention(thin) (@owned M, @owned M) -> () + destroy_addr %1 : $*M4 + dealloc_stack %0 : $*M4 + %22 = tuple () + return %22 : $() +} diff --git a/test/SILOptimizer/moveonly_addresschecker_debuginfo.sil b/test/SILOptimizer/moveonly_addresschecker_debuginfo.sil index 65b8c312f5a80..13a8ce0f0126f 100644 --- a/test/SILOptimizer/moveonly_addresschecker_debuginfo.sil +++ b/test/SILOptimizer/moveonly_addresschecker_debuginfo.sil @@ -50,13 +50,13 @@ bb1: // CHECK: [[BORROW:%.*]] = load_borrow [[STACK]] // CHECK: apply {{%.*}}([[BORROW]]) // CHECK-NEXT: end_borrow [[BORROW]] -// CHECK-NEXT: destroy_addr [[STACK]] -// CHECK-NEXT: debug_value undef : $*NonTrivialStruct, let, name "v" // {{.*}}; line:[[DEBUG_LOC]] // CHECK: br bb3 // // CHECK: bb2: -// CHECK-NEXT: destroy_addr [[STACK]] +// CHECK-NEXT: br bb3 +// CHECK: bb3: // CHECK-NEXT: debug_value undef : $*NonTrivialStruct, let, name "v" // {{.*}}; line:[[DEBUG_LOC]] +// CHECK-NEXT: destroy_addr [[STACK]] // CHECK: } // end sil function 'non_lifetime_ending_use_test_boundary_edge' sil [ossa] @non_lifetime_ending_use_test_boundary_edge : $@convention(thin) () -> () { %f = function_ref @get_nontrivial_struct : $@convention(thin) () -> @owned NonTrivialStruct diff --git a/test/SILOptimizer/moveonly_addresschecker_maximize.sil b/test/SILOptimizer/moveonly_addresschecker_maximize.sil new file mode 100644 index 0000000000000..e47ba09276d66 --- /dev/null +++ b/test/SILOptimizer/moveonly_addresschecker_maximize.sil @@ -0,0 +1,1130 @@ +// RUN: %target-sil-opt -sil-move-only-address-checker -enable-sil-verify-all %s | %FileCheck %s +sil_stage raw + +import Builtin + +// ############################################################################# +// ############################################################################# +// SCALAR STORAGE {{ +// ############################################################################# +// ############################################################################# + +sil [ossa] @condition : $@convention(thin) () -> Builtin.Int1 + +@_moveOnly struct S { + deinit +} + +sil [ossa] @get : $@convention(thin) () -> @out S +sil [ossa] @get_value : $@convention(thin) () -> @owned S + +sil [ossa] @see : $@convention(thin) (@guaranteed S) -> () +sil [ossa] @see_addr : $@convention(thin) (@in_guaranteed S) -> () + +sil [ossa] @end : $@convention(thin) (@owned S) -> () +sil [ossa] @end_addr : $@convention(thin) (@in S) -> () + +sil [ossa] @other : $@convention(thin) () -> () + +// ============================================================================= +// ============================================================================= +// Single def {{ +// ============================================================================= +// ============================================================================= + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Single block {{ +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// A load-copy of the value is passed to a value-consuming function, and the +// storage is destroyed at function end. +// +// Ensure that there is no copy and the lifetime ends at the value-consume. +// CHECK-LABEL: sil [ossa] @singleblock_consume_value_before_other : {{.*}} { +// CHECK: [[OTHER:%[^,]+]] = function_ref @other +// CHECK: [[GET_VALUE:%[^,]+]] = function_ref @get_value +// CHECK: [[END:%[^,]+]] = function_ref @end +// CHECK: [[STACK:%[^,]+]] = alloc_stack +// CHECK: [[INSTANCE:%[^,]+]] = apply [[GET_VALUE]]() +// CHECK: store [[INSTANCE]] to [init] [[STACK]] +// CHECK: [[ACCESS:%[^,]+]] = begin_access [modify] [static] [[STACK]] +// CHECK: [[INSTANCE_RELOAD:%[^,]+]] = load [take] [[ACCESS]] +// CHECK: apply [[END]]([[INSTANCE_RELOAD]]) +// CHECK: end_access [[ACCESS]] +// CHECK: apply [[OTHER]]() +// CHECK: dealloc_stack [[STACK]] +// CHECK-LABEL: } // end sil function 'singleblock_consume_value_before_other' +sil [ossa] @singleblock_consume_value_before_other : $@convention(thin) () -> () { +bb0: + %other = function_ref @other : $@convention(thin) () -> () + %get_value = function_ref @get_value : $@convention(thin) () -> @owned S + %end = function_ref @end : $@convention(thin) (@owned S) -> () + + %stack_addr = alloc_stack $S + %stack = mark_must_check [consumable_and_assignable] %stack_addr : $*S + %instance = apply %get_value() : $@convention(thin) () -> @owned S + store %instance to [init] %stack : $*S + %access = begin_access [deinit] [static] %stack : $*S + %instance_reload = load [copy] %access : $*S + apply %end(%instance_reload) : $@convention(thin) (@owned S) -> () + end_access %access : $*S + %18 = apply %other() : $@convention(thin) () -> () + destroy_addr %stack : $*S + dealloc_stack %stack_addr : $*S + %retval = tuple () + return %retval : $() +} + +// A load-copy of the value is passed to a value-borrowing function then +// destroyed, and the storage is destroyed at function end. +// +// Ensure that there is no copy and the lifetime ends at function end. +// CHECK-LABEL: sil [ossa] @singleblock_borrow_before_other : {{.*}} { +// CHECK: [[OTHER:%[^,]+]] = function_ref @other +// CHECK: [[GET_VALUE:%[^,]+]] = function_ref @get_value +// CHECK: [[SEE:%[^,]+]] = function_ref @see +// CHECK: [[STACK:%[^,]+]] = alloc_stack +// CHECK: [[INSTANCE:%[^,]+]] = apply [[GET_VALUE]]() +// CHECK: store [[INSTANCE]] to [init] [[STACK]] +// CHECK: [[ACCESS:%[^,]+]] = begin_access [deinit] [static] [[STACK]] +// CHECK: [[BORROW:%[^,]+]] = load_borrow [[ACCESS]] +// CHECK: apply [[SEE]]([[BORROW]]) +// CHECK: end_borrow [[BORROW]] +// CHECK: end_access [[ACCESS]] +// CHECK: apply [[OTHER]]() +// CHECK: destroy_addr [[STACK]] +// CHECK: dealloc_stack [[STACK]] +// CHECK-LABEL: } // end sil function 'singleblock_borrow_before_other' +sil [ossa] @singleblock_borrow_before_other : $@convention(thin) () -> () { +bb0: + %other = function_ref @other : $@convention(thin) () -> () + %get_value = function_ref @get_value : $@convention(thin) () -> @owned S + %see = function_ref @see : $@convention(thin) (@guaranteed S) -> () + %end = function_ref @end : $@convention(thin) (@owned S) -> () + + %stack_addr = alloc_stack $S + %stack = mark_must_check [consumable_and_assignable] %stack_addr : $*S + %instance = apply %get_value() : $@convention(thin) () -> @owned S + store %instance to [init] %stack : $*S + %access = begin_access [deinit] [static] %stack : $*S + %instance_reload = load [copy] %access : $*S + apply %see(%instance_reload) : $@convention(thin) (@guaranteed S) -> () + destroy_value %instance_reload : $S + end_access %access : $*S + %18 = apply %other() : $@convention(thin) () -> () + destroy_addr %stack : $*S + dealloc_stack %stack_addr : $*S + %retval = tuple () + return %retval : $() +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// }} Single block +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Multiple blocks {{ +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// There is a consuming use in right. So bottom is a consumed block. Liveness +// is retracted up to the consume in right and up to the bottom of left. +// CHECK-LABEL: sil [ossa] @diamond__consume_r__use_l__destroy_b : {{.*}} { +// CHECK: [[STACK:%[^,]+]] = alloc_stack +// CHECK: [[GET:%[^,]+]] = function_ref @get +// CHECK: [[OTHER:%[^,]+]] = function_ref @other +// CHECK: [[SEE_ADDR:%[^,]+]] = function_ref @see_addr +// CHECK: [[END:%[^,]+]] = function_ref @end +// CHECK: apply [[GET]]([[STACK]]) +// CHECK: cond_br undef, [[LEFT:bb[0-9]+]], [[RIGHT:bb[0-9]+]] +// CHECK: [[LEFT:bb[0-9]+]]: +// CHECK: apply [[SEE_ADDR]]([[STACK]]) +// CHECK: apply [[OTHER]]() +// CHECK: destroy_addr [[STACK]] +// CHECK: br [[BOTTOM:bb[0-9]+]] +// CHECK: [[RIGHT:bb[0-9]+]]: +// CHECK: [[INSTANCE:%[^,]+]] = load [take] [[STACK]] +// CHECK: apply [[END]]([[INSTANCE]]) +// CHECK: br [[BOTTOM]] +// CHECK: [[BOTTOM]]: +// CHECK-LABEL: } // end sil function 'diamond__consume_r__use_l__destroy_b' +sil [ossa] @diamond__consume_r__use_l__destroy_b : $@convention(thin) () -> () { +top: + %stack_addr = alloc_stack $S + %stack = mark_must_check [consumable_and_assignable] %stack_addr : $*S + %get = function_ref @get : $@convention(thin) () -> @out S + %other = function_ref @other : $@convention(thin) () -> () + %see = function_ref @see : $@convention(thin) (@guaranteed S) -> () + %see_addr = function_ref @see_addr : $@convention(thin) (@in_guaranteed S) -> () + %end = function_ref @end : $@convention(thin) (@owned S) -> () + %end_addr = function_ref @end_addr : $@convention(thin) (@in S) -> () + apply %get(%stack) : $@convention(thin) () -> @out S + cond_br undef, left, right +left: + apply %see_addr(%stack) : $@convention(thin) (@in_guaranteed S) -> () + apply %other() : $@convention(thin) () -> () + br bottom +right: + %copy = load [copy] %stack : $*S + apply %end(%copy) : $@convention(thin) (@owned S) -> () + br bottom +bottom: + destroy_addr %stack : $*S + dealloc_stack %stack_addr : $*S + %retval = tuple () + return %retval : $() +} + +// Only bottom is consumedAtEntry. +// CHECK-LABEL: sil [ossa] @diamond_2r__consume_r1r2__use_l__destroy_b : {{.*}} { +// CHECK: [[STACK:%[^,]+]] = alloc_stack +// CHECK: [[GET:%[^,]+]] = function_ref @get +// CHECK: [[SEE:%[^,]+]] = function_ref @see +// CHECK: [[END:%[^,]+]] = function_ref @end +// CHECK: apply [[GET]]([[STACK]]) +// CHECK: cond_br undef, [[LEFT:bb[0-9]+]], [[RIGHT:bb[0-9]+]] +// CHECK: [[LEFT]]: +// CHECK: [[BORROW:%[^,]+]] = load_borrow [[STACK]] +// CHECK: apply [[SEE]]([[BORROW]]) +// CHECK: end_borrow [[BORROW]] +// CHECK: destroy_addr [[STACK]] +// CHECK: br [[BOTTOM:bb[0-9]+]] +// CHECK: [[RIGHT]]: +// CHECK: [[BORROW_2:%[^,]+]] = load_borrow [[STACK]] +// CHECK: apply [[SEE]]([[BORROW_2]]) +// CHECK: end_borrow [[BORROW_2]] +// CHECK: br [[RIGHT_2:bb[0-9]+]] +// CHECK: [[RIGHT_2]]: +// CHECK: [[TAKE:%[^,]+]] = load [take] [[STACK]] +// CHECK: apply [[END]]([[TAKE]]) +// CHECK: br [[BOTTOM]] +// CHECK: [[BOTTOM]]: +// CHECK-LABEL: } // end sil function 'diamond_2r__consume_r1r2__use_l__destroy_b' +sil [ossa] @diamond_2r__consume_r1r2__use_l__destroy_b : $@convention(thin) () -> () { +top: + %stack_addr = alloc_stack $S + %stack = mark_must_check [consumable_and_assignable] %stack_addr : $*S + %get = function_ref @get : $@convention(thin) () -> @out S + %other = function_ref @other : $@convention(thin) () -> () + %see = function_ref @see : $@convention(thin) (@guaranteed S) -> () + %see_addr = function_ref @see_addr : $@convention(thin) (@in_guaranteed S) -> () + %end = function_ref @end : $@convention(thin) (@owned S) -> () + %end_addr = function_ref @end_addr : $@convention(thin) (@in S) -> () + apply %get(%stack) : $@convention(thin) () -> @out S + cond_br undef, left, right +left: + %copy3 = load [copy] %stack : $*S + apply %see(%copy3) : $@convention(thin) (@guaranteed S) -> () + destroy_value %copy3 : $S + br bottom +right: + %copy = load [copy] %stack : $*S + apply %see(%copy) : $@convention(thin) (@guaranteed S) -> () + destroy_value %copy : $S + br right2 +right2: + %copy2 = load [copy] %stack : $*S + apply %end(%copy2) : $@convention(thin) (@owned S) -> () + br bottom +bottom: + destroy_addr %stack : $*S + dealloc_stack %stack_addr : $*S + %retval = tuple () + return %retval : $() +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// }} Multiple blocks +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// ============================================================================= +// ============================================================================= +// }} Single def +// ============================================================================= +// ============================================================================= + +// ============================================================================= +// ============================================================================= +// Multiple defs {{ +// ============================================================================= +// ============================================================================= + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Multiple blocks {{ +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// Like diamond__consume_r__use_l__destroy_b but with a copy_addr [take] reinit +// in left. The reinit is after an apply of other. +// +// Ensure that the destroy from that deinit remains at the same location--it +// will be split into a separate instruction. +// +// TODO: Avoid the unnecessary churn of that splitting. +// CHECK-LABEL: sil [ossa] @diamond__consume_r__reinit_l__use_l__destroy_b : {{.*}} { +// CHECK: [[STACK:%[^,]+]] = alloc_stack +// CHECK: [[GET:%[^,]+]] = function_ref @get +// CHECK: [[OTHER:%[^,]+]] = function_ref @other +// CHECK: [[SEE_ADDR:%[^,]+]] = function_ref @see_addr +// CHECK: [[END:%[^,]+]] = function_ref @end +// CHECK: apply [[GET]]([[STACK]]) +// CHECK: cond_br undef, [[LEFT:bb[0-9]+]], [[RIGHT:bb[0-9]+]] +// CHECK: [[LEFT:bb[0-9]+]]: +// CHECK: apply [[OTHER]]() +// CHECK: destroy_addr [[STACK]] +// CHECK: apply [[SEE_ADDR]]([[STACK]]) +// CHECK: apply [[OTHER]]() +// CHECK: destroy_addr [[STACK]] +// CHECK: br [[BOTTOM:bb[0-9]+]] +// CHECK: [[RIGHT:bb[0-9]+]]: +// CHECK: [[INSTANCE:%[^,]+]] = load [take] [[STACK]] +// CHECK: apply [[END]]([[INSTANCE]]) +// CHECK: br [[BOTTOM]] +// CHECK: [[BOTTOM]]: +// CHECK-LABEL: } // end sil function 'diamond__consume_r__reinit_l__use_l__destroy_b' +sil [ossa] @diamond__consume_r__reinit_l__use_l__destroy_b : $@convention(thin) () -> () { +top: + %stack_addr = alloc_stack $S + %stack = mark_must_check [consumable_and_assignable] %stack_addr : $*S + %get = function_ref @get : $@convention(thin) () -> @out S + %other = function_ref @other : $@convention(thin) () -> () + %see = function_ref @see : $@convention(thin) (@guaranteed S) -> () + %see_addr = function_ref @see_addr : $@convention(thin) (@in_guaranteed S) -> () + %end = function_ref @end : $@convention(thin) (@owned S) -> () + %end_addr = function_ref @end_addr : $@convention(thin) (@in S) -> () + apply %get(%stack) : $@convention(thin) () -> @out S + cond_br undef, left, right +left: + apply %other() : $@convention(thin) () -> () + %stack2 = alloc_stack $S + apply %get(%stack2) : $@convention(thin) () -> @out S + copy_addr [take] %stack2 to %stack : $*S + dealloc_stack %stack2 : $*S + apply %see_addr(%stack) : $@convention(thin) (@in_guaranteed S) -> () + apply %other() : $@convention(thin) () -> () + br bottom +right: + %copy = load [copy] %stack : $*S + apply %end(%copy) : $@convention(thin) (@owned S) -> () + br bottom +bottom: + destroy_addr %stack : $*S + dealloc_stack %stack_addr : $*S + %retval = tuple () + return %retval : $() +} + +// Like diamond__consume_r__reinit_l__use_l__destroy_b with a store [assign] +// reinit in left. The reinit is after an apply of other. +// +// Ensure that the destroy from that deinit remains at the same location--it +// will be split into a separate instruction. +// +// TODO: Avoid the unnecessary churn of that splitting. +// CHECK-LABEL: sil [ossa] @diamond__consume_r__reinit_l__use_l__destroy_b2 : {{.*}} { +// CHECK: [[STACK:%[^,]+]] = alloc_stack +// CHECK: [[GET:%[^,]+]] = function_ref @get +// CHECK: [[OTHER:%[^,]+]] = function_ref @other +// CHECK: [[SEE_ADDR:%[^,]+]] = function_ref @see_addr +// CHECK: [[END:%[^,]+]] = function_ref @end +// CHECK: apply [[GET]]([[STACK]]) +// CHECK: cond_br undef, [[LEFT:bb[0-9]+]], [[RIGHT:bb[0-9]+]] +// CHECK: [[LEFT:bb[0-9]+]]: +// CHECK: apply [[OTHER]]() +// CHECK: destroy_addr [[STACK]] +// CHECK: apply [[SEE_ADDR]]([[STACK]]) +// CHECK: apply [[OTHER]]() +// CHECK: destroy_addr [[STACK]] +// CHECK: br [[BOTTOM:bb[0-9]+]] +// CHECK: [[RIGHT:bb[0-9]+]]: +// CHECK: [[INSTANCE:%[^,]+]] = load [take] [[STACK]] +// CHECK: apply [[END]]([[INSTANCE]]) +// CHECK: br [[BOTTOM]] +// CHECK: [[BOTTOM]]: +// CHECK-LABEL: } // end sil function 'diamond__consume_r__reinit_l__use_l__destroy_b2' +sil [ossa] @diamond__consume_r__reinit_l__use_l__destroy_b2 : $@convention(thin) () -> () { +top: + %stack_addr = alloc_stack $S + %stack = mark_must_check [consumable_and_assignable] %stack_addr : $*S + %get = function_ref @get : $@convention(thin) () -> @out S + %get_value = function_ref @get_value : $@convention(thin) () -> @owned S + %other = function_ref @other : $@convention(thin) () -> () + %see = function_ref @see : $@convention(thin) (@guaranteed S) -> () + %see_addr = function_ref @see_addr : $@convention(thin) (@in_guaranteed S) -> () + %end = function_ref @end : $@convention(thin) (@owned S) -> () + %end_addr = function_ref @end_addr : $@convention(thin) (@in S) -> () + apply %get(%stack) : $@convention(thin) () -> @out S + cond_br undef, left, right +left: + apply %other() : $@convention(thin) () -> () + %new = apply %get_value() : $@convention(thin) () -> @owned S + store %new to [assign] %stack : $*S + apply %see_addr(%stack) : $@convention(thin) (@in_guaranteed S) -> () + apply %other() : $@convention(thin) () -> () + br bottom +right: + %copy = load [copy] %stack : $*S + apply %end(%copy) : $@convention(thin) (@owned S) -> () + br bottom +bottom: + destroy_addr %stack : $*S + dealloc_stack %stack_addr : $*S + %retval = tuple () + return %retval : $() +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// }} Multiple blocks +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// ============================================================================= +// ============================================================================= +// }} Multiple defs +// ============================================================================= +// ============================================================================= + +// ############################################################################# +// ############################################################################# +// }} SCALAR STORAGE +// ############################################################################# +// ############################################################################# + +// ############################################################################# +// ############################################################################# +// AGGREGATE STORAGE {{ +// ############################################################################# +// ############################################################################# + +@_moveOnly struct S2 { + var s1: S + var s2: S +} + +sil [ossa] @get_value_S2 : $@convention(thin) () -> @owned S2 +sil [ossa] @end_S2 : $@convention(thin) (@owned S2) -> () + +@_moveOnly struct S3 { + var s1: S + var s2: S + var s3: S +} + +sil [ossa] @get_value_S3 : $@convention(thin) () -> @owned S3 +sil [ossa] @end_S3 : $@convention(thin) (@owned S3) -> () + +// ============================================================================= +// ============================================================================= +// Single def {{ +// ============================================================================= +// ============================================================================= + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Single block {{ +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// The apply of other remains before the destroy_addr. +// CHECK-LABEL: sil [ossa] @aggregate_1 : {{.*}} { +// CHECK: [[OTHER:%[^,]+]] = function_ref @other +// CHECK: [[STACK:%[^,]+]] = alloc_stack +// CHECK: apply [[OTHER]]() +// CHECK: destroy_addr [[STACK]] +// CHECK-LABEL: } // end sil function 'aggregate_1' +sil [ossa] @aggregate_1 : $@convention(thin) () -> () { +bb0: + %get_value_S2 = function_ref @get_value_S2 : $@convention(thin) () -> @owned S2 + %end = function_ref @end : $@convention(thin) (@owned S) -> () + %other = function_ref @other : $@convention(thin) () -> () + + %stack_addr = alloc_stack $S2 + %stack = mark_must_check [consumable_and_assignable] %stack_addr : $*S2 + %instance_1 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + store %instance_1 to [init] %stack : $*S2 + apply %other() : $@convention(thin) () -> () + destroy_addr %stack : $*S2 + dealloc_stack %stack_addr : $*S2 + %retval = tuple () + return %retval : $() +} + + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// }} Single block +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// ============================================================================= +// ============================================================================= +// }} Single def +// ============================================================================= +// ============================================================================= + +// ============================================================================= +// ============================================================================= +// Multiple defs {{ +// ============================================================================= +// ============================================================================= + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Single block {{ +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// Calls to other before each destroy remain before. +// CHECK-LABEL: sil [ossa] @aggregate_2 : {{.*}} { +// CHECK: [[OTHER:%[^,]+]] = function_ref @other +// CHECK: [[STACK:%[^,]+]] = alloc_stack +// CHECK: apply [[OTHER]]() +// CHECK: destroy_addr [[STACK]] : $*S2 +// CHECK: apply [[OTHER]]() +// CHECK: destroy_addr [[STACK]] : $*S2 +// CHECK-LABEL: } // end sil function 'aggregate_2' +sil [ossa] @aggregate_2 : $@convention(thin) () -> () { +bb0: + %get_value_S2 = function_ref @get_value_S2 : $@convention(thin) () -> @owned S2 + %end = function_ref @end : $@convention(thin) (@owned S) -> () + %other = function_ref @other : $@convention(thin) () -> () + + %stack_addr = alloc_stack $S2 + %stack = mark_must_check [consumable_and_assignable] %stack_addr : $*S2 + %instance_1 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + store %instance_1 to [init] %stack : $*S2 + %instance_2 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + apply %other() : $@convention(thin) () -> () + store %instance_2 to [assign] %stack : $*S2 + apply %other() : $@convention(thin) () -> () + destroy_addr %stack : $*S2 + dealloc_stack %stack_addr : $*S2 + %retval = tuple () + return %retval : $() +} + +// s1 is consumed but s2 is not and so is not destroyed until function end, after +// other. + +// CHECK-LABEL: sil [ossa] @simpleTestVar2 : {{.*}} { +// CHECK: [[OTHER:%[^,]+]] = function_ref @other +// CHECK: [[STACK:%[^,]+]] = alloc_stack +// CHECK: apply [[OTHER]]() +// CHECK: [[S2_ADDR:%[^,]+]] = struct_element_addr [[STACK]] : $*S2, #S2.s2 +// CHECK: destroy_addr [[S2_ADDR]] +// CHECK-LABEL: } // end sil function 'simpleTestVar2' +sil [ossa] @simpleTestVar2 : $@convention(thin) () -> () { +bb0: + %get_value_S2 = function_ref @get_value_S2 : $@convention(thin) () -> @owned S2 + %end = function_ref @end : $@convention(thin) (@owned S) -> () + %other = function_ref @other : $@convention(thin) () -> () + + %stack_addr = alloc_stack $S2 + %stack = mark_must_check [consumable_and_assignable] %stack_addr : $*S2 + %instance_1 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + store %instance_1 to [init] %stack : $*S2 + %instance_2 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + %access = begin_access [modify] [static] %stack : $*S2 + store %instance_2 to [assign] %access : $*S2 + end_access %access : $*S2 + %access_2 = begin_access [deinit] [static] %stack : $*S2 + %s1_addr = struct_element_addr %access_2 : $*S2, #S2.s1 + %s1 = load [copy] %s1_addr : $*S + apply %end(%s1) : $@convention(thin) (@owned S) -> () + end_access %access_2 : $*S2 + apply %other() : $@convention(thin) () -> () + destroy_addr %stack : $*S2 + dealloc_stack %stack_addr : $*S2 + %retval = tuple () + return %retval : $() +} + +// Both fields (#S2.s1, #S2.s2) are consumed before other. +// CHECK-LABEL: sil [ossa] @simpleTestVar3 : {{.*}} { +// CHECK: [[END:%[^,]+]] = function_ref @end +// CHECK: [[OTHER:%[^,]+]] = function_ref @other +// CHECK: [[STACK:%[^,]+]] = alloc_stack +// CHECK: begin_access +// CHECK: [[ACCESS_1:%[^,]+]] = begin_access [modify] [static] [[STACK]] +// CHECK: [[S1_ADDR:%[^,]+]] = struct_element_addr [[ACCESS_1]] : $*S2, #S2.s1 +// CHECK: [[S1:%[^,]+]] = load [take] [[S1_ADDR]] +// CHECK: apply [[END]]([[S1]]) +// CHECK: [[ACCESS_2:%[^,]+]] = begin_access [modify] [static] [[STACK]] +// CHECK: [[S2_ADDR:%[^,]+]] = struct_element_addr [[ACCESS_2]] : $*S2, #S2.s2 +// CHECK: [[S2:%[^,]+]] = load [take] [[S2_ADDR]] +// CHECK: apply [[END]]([[S2]]) +// CHECK: apply [[OTHER]]() +// CHECK-LABEL: } // end sil function 'simpleTestVar3' +sil [ossa] @simpleTestVar3 : $@convention(thin) () -> () { +bb0: + %get_value_S2 = function_ref @get_value_S2 : $@convention(thin) () -> @owned S2 + %end = function_ref @end : $@convention(thin) (@owned S) -> () + %other = function_ref @other : $@convention(thin) () -> () + + %stack_addr = alloc_stack $S2 + %stack = mark_must_check [consumable_and_assignable] %stack_addr : $*S2 + %instance_1 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + store %instance_1 to [init] %stack : $*S2 + %instance_2 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + %access = begin_access [modify] [static] %stack : $*S2 + store %instance_2 to [assign] %access : $*S2 + end_access %access : $*S2 + %access_2 = begin_access [deinit] [static] %stack : $*S2 + %s1_addr = struct_element_addr %access_2 : $*S2, #S2.s1 + %s1 = load [copy] %s1_addr : $*S + apply %end(%s1) : $@convention(thin) (@owned S) -> () + end_access %access_2 : $*S2 + %access_3 = begin_access [deinit] [static] %stack : $*S2 + %s2_addr = struct_element_addr %access_3 : $*S2, #S2.s2 + %s2 = load [copy] %s2_addr : $*S + apply %end(%s2) : $@convention(thin) (@owned S) -> () + end_access %access_3 : $*S2 + apply %other() : $@convention(thin) () -> () + destroy_addr %stack : $*S2 + dealloc_stack %stack_addr : $*S2 + %retval = tuple () + return %retval : $() +} + +// Addr is initialized, then both fields are individually consumed before other. +// Then addr is initialized again and neither field is consumed; then other is +// applied again. +// +// Ensure that the reinitialized fields survive to function end. +// +// CHECK-LABEL: sil [ossa] @simpleTestVar3a : {{.*}} { +// CHECK: [[GET_VALUE_S2:%[^,]+]] = function_ref @get_value_S2 +// CHECK: [[OTHER:%[^,]+]] = function_ref @other +// CHECK: [[STACK:%[^,]+]] = alloc_stack +// CHECK: apply [[OTHER]]() +// CHECK: [[INSTANCE_3:%[^,]+]] = apply [[GET_VALUE_S2]]() +// CHECK: [[ACCESS:%[^,]+]] = begin_access [modify] [static] [[STACK]] +// CHECK: store [[INSTANCE_3]] to [init] [[ACCESS]] +// CHECK: end_access [[ACCESS]] +// CHECK: apply [[OTHER]]() : $@convention(thin) () -> () +// CHECK: destroy_addr [[STACK]] +// CHECK-LABEL: } // end sil function 'simpleTestVar3a' +sil [ossa] @simpleTestVar3a : $@convention(thin) () -> () { +bb0: + %get_value_S2 = function_ref @get_value_S2 : $@convention(thin) () -> @owned S2 + %end = function_ref @end : $@convention(thin) (@owned S) -> () + %other = function_ref @other : $@convention(thin) () -> () + + %stack_addr = alloc_stack $S2 + %stack = mark_must_check [consumable_and_assignable] %stack_addr : $*S2 + %instance_1 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + store %instance_1 to [init] %stack : $*S2 + %instance_2 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + %access_1 = begin_access [modify] [static] %stack : $*S2 + store %instance_2 to [assign] %access_1 : $*S2 + end_access %access_1 : $*S2 + %access_2 = begin_access [deinit] [static] %stack : $*S2 + %s1_addr = struct_element_addr %access_2 : $*S2, #S2.s1 + %s1 = load [copy] %s1_addr : $*S + apply %end(%s1) : $@convention(thin) (@owned S) -> () + end_access %access_2 : $*S2 + %access_3 = begin_access [deinit] [static] %stack : $*S2 + %s2_addr = struct_element_addr %access_3 : $*S2, #S2.s2 + %s2 = load [copy] %s2_addr : $*S + apply %end(%s2) : $@convention(thin) (@owned S) -> () + end_access %access_3 : $*S2 + apply %other() : $@convention(thin) () -> () + %instance_3 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + %access_4 = begin_access [modify] [static] %stack : $*S2 + store %instance_3 to [assign] %access_4 : $*S2 + end_access %access_4 : $*S2 + apply %other() : $@convention(thin) () -> () + destroy_addr %stack : $*S2 + dealloc_stack %stack_addr : $*S2 + %retval = tuple () + return %retval : $() +} + +// Like simpleTestVar3a but without access scopes and the original init. +// CHECK-LABEL: sil [ossa] @simpleTestVar3a_simplified : {{.*}} { +// CHECK: [[GET_VALUE_S2:%[^,]+]] = function_ref @get_value_S2 +// CHECK: [[OTHER:%[^,]+]] = function_ref @other +// CHECK: [[STACK:%[^,]+]] = alloc_stack +// CHECK: apply [[OTHER]]() +// CHECK: [[INSTANCE_2:%[^,]+]] = apply [[GET_VALUE_S2]]() +// CHECK: store [[INSTANCE_2]] to [init] [[STACK]] +// CHECK: apply [[OTHER]]() : $@convention(thin) () -> () +// CHECK: destroy_addr [[STACK]] +// CHECK-LABEL: } // end sil function 'simpleTestVar3a_simplified' +sil [ossa] @simpleTestVar3a_simplified : $@convention(thin) () -> () { +bb0: + %get_value_S2 = function_ref @get_value_S2 : $@convention(thin) () -> @owned S2 + %end = function_ref @end : $@convention(thin) (@owned S) -> () + %other = function_ref @other : $@convention(thin) () -> () + + %stack_addr = alloc_stack $S2 + %stack = mark_must_check [consumable_and_assignable] %stack_addr : $*S2 + %instance_1 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + store %instance_1 to [init] %stack : $*S2 + %s1_addr = struct_element_addr %stack : $*S2, #S2.s1 + %s1 = load [copy] %s1_addr : $*S + apply %end(%s1) : $@convention(thin) (@owned S) -> () + %s2_addr = struct_element_addr %stack : $*S2, #S2.s2 + %s2 = load [copy] %s2_addr : $*S + apply %end(%s2) : $@convention(thin) (@owned S) -> () + apply %other() : $@convention(thin) () -> () + %instance_2 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + store %instance_2 to [assign] %stack : $*S2 + apply %other() : $@convention(thin) () -> () + destroy_addr %stack : $*S2 + dealloc_stack %stack_addr : $*S2 + %retval = tuple () + return %retval : $() +} + +// Ensure that first initialized liveness remains until original destroy. +// And ensure that reinitialized fields live until function exit. +// CHECK-LABEL: sil [ossa] @simpleTestVar3a_simplified_vary2 : {{.*}} { +// CHECK: [[GET_VALUE:%[^,]+]] = function_ref @get_value +// CHECK: [[SEE:%[^,]+]] = function_ref @see +// CHECK: [[OTHER:%[^,]+]] = function_ref @other +// CHECK: [[STACK:%[^,]+]] = alloc_stack $S +// CHECK: [[INSTANCE_1:%[^,]+]] = apply [[GET_VALUE]]() +// CHECK: store [[INSTANCE_1]] to [init] [[STACK]] +// CHECK: [[BORROW:%[^,]+]] = load_borrow [[STACK]] +// CHECK: apply [[SEE]]([[BORROW]]) +// CHECK: end_borrow [[BORROW]] +// CHECK: apply [[OTHER]]() +// CHECK: [[INSTANCE_2:%[^,]+]] = apply [[GET_VALUE]]() +// CHECK: destroy_addr [[STACK]] +// CHECK: store [[INSTANCE_2]] to [init] [[STACK]] +// CHECK: apply [[OTHER]]() +// CHECK: destroy_addr [[STACK]] +// CHECK-LABEL: } // end sil function 'simpleTestVar3a_simplified_vary2' +sil [ossa] @simpleTestVar3a_simplified_vary2 : $@convention(thin) () -> () { +bb0: + %get_value = function_ref @get_value : $@convention(thin) () -> @owned S + %see = function_ref @see : $@convention(thin) (@guaranteed S) -> () + %other = function_ref @other : $@convention(thin) () -> () + + %stack_addr = alloc_stack $S + %stack = mark_must_check [consumable_and_assignable] %stack_addr : $*S + %instance_1 = apply %get_value() : $@convention(thin) () -> @owned S + store %instance_1 to [init] %stack : $*S + %s = load_borrow %stack : $*S + apply %see(%s) : $@convention(thin) (@guaranteed S) -> () + end_borrow %s : $S + apply %other() : $@convention(thin) () -> () + %instance_2 = apply %get_value() : $@convention(thin) () -> @owned S + store %instance_2 to [assign] %stack : $*S + apply %other() : $@convention(thin) () -> () + destroy_addr %stack : $*S + dealloc_stack %stack_addr : $*S + %retval = tuple () + return %retval : $() +} + +// s1 is consumed at @end. s2 is never consumed so it's destroyed at function +// end. +// CHECK-LABEL: sil [ossa] @simpleTestVar3b : {{.*}} { +// CHECK: [[END:%[^,]+]] = function_ref @end +// CHECK: [[OTHER:%[^,]+]] = function_ref @other +// CHECK: [[STACK:%[^,]+]] = alloc_stack +// CHECK: begin_access +// CHECK: [[ACCESS:%[^,]+]] = begin_access [modify] [static] [[STACK]] +// CHECK: [[S1_ADDR:%[^,]+]] = struct_element_addr [[ACCESS]] : $*S2, #S2.s1 +// CHECK: [[S1:%[^,]+]] = load [take] [[S1_ADDR]] +// CHECK: apply [[END]]([[S1]]) +// CHECK: apply [[OTHER]]() +// CHECK: [[S2_ADDR:%[^,]+]] = struct_element_addr [[STACK]] : $*S2, #S2.s2 +// CHECK: destroy_addr [[S2_ADDR]] +// CHECK-LABEL: } // end sil function 'simpleTestVar3b' +sil [ossa] @simpleTestVar3b : $@convention(thin) () -> () { +bb0: + %get_value_S2 = function_ref @get_value_S2 : $@convention(thin) () -> @owned S2 + %end = function_ref @end : $@convention(thin) (@owned S) -> () + %see = function_ref @see : $@convention(thin) (@guaranteed S) -> () + %other = function_ref @other : $@convention(thin) () -> () + + %stack_addr = alloc_stack $S2 + %stack = mark_must_check [consumable_and_assignable] %stack_addr : $*S2 + %instance_1 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + store %instance_1 to [init] %stack : $*S2 + %instance_2 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + %access_1 = begin_access [modify] [static] %stack : $*S2 + store %instance_2 to [assign] %access_1 : $*S2 + end_access %access_1 : $*S2 + %access_2 = begin_access [deinit] [static] %stack : $*S2 + %s1_addr = struct_element_addr %access_2 : $*S2, #S2.s1 + %s1 = load [copy] %s1_addr : $*S + apply %end(%s1) : $@convention(thin) (@owned S) -> () + end_access %access_2 : $*S2 + %access_3 = begin_access [read] [static] %stack : $*S2 + %s2_addr = struct_element_addr %access_3 : $*S2, #S2.s2 + %s2 = load [copy] %s2_addr : $*S + apply %see(%s2) : $@convention(thin) (@guaranteed S) -> () + destroy_value %s2 : $S + end_access %access_3 : $*S2 + apply %other() : $@convention(thin) () -> () + destroy_addr %stack : $*S2 + dealloc_stack %stack_addr : $*S2 + %retval = tuple () + return %retval : $() +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// }} Single block +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// {{ Multiple blocks +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// Ensure that liveness extends to destroy in live-at-entry block where no def +// precedes destroy. And ensure that the reinit stack stays live until +// function exit. +// CHECK-LABEL: sil [ossa] @simpleTestVar3a_simplified_vary : {{.*}} { +// CHECK: [[GET_VALUE_S2:%[^,]+]] = function_ref @get_value_S2 +// CHECK: [[SEE:%[^,]+]] = function_ref @see +// CHECK: [[OTHER:%[^,]+]] = function_ref @other +// CHECK: [[STACK:%[^,]+]] = alloc_stack $S2 +// CHECK: [[INSTANCE_1:%[^,]+]] = apply [[GET_VALUE_S2]]() +// CHECK: store [[INSTANCE_1]] to [init] [[STACK]] +// CHECK: [[S1_ADDR:%[^,]+]] = struct_element_addr [[STACK]] +// CHECK: [[S1:%[^,]+]] = load_borrow [[S1_ADDR]] +// CHECK: apply [[SEE]]([[S1]]) +// CHECK: end_borrow [[S1]] +// CHECK: [[S2_ADDR:%[^,]+]] = struct_element_addr [[STACK]] +// CHECK: [[S2:%[^,]+]] = load_borrow [[S2_ADDR]] +// CHECK: apply [[SEE]]([[S2]]) +// CHECK: end_borrow [[S2]] +// CHECK: apply [[OTHER]]() +// CHECK: [[INSTANCE_2:%[^,]+]] = apply [[GET_VALUE_S2]]() +// CHECK: br bb1 +// CHECK: bb1: +// CHECK: destroy_addr [[STACK]] +// CHECK: store [[INSTANCE_2]] to [init] [[STACK]] +// CHECK: apply [[OTHER]]() +// CHECK: destroy_addr [[STACK]] +// CHECK-LABEL: } // end sil function 'simpleTestVar3a_simplified_vary' +sil [ossa] @simpleTestVar3a_simplified_vary : $@convention(thin) () -> () { +bb0: + %get_value_S2 = function_ref @get_value_S2 : $@convention(thin) () -> @owned S2 + %see = function_ref @see : $@convention(thin) (@guaranteed S) -> () + %other = function_ref @other : $@convention(thin) () -> () + + %stack_addr = alloc_stack $S2 + %stack = mark_must_check [consumable_and_assignable] %stack_addr : $*S2 + %instance_1 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + store %instance_1 to [init] %stack : $*S2 + %s1_addr = struct_element_addr %stack : $*S2, #S2.s1 + %s1 = load_borrow %s1_addr : $*S + apply %see(%s1) : $@convention(thin) (@guaranteed S) -> () + end_borrow %s1 : $S + %s2_addr = struct_element_addr %stack : $*S2, #S2.s2 + %s2 = load_borrow %s2_addr : $*S + apply %see(%s2) : $@convention(thin) (@guaranteed S) -> () + end_borrow %s2 : $S + apply %other() : $@convention(thin) () -> () + %instance_3 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + br bb1 +bb1: + store %instance_3 to [assign] %stack : $*S2 + apply %other() : $@convention(thin) () -> () + destroy_addr %stack : $*S2 + dealloc_stack %stack_addr : $*S2 + %retval = tuple () + return %retval : $() +} + +// Stack is initialized twice, in entry and middle. In each case, it is passed +// to a consuming function on the left block and unused on the right block; and +// each right block contains an apply of other. +// +// Verify that the destroy in each right block is after the apply of other. +// CHECK-LABEL: sil [ossa] @simpleTestVar4 : {{.*}} { +// CHECK: [[OTHER:%[^,]+]] = function_ref @other +// CHECK: [[STACK:%[^,]+]] = alloc_stack +// CHECK: cond_br {{%[^,]+}}, [[LEFT_1:bb[0-9]+]], [[RIGHT_1:bb[0-9]+]] +// CHECK: [[LEFT_1]]: +// CHECK: br [[MIDDLE:bb[0-9]+]] +// CHECK: [[RIGHT_1]]: +// CHECK: apply [[OTHER]]() +// CHECK: destroy_addr [[STACK]] +// CHECK: br [[MIDDLE]] +// CHECK: [[MIDDLE]]: +// CHECK: cond_br {{%[^,]+}}, [[LEFT_2:bb[0-9]+]], [[RIGHT_2:bb[0-9]+]] +// CHECK: [[LEFT_2]]: +// CHECK: br [[EXIT:bb[0-9]+]] +// CHECK: [[RIGHT_2]]: +// CHECK: destroy_addr [[STACK]] +// CHECK: apply [[OTHER]]() : $@convention(thin) () -> () +// CHECK: br [[EXIT]] +// CHECK-LABEL: } // end sil function 'simpleTestVar4' +sil [ossa] @simpleTestVar4 : $@convention(thin) () -> () { +entry: + %get_value_S2 = function_ref @get_value_S2 : $@convention(thin) () -> @owned S2 + %condition = function_ref @condition : $@convention(thin) () -> Builtin.Int1 + %end_S2 = function_ref @end_S2 : $@convention(thin) (@owned S2) -> () + %other = function_ref @other : $@convention(thin) () -> () + + %stack_addr = alloc_stack $S2 + %stack = mark_must_check [consumable_and_assignable] %stack_addr : $*S2 + %instance_1 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + store %instance_1 to [init] %stack : $*S2 + %instance_2 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + %access_1 = begin_access [modify] [static] %stack : $*S2 + store %instance_2 to [assign] %access_1 : $*S2 + end_access %access_1 : $*S2 + %which_1 = apply %condition() : $@convention(thin) () -> Builtin.Int1 + cond_br %which_1, left_1, right_1 + +left_1: + %access_2 = begin_access [deinit] [static] %stack : $*S2 + %reload_1 = load [copy] %access_2 : $*S2 + apply %end_S2(%reload_1) : $@convention(thin) (@owned S2) -> () + end_access %access_2 : $*S2 + br middle + +right_1: + apply %other() : $@convention(thin) () -> () + br middle + +middle: + %instance_3 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + %access_3 = begin_access [modify] [static] %stack : $*S2 + store %instance_3 to [assign] %access_3 : $*S2 + end_access %access_3 : $*S2 + %which_2 = apply %condition() : $@convention(thin) () -> Builtin.Int1 + cond_br %which_2, left_2, right_2 + +left_2: + %access_4 = begin_access [deinit] [static] %stack : $*S2 + %reload_2 = load [copy] %access_4 : $*S2 + apply %end_S2(%reload_2) : $@convention(thin) (@owned S2) -> () + end_access %access_4 : $*S2 + br end + +right_2: + apply %other() : $@convention(thin) () -> () + br end + +end: + %retval = tuple () + destroy_addr %stack : $*S2 + dealloc_stack %stack_addr : $*S2 + return %retval : $() +} + +// One field is consumed in either branch: s1 in left, s2 in right. The other +// field should live until the end of the block. +// CHECK-LABEL: sil [ossa] @simpleTestVar6 : $@convention(thin) () -> () { +// CHECK: [[OTHER:%[^,]+]] = function_ref @other +// CHECK: [[STACK:%[^,]+]] = alloc_stack +// CHECK: cond_br {{%[^,]+}}, [[LEFT:bb[0-9]+]], [[RIGHT:bb[0-9]+]] +// CHECK: [[LEFT]]: +// CHECK: apply [[OTHER]]() +// CHECK: [[S2_ADDR:%[^,]+]] = struct_element_addr [[STACK]] : $*S2, #S2.s2 +// CHECK: destroy_addr [[S2_ADDR]] : $*S +// CHECK: br [[EXIT:bb[0-9]+]] +// CHECK: [[RIGHT]]: +// CHECK: apply [[OTHER]]() +// CHECK: [[S1_ADDR:%[^,]+]] = struct_element_addr [[STACK]] : $*S2, #S2.s1 +// CHECK: destroy_addr [[S1_ADDR]] : $*S +// CHECK: br [[EXIT]] +// CHECK: [[EXIT]]: +// CHECK-LABEL: } // end sil function 'simpleTestVar6' +sil [ossa] @simpleTestVar6 : $@convention(thin) () -> () { +entry: + %get_value_S2 = function_ref @get_value_S2 : $@convention(thin) () -> @owned S2 + %condition = function_ref @condition : $@convention(thin) () -> Builtin.Int1 + %other = function_ref @other : $@convention(thin) () -> () + %end = function_ref @end : $@convention(thin) (@owned S) -> () + + %stack_addr = alloc_stack $S2 + %stack = mark_must_check [consumable_and_assignable] %stack_addr : $*S2 + %instance_1 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + store %instance_1 to [init] %stack : $*S2 + %instance_2 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + %access_1 = begin_access [modify] [static] %stack : $*S2 + store %instance_2 to [assign] %access_1 : $*S2 + end_access %access_1 : $*S2 + %which = apply %condition() : $@convention(thin) () -> Builtin.Int1 + cond_br %which, left, right + +left: + %access_2 = begin_access [deinit] [static] %stack : $*S2 + %s1_addr = struct_element_addr %access_2 : $*S2, #S2.s1 + %s1 = load [copy] %s1_addr : $*S + apply %end(%s1) : $@convention(thin) (@owned S) -> () + end_access %access_2 : $*S2 + apply %other() : $@convention(thin) () -> () + br exit + +right: + %access_3 = begin_access [deinit] [static] %stack : $*S2 + %s2_addr = struct_element_addr %access_3 : $*S2, #S2.s2 + %s2 = load [copy] %s2_addr : $*S + apply %end(%s2) : $@convention(thin) (@owned S) -> () + end_access %access_3 : $*S2 + apply %other() : $@convention(thin) () -> () + br exit + +exit: + %instance_3 = apply %get_value_S2() : $@convention(thin) () -> @owned S2 + %access_4 = begin_access [modify] [static] %stack : $*S2 + store %instance_3 to [assign] %access_4 : $*S2 + end_access %access_4 : $*S2 + destroy_addr %stack : $*S2 + dealloc_stack %stack_addr : $*S2 + %retval = tuple () + return %retval : $() +} + +// The struct has three fields: +// s1 is consumed in left but not right +// s2 is consumed in right but not left +// s3 is not consumed +// There is an apply of other after the consumes and at the beginning of exit. +// +// Ensure that the not-consumed-on-this-branch field (s2 in left, s1 in right) +// is destroyed after the apply of other in each branch block. Ensure that the +// unconsumed field is destroyed at function exit--after the apply of other in +// exit. +// CHECK-LABEL: sil [ossa] @simpleTestVar6a : $@convention(thin) () -> () { +// CHECK: [[OTHER:%[^,]+]] = function_ref @other : $@convention(thin) () -> () +// CHECK: [[STACK:%[^,]+]] = alloc_stack $S3 +// CHECK: cond_br {{%[^,]+}}, [[LEFT:bb[0-9]+]], [[RIGHT:bb[0-9]+]] +// CHECK: [[LEFT]]: +// CHECK: apply [[OTHER]]() : $@convention(thin) () -> () +// CHECK: [[S2_ADDR:%[^,]+]] = struct_element_addr [[STACK]] : $*S3, #S3.s2 +// CHECK: destroy_addr [[S2_ADDR]] : $*S +// CHECK: br [[EXIT:bb[0-9]+]] +// CHECK: [[RIGHT]]: +// CHECK: apply [[OTHER]]() : $@convention(thin) () -> () +// CHECK: [[S1_ADDR:%[^,]+]] = struct_element_addr [[STACK]] : $*S3, #S3.s1 +// CHECK: destroy_addr [[S1_ADDR]] : $*S +// CHECK: br [[EXIT]] +// CHECK: [[EXIT]]: +// CHECK: apply [[OTHER]]() : $@convention(thin) () -> () +// CHECK: [[S3_ADDR:%[^,]+]] = struct_element_addr [[STACK]] : $*S3, #S3.s3 +// CHECK: destroy_addr [[S3_ADDR]] : $*S +// CHECK-LABEL: } // end sil function 'simpleTestVar6a' +sil [ossa] @simpleTestVar6a : $@convention(thin) () -> () { +bb0: + %condition = function_ref @condition : $@convention(thin) () -> Builtin.Int1 + %end = function_ref @end : $@convention(thin) (@owned S) -> () + %get_value_S3 = function_ref @get_value_S3 : $@convention(thin) () -> @owned S3 + %other = function_ref @other : $@convention(thin) () -> () + + %stack_addr = alloc_stack $S3 + %stack = mark_must_check [consumable_and_assignable] %stack_addr : $*S3 + %instance_1 = apply %get_value_S3() : $@convention(thin) () -> @owned S3 + store %instance_1 to [init] %stack : $*S3 + %instance_2 = apply %get_value_S3() : $@convention(thin) () -> @owned S3 + %access_1 = begin_access [modify] [static] %stack : $*S3 + store %instance_2 to [assign] %access_1 : $*S3 + end_access %access_1 : $*S3 + %which = apply %condition() : $@convention(thin) () -> Builtin.Int1 + cond_br %which, left, right + +left: + %access_2 = begin_access [deinit] [static] %stack : $*S3 + %s1_addr = struct_element_addr %access_2 : $*S3, #S3.s1 + %s1 = load [copy] %s1_addr : $*S + apply %end(%s1) : $@convention(thin) (@owned S) -> () + end_access %access_2 : $*S3 + apply %other() : $@convention(thin) () -> () + br exit + +right: + %access_3 = begin_access [deinit] [static] %stack : $*S3 + %s2_addr = struct_element_addr %access_3 : $*S3, #S3.s2 + %s2 = load [copy] %s2_addr : $*S + apply %end(%s2) : $@convention(thin) (@owned S) -> () + end_access %access_3 : $*S3 + apply %other() : $@convention(thin) () -> () + br exit + +exit: + apply %other() : $@convention(thin) () -> () + destroy_addr %stack : $*S3 + dealloc_stack %stack_addr : $*S3 + %retval = tuple () + return %retval : $() +} + +/// The fields #S3.s1 and #S3.s3 are consumed in left but not right. +/// So they should be live until the end of right. +/// The field #S3.s2 is consumed in right but not left. +/// So it should be live until the end of left. +/// +// CHECK-LABEL: sil [ossa] @simpleTestVar6b : {{.*}} { +// CHECK: {{bb[0-9]+}}: +// CHECK: [[OTHER:%[^,]+]] = function_ref @other +// CHECK: [[STACK:%[^,]+]] = alloc_stack +// CHECK: cond_br {{%[^,]+}}, [[LEFT:bb[0-9]+]], [[RIGHT:bb[0-9]+]] +// CHECK: [[LEFT]]: +// CHECK: apply [[OTHER]]() +// CHECK: [[S2_ADDR:%[^,]+]] = struct_element_addr [[STACK]] : $*S3, #S3.s2 +// CHECK: destroy_addr [[S2_ADDR]] +// CHECK: br [[EXIT:bb[0-9]+]] +// CHECK: [[RIGHT]]: +// CHECK: apply [[OTHER]]() +// CHECK: [[S3_ADDR:%[^,]+]] = struct_element_addr [[STACK]] : $*S3, #S3.s3 +// CHECK: destroy_addr [[S3_ADDR]] +// CHECK: [[S1_ADDR:%[^,]+]] = struct_element_addr [[STACK]] : $*S3, #S3.s1 +// CHECK: destroy_addr [[S1_ADDR]] +// CHECK: br [[EXIT]] +// CHECK: [[EXIT]]: +// CHECK-LABEL: } // end sil function 'simpleTestVar6b' +sil [ossa] @simpleTestVar6b : $@convention(thin) () -> () { +entry: + %condition = function_ref @condition : $@convention(thin) () -> Builtin.Int1 + %end = function_ref @end : $@convention(thin) (@owned S) -> () + %get_value_S3 = function_ref @get_value_S3 : $@convention(thin) () -> @owned S3 + %other = function_ref @other : $@convention(thin) () -> () + + %stack_addr = alloc_stack $S3 + %stack = mark_must_check [consumable_and_assignable] %stack_addr : $*S3 + %instance_1 = apply %get_value_S3() : $@convention(thin) () -> @owned S3 + store %instance_1 to [init] %stack : $*S3 + %instance_2 = apply %get_value_S3() : $@convention(thin) () -> @owned S3 + %access_1 = begin_access [modify] [static] %stack : $*S3 + store %instance_2 to [assign] %access_1 : $*S3 + end_access %access_1 : $*S3 + %which = apply %condition() : $@convention(thin) () -> Builtin.Int1 + cond_br %which, left, right + +left: + %access_2 = begin_access [deinit] [static] %stack : $*S3 + %s1_addr = struct_element_addr %access_2 : $*S3, #S3.s1 + %s1 = load [copy] %s1_addr : $*S + apply %end(%s1) : $@convention(thin) (@owned S) -> () + end_access %access_2 : $*S3 + %access_3 = begin_access [deinit] [static] %stack : $*S3 + %s3_addr = struct_element_addr %access_3 : $*S3, #S3.s3 + %s3 = load [copy] %s3_addr : $*S + apply %end(%s3) : $@convention(thin) (@owned S) -> () + end_access %access_3 : $*S3 + apply %other() : $@convention(thin) () -> () + br exit + +right: + %access_4 = begin_access [deinit] [static] %stack : $*S3 + %s2_addr = struct_element_addr %access_4 : $*S3, #S3.s2 + %s2 = load [copy] %s2_addr : $*S + apply %end(%s2) : $@convention(thin) (@owned S) -> () + end_access %access_4 : $*S3 + apply %other() : $@convention(thin) () -> () + br exit + +exit: + apply %other() : $@convention(thin) () -> () + destroy_addr %stack : $*S3 + dealloc_stack %stack_addr : $*S3 + %retval = tuple () + return %retval : $() +} + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// }} Multiple blocks +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// ============================================================================= +// ============================================================================= +// }} Multiple defs +// ============================================================================= +// ============================================================================= + +// ############################################################################# +// ############################################################################# +// }} AGGREGATE STORAGE +// ############################################################################# +// ############################################################################# diff --git a/test/SILOptimizer/moveonly_lifetime.swift b/test/SILOptimizer/moveonly_lifetime.swift index 46e776ed06003..c553305067ca5 100644 --- a/test/SILOptimizer/moveonly_lifetime.swift +++ b/test/SILOptimizer/moveonly_lifetime.swift @@ -1,4 +1,4 @@ -// RUN: %target-swift-emit-sil -sil-verify-all -module-name moveonly_lifetime -o /dev/null -Xllvm -sil-print-canonical-module -Onone -verify -enable-experimental-feature MoveOnlyClasses %s 2>&1 | %FileCheck %s +// RUN: %target-swift-emit-sil -sil-verify-all -module-name moveonly_lifetime -o /dev/null -Xllvm -sil-print-canonical-module -Onone -verify -enable-experimental-feature MoveOnlyClasses %s | %FileCheck %s struct C : ~Copyable { deinit {} @@ -31,17 +31,16 @@ func something() // CHECK: [[INSTANCE:%.*]] = load [take] [[STACK]] // CHECK: [[TAKE_C:%[^,]+]] = function_ref @takeC // CHECK: apply [[TAKE_C]]([[INSTANCE]]) +// CHECK: br [[BOTTOM:bb[0-9]+]] // // CHECK: [[LEFT]]: // CHECK: [[INSTANCE:%.*]] = load_borrow [[STACK]] // CHECK: [[BORROW_C:%[^,]+]] = function_ref @borrowC // CHECK: apply [[BORROW_C]]([[INSTANCE]]) -// -// TODO: Once we maximize lifetimes this should be below something. -// CHECK: destroy_addr [[STACK]] -// // CHECK: [[SOMETHING:%[^,]+]] = function_ref @something // CHECK: apply [[SOMETHING]] +// CHECK: destroy_addr [[STACK]] +// CHECK: br [[BOTTOM]] // CHECK-LABEL: } // end sil function 'test_diamond__consume_r__use_l' @_silgen_name("test_diamond__consume_r__use_l") func test_diamond(_ condition: Bool) { diff --git a/test/Sema/moveonly_enum.swift b/test/Sema/moveonly_enum.swift index 4218967baa3ae..ed1121ad31c06 100644 --- a/test/Sema/moveonly_enum.swift +++ b/test/Sema/moveonly_enum.swift @@ -22,7 +22,7 @@ enum Foo3 { } func test_switch(x: consuming Foo3) { - switch x { // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{12-12=consume }} + switch x { // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{12-12=consume }} default: break } @@ -32,7 +32,7 @@ func test_switch(x: consuming Foo3) { break } - switch (x) { // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{13-13=consume }} + switch (x) { // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{13-13=consume }} default: break } @@ -43,7 +43,7 @@ func test_switch(x: consuming Foo3) { } let _: () -> () = { - switch x { // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{16-16=consume }} + switch x { // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{16-16=consume }} default: break } @@ -57,7 +57,7 @@ func test_switch(x: consuming Foo3) { } let _: () -> () = { - switch (x) { // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{17-17=consume }} + switch (x) { // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{17-17=consume }} default: break } @@ -72,9 +72,9 @@ func test_switch(x: consuming Foo3) { } func test_if_case(x: consuming Foo3) { - if case .bar(let y) = x { _ = y } // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{27-27=consume }} + if case .bar(let y) = x { _ = y } // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{27-27=consume }} - guard case .bar(let y) = x else { return } // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{30-30=consume }} + guard case .bar(let y) = x else { return } // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{30-30=consume }} _ = y if case .bar(let z) = consume x { _ = z } @@ -82,9 +82,9 @@ func test_if_case(x: consuming Foo3) { guard case .bar(let z) = consume x else { return } _ = z - if case .bar(let a) = (x) { _ = a } // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{28-28=consume }} + if case .bar(let a) = (x) { _ = a } // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{28-28=consume }} - guard case .bar(let a) = (x) else { return } // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{31-31=consume }} + guard case .bar(let a) = (x) else { return } // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{31-31=consume }} _ = a if case .bar(let b) = (consume x) { _ = b } @@ -93,11 +93,11 @@ func test_if_case(x: consuming Foo3) { _ = b let _: () -> () = { - if case .bar(let y) = x { _ = y } // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{31-31=consume }} + if case .bar(let y) = x { _ = y } // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{31-31=consume }} } let _: () -> () = { - guard case .bar(let y) = x else { return } // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{34-34=consume }} + guard case .bar(let y) = x else { return } // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{34-34=consume }} _ = y } @@ -111,11 +111,11 @@ func test_if_case(x: consuming Foo3) { } let _: () -> () = { - if case .bar(let a) = (x) { _ = a } // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{32-32=consume }} + if case .bar(let a) = (x) { _ = a } // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{32-32=consume }} } let _: () -> () = { - guard case .bar(let a) = (x) else { return } // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{35-35=consume }} + guard case .bar(let a) = (x) else { return } // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{35-35=consume }} _ = a } @@ -130,7 +130,7 @@ func test_if_case(x: consuming Foo3) { } func test_switch_b(x: __owned Foo3) { - switch x { // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{12-12=consume }} + switch x { // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{12-12=consume }} default: break } @@ -140,7 +140,7 @@ func test_switch_b(x: __owned Foo3) { break } - switch (x) { // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{13-13=consume }} + switch (x) { // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{13-13=consume }} default: break } @@ -151,7 +151,7 @@ func test_switch_b(x: __owned Foo3) { } let _: () -> () = { - switch x { // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{16-16=consume }} + switch x { // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{16-16=consume }} default: break } @@ -165,7 +165,7 @@ func test_switch_b(x: __owned Foo3) { } let _: () -> () = { - switch (x) { // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{17-17=consume }} + switch (x) { // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{17-17=consume }} default: break } @@ -180,9 +180,9 @@ func test_switch_b(x: __owned Foo3) { } func test_if_case_b(x: __owned Foo3) { - if case .bar(let y) = x { _ = y } // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{27-27=consume }} + if case .bar(let y) = x { _ = y } // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{27-27=consume }} - guard case .bar(let y) = x else { return } // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{30-30=consume }} + guard case .bar(let y) = x else { return } // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{30-30=consume }} _ = y if case .bar(let z) = consume x { _ = z } @@ -190,9 +190,9 @@ func test_if_case_b(x: __owned Foo3) { guard case .bar(let z) = consume x else { return } _ = z - if case .bar(let a) = (x) { _ = a } // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{28-28=consume }} + if case .bar(let a) = (x) { _ = a } // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{28-28=consume }} - guard case .bar(let a) = (x) else { return } // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{31-31=consume }} + guard case .bar(let a) = (x) else { return } // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{31-31=consume }} _ = a if case .bar(let b) = (consume x) { _ = b } @@ -201,11 +201,11 @@ func test_if_case_b(x: __owned Foo3) { _ = b let _: () -> () = { - if case .bar(let y) = x { _ = y } // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{31-31=consume }} + if case .bar(let y) = x { _ = y } // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{31-31=consume }} } let _: () -> () = { - guard case .bar(let y) = x else { return } // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{34-34=consume }} + guard case .bar(let y) = x else { return } // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{34-34=consume }} _ = y } @@ -219,11 +219,11 @@ func test_if_case_b(x: __owned Foo3) { } let _: () -> () = { - if case .bar(let a) = (x) { _ = a } // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{32-32=consume }} + if case .bar(let a) = (x) { _ = a } // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{32-32=consume }} } let _: () -> () = { - guard case .bar(let a) = (x) else { return } // expected-warning{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{35-35=consume }} + guard case .bar(let a) = (x) else { return } // expected-error{{noncopyable binding being pattern-matched must have the 'consume' operator applied}} {{35-35=consume }} _ = a } diff --git a/test/SourceKit/InterfaceGen/error_clang_module.swift b/test/SourceKit/InterfaceGen/error_clang_module.swift new file mode 100644 index 0000000000000..b31501ab1a6c7 --- /dev/null +++ b/test/SourceKit/InterfaceGen/error_clang_module.swift @@ -0,0 +1,43 @@ +// RUN: %empty-directory(%t/Inputs) +// RUN: %empty-directory(%t/Inputs/objcfail) +// RUN: split-file %s %t/Inputs + +//--- objcfail/objcfail.h + +#ifdef FAIL +#error some error from Clang module + +// We only record the first error emitted, so we ignore this one. +#error another error from Clang module +#endif + +void foo(void); + +//--- objcfail/module.modulemap + +module ObjCFail { + header "objcfail.h" + export * +} + +//--- Library.swift + +import ObjCFail + +// First try printing the interface of the Clang module directly. + +// RUN: %sourcekitd-test -req=interface-gen -module ObjCFail -- -I %t/Inputs/objcfail -target %target-triple %s | %FileCheck --check-prefix DIRECT-SUCCESS %s +// DIRECT-SUCCESS: public func foo() + +// RUN: not %sourcekitd-test -req=interface-gen -module ObjCFail -- -Xcc -DFAIL -I %t/Inputs/objcfail -target %target-triple %s 2>&1 | %FileCheck --check-prefix DIRECT-FAIL %s +// DIRECT-FAIL: Could not load module: ObjCFail (could not build {{Objective-C|C}} module 'ObjCFail', some error from Clang module) + +// Now try doing it transitively + +// RUN: %target-swift-frontend -emit-module %t/Inputs/Library.swift -I %t/Inputs/objcfail -module-name Library -o %t + +// RUN: %sourcekitd-test -req=interface-gen -module Library -- -I %t -target %target-triple %s | %FileCheck --check-prefix TRANSITIVE-SUCCESS %s +// TRANSITIVE-SUCCESS: import ObjCFail + +// RUN: not %sourcekitd-test -req=interface-gen -module Library -- -Xcc -DFAIL -I %t -target %target-triple %s 2>&1 | %FileCheck --check-prefix TRANSITIVE-FAIL %s +// TRANSITIVE-FAIL: Could not load module: Library (could not build {{Objective-C|C}} module 'ObjCFail', some error from Clang module) diff --git a/test/SourceKit/InterfaceGen/error_swift_module.swift b/test/SourceKit/InterfaceGen/error_swift_module.swift new file mode 100644 index 0000000000000..61ab865b16d58 --- /dev/null +++ b/test/SourceKit/InterfaceGen/error_swift_module.swift @@ -0,0 +1,58 @@ +// RUN: %empty-directory(%t/Inputs) +// RUN: split-file %s %t/Inputs + +//--- Transitive.swift + +public func foo() {} + +//--- Library.swift + +import Transitive + +//--- LibraryWrong.swift + +import WrongName + +//--- LibraryNonExistant.swift + +import NonExistant + +// RUN: %target-swift-frontend -emit-module %t/Inputs/Transitive.swift -module-name Transitive -o %t/WrongName.swiftmodule +// RUN: %target-swift-frontend -emit-module %t/Inputs/Transitive.swift -module-name Transitive -o %t/Transitive.swiftmodule + +// First try printing the interface of the Transitive module directly. + +// RUN: %sourcekitd-test -req=interface-gen -module Transitive -- -I %t -target %target-triple %s | %FileCheck --check-prefix DIRECT-SUCCESS %s +// DIRECT-SUCCESS: public func foo() + +// RUN: not %sourcekitd-test -req=interface-gen -module WrongName -- -I %t -target %target-triple %s 2>&1 | %FileCheck --check-prefix DIRECT-FAIL %s +// DIRECT-FAIL: Could not load module: WrongName (cannot load module 'Transitive' as 'WrongName') + +// Now try doing it transitively + +// First undo the WrongName module +// RUN: %target-swift-frontend -emit-module %t/Inputs/Transitive.swift -module-name WrongName -o %t/WrongName.swiftmodule + +// RUN: %target-swift-frontend -emit-module %t/Inputs/Library.swift -I %t -module-name Library -o %t +// RUN: %target-swift-frontend -emit-module %t/Inputs/LibraryWrong.swift -I %t -module-name LibraryWrong -o %t + +// Then redo the WrongName module +// RUN: %target-swift-frontend -emit-module %t/Inputs/Transitive.swift -module-name Transitive -o %t/WrongName.swiftmodule + +// RUN: %sourcekitd-test -req=interface-gen -module Library -- -I %t -target %target-triple %s | %FileCheck --check-prefix TRANSITIVE-SUCCESS %s +// TRANSITIVE-SUCCESS: import Transitive + +// RUN: not %sourcekitd-test -req=interface-gen -module LibraryWrong -- -I %t -target %target-triple %s 2>&1 | %FileCheck --check-prefix TRANSITIVE-FAIL %s +// TRANSITIVE-FAIL: Could not load module: LibraryWrong (cannot load module 'Transitive' as 'WrongName') + +// Try a non-existant module + +// RUN: not %sourcekitd-test -req=interface-gen -module NonExistant -- -I %t -target %target-triple %s 2>&1 | %FileCheck --check-prefix DIRECT-NONEXISTANT %s +// DIRECT-NONEXISTANT: Could not load module: NonExistant + +// RUN: %target-swift-frontend -emit-module %t/Inputs/Transitive.swift -module-name NonExistant -o %t +// RUN: %target-swift-frontend -emit-module %t/Inputs/LibraryNonExistant.swift -module-name LibraryNonExistant -I %t -o %t +// RUN: rm -rf %t/NonExistant.swiftmodule + +// RUN: not %sourcekitd-test -req=interface-gen -module LibraryNonExistant -- -I %t -target %target-triple %s 2>&1 | %FileCheck --check-prefix TRANSITIVE-NONEXISTANT %s +// TRANSITIVE-NONEXISTANT: Could not load module: LibraryNonExistant (missing required module 'NonExistant') diff --git a/test/decl/import/import.swift b/test/decl/import/import.swift index 6f7c10f537fcf..dc39bc85b6c80 100644 --- a/test/decl/import/import.swift +++ b/test/decl/import/import.swift @@ -35,9 +35,9 @@ import func Swift.print // rdar://14418336 #import something_nonexistent -// expected-error@-1 {{keyword 'import' cannot be used as an identifier here}} expected-note@-1 {{use backticks to escape it}} -// expected-error@-2 {{no macro named 'import'}} -// expected-error@-3 {{consecutive statements on a line}} expected-error@-3 {{cannot find 'something_nonexistent' in scope}} +// expected-error@-1 {{no macro named 'import'}} +// expected-error@-2 {{consecutive statements on a line}} +// expected-error@-3 {{cannot find 'something_nonexistent' in scope}} // Import specific decls import typealias Swift.Int diff --git a/test/decl/var/init_accessors.swift b/test/decl/var/init_accessors.swift index 6d8633bac190f..3105ae28c478b 100644 --- a/test/decl/var/init_accessors.swift +++ b/test/decl/var/init_accessors.swift @@ -444,3 +444,24 @@ func test_memberwise_ordering() { _ = Test5(_a: 0, _b: 1, c: 2) // Ok } + +func test_default_arguments_are_analyzed() { + struct Test { + var pair: (Int, Int) = (0, 1) { // Ok + init {} + } + + var other: (Int, String) = ("", 42) { + // expected-error@-1 {{cannot convert value of type '(String, Int)' to specified type '(Int, String)'}} + init(initialValue) {} + } + + var otherPair = (0, 1) { + // expected-error@-1 {{computed property must have an explicit type}} + init(initalValue) {} + + get { 42 } + // expected-error@-1 {{cannot convert return expression of type 'Int' to return type '(Int, Int)'}} + } + } +} diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditorInterfaceGen.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditorInterfaceGen.cpp index 993506166af39..80f7f1b17b556 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftEditorInterfaceGen.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftEditorInterfaceGen.cpp @@ -265,6 +265,46 @@ static void reportSemanticAnnotations(const SourceTextInfo &IFaceInfo, } } +namespace { +/// A diagnostic consumer that picks up module loading errors. +class ModuleLoadingErrorConsumer final : public DiagnosticConsumer { + llvm::SmallVector DiagMessages; + + void handleDiagnostic(SourceManager &SM, + const DiagnosticInfo &Info) override { + // Only record errors for now. In the future it might be useful to pick up + // some notes, but some notes are just noise. + if (Info.Kind != DiagnosticKind::Error) + return; + + std::string Message; + { + llvm::raw_string_ostream Out(Message); + DiagnosticEngine::formatDiagnosticText(Out, Info.FormatString, + Info.FormatArgs); + } + // We're only interested in the first and last errors. For a clang module + // failure, the first error will be the reason why the module failed to + // load, and the last error will be a generic "could not build Obj-C module" + // error. For a Swift module, we'll typically only emit one error. + // + // NOTE: Currently when loading transitive dependencies for a Swift module, + // we'll only diagnose the root failure, and not record the error for the + // top-level module failure, as we stop emitting errors after a fatal error + // has been recorded. This is currently fine for our use case though, as + // we already include the top-level module name in the error we hand back. + if (DiagMessages.size() < 2) { + DiagMessages.emplace_back(std::move(Message)); + } else { + DiagMessages.back() = std::move(Message); + } + } + +public: + ArrayRef getDiagMessages() { return DiagMessages; } +}; +} // end anonymous namespace + static bool getModuleInterfaceInfo(ASTContext &Ctx, StringRef ModuleName, Optional Group, @@ -280,21 +320,35 @@ static bool getModuleInterfaceInfo(ASTContext &Ctx, return true; } - // Get the (sub)module to generate. - Mod = Ctx.getModuleByName(ModuleName); - if (!Mod) { - ErrMsg = "Could not load module: "; - ErrMsg += ModuleName; - return true; - } - if (Mod->failedToLoad()) { - // We might fail to load the underlying Clang module - // for a Swift overlay module like 'CxxStdlib', or a mixed-language - // framework. Make sure an error is reported in this case, so that we can - // either retry to load with C++ interoperability enabled, and if that - // fails, we can report this to the user. - ErrMsg = "Could not load underlying module for: "; - ErrMsg += ModuleName; + // Get the (sub)module to generate, recording the errors emitted. + ModuleLoadingErrorConsumer DiagConsumer; + { + DiagnosticConsumerRAII R(Ctx.Diags, DiagConsumer); + Mod = Ctx.getModuleByName(ModuleName); + } + + // Check to see if we either couldn't find the module, or we failed to load + // it, and report an error message back that includes the diagnostics we + // collected, which should help pinpoint what the issue was. Note we do this + // even if `Mod` is null, as the clang importer currently returns nullptr + // when a module fails to load, and there may be interesting errors to + // collect there. + // Note that us failing here also means the caller may retry with e.g C++ + // interoperability enabled. + if (!Mod || Mod->failedToLoad()) { + llvm::raw_string_ostream OS(ErrMsg); + + OS << "Could not load module: "; + OS << ModuleName; + auto ModuleErrs = DiagConsumer.getDiagMessages(); + if (!ModuleErrs.empty()) { + // We print the errors in reverse, as they are typically emitted in + // a bottom-up manner by module loading, and a top-down presentation + // makes more sense. + OS << " ("; + llvm::interleaveComma(llvm::reverse(ModuleErrs), OS); + OS << ")"; + } return true; } diff --git a/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp b/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp index 6d9314b3ecd3a..4f0c4a44acd42 100644 --- a/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp +++ b/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp @@ -89,15 +89,25 @@ static bool validateModule( llvm::outs() << ", system=" << (searchPath.IsSystem ? "true" : "false") << "\n"; } - llvm::outs() << "- Macro Search Paths:\n"; - for (auto path : extendedInfo.getPluginSearchPaths()) - llvm::outs() << " -plugin-path: " << path << "\n"; - for (auto path : extendedInfo.getExternalPluginSearchPaths()) - llvm::outs() << " -external-plugin-path: " << path << "\n"; - for (auto path : extendedInfo.getCompilerPluginLibraryPaths()) - llvm::outs() << " -load-plugin-library: " << path << "\n"; - for (auto path : extendedInfo.getCompilerPluginExecutablePaths()) - llvm::outs() << " -load-plugin-executable: " << path << "\n"; + llvm::outs() << "- Plugin Search Options:\n"; + for (auto opt : extendedInfo.getPluginSearchOptions()) { + StringRef optStr; + switch (opt.first) { + case swift::PluginSearchOption::Kind::PluginPath: + optStr = "-plugin-path"; + break; + case swift::PluginSearchOption::Kind::ExternalPluginPath: + optStr = "-external-plugin-path"; + break; + case swift::PluginSearchOption::Kind::LoadPluginLibrary: + optStr = "-load-plugin-library"; + break; + case swift::PluginSearchOption::Kind::LoadPluginExecutable: + optStr = "-load-plugin-executable"; + break; + } + llvm::outs() << " " << optStr << " " << opt.second << "\n"; + } } return true; diff --git a/utils/build-presets.ini b/utils/build-presets.ini index c0c5ed5262643..a41f554a172d2 100644 --- a/utils/build-presets.ini +++ b/utils/build-presets.ini @@ -2625,6 +2625,7 @@ swift-stdlib-has-stdin=0 swift-stdlib-has-environ=0 swift-stdlib-has-locale=0 swift-runtime-static-image-inspection=1 +swift-stdlib-tracing=0 swift-stdlib-concurrency-tracing=0 swift-stdlib-os-versioning=0 swift-stdlib-has-commandline=0 diff --git a/utils/build-script-impl b/utils/build-script-impl index 21712a923143b..b08ee527e3b0e 100755 --- a/utils/build-script-impl +++ b/utils/build-script-impl @@ -211,6 +211,7 @@ KNOWN_SETTINGS=( swift-runtime-static-image-inspection "0" "whether to build stdlib assuming the runtime environment only supports a single runtime image with Swift code" swift-threading-package "" "override the threading package for the host build; this is either a single package or a semicolon-separated list of sdk:package pairs. Valid packages are empty string (no override), 'pthreads', 'darwin', 'linux', 'win32', 'c11', 'none'" swift-stdlib-single-threaded-concurrency "0" "build Swift concurrency in single-threaded mode" + swift-stdlib-tracing "" "whether to enable tracing signposts for the stdlib; default is 1 on Darwin platforms, 0 otherwise" swift-stdlib-concurrency-tracing "" "whether to enable tracing signposts for concurrency; default is 1 on Darwin platforms, 0 otherwise" swift-stdlib-use-relative-protocol-witness-tables "0" "whether to use relative protocol witness table" swift-enable-runtime-function-counters "" "whether to enable runtime function counters"