Merge pull request #13236 from troughton/windows-toolchain-pr
[driver] Implement a Windows toolchain for cross-compiling
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 0000000..56edf36
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,134 @@
+Adrian-Constantin Popescu <epsilon.gamma@gmail.com> <adrian-constantin.popescu@outlook.com>
+Alex Blewitt <alblue@apple.com> <alex.blewitt@gmail.com>
+Alex Hoppen <alex@alexhoppen.de> <alex@ateamer.de>
+Alexis Beingessner <abeingessner@apple.com> <a.beingessner@gmail.com>
+Alper Çugun <github@alper.nl> <alper@users.noreply.github.com>
+Amr Aboelela <amraboelela@gmail.com> <amraboelela@users.noreply.github.com>
+Ankit Aggarwal <ankit_aggarwal@apple.com> <ankit.spd@gmail.com>
+Argyrios Kyrtzidis <kyrtzidis@apple.com> <akyrtzi@gmail.com>
+Arsen Gasparyan <to.arsen.gasparyan@gmail.com> <frootloops@users.noreply.github.com>
+Ben Cohen <ben_cohen@apple.com>
+Ben Cohen <ben_cohen@apple.com> <airspeedswift@users.noreply.github.com>
+Ben Cohen <ben_cohen@apple.com> <ben@airspeedvelocity.net>
+Ben Langmuir <blangmuir@apple.com> <ben.langmuir@gmail.com>
+Brent Royal-Gordon <brent@brentdax.com> <brent@architechies.com>
+Brian Croom <bcroom@apple.com> <brian.s.croom@gmail.com>
+Brian Gesiak <bgesiak@fb.com> <modocache@gmail.com>
+Bryan Chan <bryan.chan@ca.ibm.com> <bryanpkc@gmail.com>
+Calvin Hill <mr_j.c.h@hotmail.com> <return@users.noreply.github.com>
+Chris Bieneman <beanz@apple.com>
+Chris Bieneman <beanz@apple.com> <cbieneman@apple.com>
+Chris Lattner <clattner@nondot.org> <clattner@apple.com>
+Chris Lattner <clattner@nondot.org> <lattner@users.noreply.github.com>
+Chris Lattner <clattner@nondot.org> <sabre@iMac.local>
+Chris Williams <cwilliams@fitbit.com> <ultramiraculous@users.noreply.github.com>
+codester <sahil.profile@gmail.com> codestergit <sahil.profile@gmail.com>
+Dan Liew <dliew@apple.com> <36706441+danliew-apple@users.noreply.github.com>
+Daniel Duan <daniel@duan.org> <danmarner@gmail.com>
+Dante Broggi <34220985+Dante-Broggi@users.noreply.github.com>
+Dave <davesweeris@mac.com>
+Dave Abrahams <dabrahams@apple.com> <dave@boostpro.com>
+Dave Abrahams <dabrahams@apple.com> <dave@fripp.apple.com>
+Dave Abrahams <dabrahams@apple.com> <dave@Skree.local>
+Dave Abrahams <dabrahams@apple.com> <dave@Wingy.local>
+Dave Lee <davelee@lyft.com> <davelee.com@gmail.com>
+David Rönnqvist <david.ronnqvist@gmail.com> <david.ronnqvist@skype.net>
+David Zarzycki <dave@znu.io> <zarzycki@icloud.com>
+David Zarzycki <dave@znu.io> <zarzycki@mac.com>
+Davide Italiano <ditaliano@apple.com> <dcci@users.noreply.github.com>
+Davide Italiano <ditaliano@apple.com> <dccitaliano@gmail.com>
+Dmitri Gribenko <gribozavr@gmail.com> <dgribenko@apple.com>
+Doug Coleman <doug_coleman@apple.com> <doug.coleman@gmail.com>
+Enrico Granata <egranata@apple.com> <egranata@egranata.apple.com>
+Enrico Granata <egranata@apple.com> <granata.enrico@gmail.com>
+Erik Eckstein <eeckstein@apple.com> <eeckstein@apple.com>
+Erik Eckstein <eeckstein@apple.com> <eeckstein@rad-main.corp.apple.com>
+Erik Verbruggen <erik.verbruggen@me.com> <erikjv@users.noreply.github.com>
+Ewa Matejska <ematejska@apple.com> <ematejska@apple.com>
+Ewa Matejska <ematejska@apple.com> <ematejska@Ewas-MacBook-Pro.local>
+Ewa Matejska <ematejska@apple.com> <ewamatejska@Ewas-iMac.local>
+Florent Bruneau <florent.bruneau@intersec.com> <florent.bruneau_github@m4x.org>
+Francis Ricci <fjricci@fb.com> <francisjricci@gmail.com>
+GauravDS <er.gauravds@gmail.com> <gaurav.sharma@punchh.com>
+Graydon Hoare <ghoare@apple.com> <graydon@users.noreply.github.com>
+Greg Parker <gparker@apple.com> <gparker-github@sealiesoftware.com>
+Guillaume Lessard <dhtnstff@gmail.com> <glessard@users.noreply.github.com>
+Hamish <hamish2knight@gmail.com> <hamish2knight@gmail.com>
+Han Sangjin <tinysun@jssolution.co.kr> <tinysun.net@gmail.com>
+Harlan Haskins <harlan@apple.com> <harlan@harlanhaskins.com>
+Hitster GTD <hitstergtd@users.noreply.github.com> <hitstergtd@users.noreply.github.com>
+Huon Wilson <huon@apple.com> <dbau.pp+github@gmail.com>
+Ingmar Stein <IngmarStein@users.noreply.github.com>
+Itai Ferber <iferber@apple.com> <itai@itaiferber.net>
+Jacob Bandes-Storch <jacob@bandes-stor.ch> <jacob@bandes-storch.net>
+Jacob Mizraji <jmizraji@apple.com> <jacobmizraji@gmail.com>
+Janosch Hildebrand <jnosh@jnosh.com> <jnosh+git@jnosh.com>
+Janosch Hildebrand <jnosh@jnosh.com> <jnosh+github@jnosh.com>
+Javier Soto <jsbustos@twitch.tv> <javier.api@gmail.com>
+Javier Soto <jsbustos@twitch.tv> <javiers@twitter.com>
+Joe <joe@iachieved.it>
+Joe <joewillsher@icloud.com>
+joe DeCapo <joe@polka.cat>
+Joe Groff <jgroff@apple.com> <arcata@gmail.com>
+Joe Shajrawi <shajrawi@apple.com> <joeshajrawi@iMac-2.local>
+Joe Shajrawi <shajrawi@apple.com> <joeshajrawi@Joes-iMac-Pro.local>
+Johannes Weiß <johannesweiss@apple.com> <github@tux4u.de>
+John Regner <john@johnregner.com> <regnerjr@gmail.com>
+Karoy Lorentey <klorentey@apple.com> <karoly@lorentey.hu>
+Keith Smiley <k@keith.so> <keithbsmiley@gmail.com>
+Kevin Ballard <kevin@sb.org> <kevin.ballard@postmates.com>
+Kosuke Ogawa <ogawa_kousuke@aratana.jp> <koogawa.app@gmail.com>
+Kuba Mracek <mracek@apple.com> <jbrecka@apple.com>
+Luiz Fernando Silva <luizinho_mack@yahoo.com.br>
+Luqman Aden <luqman@apple.com> <luqman_aden@apple.com>
+Marcelo Fabri <me@marcelofabri.com> <marcelofabri@users.noreply.github.com>
+Mark Lacey <mark.lacey@apple.com> <rudkx@icloud.com>
+Mark Lacey <mark.lacey@apple.com> <rudkx@users.noreply.github.com>
+Matt Rajca <matt.rajca@me.com> <mattrajca@users.noreply.github.com>
+Max Moiseev <moiseev@apple.com> <maxim.moiseev@gmail.com>
+Max Moiseev <moiseev@apple.com> <moiseev@users.noreply.github.com>
+Maxwell Swadling <maxs@apple.com> <maxwellswadling@gmail.com>
+Maxwell Swadling <maxs@apple.com> <mswadling@apple.com>
+Mayur Raiturkar <mayur@mayur.xyz> <mayurkr@users.noreply.github.com>
+Michael Gottesman <mgottesman@apple.com> <gottesmm@users.noreply.github.com>
+Michael Ilseman <milseman@apple.com> <michael.ilseman@gmail.com>
+Mike Ash <mikeash@apple.com> <mike@mikeash.com>
+Mike Ferris <mferris@apple.com> <mike@lorax.com>
+Mishal Awadah <mawadah@apple.com>
+Mishal Shah <mishal_shah@apple.com> <shahmishal@users.noreply.github.com>
+Nadav Rotem <nrotem@apple.com> <nadavrot@users.noreply.github.com>
+Nate Cook <natecook@apple.com> <nate@Nates-MacBook-Pro.local>
+Nate Cook <natecook@apple.com> <natecook@gmail.com>
+Nate Cook <natecook@apple.com> <natecook1000@users.noreply.github.com>
+Nate Cook <natecook@apple.com> <nmersethcook@apple.com>
+Nathan Lanza <lanza@fb.com> <nathan@lanza.io>
+Nicole Jacque <jacque@apple.com>
+Niels Andriesse <andriesseniels@gmail.com> <nielsandriesse@users.noreply.github.com>
+Paul Meng <mno2@mno2.org> <mno2.csie@gmail.com>
+Pavel Yaskevich <pyaskevich@apple.com> <xedin@apache.org>
+Paweł Szot <pszot@pgs-soft.com>
+Paweł Szot <pszot@pgs-soft.com> <qwertyszot@gmail.com>
+Pete Cooper <peter_cooper@apple.com>
+Philip Ridgeway <pridgeway@vernier.com> <philip.ridgeway@gmail.com>
+Richard Wei <rxwei@apple.com> <rxwei@google.com>
+Rintaro Ishizaki <rishizaki@apple.com> <fs.output@gmail.com>
+Robert Widmann <rwidmann@apple.com> <devteam.codafi@gmail.com>
+Roman Levenstein <rlevenstein@apple.com> <swiftix@users.noreply.github.com>
+Ross Bayer <ross.m.bayer@gmail.com> <Rostepher@users.noreply.github.com>
+Russ Bishop <rbishopjr@apple.com> <russ@plangrid.com>
+Ryan Lovelett <ryan@lovelett.me> <RLovelett@users.noreply.github.com>
+Shawn Erickson <shawn.erickson@citrix.com> <shawnce@gmail.com>
+Slava Pestov <spestov@apple.com> <spestov@rad-main.corp.apple.com>
+Slava Pestov <spestov@apple.com> <sviatoslav.pestov@gmail.com>
+Stephen Canon <scanon@apple.com>
+Stephen Canon <scanon@apple.com> <stephentyrone@gmail.com>
+Sukolsak Sakshuwong <sukolsak@gmail.com>
+Todd Fiala <tfiala@apple.com> <todd.fiala@gmail.com>
+Toni Suter <tonisuter@me.com> <tonisuter@users.noreply.github.com>
+Vedant Kumar <vsk@apple.com> <vk@vedantk.com>
+Xi Ge <xi_ge@apple.com> <xi_ge@rad-main.corp.apple.com>
+Xin Tong <xin_tong@apple.com> <trent.xin.tong@gmail.com>
+Xin Tong <xin_tong@apple.com> <trentxintong@Xins-MacBook-Pro.local>
+Yuka Ezura <ezura@users.noreply.github.com> <2020337+ezura@users.noreply.github.com>
+Yurii Samsoniuk <ura@google.com> <mr.sigito@gmail.com>
+Zac Bowling <zbowling@google.com> <zac@zacbowling.com>
diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake
index b12e620..dd142af 100644
--- a/cmake/modules/AddSwift.cmake
+++ b/cmake/modules/AddSwift.cmake
@@ -227,12 +227,12 @@
if(NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
list(APPEND result -Xclang;--dependent-lib=oldnames)
# TODO(compnerd) handle /MT, /MTd, /MD, /MDd
- if("${CMAKE_BUILD_TYPE}" STREQUAL "RELEASE")
- list(APPEND result "-D_MD")
- list(APPEND result -Xclang;--dependent-lib=msvcrt)
- else()
+ if("${CMAKE_BUILD_TYPE}" STREQUAL "DEBUG")
list(APPEND result "-D_MDd")
list(APPEND result -Xclang;--dependent-lib=msvcrtd)
+ else()
+ list(APPEND result "-D_MD")
+ list(APPEND result -Xclang;--dependent-lib=msvcrt)
endif()
endif()
@@ -425,7 +425,7 @@
list(APPEND library_search_directories "${SWIFT_${sdk}_${arch}_ICU_UC_LIBDIR}")
endif()
if(NOT "${SWIFT_${LFLAGS_SDK}_${LFLAGS_ARCH}_ICU_I18N}" STREQUAL "")
- get_filename_component(SWIFT_${sdk}_${arch}_ICU_I18N_LIBDIR "${SWIFT_${sdk}_${arch}_IC_I18N}" DIRECTORY)
+ get_filename_component(SWIFT_${sdk}_${arch}_ICU_I18N_LIBDIR "${SWIFT_${sdk}_${arch}_ICU_I18N}" DIRECTORY)
list(APPEND library_search_directories "${SWIFT_${sdk}_${arch}_ICU_I18N_LIBDIR}")
endif()
@@ -792,6 +792,7 @@
swift_windows_generate_sdk_vfs_overlay(SWIFTLIB_SINGLE_VFS_OVERLAY_FLAGS)
foreach(flag ${SWIFTLIB_SINGLE_VFS_OVERLAY_FLAGS})
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS -Xcc;${flag})
+ list(APPEND SWIFTLIB_SINGLE_C_COMPILE_FLAGS ${flag})
endforeach()
foreach(directory ${SWIFTLIB_INCLUDE})
list(APPEND SWIFTLIB_SINGLE_SWIFT_COMPILE_FLAGS -Xfrontend;-I${directory})
@@ -1719,6 +1720,19 @@
endif()
endif()
+ # We unconditionally removed "-z,defs" from CMAKE_SHARED_LINKER_FLAGS in
+ # swift_common_standalone_build_config_llvm within SwiftSharedCMakeConfig.cmake,
+ # where it was added by a call to HandleLLVMOptions.
+ #
+ # Rather than applying it to all targets and libraries, we here add it back to
+ # supported targets and libraries only.
+ # This is needed for ELF targets only; however, RemoteMirror needs to build
+ # with undefined symbols.
+ if("${SWIFT_SDK_${LFLAGS_SDK}_OBJECT_FORMAT}" STREQUAL "ELF"
+ AND NOT "${name}" STREQUAL "swiftRemoteMirror")
+ list(APPEND swiftlib_link_flags_all "-Wl,-z,defs")
+ endif()
+
# Add this library variant.
_add_swift_library_single(
${VARIANT_NAME}
diff --git a/cmake/modules/SwiftConfigureSDK.cmake b/cmake/modules/SwiftConfigureSDK.cmake
index 0aaec27..9aeaefb 100644
--- a/cmake/modules/SwiftConfigureSDK.cmake
+++ b/cmake/modules/SwiftConfigureSDK.cmake
@@ -14,10 +14,10 @@
message(STATUS " UCRT Version: $ENV{UCRTVersion}")
message(STATUS " UCRT SDK Dir: $ENV{UniversalCRTSdkDir}")
message(STATUS " VC Dir: $ENV{VCToolsInstallDir}")
- if("${CMAKE_BUILD_TYPE}" STREQUAL "RELEASE")
- message(STATUS " ${CMAKE_BUILD_TYPE} VC++ CRT: MD")
- else()
+ if("${CMAKE_BUILD_TYPE}" STREQUAL "DEBUG")
message(STATUS " ${CMAKE_BUILD_TYPE} VC++ CRT: MDd")
+ else()
+ message(STATUS " ${CMAKE_BUILD_TYPE} VC++ CRT: MD")
endif()
foreach(arch ${SWIFT_SDK_${prefix}_ARCHITECTURES})
diff --git a/cmake/modules/SwiftSharedCMakeConfig.cmake b/cmake/modules/SwiftSharedCMakeConfig.cmake
index 498ca90..48243be 100644
--- a/cmake/modules/SwiftSharedCMakeConfig.cmake
+++ b/cmake/modules/SwiftSharedCMakeConfig.cmake
@@ -78,9 +78,17 @@
include(AddSwiftTableGen) # This imports TableGen from LLVM.
include(HandleLLVMOptions)
- # HACK: this ugly tweaking is to prevent the propagation of the flag from LLVM
- # into swift. The use of this flag pollutes all targets, and we are not able
- # to remove it on a per-target basis which breaks cross-compilation.
+ # HACK: Not all targets support -z,defs as a linker flag.
+ #
+ # Normally, LLVM would only add it as an option for known ELF targets;
+ # however, due to the custom scheme Swift uses for cross-compilation, the
+ # CMAKE_SHARED_LINKER_FLAGS are determined based on the host system and
+ # then applied to all targets. This causes issues in cross-compiling to
+ # Windows from a Linux host.
+ #
+ # To work around this, we unconditionally remove the flag here and then
+ # selectively add it to the per-target link flags; this is currently done
+ # in add_swift_library within AddSwift.cmake.
string(REGEX REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}")
diff --git a/docs/Lexicon.rst b/docs/Lexicon.rst
index 602d79f..4787fd0 100644
--- a/docs/Lexicon.rst
+++ b/docs/Lexicon.rst
@@ -339,6 +339,10 @@
script mode
The parsing mode that allows top-level imperative code in a source file.
+
+ Sema
+ Short for 'Semantic Analysis', the compiler pass that performs type checking,
+ validation, and expression rewriting before SILGen.
SIL
"Swift Intermediate Language". A high-level IR used by the Swift compiler
diff --git a/docs/SIL.rst b/docs/SIL.rst
index c2001d9..2a81532 100644
--- a/docs/SIL.rst
+++ b/docs/SIL.rst
@@ -4649,6 +4649,14 @@
function type. Something must guarantee the lifetime of the input ``%0`` for the
duration of the use ``%1``.
+A ``convert_escape_to_noescape [not_guaranteed] %opd`` indicates that the
+lifetime of its operand was not guaranteed by SILGen and a mandatory pass must
+be run to ensure the lifetime of ``%opd``` for the conversion's uses.
+
+A ``convert_escape_to_noescape [escaped]`` indiciates that the result was
+passed to a function (materializeForSet) which escapes the closure in a way not
+expressed by the convert's users. The mandatory pass must ensure the lifetime
+in a conservative way.
thin_function_to_pointer
````````````````````````
diff --git a/include/swift/AST/Attr.h b/include/swift/AST/Attr.h
index 78f21c4..191dfe4 100644
--- a/include/swift/AST/Attr.h
+++ b/include/swift/AST/Attr.h
@@ -17,6 +17,7 @@
#ifndef SWIFT_ATTR_H
#define SWIFT_ATTR_H
+#include "swift/Basic/InlineBitfield.h"
#include "swift/Basic/SourceLoc.h"
#include "swift/Basic/UUID.h"
#include "swift/Basic/STLExtras.h"
@@ -182,60 +183,82 @@
class DeclAttribute : public AttributeBase {
friend class DeclAttributes;
protected:
- class DeclAttrBitFields {
- friend class DeclAttribute;
-
- // The kind.
- unsigned Kind : 8;
-
- // Whether this attribute was implicitly added.
- unsigned Implicit : 1;
-
- unsigned Invalid : 1;
- };
- enum { NumDeclAttrBits = 10 };
- static_assert(NumDeclAttrBits <= 32, "fits in an unsigned");
-
- class ObjCAttrBitFields {
- friend class ObjCAttr;
- unsigned : NumDeclAttrBits;
-
- /// Whether this attribute has location information that trails the main
- /// record, which contains the locations of the parentheses and any names.
- unsigned HasTrailingLocationInfo : 1;
-
- /// Whether the name is implicit, produced as the result of caching.
- unsigned ImplicitName : 1;
-
- /// Whether the @objc was inferred using Swift 3's deprecated inference
- /// rules.
- unsigned Swift3Inferred : 1;
- };
- enum { NumObjCAttrBits = NumDeclAttrBits + 3 };
- static_assert(NumObjCAttrBits <= 32, "fits in an unsigned");
-
- class AccessControlAttrBitFields {
- friend class AbstractAccessControlAttr;
- unsigned : NumDeclAttrBits;
-
- unsigned AccessLevel : 3;
- };
- enum { NumAccessControlAttrBits = NumDeclAttrBits + 3 };
- static_assert(NumAccessControlAttrBits <= 32, "fits in an unsigned");
-
union {
- DeclAttrBitFields DeclAttrBits;
- ObjCAttrBitFields ObjCAttrBits;
- AccessControlAttrBitFields AccessControlAttrBits;
- };
+ uint64_t OpaqueBits;
+
+ SWIFT_INLINE_BITFIELD_BASE(DeclAttribute, bitmax(NumDeclAttrKindBits,8)+1+1,
+ Kind : bitmax(NumDeclAttrKindBits,8),
+ // Whether this attribute was implicitly added.
+ Implicit : 1,
+
+ Invalid : 1
+ );
+
+ SWIFT_INLINE_BITFIELD(ObjCAttr, DeclAttribute, 1+1+1,
+ /// Whether this attribute has location information that trails the main
+ /// record, which contains the locations of the parentheses and any names.
+ HasTrailingLocationInfo : 1,
+
+ /// Whether the name is implicit, produced as the result of caching.
+ ImplicitName : 1,
+
+ /// Whether the @objc was inferred using Swift 3's deprecated inference
+ /// rules.
+ Swift3Inferred : 1
+ );
+
+ SWIFT_INLINE_BITFIELD(AbstractAccessControlAttr, DeclAttribute, 3,
+ AccessLevel : 3
+ );
+
+ SWIFT_INLINE_BITFIELD_FULL(AlignmentAttr, DeclAttribute, 32,
+ : NumPadBits,
+ // The alignment value.
+ Value : 32
+ );
+
+ SWIFT_INLINE_BITFIELD(ClangImporterSynthesizedTypeAttr, DeclAttribute, 1,
+ kind : 1
+ );
+
+ SWIFT_INLINE_BITFIELD(EffectsAttr, DeclAttribute, NumEffectsKindBits,
+ kind : NumEffectsKindBits
+ );
+
+ SWIFT_INLINE_BITFIELD(InlineAttr, DeclAttribute, NumInlineKindBits,
+ kind : NumInlineKindBits
+ );
+
+ SWIFT_INLINE_BITFIELD(OptimizeAttr, DeclAttribute, NumOptimizationModeBits,
+ mode : NumOptimizationModeBits
+ );
+
+ SWIFT_INLINE_BITFIELD(ReferenceOwnershipAttr, DeclAttribute,
+ NumReferenceOwnershipBits,
+ ownership : NumReferenceOwnershipBits
+ );
+
+ SWIFT_INLINE_BITFIELD_FULL(SpecializeAttr, DeclAttribute, 1+1+32,
+ exported : 1,
+ kind : 1,
+ : NumPadBits,
+ numRequirements : 32
+ );
+
+ SWIFT_INLINE_BITFIELD(SynthesizedProtocolAttr, DeclAttribute,
+ NumKnownProtocolKindBits,
+ kind : NumKnownProtocolKindBits
+ );
+ } Bits;
DeclAttribute *Next = nullptr;
DeclAttribute(DeclAttrKind DK, SourceLoc AtLoc, SourceRange Range,
bool Implicit) : AttributeBase(AtLoc, Range) {
- DeclAttrBits.Kind = static_cast<unsigned>(DK);
- DeclAttrBits.Implicit = Implicit;
- DeclAttrBits.Invalid = 0;
+ Bits.OpaqueBits = 0;
+ Bits.DeclAttribute.Kind = static_cast<unsigned>(DK);
+ Bits.DeclAttribute.Implicit = Implicit;
+ Bits.DeclAttribute.Invalid = false;
}
public:
@@ -326,22 +349,22 @@
public:
DeclAttrKind getKind() const {
- return static_cast<DeclAttrKind>(DeclAttrBits.Kind);
+ return static_cast<DeclAttrKind>(Bits.DeclAttribute.Kind);
}
/// Whether this attribute was implicitly added.
- bool isImplicit() const { return DeclAttrBits.Implicit; }
+ bool isImplicit() const { return Bits.DeclAttribute.Implicit; }
/// Set whether this attribute was implicitly added.
- void setImplicit(bool Implicit) {
- DeclAttrBits.Implicit = Implicit;
+ void setImplicit(bool Implicit = true) {
+ Bits.DeclAttribute.Implicit = Implicit;
}
/// Returns true if this attribute was find to be invalid in some way by
/// semantic analysis. In that case, the attribute should not be considered,
/// the attribute node should be only used to retrieve source information.
- bool isInvalid() const { return DeclAttrBits.Invalid; }
- void setInvalid() { DeclAttrBits.Invalid = true; }
+ bool isInvalid() const { return Bits.DeclAttribute.Invalid; }
+ void setInvalid() { Bits.DeclAttribute.Invalid = true; }
bool isValid() const { return !isInvalid(); }
@@ -518,11 +541,11 @@
public:
AlignmentAttr(unsigned Value, SourceLoc AtLoc, SourceRange Range,
bool Implicit)
- : DeclAttribute(DAK_Alignment, AtLoc, Range, Implicit),
- Value(Value) {}
-
- // The alignment value.
- const unsigned Value;
+ : DeclAttribute(DAK_Alignment, AtLoc, Range, Implicit) {
+ Bits.AlignmentAttr.Value = Value;
+ }
+
+ unsigned getValue() const { return Bits.AlignmentAttr.Value; }
static bool classof(const DeclAttribute *DA) {
return DA->getKind() == DAK_Alignment;
@@ -722,9 +745,9 @@
: DeclAttribute(DAK_ObjC, SourceLoc(), SourceRange(), /*Implicit=*/true),
NameData(nullptr)
{
- ObjCAttrBits.HasTrailingLocationInfo = false;
- ObjCAttrBits.ImplicitName = implicitName;
- ObjCAttrBits.Swift3Inferred = false;
+ Bits.ObjCAttr.HasTrailingLocationInfo = false;
+ Bits.ObjCAttr.ImplicitName = implicitName;
+ Bits.ObjCAttr.Swift3Inferred = false;
if (name) {
NameData = name->getOpaqueValue();
@@ -737,7 +760,7 @@
/// Determine whether this attribute has trailing location information.
bool hasTrailingLocationInfo() const {
- return ObjCAttrBits.HasTrailingLocationInfo;
+ return Bits.ObjCAttr.HasTrailingLocationInfo;
}
/// Retrieve the trailing location information.
@@ -815,7 +838,7 @@
/// Determine whether the name associated with this attribute was
/// implicit.
- bool isNameImplicit() const { return ObjCAttrBits.ImplicitName; }
+ bool isNameImplicit() const { return Bits.ObjCAttr.ImplicitName; }
/// Set the name of this entity.
void setName(ObjCSelector name, bool implicit) {
@@ -825,23 +848,23 @@
if (hasTrailingLocationInfo() &&
(!hasName() ||
getName()->getNumSelectorPieces() < name.getNumSelectorPieces())) {
- ObjCAttrBits.HasTrailingLocationInfo = false;
+ Bits.ObjCAttr.HasTrailingLocationInfo = false;
}
NameData = name.getOpaqueValue();
- ObjCAttrBits.ImplicitName = implicit;
+ Bits.ObjCAttr.ImplicitName = implicit;
}
/// Determine whether this attribute was inferred based on Swift 3's
/// deprecated @objc inference rules.
bool isSwift3Inferred() const {
- return ObjCAttrBits.Swift3Inferred;
+ return Bits.ObjCAttr.Swift3Inferred;
}
/// Set whether this attribute was inferred based on Swift 3's deprecated
/// @objc inference rules.
void setSwift3Inferred(bool inferred = true) {
- ObjCAttrBits.Swift3Inferred = inferred;
+ Bits.ObjCAttr.Swift3Inferred = inferred;
}
/// Clear the name of this entity.
@@ -874,13 +897,13 @@
AbstractAccessControlAttr(DeclAttrKind DK, SourceLoc atLoc, SourceRange range,
AccessLevel access, bool implicit)
: DeclAttribute(DK, atLoc, range, implicit) {
- AccessControlAttrBits.AccessLevel = static_cast<unsigned>(access);
+ Bits.AbstractAccessControlAttr.AccessLevel = static_cast<unsigned>(access);
assert(getAccess() == access && "not enough bits for access control");
}
public:
AccessLevel getAccess() const {
- return static_cast<AccessLevel>(AccessControlAttrBits.AccessLevel);
+ return static_cast<AccessLevel>(Bits.AbstractAccessControlAttr.AccessLevel);
}
static bool classof(const DeclAttribute *DA) {
@@ -918,16 +941,16 @@
/// Represents an inline attribute.
class InlineAttr : public DeclAttribute {
- InlineKind Kind;
public:
InlineAttr(SourceLoc atLoc, SourceRange range, InlineKind kind)
- : DeclAttribute(DAK_Inline, atLoc, range, /*Implicit=*/false),
- Kind(kind) {}
+ : DeclAttribute(DAK_Inline, atLoc, range, /*Implicit=*/false) {
+ Bits.InlineAttr.kind = unsigned(kind);
+ }
InlineAttr(InlineKind kind)
: InlineAttr(SourceLoc(), SourceRange(), kind) {}
- InlineKind getKind() const { return Kind; }
+ InlineKind getKind() const { return InlineKind(Bits.InlineAttr.kind); }
static bool classof(const DeclAttribute *DA) {
return DA->getKind() == DAK_Inline;
}
@@ -935,16 +958,18 @@
/// Represents the optimize attribute.
class OptimizeAttr : public DeclAttribute {
- OptimizationMode Mode;
public:
OptimizeAttr(SourceLoc atLoc, SourceRange range, OptimizationMode mode)
- : DeclAttribute(DAK_Optimize, atLoc, range, /*Implicit=*/false),
- Mode(mode) {}
+ : DeclAttribute(DAK_Optimize, atLoc, range, /*Implicit=*/false) {
+ Bits.OptimizeAttr.mode = unsigned(mode);
+ }
OptimizeAttr(OptimizationMode mode)
: OptimizeAttr(SourceLoc(), SourceRange(), mode) {}
- OptimizationMode getMode() const { return Mode; }
+ OptimizationMode getMode() const {
+ return OptimizationMode(Bits.OptimizeAttr.mode);
+ }
static bool classof(const DeclAttribute *DA) {
return DA->getKind() == DAK_Optimize;
}
@@ -952,16 +977,16 @@
/// Represents the side effects attribute.
class EffectsAttr : public DeclAttribute {
- EffectsKind Kind;
public:
EffectsAttr(SourceLoc atLoc, SourceRange range, EffectsKind kind)
- : DeclAttribute(DAK_Effects, atLoc, range, /*Implicit=*/false),
- Kind(kind) {}
+ : DeclAttribute(DAK_Effects, atLoc, range, /*Implicit=*/false) {
+ Bits.EffectsAttr.kind = unsigned(kind);
+ }
EffectsAttr(EffectsKind kind)
: EffectsAttr(SourceLoc(), SourceRange(), kind) {}
- EffectsKind getKind() const { return Kind; }
+ EffectsKind getKind() const { return EffectsKind(Bits.EffectsAttr.kind); }
static bool classof(const DeclAttribute *DA) {
return DA->getKind() == DAK_Effects;
}
@@ -971,18 +996,19 @@
/// Represents weak/unowned/unowned(unsafe) decl modifiers.
class ReferenceOwnershipAttr : public DeclAttribute {
- const ReferenceOwnership ownership;
-
public:
ReferenceOwnershipAttr(SourceRange range, ReferenceOwnership kind)
: DeclAttribute(DAK_ReferenceOwnership, range.Start, range,
- /*Implicit=*/false),
- ownership(kind) {}
+ /*Implicit=*/false) {
+ Bits.ReferenceOwnershipAttr.ownership = unsigned(kind);
+ }
ReferenceOwnershipAttr(ReferenceOwnership kind)
: ReferenceOwnershipAttr(SourceRange(), kind) {}
- ReferenceOwnership get() const { return ownership; }
+ ReferenceOwnership get() const {
+ return ReferenceOwnership(Bits.ReferenceOwnershipAttr.ownership);
+ }
/// Returns a copy of this attribute without any source information.
ReferenceOwnershipAttr *clone(ASTContext &context) const {
@@ -1045,21 +1071,22 @@
/// rather, it is introduced by the Clang importer to indicate
/// synthesized conformances.
class SynthesizedProtocolAttr : public DeclAttribute {
- KnownProtocolKind ProtocolKind;
LazyConformanceLoader *Loader;
public:
SynthesizedProtocolAttr(KnownProtocolKind protocolKind,
LazyConformanceLoader *Loader)
: DeclAttribute(DAK_SynthesizedProtocol, SourceLoc(), SourceRange(),
- /*Implicit=*/true),
- ProtocolKind(protocolKind), Loader(Loader)
+ /*Implicit=*/true), Loader(Loader)
{
+ Bits.SynthesizedProtocolAttr.kind = unsigned(protocolKind);
}
/// Retrieve the known protocol kind naming the protocol to be
/// synthesized.
- KnownProtocolKind getProtocolKind() const { return ProtocolKind; }
+ KnownProtocolKind getProtocolKind() const {
+ return KnownProtocolKind(Bits.SynthesizedProtocolAttr.kind);
+ }
/// Retrieve the lazy loader that will be used to populate the
/// synthesized conformance.
@@ -1074,16 +1101,14 @@
/// type list.
class SpecializeAttr : public DeclAttribute {
public:
+ // NOTE: When adding new kinds, you must update the inline bitfield macro.
enum class SpecializationKind {
Full,
Partial
};
private:
- unsigned numRequirements;
TrailingWhereClause *trailingWhereClause;
- SpecializationKind kind;
- bool exported;
Requirement *getRequirementsData() {
return reinterpret_cast<Requirement *>(this+1);
@@ -1113,25 +1138,25 @@
ArrayRef<Requirement> getRequirements() const;
MutableArrayRef<Requirement> getRequirements() {
- return { getRequirementsData(), numRequirements };
+ return { getRequirementsData(), Bits.SpecializeAttr.numRequirements };
}
void setRequirements(ASTContext &Ctx, ArrayRef<Requirement> requirements);
bool isExported() const {
- return exported;
+ return Bits.SpecializeAttr.exported;
}
SpecializationKind getSpecializationKind() const {
- return kind;
+ return SpecializationKind(Bits.SpecializeAttr.kind);
}
bool isFullSpecialization() const {
- return kind == SpecializationKind::Full;
+ return getSpecializationKind() == SpecializationKind::Full;
}
bool isPartialSpecialization() const {
- return kind == SpecializationKind::Partial;
+ return getSpecializationKind() == SpecializationKind::Partial;
}
static bool classof(const DeclAttribute *DA) {
@@ -1214,6 +1239,7 @@
/// Used to control manglings.
class ClangImporterSynthesizedTypeAttr : public DeclAttribute {
public:
+ // NOTE: When adding new kinds, you must update the inline bitfield macro.
enum class Kind : char {
/// A struct synthesized by the importer to represent an NSError with a
/// particular domain, as specified by an enum with the \c ns_error_domain
@@ -1236,18 +1262,22 @@
///
/// Must be a valid Swift identifier as well, for mangling purposes.
const StringRef originalTypeName;
- const Kind kind;
explicit ClangImporterSynthesizedTypeAttr(StringRef originalTypeName,
Kind kind)
: DeclAttribute(DAK_ClangImporterSynthesizedType, SourceLoc(),
SourceRange(), /*Implicit=*/true),
- originalTypeName(originalTypeName), kind(kind) {
+ originalTypeName(originalTypeName) {
assert(!originalTypeName.empty());
+ Bits.ClangImporterSynthesizedTypeAttr.kind = unsigned(kind);
+ }
+
+ Kind getKind() const {
+ return Kind(Bits.ClangImporterSynthesizedTypeAttr.kind);
}
StringRef getManglingName() const {
- return manglingNameForKind(kind);
+ return manglingNameForKind(getKind());
}
static StringRef manglingNameForKind(Kind kind) {
diff --git a/include/swift/AST/AttrKind.h b/include/swift/AST/AttrKind.h
index e67569a..5c02ce6 100644
--- a/include/swift/AST/AttrKind.h
+++ b/include/swift/AST/AttrKind.h
@@ -17,6 +17,7 @@
#ifndef SWIFT_ATTRKIND_H
#define SWIFT_ATTRKIND_H
+#include "swift/Basic/InlineBitfield.h"
#include "swift/Config.h"
#include "llvm/Support/DataTypes.h"
@@ -64,9 +65,13 @@
enum class InlineKind : uint8_t {
Never = 0,
- Always = 1
+ Always = 1,
+ Last_InlineKind = Always
};
+enum : unsigned { NumInlineKindBits =
+ countBitsUsed(static_cast<unsigned>(InlineKind::Last_InlineKind)) };
+
/// This enum represents the possible values of the @effects attribute.
/// These values are ordered from the strongest guarantee to the weakest,
/// so please do not reorder existing values.
@@ -75,9 +80,13 @@
ReadOnly,
ReleaseNone,
ReadWrite,
- Unspecified
+ Unspecified,
+ Last_EffectsKind = Unspecified
};
+enum : unsigned { NumEffectsKindBits =
+ countBitsUsed(static_cast<unsigned>(EffectsKind::Last_EffectsKind)) };
+
enum DeclAttrKind : unsigned {
#define DECL_ATTR(_, NAME, ...) DAK_##NAME,
@@ -85,6 +94,9 @@
DAK_Count
};
+enum : unsigned { NumDeclAttrKindBits =
+ countBitsUsed(static_cast<unsigned>(DeclAttrKind::DAK_Count - 1)) };
+
// Define enumerators for each type attribute, e.g. TAK_weak.
enum TypeAttrKind {
#define TYPE_ATTR(X) TAK_##X,
diff --git a/include/swift/AST/Builtins.def b/include/swift/AST/Builtins.def
index 2f05bbc..170e537 100644
--- a/include/swift/AST/Builtins.def
+++ b/include/swift/AST/Builtins.def
@@ -294,6 +294,27 @@
/// allocated element type 'E'.
BUILTIN_SIL_OPERATION(GetTailAddr, "getTailAddr", Integer)
+/// performInstantaneousReadAccess(Builtin.RawPointer, T.Type) -> ()
+/// Begin and then immediately end a read access to the given raw pointer,
+/// which will be treated as an address of type 'T'.
+BUILTIN_SIL_OPERATION(PerformInstantaneousReadAccess,
+ "performInstantaneousReadAccess", Special)
+
+/// beginUnpairedModifyAccess(Builtin.RawPointer, Builtin.RawPointer,
+/// T.Type) -> ()
+/// Begins but does not end a 'modify' access to the first raw pointer argument.
+/// The second raw pointer must be a pointer to an UnsafeValueBuffer, which
+/// will be used by the runtime to record the access. The lifetime of the
+/// value buffer must be longer than that of the access itself. The accessed
+/// address will be treated as having type 'T'.
+BUILTIN_SIL_OPERATION(BeginUnpairedModifyAccess, "beginUnpairedModifyAccess",
+ Special)
+
+/// endUnpairedAccess(Builtin.RawPointer) -> ()
+/// Ends an in-progress unpaired access. The raw pointer argument must be
+/// be a pointer to an UnsafeValueBuffer that records an in progress access.
+BUILTIN_SIL_OPERATION(EndUnpairedAccess, "endUnpairedAccess", Special)
+
/// condfail(Int1) -> ()
/// Triggers a runtime failure if the condition is true.
BUILTIN_SIL_OPERATION(CondFail, "condfail", Special)
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index acf7142..ed129ae 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -2304,8 +2304,14 @@
bool treatUsableFromInlineAsPublic = false) const;
- /// Copy the formal access level and @usableFromInline attribute from source.
- void copyFormalAccessFrom(ValueDecl *source);
+ /// Copy the formal access level and @usableFromInline attribute from
+ /// \p source.
+ ///
+ /// If \p sourceIsParentContext is true, an access level of \c private will
+ /// be copied as \c fileprivate, to ensure that this declaration will be
+ /// available everywhere \p source is.
+ void copyFormalAccessFrom(const ValueDecl *source,
+ bool sourceIsParentContext = false);
/// Returns the access level that actually controls how a declaration should
/// be emitted and may be used.
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index 15e16df..271fa99 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -3937,6 +3937,9 @@
NOTE(missing_unknown_case,none,
"handle unknown values using \"@unknown default\"", ())
+NOTE(non_exhaustive_switch_drop_unknown,none,
+ "remove '@unknown' to handle remaining values", ())
+
NOTE(missing_particular_case,none,
"add missing case: '%0'", (StringRef))
WARNING(redundant_particular_case,none,
diff --git a/include/swift/AST/KnownProtocols.h b/include/swift/AST/KnownProtocols.h
index f388fdd..f70bc07 100644
--- a/include/swift/AST/KnownProtocols.h
+++ b/include/swift/AST/KnownProtocols.h
@@ -13,6 +13,7 @@
#ifndef SWIFT_AST_KNOWNPROTOCOLS_H
#define SWIFT_AST_KNOWNPROTOCOLS_H
+#include "swift/Basic/InlineBitfield.h"
#include "swift/Config.h"
namespace llvm {
@@ -37,6 +38,9 @@
#include "swift/AST/KnownProtocols.def"
};
+enum : unsigned { NumKnownProtocolKindBits =
+ countBitsUsed(static_cast<unsigned>(NumKnownProtocols - 1)) };
+
/// Retrieve the name of the given known protocol.
llvm::StringRef getProtocolName(KnownProtocolKind kind);
diff --git a/include/swift/AST/Ownership.h b/include/swift/AST/Ownership.h
index a3dbfe5..ac6599e 100644
--- a/include/swift/AST/Ownership.h
+++ b/include/swift/AST/Ownership.h
@@ -19,6 +19,7 @@
#ifndef SWIFT_OWNERSHIP_H
#define SWIFT_OWNERSHIP_H
+#include "swift/Basic/InlineBitfield.h"
#include <stdint.h>
namespace swift {
@@ -38,8 +39,13 @@
/// \brief an 'unowned(unsafe)' reference
Unmanaged,
+
+ Last_Kind = Unmanaged
};
+enum : unsigned { NumReferenceOwnershipBits =
+ countBitsUsed(static_cast<unsigned>(ReferenceOwnership::Last_Kind)) };
+
/// Different kinds of value ownership supported by Swift.
enum class ValueOwnership : uint8_t {
/// \brief the context-dependent default ownership (sometimes shared,
diff --git a/include/swift/AST/SILOptions.h b/include/swift/AST/SILOptions.h
index e0c0eb4..309c529 100644
--- a/include/swift/AST/SILOptions.h
+++ b/include/swift/AST/SILOptions.h
@@ -42,20 +42,6 @@
/// The number of threads for multi-threaded code generation.
int NumThreads = 0;
- enum LinkingMode {
- /// Skip SIL linking.
- LinkNone,
-
- /// Perform normal SIL linking.
- LinkNormal,
-
- /// Link all functions during SIL linking.
- LinkAll
- };
-
- /// Controls how to perform SIL linking.
- LinkingMode LinkMode = LinkNormal;
-
/// Controls whether to pull in SIL from partial modules during the
/// merge modules step. Could perhaps be merged with the link mode
/// above but the interactions between all the flags are tricky.
diff --git a/include/swift/AST/TypeRepr.h b/include/swift/AST/TypeRepr.h
index b731336..59c0c77 100644
--- a/include/swift/AST/TypeRepr.h
+++ b/include/swift/AST/TypeRepr.h
@@ -92,6 +92,11 @@
NumTypes : 32
);
+ SWIFT_INLINE_BITFIELD_FULL(SILBoxTypeRepr, TypeRepr, 32,
+ NumGenericArgs : NumPadBits,
+ NumFields : 32
+ );
+
} Bits;
TypeRepr(TypeReprKind K) {
@@ -996,29 +1001,44 @@
friend class TypeRepr;
};
+class SILBoxTypeReprField {
+ SourceLoc VarOrLetLoc;
+ llvm::PointerIntPair<TypeRepr*, 1, bool> FieldTypeAndMutable;
+
+public:
+ SILBoxTypeReprField(SourceLoc loc, bool isMutable, TypeRepr *fieldType)
+ : VarOrLetLoc(loc), FieldTypeAndMutable(fieldType, isMutable) {
+ }
+
+ SourceLoc getLoc() const { return VarOrLetLoc; }
+ TypeRepr *getFieldType() const { return FieldTypeAndMutable.getPointer(); }
+ bool isMutable() const { return FieldTypeAndMutable.getInt(); }
+};
+
/// SIL-only TypeRepr for box types.
///
/// Boxes are either concrete: { var Int, let String }
/// or generic: <T: Runcible> { var T, let String } <Int>
-class SILBoxTypeRepr : public TypeRepr {
+class SILBoxTypeRepr final : public TypeRepr,
+ private llvm::TrailingObjects<SILBoxTypeRepr,
+ SILBoxTypeReprField, TypeRepr *> {
+ friend TrailingObjects;
GenericParamList *GenericParams;
GenericEnvironment *GenericEnv = nullptr;
SourceLoc LBraceLoc, RBraceLoc;
SourceLoc ArgLAngleLoc, ArgRAngleLoc;
+
+ size_t numTrailingObjects(OverloadToken<SILBoxTypeReprField>) const {
+ return Bits.SILBoxTypeRepr.NumFields;
+ }
+ size_t numTrailingObjects(OverloadToken<TypeRepr*>) const {
+ return Bits.SILBoxTypeRepr.NumGenericArgs;
+ }
public:
- struct Field {
- SourceLoc VarOrLetLoc;
- bool Mutable;
- TypeRepr *FieldType;
- };
-
-private:
- ArrayRef<Field> Fields;
- ArrayRef<TypeRepr *> GenericArgs;
-
-public:
+ using Field = SILBoxTypeReprField;
+
SILBoxTypeRepr(GenericParamList *GenericParams,
SourceLoc LBraceLoc, ArrayRef<Field> Fields,
SourceLoc RBraceLoc,
@@ -1026,9 +1046,17 @@
SourceLoc ArgRAngleLoc)
: TypeRepr(TypeReprKind::SILBox),
GenericParams(GenericParams), LBraceLoc(LBraceLoc), RBraceLoc(RBraceLoc),
- ArgLAngleLoc(ArgLAngleLoc), ArgRAngleLoc(ArgRAngleLoc),
- Fields(Fields), GenericArgs(GenericArgs)
- {}
+ ArgLAngleLoc(ArgLAngleLoc), ArgRAngleLoc(ArgRAngleLoc)
+ {
+ Bits.SILBoxTypeRepr.NumFields = Fields.size();
+ Bits.SILBoxTypeRepr.NumGenericArgs = GenericArgs.size();
+
+ std::uninitialized_copy(Fields.begin(), Fields.end(),
+ getTrailingObjects<SILBoxTypeReprField>());
+
+ std::uninitialized_copy(GenericArgs.begin(), GenericArgs.end(),
+ getTrailingObjects<TypeRepr*>());
+ }
static SILBoxTypeRepr *create(ASTContext &C,
GenericParamList *GenericParams,
@@ -1043,10 +1071,12 @@
}
ArrayRef<Field> getFields() const {
- return Fields;
+ return {getTrailingObjects<Field>(),
+ Bits.SILBoxTypeRepr.NumFields};
}
ArrayRef<TypeRepr *> getGenericArguments() const {
- return GenericArgs;
+ return {getTrailingObjects<TypeRepr*>(),
+ Bits.SILBoxTypeRepr.NumGenericArgs};
}
GenericParamList *getGenericParams() const {
diff --git a/include/swift/Basic/OptimizationMode.h b/include/swift/Basic/OptimizationMode.h
index e57b8e6..9f1e6b9 100644
--- a/include/swift/Basic/OptimizationMode.h
+++ b/include/swift/Basic/OptimizationMode.h
@@ -13,6 +13,7 @@
#ifndef SWIFT_BASIC_OPTIMIZATIONMODE_H
#define SWIFT_BASIC_OPTIMIZATIONMODE_H
+#include "swift/Basic/InlineBitfield.h"
#include "llvm/Support/DataTypes.h"
namespace swift {
@@ -27,6 +28,9 @@
LastMode = ForSize
};
+enum : unsigned { NumOptimizationModeBits =
+ countBitsUsed(static_cast<unsigned>(OptimizationMode::LastMode)) };
+
} // end namespace swift
#endif // SWIFT_BASIC_OPTIMIZATIONMODE_H
diff --git a/include/swift/IDE/RefactoringKinds.def b/include/swift/IDE/RefactoringKinds.def
index 3e26049..cbb0e1e 100644
--- a/include/swift/IDE/RefactoringKinds.def
+++ b/include/swift/IDE/RefactoringKinds.def
@@ -10,6 +10,10 @@
#define RANGE_REFACTORING(KIND, NAME, ID) SEMANTIC_REFACTORING(KIND, NAME, ID)
#endif
+#ifndef INTERNAL_RANGE_REFACTORING
+#define INTERNAL_RANGE_REFACTORING(KIND, NAME, ID) RANGE_REFACTORING(KIND, NAME, ID)
+#endif
+
#ifndef CURSOR_REFACTORING
#define CURSOR_REFACTORING(KIND, NAME, ID) SEMANTIC_REFACTORING(KIND, NAME, ID)
#endif
@@ -60,9 +64,14 @@
RANGE_REFACTORING(ConvertToTernaryExpr, "Convert To Ternary Expression", convert.ternary.expr)
-RANGE_REFACTORING(ReplaceBodiesWithFatalError, "Replace function bodies with fatalError", replace.bodies.with.fatalError)
+// These internal refactorings are designed to be helpful for working on
+// the compiler/standard library, etc., but are likely to be just confusing and
+// noise for general development.
+
+INTERNAL_RANGE_REFACTORING(ReplaceBodiesWithFatalError, "Replace Function Bodies With 'fatalError()'", replace.bodies.with.fatalError)
#undef CURSOR_REFACTORING
+#undef INTERNAL_RANGE_REFACTORING
#undef RANGE_REFACTORING
#undef SEMANTIC_REFACTORING
#undef REFACTORING
diff --git a/include/swift/Migrator/EditorAdapter.h b/include/swift/Migrator/EditorAdapter.h
index b6a9ec4..1a00e50 100644
--- a/include/swift/Migrator/EditorAdapter.h
+++ b/include/swift/Migrator/EditorAdapter.h
@@ -51,6 +51,8 @@
/// below. That doesn't handle duplicate or redundant changes.
mutable llvm::SmallSet<Replacement, 32> Replacements;
+ bool CacheEnabled;
+
/// A running transactional collection of basic edit operations.
/// Clang uses this transaction concept to cancel a batch of edits due to
/// incompatibilities, such as those due to macro expansions, but we don't
@@ -82,7 +84,7 @@
public:
EditorAdapter(swift::SourceManager &SwiftSrcMgr,
clang::SourceManager &ClangSrcMgr)
- : SwiftSrcMgr(SwiftSrcMgr), ClangSrcMgr(ClangSrcMgr),
+ : SwiftSrcMgr(SwiftSrcMgr), ClangSrcMgr(ClangSrcMgr), CacheEnabled(true),
Edits(clang::edit::Commit(ClangSrcMgr, clang::LangOptions())) {}
/// Lookup the BufferID in the SwiftToClangBufferMap. If it doesn't exist,
@@ -128,6 +130,8 @@
const clang::edit::Commit &getEdits() const {
return Edits;
}
+ void enableCache() { CacheEnabled = true; }
+ void disableCache() { CacheEnabled = false; }
};
} // end namespace migrator
diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td
index e3ebc8e..4a2e739 100644
--- a/include/swift/Option/FrontendOptions.td
+++ b/include/swift/Option/FrontendOptions.td
@@ -243,9 +243,6 @@
HelpText<"Limit the size of stack promoted objects to the provided number "
"of bytes.">;
-def disable_sil_linking : Flag<["-"], "disable-sil-linking">,
- HelpText<"Don't link SIL functions">;
-
def dump_clang_diagnostics : Flag<["-"], "dump-clang-diagnostics">,
HelpText<"Dump Clang diagnostics to stderr">;
diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h
index a198c8c..37e5a11 100644
--- a/include/swift/SIL/SILBuilder.h
+++ b/include/swift/SIL/SILBuilder.h
@@ -799,10 +799,10 @@
ConvertEscapeToNoEscapeInst *
createConvertEscapeToNoEscape(SILLocation Loc, SILValue Op, SILType Ty,
- bool lifetimeGuaranteed) {
+ bool isEscapedByUser, bool lifetimeGuaranteed) {
return insert(ConvertEscapeToNoEscapeInst::create(
getSILDebugLocation(Loc), Op, Ty, getFunction(), OpenedArchetypes,
- lifetimeGuaranteed));
+ isEscapedByUser, lifetimeGuaranteed));
}
ThinFunctionToPointerInst *
diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h
index 4c18ec2..681891c 100644
--- a/include/swift/SIL/SILCloner.h
+++ b/include/swift/SIL/SILCloner.h
@@ -986,10 +986,11 @@
void SILCloner<ImplClass>::visitConvertEscapeToNoEscapeInst(
ConvertEscapeToNoEscapeInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
- doPostProcess(
- Inst, getBuilder().createConvertEscapeToNoEscape(
- getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand()),
- getOpType(Inst->getType()), Inst->isLifetimeGuaranteed()));
+ doPostProcess(Inst,
+ getBuilder().createConvertEscapeToNoEscape(
+ getOpLocation(Inst->getLoc()),
+ getOpValue(Inst->getOperand()), getOpType(Inst->getType()),
+ Inst->isEscapedByUser(), Inst->isLifetimeGuaranteed()));
}
template<typename ImplClass>
diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h
index d8b5acc..cc356bc 100644
--- a/include/swift/SIL/SILInstruction.h
+++ b/include/swift/SIL/SILInstruction.h
@@ -3995,13 +3995,18 @@
friend SILBuilder;
bool lifetimeGuaranteed;
+ bool isEscaped; // Even if we can analyze this
+ // instruction the user might have
+ // escaped it.
ConvertEscapeToNoEscapeInst(SILDebugLocation DebugLoc, SILValue Operand,
ArrayRef<SILValue> TypeDependentOperands,
- SILType Ty, bool isLifetimeGuaranteed)
+ SILType Ty, bool isEscapedByUser,
+ bool isLifetimeGuaranteed)
: UnaryInstructionWithTypeDependentOperandsBase(
DebugLoc, Operand, TypeDependentOperands, Ty),
- lifetimeGuaranteed(isLifetimeGuaranteed) {
+ lifetimeGuaranteed(isLifetimeGuaranteed),
+ isEscaped(isEscapedByUser) {
assert(!Operand->getType().castTo<SILFunctionType>()->isNoEscape());
assert(Ty.castTo<SILFunctionType>()->isNoEscape());
}
@@ -4009,11 +4014,17 @@
static ConvertEscapeToNoEscapeInst *
create(SILDebugLocation DebugLoc, SILValue Operand, SILType Ty,
SILFunction &F, SILOpenedArchetypesState &OpenedArchetypes,
- bool lifetimeGuaranteed);
+ bool isEscapedByUser, bool lifetimeGuaranteed);
public:
bool isLifetimeGuaranteed() const {
return lifetimeGuaranteed;
}
+
+ bool isEscapedByUser() const {
+ return isEscaped;
+ }
+
+ void setEscapedByUser(bool isEscaped = true) { this->isEscaped = isEscaped; }
};
/// ThinFunctionToPointerInst - Convert a thin function pointer to a
diff --git a/include/swift/SIL/SILModule.h b/include/swift/SIL/SILModule.h
index a6760a6..66251e7 100644
--- a/include/swift/SIL/SILModule.h
+++ b/include/swift/SIL/SILModule.h
@@ -110,7 +110,15 @@
using DefaultWitnessTableListType = llvm::ilist<SILDefaultWitnessTable>;
using CoverageMapCollectionType =
llvm::MapVector<StringRef, SILCoverageMap *>;
- using LinkingMode = SILOptions::LinkingMode;
+
+ enum class LinkingMode : uint8_t {
+ /// Link functions with non-public linkage. Used by the mandatory pipeline.
+ LinkNormal,
+
+ /// Link all functions. Used by the performance pipeine.
+ LinkAll
+ };
+
using ActionCallback = std::function<void()>;
private:
@@ -499,7 +507,7 @@
///
/// \return false if the linking failed.
bool linkFunction(SILFunction *F,
- LinkingMode LinkAll = LinkingMode::LinkNormal);
+ LinkingMode LinkMode = LinkingMode::LinkNormal);
/// Check if a given function exists in any of the modules with a
/// required linkage, i.e. it can be linked by linkFunction.
diff --git a/include/swift/SILOptimizer/Analysis/SideEffectAnalysis.h b/include/swift/SILOptimizer/Analysis/SideEffectAnalysis.h
index a950db4..7fc56cb 100644
--- a/include/swift/SILOptimizer/Analysis/SideEffectAnalysis.h
+++ b/include/swift/SILOptimizer/Analysis/SideEffectAnalysis.h
@@ -2,7 +2,7 @@
//
// This source file is part of the Swift.org open source project
//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
@@ -34,103 +34,215 @@
RetainObserveKindEnd
};
-/// The SideEffectAnalysis provides information about side-effects of SIL
-/// functions. Side-effect information is provided per function and includes:
-/// Does the function read or write memory? Does the function retain or release
-/// objects? etc.
-/// For details see SideEffectAnalysis::FunctionEffects and
-/// SideEffectAnalysis::Effects.
-class SideEffectAnalysis : public BottomUpIPAnalysis {
-public:
+/// Generic base class for any bottom up analysis that summarizes per-function
+/// "effects" by first computing local effects, then propagating those effects
+/// bottom-up through the call graph.
+///
+/// FunctionEffects constraints:
+/// - void clear()
+/// - void setWorstEffects()
+/// - bool summarizeFunction(SILFunction *)
+/// - bool summarizeCall(FullApplySite)
+/// - bool mergeFrom(const FunctionSideEffects &)
+/// - bool mergeFromApply(const FunctionEffects &, FullApplySite)
+/// - void analyzeInstruction(SILInstruction *)
+template <typename FunctionEffects>
+class GenericFunctionEffectAnalysis : public BottomUpIPAnalysis {
- using MemoryBehavior = SILInstruction::MemoryBehavior;
- /// Set \p dest if \p src is set and return true if \p dest was not set
- /// before.
- static bool updateFlag(bool &dest, bool src) {
- if (src && !dest) {
- dest = src;
- return true;
- }
- return false;
- }
+ /// Stores the analysis data, e.g. side-effects, for a function.
+ struct FunctionInfo : public FunctionInfoBase<FunctionInfo> {
- /// Side-effect information for the function (global effects) or a specific
- /// parameter of the function. See FunctionEffects.
- class Effects {
- bool Reads = false;
- bool Writes = false;
- bool Retains = false;
- bool Releases = false;
-
- /// Sets the most conservative effects.
- void setWorstEffects() {
- Reads = true;
- Writes = true;
- Retains = true;
- Releases = true;
- }
+ /// The function effects.
+ FunctionEffects functionEffects;
- /// Clears all effects.
- void clear() {
- Reads = false;
- Writes = false;
- Retains = false;
- Releases = false;
- }
+ /// Back-link to the function.
+ SILFunction *F;
- friend class SideEffectAnalysis;
-
- public:
-
- /// Does the function read from memory (excluding reads from locally
- /// allocated memory)?
- bool mayRead() const { return Reads; }
+ /// Used during recomputation to indicate if the side-effects of a caller
+ /// must be updated.
+ bool needUpdateCallers = false;
- /// Does the function write to memory (excluding writes to locally
- /// allocated memory)?
- bool mayWrite() const { return Writes; }
-
- /// Does the function retain objects (excluding retains of locally
- /// allocated objects)?
- bool mayRetain() const { return Retains; }
+ FunctionInfo(SILFunction *F) : F(F) {}
- /// Does the function release objects (excluding releases of locally
- /// allocated objects)?
- bool mayRelease() const { return Releases; }
-
- /// Gets the memory behavior considering the global effects and
- /// all parameter effects. If \p ScanKind equals ignoreRetains then retain
- /// instructions are considered as side effects.
- MemoryBehavior getMemBehavior(RetainObserveKind ScanKind) const {
- if (mayRelease())
- return MemoryBehavior::MayHaveSideEffects;
-
- if (ScanKind == RetainObserveKind::ObserveRetains && mayRetain())
- return MemoryBehavior::MayHaveSideEffects;
-
- if (mayWrite())
- return mayRead() ? MemoryBehavior::MayReadWrite :
- MemoryBehavior::MayWrite;
-
- if (mayRead())
- return MemoryBehavior::MayRead;
-
- return MemoryBehavior::None;
- }
-
- /// Merge effects from \p RHS.
- bool mergeFrom(const Effects &RHS) {
- bool Changed = false;
- Changed |= updateFlag(Reads, RHS.Reads);
- Changed |= updateFlag(Writes, RHS.Writes);
- Changed |= updateFlag(Retains, RHS.Retains);
- Changed |= updateFlag(Releases, RHS.Releases);
- return Changed;
- }
+ /// Clears the analysis data on invalidation.
+ void clear() { functionEffects.clear(); }
};
+ typedef BottomUpFunctionOrder<FunctionInfo> FunctionOrder;
+
+ enum {
+ /// The maximum call-graph recursion depth for recomputing the analysis.
+ /// This is a relatively small number to reduce compile time in case of
+ /// large cycles in the call-graph.
+ /// In case of no cycles, we should not hit this limit at all because the
+ /// pass manager processes functions in bottom-up order.
+ MaxRecursionDepth = 5
+ };
+
+ /// All the function effect information for the whole module.
+ llvm::DenseMap<SILFunction *, FunctionInfo *> functionInfoMap;
+
+ /// The allocator for the map of values in FunctionInfoMap.
+ llvm::SpecificBumpPtrAllocator<FunctionInfo> allocator;
+
+ /// Callee analysis, used for determining the callees at call sites.
+ BasicCalleeAnalysis *BCA;
+
+public:
+ GenericFunctionEffectAnalysis(AnalysisKind kind) : BottomUpIPAnalysis(kind) {}
+
+ const FunctionEffects &getEffects(SILFunction *F) {
+ FunctionInfo *functionInfo = getFunctionInfo(F);
+ if (!functionInfo->isValid())
+ recompute(functionInfo);
+ return functionInfo->functionEffects;
+ }
+
+ /// Get the merged effects of all callees at the given call site from the
+ /// callee's perspective (don't transform parameter effects).
+ void getCalleeEffects(FunctionEffects &calleeEffects,
+ FullApplySite fullApply);
+
+ /// Get the merge effects of all callees at the given call site from the
+ /// caller's perspective. Parameter effects are translated into information
+ /// for the caller's arguments, and local effects are dropped.
+ void getCallSiteEffects(FunctionEffects &callEffects,
+ FullApplySite fullApply) {
+ FunctionEffects calleeEffects;
+ getCalleeEffects(calleeEffects, fullApply);
+ callEffects.mergeFromApply(calleeEffects, fullApply);
+ }
+
+ virtual void initialize(SILPassManager *PM) override;
+
+ /// Invalidate all information in this analysis.
+ virtual void invalidate() override;
+
+ /// Invalidate all of the information for a specific function.
+ virtual void invalidate(SILFunction *F, InvalidationKind K) override;
+
+ /// Notify the analysis about a newly created function.
+ virtual void notifyAddFunction(SILFunction *F) override {}
+
+ /// Notify the analysis about a function which will be deleted from the
+ /// module.
+ virtual void notifyDeleteFunction(SILFunction *F) override {
+ invalidate(F, InvalidationKind::Nothing);
+ }
+
+ /// Notify the analysis about changed witness or vtables.
+ virtual void invalidateFunctionTables() override {}
+
+private:
+ /// Gets or creates FunctionEffects for \p F.
+ FunctionInfo *getFunctionInfo(SILFunction *F) {
+ FunctionInfo *&functionInfo = functionInfoMap[F];
+ if (!functionInfo) {
+ functionInfo = new (allocator.Allocate()) FunctionInfo(F);
+ }
+ return functionInfo;
+ }
+
+ /// Analyze the side-effects of a function, including called functions.
+ /// Visited callees are added to \p BottomUpOrder until \p RecursionDepth
+ /// reaches MaxRecursionDepth.
+ void analyzeFunction(FunctionInfo *functionInfo, FunctionOrder &bottomUpOrder,
+ int recursionDepth);
+
+ void analyzeCall(FunctionInfo *functionInfo, FullApplySite fullApply,
+ FunctionOrder &bottomUpOrder, int recursionDepth);
+
+ /// Recomputes the side-effect information for the function \p Initial and
+ /// all called functions, up to a recursion depth of MaxRecursionDepth.
+ void recompute(FunctionInfo *initialInfo);
+};
+
+/// Set \p dest if \p src is set and return true if \p dest was not set
+/// before.
+static bool changedFlagByInPlaceOr(bool &dest, bool src) {
+ if (src && !dest) {
+ dest = src;
+ return true;
+ }
+ return false;
+}
+
+/// Side-effect information for the function (global effects) or a specific
+/// parameter of the function. See FunctionSideEffects.
+class FunctionSideEffectFlags {
+ friend class FunctionSideEffects;
+ using MemoryBehavior = SILInstruction::MemoryBehavior;
+
+ bool Reads = false;
+ bool Writes = false;
+ bool Retains = false;
+ bool Releases = false;
+
+ /// Sets the most conservative effects.
+ void setWorstEffects() {
+ Reads = true;
+ Writes = true;
+ Retains = true;
+ Releases = true;
+ }
+
+ /// Clears all effects.
+ void clear() {
+ Reads = false;
+ Writes = false;
+ Retains = false;
+ Releases = false;
+ }
+
+public:
+ /// Does the function read from memory (excluding reads from locally
+ /// allocated memory)?
+ bool mayRead() const { return Reads; }
+
+ /// Does the function write to memory (excluding writes to locally
+ /// allocated memory)?
+ bool mayWrite() const { return Writes; }
+
+ /// Does the function retain objects (excluding retains of locally
+ /// allocated objects)?
+ bool mayRetain() const { return Retains; }
+
+ /// Does the function release objects (excluding releases of locally
+ /// allocated objects)?
+ bool mayRelease() const { return Releases; }
+
+ /// Gets the memory behavior considering the global effects and
+ /// all parameter effects. If \p ScanKind equals ignoreRetains then retain
+ /// instructions are considered as side effects.
+ MemoryBehavior getMemBehavior(RetainObserveKind ScanKind) const {
+ if (mayRelease())
+ return MemoryBehavior::MayHaveSideEffects;
+
+ if (ScanKind == RetainObserveKind::ObserveRetains && mayRetain())
+ return MemoryBehavior::MayHaveSideEffects;
+
+ if (mayWrite())
+ return mayRead() ? MemoryBehavior::MayReadWrite
+ : MemoryBehavior::MayWrite;
+
+ if (mayRead())
+ return MemoryBehavior::MayRead;
+
+ return MemoryBehavior::None;
+ }
+
+ /// Merge effects from \p RHS.
+ bool mergeFrom(const FunctionSideEffectFlags &RHS) {
+ bool Changed = false;
+ Changed |= changedFlagByInPlaceOr(Reads, RHS.Reads);
+ Changed |= changedFlagByInPlaceOr(Writes, RHS.Writes);
+ Changed |= changedFlagByInPlaceOr(Retains, RHS.Retains);
+ Changed |= changedFlagByInPlaceOr(Releases, RHS.Releases);
+ return Changed;
+ }
+
friend raw_ostream &operator<<(raw_ostream &os,
- const SideEffectAnalysis::Effects &Effects) {
+ const FunctionSideEffectFlags &Effects) {
if (Effects.mayRead())
os << 'r';
if (Effects.mayWrite())
@@ -141,134 +253,169 @@
os << '-';
return os;
}
+};
- /// Summarizes the side-effects of a function. The side-effect information
- /// is divided into global effects and effects for specific function
- /// parameters.
- /// If a side-effect can be associated to a specific function parameter, it is
- /// not added to the global effects of the function. E.g. if a memory write is
- /// only done through an @inout parameter, the mayWrite side-effect is only
- /// accounted for this parameter.
- /// Effects for a parameter make only sense if the parameter is implemented as
- /// a pointer or contains a pointer:
- /// *) The parameter is an address parameter, e.g. @out, @inout, etc.
- /// *) The parameter is a reference
- /// *) The parameter is a value type (e.g. struct) and contains a reference.
- /// In this case the effects refer to all references in the value type.
- /// E.g. if a struct contains 2 references, a mayWrite effect means that
- /// memory is written to one of the referenced objects (or to both).
- class FunctionEffects {
-
- /// Side-effects which can be associated to a parameter.
- llvm::SmallVector<Effects, 6> ParamEffects;
-
- /// All other side-effects which cannot be associated to a parameter.
- Effects GlobalEffects;
-
- /// Side-effects on locally allocated storage. Such side-effects are not
- /// relevant to optimizations. The LocalEffects are only used to return
- /// "something" for local storage in getEffectsOn().
- Effects LocalEffects;
-
- /// Does the function allocate objects, boxes, etc., i.e. everything which
- /// has a reference count.
- bool AllocsObjects = false;
-
- /// Can this function trap or exit the program in any way?
- bool Traps = false;
-
- /// Does this function read a reference count other than with retain or
- /// release instructions, e.g. isUnique?
- bool ReadsRC = false;
-
- /// Returns the effects for an address or reference. This might be a
- /// parameter, the LocalEffects or, if the value cannot be associated to one
- /// of them, the GlobalEffects.
- Effects *getEffectsOn(SILValue Addr);
-
- FunctionEffects(unsigned numParams) : ParamEffects(numParams) { }
+/// Summarizes the side-effects of a function. The side-effect information
+/// is divided into global effects and effects for specific function
+/// parameters.
+/// If a side-effect can be associated to a specific function parameter, it is
+/// not added to the global effects of the function. E.g. if a memory write is
+/// only done through an @inout parameter, the mayWrite side-effect is only
+/// accounted for this parameter.
+/// Effects for a parameter make only sense if the parameter is implemented as
+/// a pointer or contains a pointer:
+/// *) The parameter is an address parameter, e.g. @out, @inout, etc.
+/// *) The parameter is a reference
+/// *) The parameter is a value type (e.g. struct) and contains a reference.
+/// In this case the effects refer to all references in the value type.
+/// E.g. if a struct contains 2 references, a mayWrite effect means that
+/// memory is written to one of the referenced objects (or to both).
+class FunctionSideEffects {
+ using MemoryBehavior = SILInstruction::MemoryBehavior;
- /// Sets the most conservative effects, if we don't know anything about the
- /// function.
- void setWorstEffects() {
- GlobalEffects.setWorstEffects();
- AllocsObjects = true;
- Traps = true;
- ReadsRC = true;
- }
-
- /// Clears all effects.
- void clear() {
- GlobalEffects.clear();
- for (Effects &PE : ParamEffects)
- PE.clear();
- AllocsObjects = false;
- Traps = false;
- ReadsRC = false;
- }
-
- /// Merge the flags from \p RHS.
- bool mergeFlags(const FunctionEffects &RHS) {
- bool Changed = false;
- Changed |= updateFlag(Traps, RHS.Traps);
- Changed |= updateFlag(AllocsObjects, RHS.AllocsObjects);
- Changed |= updateFlag(ReadsRC, RHS.ReadsRC);
- return Changed;
- }
-
- friend class SideEffectAnalysis;
-
- public:
-
- /// Constructs "empty" function effects.
- FunctionEffects() { }
+ /// Side-effects which can be associated to a parameter.
+ llvm::SmallVector<FunctionSideEffectFlags, 6> ParamEffects;
- /// Does the function allocate objects, boxes, etc., i.e. everything which
- /// has a reference count.
- bool mayAllocObjects() const { return AllocsObjects; }
+ /// All other side-effects which cannot be associated to a parameter.
+ FunctionSideEffectFlags GlobalEffects;
- /// Can this function trap or exit the program in any way?
- bool mayTrap() const { return Traps; }
+ /// Side-effects on locally allocated storage. Such side-effects are not
+ /// relevant to optimizations. The LocalEffects are only used to return
+ /// "something" for local storage in getEffectsOn().
+ FunctionSideEffectFlags LocalEffects;
- /// Does this function read a reference count other than with retain or
- /// release instructions, e.g. isUnique?
- bool mayReadRC() const { return ReadsRC; }
+ /// Does the function allocate objects, boxes, etc., i.e. everything which
+ /// has a reference count.
+ bool AllocsObjects = false;
- /// Gets the memory behavior considering the global effects and
- /// all parameter effects. If \p ScanKind equals ignoreRetains then retain
- /// instructions are considered as side effects.
- MemoryBehavior getMemBehavior(RetainObserveKind ScanKind) const;
+ /// Can this function trap or exit the program in any way?
+ bool Traps = false;
- /// Get the global effects for the function. These are effects which cannot
- /// be associated to a specific parameter, e.g. writes to global variables
- /// or writes to unknown pointers.
- const Effects &getGlobalEffects() const { return GlobalEffects; }
-
- /// Get the array of parameter effects. If a side-effect can be associated
- /// to a specific parameter, it is contained here instead of the global
- /// effects.
- /// Note that if a parameter effect is mayRelease(), it means that the
- /// global function effects can be anything, because the destructor of an
- /// object can have arbitrary side effects.
- ArrayRef<Effects> getParameterEffects() const { return ParamEffects; }
-
- /// Merge effects from \p RHS.
- bool mergeFrom(const FunctionEffects &RHS);
+ /// Does this function read a reference count other than with retain or
+ /// release instructions, e.g. isUnique?
+ bool ReadsRC = false;
- /// Merge effects from a function apply site within the function.
- bool mergeFromApply(const FunctionEffects &CalleeEffects,
- SILInstruction *FAS);
+ /// Returns the effects for an address or reference. This might be a
+ /// parameter, the LocalEffects or, if the value cannot be associated to one
+ /// of them, the GlobalEffects.
+ FunctionSideEffectFlags *getEffectsOn(SILValue Addr);
- /// Merge effects from an apply site within the function.
- bool mergeFromApply(const FunctionEffects &CalleeEffects,
- FullApplySite FAS);
-
- /// Print the function effects.
- void dump() const;
- };
+public:
+ /// Constructs "empty" function effects. This effects object can later be
+ /// populated by summarizeFunction or summarizeCall.
+ FunctionSideEffects() {}
+
+ /// Sets the most conservative effects, if we don't know anything about the
+ /// function.
+ void setWorstEffects() {
+ GlobalEffects.setWorstEffects();
+ AllocsObjects = true;
+ Traps = true;
+ ReadsRC = true;
+ }
+
+ /// Clears all effects.
+ void clear() {
+ ParamEffects.clear();
+ GlobalEffects.clear();
+ AllocsObjects = false;
+ Traps = false;
+ ReadsRC = false;
+ }
+
+ /// Merge the flags from \p RHS.
+ bool mergeFlags(const FunctionSideEffects &RHS) {
+ bool Changed = false;
+ Changed |= changedFlagByInPlaceOr(Traps, RHS.Traps);
+ Changed |= changedFlagByInPlaceOr(AllocsObjects, RHS.AllocsObjects);
+ Changed |= changedFlagByInPlaceOr(ReadsRC, RHS.ReadsRC);
+ return Changed;
+ }
+
+ // Summarize the given function's effects using this FunctionSideEffects
+ // object.
+ //
+ // Return true if the function's' effects have been fully summarized without
+ // visiting it's body.
+ bool summarizeFunction(SILFunction *F);
+
+ /// Summarize the callee side effects of a call instruction using this
+ /// FunctionSideEffects object without analyzing the callee function bodies or
+ /// scheduling the callees for bottom-up propagation.
+ ///
+ /// The side effects are represented from the callee's perspective. Parameter
+ /// effects are not translated into information on the caller's argument, and
+ /// local effects are not dropped.
+ ///
+ /// Return true if this call-site's effects are summarized without visiting
+ /// the callee.
+ bool summarizeCall(FullApplySite fullApply);
+
+ /// Merge effects directly from \p RHS.
+ bool mergeFrom(const FunctionSideEffects &RHS);
+
+ /// Merge the effects represented in CalleeEffects into this
+ /// FunctionSideEffects object. CalleeEffects must correspond to at least one
+ /// callee at the apply site `FAS`. Merging drops any local effects, and
+ /// translates parameter effects into effects on the caller-side arguments.
+ ///
+ /// The full caller-side effects at a call site can be obtained with
+ /// SideEffectsAnalysis::getCallSiteEffects().
+ bool mergeFromApply(const FunctionSideEffects &CalleeEffects,
+ FullApplySite FAS);
+
+ /// Analyze the side-effects of a single SIL instruction \p I.
+ /// Visited callees are added to \p BottomUpOrder until \p RecursionDepth
+ /// reaches MaxRecursionDepth.
+ void analyzeInstruction(SILInstruction *I);
+
+ /// Print the function effects.
+ void dump() const;
+
+ /// Does the function allocate objects, boxes, etc., i.e. everything which
+ /// has a reference count.
+ bool mayAllocObjects() const { return AllocsObjects; }
+
+ /// Can this function trap or exit the program in any way?
+ bool mayTrap() const { return Traps; }
+
+ /// Does this function read a reference count other than with retain or
+ /// release instructions, e.g. isUnique?
+ bool mayReadRC() const { return ReadsRC; }
+
+ /// Gets the memory behavior considering the global effects and
+ /// all parameter effects. If \p ScanKind equals ignoreRetains then retain
+ /// instructions are considered as side effects.
+ MemoryBehavior getMemBehavior(RetainObserveKind ScanKind) const;
+
+ /// Get the global effects for the function. These are effects which cannot
+ /// be associated to a specific parameter, e.g. writes to global variables
+ /// or writes to unknown pointers.
+ const FunctionSideEffectFlags &getGlobalEffects() const {
+ return GlobalEffects;
+ }
+
+ /// Get the array of parameter effects. If a side-effect can be associated
+ /// to a specific parameter, it is contained here instead of the global
+ /// effects.
+ /// Note that if a parameter effect is mayRelease(), it means that the
+ /// global function effects can be anything, because the destructor of an
+ /// object can have arbitrary side effects.
+ ArrayRef<FunctionSideEffectFlags> getParameterEffects() const {
+ return ParamEffects;
+ }
+
+protected:
+ /// Set the side-effects of a function, which has an @effects attribute.
+ /// Returns true if \a F has an @effects attribute which could be handled.
+ bool setDefinedEffects(SILFunction *F);
+
+ /// Set the side-effects of a semantic call.
+ /// Return true if \p ASC could be handled.
+ bool setSemanticEffects(ArraySemanticsCall ASC);
friend raw_ostream &operator<<(raw_ostream &os,
- const SideEffectAnalysis::FunctionEffects &Effects) {
+ const FunctionSideEffects &Effects) {
os << "func=" << Effects.getGlobalEffects();
int ParamIdx = 0;
for (auto &E : Effects.getParameterEffects()) {
@@ -282,126 +429,25 @@
os << ";readrc";
return os;
}
+};
-private:
-
- /// Stores the analysis data, i.e. the side-effects, for a function.
- struct FunctionInfo : public FunctionInfoBase<FunctionInfo> {
-
- /// The side-effects of the function.
- FunctionEffects FE;
-
- /// Back-link to the function.
- SILFunction *F;
-
- /// Used during recomputation to indicate if the side-effects of a caller
- /// must be updated.
- bool NeedUpdateCallers = false;
-
- FunctionInfo(SILFunction *F) :
- FE(F->empty() ? 0 : F->getArguments().size()), F(F) { }
-
- /// Clears the analysis data on invalidation.
- void clear() { FE.clear(); }
- };
-
- typedef BottomUpFunctionOrder<FunctionInfo> FunctionOrder;
-
- enum {
- /// The maximum call-graph recursion depth for recomputing the analysis.
- /// This is a relatively small number to reduce compile time in case of
- /// large cycles in the call-graph.
- /// In case of no cycles, we should not hit this limit at all because the
- /// pass manager processes functions in bottom-up order.
- MaxRecursionDepth = 5
- };
-
- /// All the side-effect information for the whole module.
- llvm::DenseMap<SILFunction *, FunctionInfo *> Function2Info;
-
- /// The allocator for the map values in Function2Info.
- llvm::SpecificBumpPtrAllocator<FunctionInfo> Allocator;
-
- /// Callee analysis, used for determining the callees at call sites.
- BasicCalleeAnalysis *BCA;
-
- /// Get the side-effects of a function, which has an @effects attribute.
- /// Returns true if \a F has an @effects attribute which could be handled.
- static bool getDefinedEffects(FunctionEffects &Effects, SILFunction *F);
-
- /// Get the side-effects of a semantic call.
- /// Return true if \p ASC could be handled.
- bool getSemanticEffects(FunctionEffects &Effects, ArraySemanticsCall ASC);
-
- /// Analyze the side-effects of a function, including called functions.
- /// Visited callees are added to \p BottomUpOrder until \p RecursionDepth
- /// reaches MaxRecursionDepth.
- void analyzeFunction(FunctionInfo *FInfo,
- FunctionOrder &BottomUpOrder,
- int RecursionDepth);
-
- /// Analyze the side-effects of a single SIL instruction \p I.
- /// Visited callees are added to \p BottomUpOrder until \p RecursionDepth
- /// reaches MaxRecursionDepth.
- void analyzeInstruction(FunctionInfo *FInfo,
- SILInstruction *I,
- FunctionOrder &BottomUpOrder,
- int RecursionDepth);
-
- /// Gets or creates FunctionEffects for \p F.
- FunctionInfo *getFunctionInfo(SILFunction *F) {
- FunctionInfo *&FInfo = Function2Info[F];
- if (!FInfo) {
- FInfo = new (Allocator.Allocate()) FunctionInfo(F);
- }
- return FInfo;
- }
-
- /// Recomputes the side-effect information for the function \p Initial and
- /// all called functions, up to a recursion depth of MaxRecursionDepth.
- void recompute(FunctionInfo *Initial);
-
+/// The SideEffectAnalysis provides information about side-effects of SIL
+/// functions. Side-effect information is provided per function and includes:
+/// Does the function read or write memory? Does the function retain or release
+/// objects? etc.
+/// For details see FunctionSideEffects.
+class SideEffectAnalysis
+ : public GenericFunctionEffectAnalysis<FunctionSideEffects> {
public:
SideEffectAnalysis()
- : BottomUpIPAnalysis(AnalysisKind::SideEffect) {}
+ : GenericFunctionEffectAnalysis<FunctionSideEffects>(
+ AnalysisKind::SideEffect) {}
static bool classof(const SILAnalysis *S) {
return S->getKind() == AnalysisKind::SideEffect;
}
-
- virtual void initialize(SILPassManager *PM) override;
-
- /// Get the side-effects of a function.
- const FunctionEffects &getEffects(SILFunction *F) {
- FunctionInfo *FInfo = getFunctionInfo(F);
- if (!FInfo->isValid())
- recompute(FInfo);
- return FInfo->FE;
- }
-
- /// Get the side-effects of a call site.
- void getEffects(FunctionEffects &ApplyEffects, FullApplySite FAS);
-
- /// Invalidate all information in this analysis.
- virtual void invalidate() override;
-
- /// Invalidate all of the information for a specific function.
- virtual void invalidate(SILFunction *F, InvalidationKind K) override;
-
- /// Notify the analysis about a newly created function.
- virtual void notifyAddFunction(SILFunction *F) override { }
-
- /// Notify the analysis about a function which will be deleted from the
- /// module.
- virtual void notifyDeleteFunction(SILFunction *F) override {
- invalidate(F, InvalidationKind::Nothing);
- }
-
- /// Notify the analysis about changed witness or vtables.
- virtual void invalidateFunctionTables() override { }
};
} // end namespace swift
-#endif
-
+#endif // SWIFT_SILOPTIMIZER_ANALYSIS_SIDEEFFECTANALYSIS_H_
diff --git a/include/swift/SILOptimizer/PassManager/Passes.def b/include/swift/SILOptimizer/PassManager/Passes.def
index c74bf64..a5062e5 100644
--- a/include/swift/SILOptimizer/PassManager/Passes.def
+++ b/include/swift/SILOptimizer/PassManager/Passes.def
@@ -90,6 +90,8 @@
"Captured Constant Propagation")
PASS(ClosureSpecializer, "closure-specialize",
"Closure Specialization on Constant Function Arguments")
+PASS(ClosureLifetimeFixup, "closure-lifetime-fixup",
+ "Closure Lifetime Fixup")
PASS(CodeSinking, "code-sinking",
"Code Sinking")
PASS(ComputeDominanceInfo, "compute-dominance-info",
@@ -226,20 +228,22 @@
"Late SIL release Hoisting Preserving Epilogues")
IRGEN_PASS(LoadableByAddress, "loadable-address",
"SIL Large Loadable type by-address lowering.")
+PASS(MandatorySILLinker, "mandatory-linker",
+ "Deserialize all referenced SIL functions that are shared or transparent")
+PASS(PerformanceSILLinker, "performance-linker",
+ "Deserialize all referenced SIL functions")
PASS(RemovePins, "remove-pins",
"Remove SIL pin/unpin pairs")
PASS(TempRValueOpt, "temp-rvalue-opt",
"Remove short-lived immutable temporary copies")
PASS(SideEffectsDumper, "side-effects-dump",
"Print Side-Effect Information for all Functions")
-PASS(SILCleanup, "cleanup",
- "SIL Cleanup Preparation for IRGen")
+PASS(IRGenPrepare, "irgen-prepare",
+ "Cleanup SIL in preparation for IRGen")
PASS(SILCombine, "sil-combine",
"Combine SIL Instructions via Peephole Optimization")
PASS(SILDebugInfoGenerator, "sil-debuginfo-gen",
"Generate Debug Information with Source Locations into Textual SIL")
-PASS(SILLinker, "linker",
- "Link all SIL Referenced within the Module via Deserialization")
PASS(SROA, "sroa",
"Scalar Replacement of Aggregate Stack Objects")
PASS(SROABBArgs, "sroa-bb-args",
diff --git a/include/swift/Sema/TypeCheckRequestKinds.def b/include/swift/Sema/TypeCheckRequestKinds.def
index d7c3536..e783285 100644
--- a/include/swift/Sema/TypeCheckRequestKinds.def
+++ b/include/swift/Sema/TypeCheckRequestKinds.def
@@ -45,10 +45,6 @@
/// Compute the set of inherited protocols for a given protocol.
TYPE_CHECK_REQUEST(InheritedProtocols, Protocol)
-/// Partially resolve a type, forming enough of its structure to make
-/// structural queries but not determining correctness.
-TYPE_CHECK_REQUEST(ResolveTypeRepr, TypeResolution)
-
/// Resolve the given type declaration to the requested type
/// resolution stage.
TYPE_CHECK_REQUEST(ResolveTypeDecl, TypeDeclResolution)
diff --git a/include/swift/Strings.h b/include/swift/Strings.h
index 40afd01..4d02d9d 100644
--- a/include/swift/Strings.h
+++ b/include/swift/Strings.h
@@ -16,73 +16,79 @@
namespace swift {
/// The extension for serialized modules.
-static const char SERIALIZED_MODULE_EXTENSION[] = "swiftmodule";
+constexpr static const char SERIALIZED_MODULE_EXTENSION[] = "swiftmodule";
/// The extension for serialized documentation comments.
-static const char SERIALIZED_MODULE_DOC_EXTENSION[] = "swiftdoc";
+constexpr static const char SERIALIZED_MODULE_DOC_EXTENSION[] = "swiftdoc";
/// The extension for PCH files.
-static const char PCH_EXTENSION[] = "pch";
+constexpr static const char PCH_EXTENSION[] = "pch";
/// The extension for replacement map files.
-static const char REMAP_EXTENSION[] = "remap";
+constexpr static const char REMAP_EXTENSION[] = "remap";
/// The extension for SIL files.
-static const char SIL_EXTENSION[] = "sil";
+constexpr static const char SIL_EXTENSION[] = "sil";
/// The extension for SIB files.
-static const char SIB_EXTENSION[] = "sib";
+constexpr static const char SIB_EXTENSION[] = "sib";
/// The extension for LLVM IR files.
-static const char LLVM_BC_EXTENSION[] = "bc";
-static const char LLVM_IR_EXTENSION[] = "ll";
+constexpr static const char LLVM_BC_EXTENSION[] = "bc";
+constexpr static const char LLVM_IR_EXTENSION[] = "ll";
/// The name of the standard library, which is a reserved module name.
-static const char STDLIB_NAME[] = "Swift";
+constexpr static const char STDLIB_NAME[] = "Swift";
/// The name of the Onone support library, which is a reserved module name.
-static const char SWIFT_ONONE_SUPPORT[] = "SwiftOnoneSupport";
+constexpr static const char SWIFT_ONONE_SUPPORT[] = "SwiftOnoneSupport";
/// The name of the SwiftShims module, which contains private stdlib decls.
-static const char SWIFT_SHIMS_NAME[] = "SwiftShims";
+constexpr static const char SWIFT_SHIMS_NAME[] = "SwiftShims";
/// The name of the Builtin module, which contains Builtin functions.
-static const char BUILTIN_NAME[] = "Builtin";
+constexpr static const char BUILTIN_NAME[] = "Builtin";
/// The prefix of module names used by LLDB to capture Swift expressions
-static const char LLDB_EXPRESSIONS_MODULE_NAME_PREFIX[] = "__lldb_expr_";
+constexpr static const char LLDB_EXPRESSIONS_MODULE_NAME_PREFIX[] =
+ "__lldb_expr_";
/// The name of the fake module used to hold imported Objective-C things.
-static const char MANGLING_MODULE_OBJC[] = "__C";
+constexpr static const char MANGLING_MODULE_OBJC[] = "__C";
/// The name of the fake module used to hold synthesized ClangImporter things.
-static const char MANGLING_MODULE_CLANG_IMPORTER[] = "__C_Synthesized";
+constexpr static const char MANGLING_MODULE_CLANG_IMPORTER[] =
+ "__C_Synthesized";
/// The name of the Builtin type prefix
-static const char BUILTIN_TYPE_NAME_PREFIX[] = "Builtin.";
+constexpr static const char BUILTIN_TYPE_NAME_PREFIX[] = "Builtin.";
/// The name of the Builtin type for Int
-static const char BUILTIN_TYPE_NAME_INT[] = "Builtin.Int";
+constexpr static const char BUILTIN_TYPE_NAME_INT[] = "Builtin.Int";
/// The name of the Builtin type for Int8
-static const char BUILTIN_TYPE_NAME_INT8[] = "Builtin.Int8";
+constexpr static const char BUILTIN_TYPE_NAME_INT8[] = "Builtin.Int8";
/// The name of the Builtin type for Int16
-static const char BUILTIN_TYPE_NAME_INT16[] = "Builtin.Int16";
+constexpr static const char BUILTIN_TYPE_NAME_INT16[] = "Builtin.Int16";
/// The name of the Builtin type for Int32
-static const char BUILTIN_TYPE_NAME_INT32[] = "Builtin.Int32";
+constexpr static const char BUILTIN_TYPE_NAME_INT32[] = "Builtin.Int32";
/// The name of the Builtin type for Int64
-static const char BUILTIN_TYPE_NAME_INT64[] = "Builtin.Int64";
+constexpr static const char BUILTIN_TYPE_NAME_INT64[] = "Builtin.Int64";
/// The name of the Builtin type for Int128
-static const char BUILTIN_TYPE_NAME_INT128[] = "Builtin.Int128";
+constexpr static const char BUILTIN_TYPE_NAME_INT128[] = "Builtin.Int128";
/// The name of the Builtin type for Int256
-static const char BUILTIN_TYPE_NAME_INT256[] = "Builtin.Int256";
+constexpr static const char BUILTIN_TYPE_NAME_INT256[] = "Builtin.Int256";
/// The name of the Builtin type for Int512
-static const char BUILTIN_TYPE_NAME_INT512[] = "Builtin.Int512";
+constexpr static const char BUILTIN_TYPE_NAME_INT512[] = "Builtin.Int512";
/// The name of the Builtin type for Float
-static const char BUILTIN_TYPE_NAME_FLOAT[] = "Builtin.Float";
+constexpr static const char BUILTIN_TYPE_NAME_FLOAT[] = "Builtin.Float";
/// The name of the Builtin type for NativeObject
-static const char BUILTIN_TYPE_NAME_NATIVEOBJECT[] = "Builtin.NativeObject";
+constexpr static const char BUILTIN_TYPE_NAME_NATIVEOBJECT[] =
+ "Builtin.NativeObject";
/// The name of the Builtin type for BridgeObject
-static const char BUILTIN_TYPE_NAME_BRIDGEOBJECT[] = "Builtin.BridgeObject";
+constexpr static const char BUILTIN_TYPE_NAME_BRIDGEOBJECT[] =
+ "Builtin.BridgeObject";
/// The name of the Builtin type for RawPointer
-static const char BUILTIN_TYPE_NAME_RAWPOINTER[] = "Builtin.RawPointer";
+constexpr static const char BUILTIN_TYPE_NAME_RAWPOINTER[] =
+ "Builtin.RawPointer";
/// The name of the Builtin type for UnsafeValueBuffer
-static const char BUILTIN_TYPE_NAME_UNSAFEVALUEBUFFER[] = "Builtin.UnsafeValueBuffer";
+constexpr static const char BUILTIN_TYPE_NAME_UNSAFEVALUEBUFFER[] =
+ "Builtin.UnsafeValueBuffer";
/// The name of the Builtin type for UnknownObject
-static const char BUILTIN_TYPE_NAME_UNKNOWNOBJECT[] = "Builtin.UnknownObject";
+constexpr static const char BUILTIN_TYPE_NAME_UNKNOWNOBJECT[] =
+ "Builtin.UnknownObject";
/// The name of the Builtin type for Vector
-static const char BUILTIN_TYPE_NAME_VEC[] = "Builtin.Vec";
+constexpr static const char BUILTIN_TYPE_NAME_VEC[] = "Builtin.Vec";
/// The name of the Builtin type for SILToken
-static const char BUILTIN_TYPE_NAME_SILTOKEN[] = "Builtin.SILToken";
+constexpr static const char BUILTIN_TYPE_NAME_SILTOKEN[] = "Builtin.SILToken";
/// The name of the Builtin type for Word
-static const char BUILTIN_TYPE_NAME_WORD[] = "Builtin.Word";
-
+constexpr static const char BUILTIN_TYPE_NAME_WORD[] = "Builtin.Word";
} // end namespace swift
#endif // SWIFT_STRINGS_H
diff --git a/lib/AST/ASTWalker.cpp b/lib/AST/ASTWalker.cpp
index 1d0861d..4fedbe7 100644
--- a/lib/AST/ASTWalker.cpp
+++ b/lib/AST/ASTWalker.cpp
@@ -1705,7 +1705,7 @@
bool Traversal::visitSILBoxTypeRepr(SILBoxTypeRepr *T) {
for (auto &field : T->getFields()) {
- if (doIt(field.FieldType))
+ if (doIt(field.getFieldType()))
return true;
}
for (auto &arg : T->getGenericArguments()) {
diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp
index 671b16c..a64b887 100644
--- a/lib/AST/Attr.cpp
+++ b/lib/AST/Attr.cpp
@@ -370,7 +370,7 @@
case DAK_Alignment:
Printer.printAttrName("@_alignment");
- Printer << "(" << cast<AlignmentAttr>(this)->Value << ")";
+ Printer << "(" << cast<AlignmentAttr>(this)->getValue() << ")";
break;
case DAK_SILGenName:
@@ -664,17 +664,17 @@
NameData = name->getOpaqueValue();
// Store location information.
- ObjCAttrBits.HasTrailingLocationInfo = true;
+ Bits.ObjCAttr.HasTrailingLocationInfo = true;
getTrailingLocations()[0] = parenRange.Start;
getTrailingLocations()[1] = parenRange.End;
std::memcpy(getTrailingLocations().slice(2).data(), nameLocs.data(),
nameLocs.size() * sizeof(SourceLoc));
} else {
- ObjCAttrBits.HasTrailingLocationInfo = false;
+ Bits.ObjCAttr.HasTrailingLocationInfo = false;
}
- ObjCAttrBits.ImplicitName = false;
- ObjCAttrBits.Swift3Inferred = false;
+ Bits.ObjCAttr.ImplicitName = false;
+ Bits.ObjCAttr.Swift3Inferred = false;
}
ObjCAttr *ObjCAttr::create(ASTContext &Ctx, Optional<ObjCSelector> name,
@@ -865,17 +865,20 @@
bool exported,
SpecializationKind kind)
: DeclAttribute(DAK_Specialize, atLoc, range, /*Implicit=*/false),
- numRequirements(0), trailingWhereClause(clause),
- kind(kind), exported(exported) {
+ trailingWhereClause(clause) {
+ Bits.SpecializeAttr.exported = exported;
+ Bits.SpecializeAttr.kind = unsigned(kind);
+ Bits.SpecializeAttr.numRequirements = 0;
}
SpecializeAttr::SpecializeAttr(SourceLoc atLoc, SourceRange range,
ArrayRef<Requirement> requirements,
bool exported,
SpecializationKind kind)
- : DeclAttribute(DAK_Specialize, atLoc, range, /*Implicit=*/false),
- numRequirements(0), kind(kind), exported(exported) {
- numRequirements = requirements.size();
+ : DeclAttribute(DAK_Specialize, atLoc, range, /*Implicit=*/false) {
+ Bits.SpecializeAttr.exported = exported;
+ Bits.SpecializeAttr.kind = unsigned(kind);
+ Bits.SpecializeAttr.numRequirements = requirements.size();
std::copy(requirements.begin(), requirements.end(), getRequirementsData());
}
@@ -886,7 +889,7 @@
assert(requirements.size() <= numClauseRequirements);
if (!numClauseRequirements)
return;
- numRequirements = requirements.size();
+ Bits.SpecializeAttr.numRequirements = requirements.size();
std::copy(requirements.begin(), requirements.end(), getRequirementsData());
}
diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp
index 6d2a220..0e5b40b 100644
--- a/lib/AST/Builtins.cpp
+++ b/lib/AST/Builtins.cpp
@@ -738,6 +738,31 @@
return builder.build(Id);
}
+static ValueDecl *getBeginUnpairedAccessOperation(ASTContext &Context,
+ Identifier Id) {
+ BuiltinGenericSignatureBuilder builder(Context);
+ builder.addParameter(makeConcrete(Context.TheRawPointerType));
+ builder.addParameter(makeConcrete(Context.TheRawPointerType));
+ builder.addParameter(makeMetatype(makeGenericParam(0)));
+ builder.setResult(makeConcrete(Context.TheEmptyTupleType));
+ return builder.build(Id);
+}
+
+static ValueDecl *
+getPerformInstantaneousReadAccessOperation(ASTContext &Context,
+ Identifier Id) {
+ BuiltinGenericSignatureBuilder builder(Context);
+ builder.addParameter(makeConcrete(Context.TheRawPointerType));
+ builder.addParameter(makeMetatype(makeGenericParam(0)));
+ builder.setResult(makeConcrete(Context.TheEmptyTupleType));
+ return builder.build(Id);
+}
+
+static ValueDecl *getEndUnpairedAccessOperation(ASTContext &Context,
+ Identifier Id) {
+ return getBuiltinFunction(Id, { Context.TheRawPointerType },
+ Context.TheEmptyTupleType);
+}
static ValueDecl *getSizeOrAlignOfOperation(ASTContext &Context,
Identifier Id) {
BuiltinGenericSignatureBuilder builder(Context);
@@ -1644,6 +1669,18 @@
if (Types.size() != 1) return nullptr;
return getGetTailAddrOperation(Context, Id, Types[0]);
+ case BuiltinValueKind::PerformInstantaneousReadAccess:
+ if (!Types.empty()) return nullptr;
+ return getPerformInstantaneousReadAccessOperation(Context, Id);
+
+ case BuiltinValueKind::BeginUnpairedModifyAccess:
+ if (!Types.empty()) return nullptr;
+ return getBeginUnpairedAccessOperation(Context, Id);
+
+ case BuiltinValueKind::EndUnpairedAccess:
+ if (!Types.empty()) return nullptr;
+ return getEndUnpairedAccessOperation(Context, Id);
+
#define BUILTIN(id, name, Attrs)
#define BUILTIN_BINARY_OPERATION(id, name, attrs, overload) case BuiltinValueKind::id:
#include "swift/AST/Builtins.def"
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index ed4d355..6293513 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -2259,9 +2259,24 @@
llvm_unreachable("unknown access level");
}
-void ValueDecl::copyFormalAccessFrom(ValueDecl *source) {
+void ValueDecl::copyFormalAccessFrom(const ValueDecl *source,
+ bool sourceIsParentContext) {
if (!hasAccess()) {
- setAccess(source->getFormalAccess());
+ AccessLevel access = source->getFormalAccess();
+
+ // To make something have the same access as a 'private' parent, it has to
+ // be 'fileprivate' or greater.
+ if (sourceIsParentContext && access == AccessLevel::Private)
+ access = AccessLevel::FilePrivate;
+
+ // Only certain declarations can be 'open'.
+ if (access == AccessLevel::Open && !isPotentiallyOverridable()) {
+ assert(!isa<ClassDecl>(this) &&
+ "copying 'open' onto a class has complications");
+ access = AccessLevel::Public;
+ }
+
+ setAccess(access);
}
// Inherit the @usableFromInline attribute.
@@ -2816,7 +2831,7 @@
setHasDestructor();
// Propagate access control and versioned-ness.
- DD->copyFormalAccessFrom(this);
+ DD->copyFormalAccessFrom(this, /*sourceIsParentContext*/true);
// Wire up generic environment of DD.
DD->setGenericEnvironment(getGenericEnvironmentOfContext());
diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp
index 77723d5..8edf627 100644
--- a/lib/AST/GenericSignature.cpp
+++ b/lib/AST/GenericSignature.cpp
@@ -345,17 +345,30 @@
auto genericParams = getGenericParams();
unsigned curGenericParamIdx = 0, numGenericParams = genericParams.size();
- // Figure out which generic parameters are complete.
- SmallVector<bool, 4> genericParamsAreConcrete(genericParams.size(), false);
+ // Figure out which generic parameters are concrete or same-typed to another
+ // generic parameter.
+ auto genericParamsAreNonCanonical =
+ SmallVector<bool, 4>(genericParams.size(), false);
for (auto req : reqs) {
if (req.getKind() != RequirementKind::SameType) continue;
- if (req.getSecondType()->isTypeParameter()) continue;
-
- auto gp = req.getFirstType()->getAs<GenericTypeParamType>();
- if (!gp) continue;
+
+ GenericTypeParamType *gp;
+ if (auto secondGP = req.getSecondType()->getAs<GenericTypeParamType>()) {
+ // If two generic parameters are same-typed, then the left-hand one
+ // is canonical.
+ gp = secondGP;
+ } else {
+ // If an associated type is same-typed, it doesn't constrain the generic
+ // parameter itself.
+ if (req.getSecondType()->isTypeParameter()) continue;
+
+ // Otherwise, the generic parameter is concrete.
+ gp = req.getFirstType()->getAs<GenericTypeParamType>();
+ if (!gp) continue;
+ }
unsigned index = GenericParamKey(gp).findIndexIn(genericParams);
- genericParamsAreConcrete[index] = true;
+ genericParamsAreNonCanonical[index] = true;
}
/// Local function to 'catch up' to the next dependent type we're going to
@@ -382,7 +395,7 @@
if (curGenericParam->getDepth() < stopDepth ||
(curGenericParam->getDepth() == stopDepth &&
curGenericParam->getIndex() < stopIndex)) {
- if (!genericParamsAreConcrete[curGenericParamIdx] &&
+ if (!genericParamsAreNonCanonical[curGenericParamIdx] &&
fn(curGenericParam, { }))
return true;
@@ -441,7 +454,7 @@
// parameter we can't skip, invoke the callback.
if ((startIdx != endIdx ||
(isa<GenericTypeParamType>(depTy) &&
- !genericParamsAreConcrete[
+ !genericParamsAreNonCanonical[
GenericParamKey(cast<GenericTypeParamType>(depTy))
.findIndexIn(genericParams)])) &&
fn(depTy, reqs.slice(startIdx, endIdx-startIdx)))
@@ -807,7 +820,7 @@
}
bool GenericSignature::isCanonicalTypeInContext(Type type,
- GenericSignatureBuilder &builder) {
+ GenericSignatureBuilder &builder) {
// If the type isn't independently canonical, it's certainly not canonical
// in this context.
if (!type->isCanonical())
@@ -835,7 +848,7 @@
}
CanType GenericSignature::getCanonicalTypeInContext(Type type,
- GenericSignatureBuilder &builder) {
+ GenericSignatureBuilder &builder) {
type = type->getCanonicalType();
// All the contextual canonicality rules apply to type parameters, so if the
diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp
index 6ed4015..fb8e895 100644
--- a/lib/AST/Module.cpp
+++ b/lib/AST/Module.cpp
@@ -190,6 +190,12 @@
}
if (auto *NTD = dyn_cast<NominalTypeDecl>(D))
doPopulateCache(NTD->getMembers(), true);
+
+ // Avoid populating the cache with the members of invalid extension
+ // declarations. These members can be used to point validation inside of
+ // a malformed context.
+ if (D->isInvalid()) continue;
+
if (auto *ED = dyn_cast<ExtensionDecl>(D))
doPopulateCache(ED->getMembers(), true);
}
diff --git a/lib/AST/RequirementEnvironment.cpp b/lib/AST/RequirementEnvironment.cpp
index 8a29803..8989f1a 100644
--- a/lib/AST/RequirementEnvironment.cpp
+++ b/lib/AST/RequirementEnvironment.cpp
@@ -209,13 +209,6 @@
// Next, add each of the requirements (mapped from the requirement's
// interface types into the abstract type parameters).
for (auto &rawReq : reqSig->getRequirements()) {
- // FIXME: This should not be necessary, since the constraint is redundant,
- // but we need it to work around some crashes for now.
- if (rawReq.getKind() == RequirementKind::Conformance &&
- rawReq.getFirstType()->isEqual(selfType) &&
- rawReq.getSecondType()->isEqual(proto->getDeclaredType()))
- continue;
-
if (auto req = rawReq.subst(reqToSyntheticEnvMap))
builder.addRequirement(*req, source, conformanceDC->getParentModule());
}
diff --git a/lib/AST/TypeRepr.cpp b/lib/AST/TypeRepr.cpp
index f848364..9ac6c10 100644
--- a/lib/AST/TypeRepr.cpp
+++ b/lib/AST/TypeRepr.cpp
@@ -237,8 +237,8 @@
SmallVector<TypeRepr *, 4> cloneArgs;
for (auto &field : type->getFields())
- cloneFields.push_back({field.VarOrLetLoc, field.Mutable,
- visit(field.FieldType)});
+ cloneFields.push_back({field.getLoc(), field.isMutable(),
+ visit(field.getFieldType())});
for (auto *arg : type->getGenericArguments())
cloneArgs.push_back(visit(arg));
@@ -471,10 +471,11 @@
SourceLoc RBraceLoc,
SourceLoc ArgLAngleLoc, ArrayRef<TypeRepr *> GenericArgs,
SourceLoc ArgRAngleLoc) {
- return new (C) SILBoxTypeRepr(GenericParams,
- LBraceLoc, C.AllocateCopy(Fields), RBraceLoc,
- ArgLAngleLoc, C.AllocateCopy(GenericArgs),
- ArgRAngleLoc);
+ auto size = totalSizeToAlloc<Field, TypeRepr*>(Fields.size(),
+ GenericArgs.size());
+ auto mem = C.Allocate(size, alignof(SILBoxTypeRepr));
+ return new (mem) SILBoxTypeRepr(GenericParams, LBraceLoc, Fields, RBraceLoc,
+ ArgLAngleLoc, GenericArgs, ArgRAngleLoc);
}
SourceLoc SILBoxTypeRepr::getStartLocImpl() const {
diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp
index 217bb57..415adcc 100644
--- a/lib/ClangImporter/ClangImporter.cpp
+++ b/lib/ClangImporter/ClangImporter.cpp
@@ -27,6 +27,7 @@
#include "swift/AST/Module.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/Types.h"
+#include "swift/Basic/Defer.h"
#include "swift/Basic/Platform.h"
#include "swift/Basic/Range.h"
#include "swift/Basic/StringExtras.h"
@@ -715,16 +716,32 @@
CompilerInstance &CI = *Impl.Instance;
auto clangDiags = CompilerInstance::createDiagnostics(
new clang::DiagnosticOptions());
+
+ // Note: Reusing the file manager is safe; this is a component that's already
+ // reused when building PCM files for the module cache.
clang::SourceManager clangSrcMgr(*clangDiags, CI.getFileManager());
auto FID = clangSrcMgr.createFileID(
llvm::make_unique<ZeroFilledMemoryBuffer>(1, "<main>"));
clangSrcMgr.setMainFileID(FID);
+
+ // Note: Reusing the real HeaderSearch is dangerous, but it's not easy to
+ // copy. We put in some effort to reset it to the way it was below.
+ clang::HeaderSearch &headerSearchInfo =
+ CI.getPreprocessor().getHeaderSearchInfo();
+ assert(headerSearchInfo.getExternalLookup() == nullptr &&
+ "already configured an ASTReader");
+
+ // Note: Reusing the PCM cache is safe because that's already shared when
+ // building PCM files for the module cache. Using the top-level compiler
+ // instance as a module loader does seem a little dangerous but does not
+ // appear to cause problems at the moment.
clang::Preprocessor PP(CI.getInvocation().getPreprocessorOptsPtr(),
*clangDiags,
CI.getLangOpts(),
clangSrcMgr,
CI.getPCMCache(),
- CI.getPreprocessor().getHeaderSearchInfo(), CI,
+ headerSearchInfo,
+ (clang::ModuleLoader &)CI,
/*IILookup=*/nullptr,
/*OwnsHeaderSearch=*/false);
PP.Initialize(CI.getTarget());
@@ -732,6 +749,8 @@
PP.getIdentifierTable(), PP.getSelectorTable(),
PP.getBuiltinInfo());
+ // Note: Reusing the PCHContainerReader or ModuleFileExtensions could be
+ // dangerous.
std::unique_ptr<clang::ASTReader> Reader(new clang::ASTReader(
PP, &ctx, CI.getPCHContainerReader(),
CI.getFrontendOpts().ModuleFileExtensions,
@@ -740,6 +759,12 @@
/*AllowPCHWithCompilerErrors*/ false,
/*AllowConfigurationMismatch*/ false,
/*ValidateSystemInputs*/ true));
+ SWIFT_DEFER {
+ assert(headerSearchInfo.getExternalLookup() == Reader.get() ||
+ headerSearchInfo.getExternalLookup() == nullptr);
+ headerSearchInfo.SetExternalLookup(nullptr);
+ headerSearchInfo.SetExternalSource(nullptr);
+ };
ctx.InitBuiltinTypes(CI.getTarget());
auto result = Reader->ReadAST(PCHFilename,
@@ -2837,6 +2862,11 @@
ModuleDecl::LinkLibraryCallback callback) const {
if (!clangModule)
return;
+
+ // Skip this lib name in favor of export_as name.
+ if (clangModule->UseExportAsModuleLinkName)
+ return;
+
for (auto clangLinkLib : clangModule->LinkLibraries) {
LibraryKind kind;
if (clangLinkLib.IsFramework)
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 821fac2..679bc8d 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -576,9 +576,6 @@
}
}
- if (const Arg *A = Args.getLastArg(OPT_disable_sil_linking))
- Opts.LinkMode = SILOptions::LinkNone;
-
if (Args.hasArg(OPT_sil_merge_partial_modules))
Opts.MergePartialModules = true;
diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp
index 88fe861..080e7ed 100644
--- a/lib/IDE/CodeCompletion.cpp
+++ b/lib/IDE/CodeCompletion.cpp
@@ -1827,36 +1827,47 @@
void addImportModuleNames() {
// FIXME: Add user-defined swift modules
- SmallVector<clang::Module*, 20> Modules;
- Ctx.getVisibleTopLevelClangModules(Modules);
- std::sort(Modules.begin(), Modules.end(),
- [](clang::Module* LHS , clang::Module* RHS) {
- return LHS->getTopLevelModuleName().compare_lower(
- RHS->getTopLevelModuleName()) < 0;
+ SmallVector<StringRef, 20> ModuleNames;
+
+ // Collect clang module names.
+ {
+ SmallVector<clang::Module*, 20> ClangModules;
+ Ctx.getVisibleTopLevelClangModules(ClangModules);
+ for (auto *M : ClangModules) {
+ if (!M->isAvailable())
+ continue;
+ if (M->getTopLevelModuleName().startswith("_"))
+ continue;
+ if (M->getTopLevelModuleName() == Ctx.SwiftShimsModuleName.str())
+ continue;
+
+ ModuleNames.push_back(M->getTopLevelModuleName());
+ }
+ }
+
+ std::sort(ModuleNames.begin(), ModuleNames.end(),
+ [](StringRef LHS, StringRef RHS) {
+ return LHS.compare_lower(RHS) < 0;
});
+
llvm::StringSet<> ImportedModules;
collectImportedModules(ImportedModules);
- for (auto *M : Modules) {
- if (M->isAvailable() &&
- !M->getTopLevelModuleName().startswith("_") &&
- M->getTopLevelModuleName() != CurrDeclContext->getASTContext().
- SwiftShimsModuleName.str()) {
- auto MD = ModuleDecl::create(Ctx.getIdentifier(M->getTopLevelModuleName()),
- Ctx);
- CodeCompletionResultBuilder Builder(Sink,
- CodeCompletionResult::ResultKind::
- Declaration,
- SemanticContextKind::OtherModule,
- ExpectedTypes);
- Builder.setAssociatedDecl(MD);
- Builder.addTextChunk(MD->getNameStr());
- Builder.addTypeAnnotation("Module");
- // Imported modules are not recommended.
- if (ImportedModules.count(MD->getNameStr()) != 0)
- Builder.setNotRecommended(CodeCompletionResult::NotRecommendedReason::
- Redundant);
- }
+ for (auto ModuleName : ModuleNames) {
+ auto MD = ModuleDecl::create(Ctx.getIdentifier(ModuleName), Ctx);
+ CodeCompletionResultBuilder Builder(
+ Sink,
+ CodeCompletionResult::ResultKind::Declaration,
+ SemanticContextKind::OtherModule,
+ ExpectedTypes);
+ Builder.setAssociatedDecl(MD);
+ Builder.addTextChunk(MD->getNameStr());
+ Builder.addTypeAnnotation("Module");
+
+ // Imported modules are not recommended.
+ if (ImportedModules.count(MD->getNameStr()) != 0)
+ Builder.setNotRecommended(
+ CodeCompletionResult::NotRecommendedReason::Redundant);
}
}
diff --git a/lib/IDE/Refactoring.cpp b/lib/IDE/Refactoring.cpp
index b299a86..9d3974d 100644
--- a/lib/IDE/Refactoring.cpp
+++ b/lib/IDE/Refactoring.cpp
@@ -1639,7 +1639,7 @@
}
bool RefactoringActionReplaceBodiesWithFatalError::performChange() {
- const StringRef replacement = "{ fatalError() }";
+ const StringRef replacement = "{\nfatalError()\n}";
llvm::SmallPtrSet<Decl *, 16> Found;
for (auto decl : RangeInfo.DeclaredDecls) {
FindAllSubDecls(Found).walk(decl.VD);
@@ -3099,9 +3099,14 @@
Range.getEnd(SF->getASTContext().SourceMgr));
ResolvedRangeInfo Result = Resolver.resolve();
+ bool enableInternalRefactoring = getenv("SWIFT_ENABLE_INTERNAL_REFACTORING_ACTIONS");
+
#define RANGE_REFACTORING(KIND, NAME, ID) \
if (RefactoringAction##KIND::isApplicable(Result, DiagEngine)) \
Scratch.push_back(RefactoringKind::KIND);
+#define INTERNAL_RANGE_REFACTORING(KIND, NAME, ID) \
+ if (enableInternalRefactoring) \
+ RANGE_REFACTORING(KIND, NAME, ID)
#include "swift/IDE/RefactoringKinds.def"
RangeStartMayNeedRename = rangeStartMayNeedRename(Result);
diff --git a/lib/IRGen/GenArchetype.cpp b/lib/IRGen/GenArchetype.cpp
index 16415ed..f99a067 100644
--- a/lib/IRGen/GenArchetype.cpp
+++ b/lib/IRGen/GenArchetype.cpp
@@ -99,7 +99,7 @@
void collectMetadataForOutlining(OutliningMetadataCollector &collector,
SILType T) const override {
// We'll need formal type metadata for this archetype.
- collector.collectFormalTypeMetadata(T.getSwiftRValueType());
+ collector.collectTypeMetadataForLayout(T);
}
};
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index bbc4482..47b3c78 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -548,6 +548,7 @@
init, name);
var->setSection(section);
var->setAlignment(alignment.getValue());
+ disableAddressSanitizer(IGM, var);
// Mark the variable as used if doesn't have external linkage.
// (Note that we'd specifically like to not put @llvm.used in itself.)
@@ -1984,6 +1985,31 @@
return var;
}
+void swift::irgen::disableAddressSanitizer(IRGenModule &IGM, llvm::GlobalVariable *var) {
+ // Add an operand to llvm.asan.globals blacklisting this global variable.
+ llvm::Metadata *metadata[] = {
+ // The global variable to blacklist.
+ llvm::ConstantAsMetadata::get(var),
+
+ // Source location. Optional, unnecessary here.
+ nullptr,
+
+ // Name. Optional, unnecessary here.
+ nullptr,
+
+ // Whether the global is dynamically initialized.
+ llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
+ llvm::Type::getInt1Ty(IGM.Module.getContext()), false)),
+
+ // Whether the global is blacklisted.
+ llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
+ llvm::Type::getInt1Ty(IGM.Module.getContext()), true))};
+
+ auto *globalNode = llvm::MDNode::get(IGM.Module.getContext(), metadata);
+ auto *asanMetadata = IGM.Module.getOrInsertNamedMetadata("llvm.asan.globals");
+ asanMetadata->addOperand(globalNode);
+}
+
/// Emit a global declaration.
void IRGenModule::emitGlobalDecl(Decl *D) {
switch (D->getKind()) {
@@ -2729,6 +2755,9 @@
}
var->setSection(sectionName);
+
+ disableAddressSanitizer(*this, var);
+
addUsedGlobal(var);
return var;
}
@@ -2915,8 +2944,10 @@
}
var->setSection(sectionName);
- addUsedGlobal(var);
+
+ disableAddressSanitizer(*this, var);
+ addUsedGlobal(var);
return var;
}
@@ -2982,8 +3013,10 @@
var->setInitializer(initializer);
var->setSection(sectionName);
var->setAlignment(4);
- addUsedGlobal(var);
+
+ disableAddressSanitizer(*this, var);
+ addUsedGlobal(var);
return var;
}
@@ -3029,6 +3062,9 @@
var->setInitializer(llvm::ConstantArray::get(arrayTy, elts));
var->setSection(sectionName);
var->setAlignment(4);
+
+ disableAddressSanitizer(*this, var);
+
addUsedGlobal(var);
return var;
}
diff --git a/lib/IRGen/GenDecl.h b/lib/IRGen/GenDecl.h
index f06269a..3e5eb42 100644
--- a/lib/IRGen/GenDecl.h
+++ b/lib/IRGen/GenDecl.h
@@ -54,6 +54,7 @@
Optional<SILLocation> DebugLoc = None,
StringRef DebugName = StringRef());
+ void disableAddressSanitizer(IRGenModule &IGM, llvm::GlobalVariable *var);
}
}
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index e66b9b9..df147e2 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -101,6 +101,8 @@
}
void IRGenModule::setTrueConstGlobal(llvm::GlobalVariable *var) {
+ disableAddressSanitizer(*this, var);
+
switch (TargetInfo.OutputObjectFormat) {
case llvm::Triple::UnknownObjectFormat:
llvm_unreachable("unknown object format");
@@ -223,10 +225,10 @@
for (auto param : canSig->getGenericParams()) {
// Currently, there are only type parameters. The parameter is a key
- // argument if it hasn't been grounded by a same-type constraint.
+ // argument if it's canonical in its generic context.
asImpl().addGenericParameter(GenericParamKind::Type,
- /*key argument*/ !canSig->isConcreteType(param),
- /*extra argument*/ false);
+ /*key argument*/ canSig->isCanonicalTypeInContext(param),
+ /*extra argument*/ false);
}
// Pad the structure up to four bytes for the following requirements.
@@ -3719,6 +3721,7 @@
auto var = cast<llvm::GlobalVariable>(
getAddrOfProtocolDescriptor(protocol, init.finishAndCreateFuture()));
var->setConstant(true);
+ disableAddressSanitizer(*this, var);
// Note that we emitted this protocol.
SwiftProtocols.push_back(protocol);
diff --git a/lib/IRGen/GenReflection.cpp b/lib/IRGen/GenReflection.cpp
index 57d9cb7..bb61f72 100644
--- a/lib/IRGen/GenReflection.cpp
+++ b/lib/IRGen/GenReflection.cpp
@@ -273,6 +273,8 @@
IGM.addUsedGlobal(var);
+ disableAddressSanitizer(IGM, var);
+
return var;
}
@@ -845,6 +847,7 @@
entry = createStringConstant(Name, /*willBeRelativelyAddressed*/ true,
getReflectionStringsSectionName());
+ disableAddressSanitizer(*this, entry.first);
return entry.second;
}
diff --git a/lib/IRGen/LoadableByAddress.cpp b/lib/IRGen/LoadableByAddress.cpp
index 1b3c561..dc5c3df 100644
--- a/lib/IRGen/LoadableByAddress.cpp
+++ b/lib/IRGen/LoadableByAddress.cpp
@@ -2520,7 +2520,7 @@
auto instr = cast<ConvertEscapeToNoEscapeInst>(convInstr);
newInstr = convBuilder.createConvertEscapeToNoEscape(
instr->getLoc(), instr->getOperand(), newType,
- instr->isLifetimeGuaranteed());
+ instr->isEscapedByUser(), instr->isLifetimeGuaranteed());
break;
}
case SILInstructionKind::MarkDependenceInst: {
diff --git a/lib/IRGen/Outlining.cpp b/lib/IRGen/Outlining.cpp
index cae28be..c4c60dc 100644
--- a/lib/IRGen/Outlining.cpp
+++ b/lib/IRGen/Outlining.cpp
@@ -35,10 +35,14 @@
return;
}
+ CanType formalType = type.getSwiftRValueType();
+ if (isa<FixedTypeInfo>(IGF.IGM.getTypeInfoForLowered(formalType))) {
+ return;
+ }
+
// If the type is a legal formal type, add it as a formal type.
// FIXME: does this force us to emit a more expensive metadata than we need
// to?
- CanType formalType = type.getSwiftRValueType();
if (formalType->isLegalFormalType()) {
return collectFormalTypeMetadata(formalType);
}
@@ -53,9 +57,7 @@
void OutliningMetadataCollector::collectFormalTypeMetadata(CanType type) {
// If the type has no archetypes, we can emit it from scratch in the callee.
- if (!type->hasArchetype()) {
- return;
- }
+ assert(type->hasArchetype());
auto key = LocalTypeDataKey(type, LocalTypeDataKind::forFormalTypeMetadata());
if (Values.count(key)) return;
diff --git a/lib/IRGen/StructLayout.cpp b/lib/IRGen/StructLayout.cpp
index d8faf8c..de18d75 100644
--- a/lib/IRGen/StructLayout.cpp
+++ b/lib/IRGen/StructLayout.cpp
@@ -114,18 +114,18 @@
return;
if (auto alignment = decl->getAttrs().getAttribute<AlignmentAttr>()) {
- assert(alignment->Value != 0
- && ((alignment->Value - 1) & alignment->Value) == 0
+ auto value = alignment->getValue();
+ assert(value != 0 && ((value - 1) & value) == 0
&& "alignment not a power of two!");
if (!IsFixedLayout)
Diags.diagnose(alignment->getLocation(),
diag::alignment_dynamic_type_layout_unsupported);
- else if (alignment->Value < MinimumAlign.getValue())
+ else if (value < MinimumAlign.getValue())
Diags.diagnose(alignment->getLocation(),
diag::alignment_less_than_natural, MinimumAlign.getValue());
else
- MinimumAlign = Alignment(alignment->Value);
+ MinimumAlign = Alignment(value);
}
}
diff --git a/lib/Migrator/APIDiffMigratorPass.cpp b/lib/Migrator/APIDiffMigratorPass.cpp
index 137af75..b829d1f 100644
--- a/lib/Migrator/APIDiffMigratorPass.cpp
+++ b/lib/Migrator/APIDiffMigratorPass.cpp
@@ -28,6 +28,7 @@
#include "clang/Rewrite/Core/RewriteBuffer.h"
#include "llvm/Support/FileSystem.h"
#include "swift/IDE/APIDigesterData.h"
+#include "swift/Basic/Defer.h"
using namespace swift;
using namespace swift::migrator;
@@ -302,13 +303,12 @@
return false;
}
+ std::set<std::string> InsertedFunctions;
SourceLoc FileEndLoc;
- llvm::SmallSet<StringRef, 4> InsertedFunctions;
-
APIDiffMigratorPass(EditorAdapter &Editor, SourceFile *SF,
- const MigratorOptions &Opts)
- : ASTMigratorPass(Editor, SF, Opts),
- FileEndLoc(SM.getRangeForBuffer(BufferID).getEnd()) {}
+ const MigratorOptions &Opts):
+ ASTMigratorPass(Editor, SF, Opts),
+ FileEndLoc(SM.getRangeForBuffer(BufferID).getEnd()) {}
void run() {
if (Opts.APIDigesterDataStorePaths.empty())
@@ -686,67 +686,77 @@
return false;
for (auto *Item: getRelatedDiffItems(RD)) {
if (auto *CI = dyn_cast<CommonDiffItem>(Item)) {
- switch(CI->DiffKind) {
- case NodeAnnotation::SimpleStringRepresentableUpdate: {
- Editor.insertBefore(ASE->getSrc()->getStartLoc(),
- (Twine(CI->RightComment) + "(rawValue: ").str());
+ if (CI->isStringRepresentableChange() &&
+ CI->NodeKind == SDKNodeKind::DeclVar) {
+ SmallString<256> Buffer;
+ auto Func = insertHelperFunction(CI->DiffKind, CI->RightComment,
+ Buffer, true);
+ Editor.insert(ASE->getSrc()->getStartLoc(), (Twine(Func) + "(").str());
Editor.insertAfterToken(ASE->getSrc()->getEndLoc(), ")");
return true;
}
- default:
- continue;
- }
}
}
return false;
}
StringRef insertHelperFunction(NodeAnnotation Anno, StringRef NewType,
- SmallString<256> &Buffer) {
+ SmallString<256> &Buffer, bool FromString) {
llvm::raw_svector_ostream OS(Buffer);
OS << "\n";
OS << "// Helper function inserted by Swift 4.2 migrator.\n";
OS << "fileprivate func ";
unsigned FuncNameStart = Buffer.size();
- OS << "converTo";
+ OS << (FromString ? "convertTo" : "convertFrom");
SmallVector<std::string, 8> Segs;
+ StringRef guard = "\tguard let input = input else { return nil }\n";
switch(Anno) {
case NodeAnnotation::OptionalArrayMemberUpdate:
Segs = {"Optional", "Array", "[String]?"};
Segs.push_back((Twine("[") + NewType +"]?").str());
- Segs.push_back("// Not implemented");
+ Segs.push_back((Twine(guard) + "\treturn input.map { key in " + NewType +"(key) }").str());
+ Segs.push_back((Twine(guard) + "\treturn input.map { key in key.rawValue }").str());
break;
case NodeAnnotation::OptionalDictionaryKeyUpdate:
Segs = {"Optional", "Dictionary", "[String: Any]?"};
Segs.push_back((Twine("[") + NewType +": Any]?").str());
- Segs.push_back((Twine("\tguard let input = input else { return nil }\n"
- "\treturn Dictionary(uniqueKeysWithValues: input.map"
- " { key, value in (") + NewType + "(rawValue: key), value)})").str());
+ Segs.push_back((Twine(guard) +
+ "\treturn Dictionary(uniqueKeysWithValues: input.map"
+ " { key, value in (" + NewType + "(rawValue: key), value)})").str());
+ Segs.push_back((Twine(guard) +
+ "\treturn Dictionary(uniqueKeysWithValues: input.map"
+ " {key, value in (key.rawValue, value)})").str());
break;
case NodeAnnotation::ArrayMemberUpdate:
Segs = {"", "Array", "[String]"};
Segs.push_back((Twine("[") + NewType +"]").str());
- Segs.push_back("// Not implemented");
+ Segs.push_back((Twine("\treturn input.map { key in ") + NewType +"(key) }").str());
+ Segs.push_back("\treturn input.map { key in key.rawValue }");
break;
case NodeAnnotation::DictionaryKeyUpdate:
Segs = {"", "Dictionary", "[String: Any]"};
Segs.push_back((Twine("[") + NewType +": Any]").str());
Segs.push_back((Twine("\treturn Dictionary(uniqueKeysWithValues: input.map"
" { key, value in (") + NewType + "(rawValue: key), value)})").str());
+ Segs.push_back("\treturn Dictionary(uniqueKeysWithValues: input.map"
+ " {key, value in (key.rawValue, value)})");
break;
case NodeAnnotation::SimpleStringRepresentableUpdate:
Segs = {"", "", "String"};
Segs.push_back(NewType);
- Segs.push_back("// Not implemented");
+ Segs.push_back((Twine("\treturn ") + NewType + "(rawValue: input)").str());
+ Segs.push_back("\treturn input.rawValue");
break;
case NodeAnnotation::SimpleOptionalStringRepresentableUpdate:
Segs = {"Optional", "", "String?"};
Segs.push_back((Twine(NewType) +"?").str());
- Segs.push_back("// Not implemented");
+ Segs.push_back((Twine(guard) + "\treturn " + NewType + "(rawValue: input)").str());
+ Segs.push_back((Twine(guard) + "\treturn input.rawValue").str());
break;
default:
llvm_unreachable("shouldn't handle this key.");
}
+ assert(Segs.size() == 6);
OS << Segs[0];
SmallVector<StringRef, 4> Parts;
NewType.split(Parts, '.');
@@ -755,15 +765,22 @@
OS << Segs[1];
auto FuncName = Buffer.str().substr(FuncNameStart);
if (!InsertedFunctions.count(FuncName)) {
- OS << "(_ input: " << Segs[2] << ") -> " << Segs[3] << " {\n";
- OS << Segs[4] << "\n}\n";
+ if (FromString) {
+ OS << "(_ input: " << Segs[2] << ") -> " << Segs[3] << " {\n";
+ OS << Segs[4] << "\n}\n";
+ } else {
+ OS << "(_ input: " << Segs[3] << ") -> " << Segs[2] << " {\n";
+ OS << Segs[5] << "\n}\n";
+ }
Editor.insert(FileEndLoc, OS.str());
InsertedFunctions.insert(FuncName);
}
return FuncName;
}
- void handleStringRepresentableArg(ValueDecl *FD, Expr *Arg) {
+ void handleStringRepresentableArg(ValueDecl *FD, Expr *Arg, Expr *Call) {
+ Editor.disableCache();
+ SWIFT_DEFER { Editor.enableCache(); };
NodeAnnotation Kind;
StringRef NewAttributeType;
uint8_t ArgIdx;
@@ -778,17 +795,23 @@
}
}
}
- if (NewAttributeType.empty() || !ArgIdx)
- return;
- ArgIdx --;
- auto AllArgs = getCallArgInfo(SM, Arg, LabelRangeEndAt::LabelNameOnly);
- if (AllArgs.size() <= ArgIdx)
+ if (NewAttributeType.empty())
return;
SmallString<256> Buffer;
- auto FuncName = insertHelperFunction(Kind, NewAttributeType, Buffer);
- auto Exp = AllArgs[ArgIdx].ArgExp;
- Editor.insert(Exp->getStartLoc(), (Twine(FuncName) + "(").str());
- Editor.insertAfterToken(Exp->getEndLoc(), ")");
+ auto FuncName = insertHelperFunction(Kind, NewAttributeType, Buffer,
+ /*FromString*/ArgIdx);
+ if (ArgIdx) {
+ ArgIdx --;
+ auto AllArgs = getCallArgInfo(SM, Arg, LabelRangeEndAt::LabelNameOnly);
+ if (AllArgs.size() <= ArgIdx)
+ return;
+ auto Exp = AllArgs[ArgIdx].ArgExp;
+ Editor.insert(Exp->getStartLoc(), (Twine(FuncName) + "(").str());
+ Editor.insertAfterToken(Exp->getEndLoc(), ")");
+ } else {
+ Editor.insert(Call->getStartLoc(), (Twine(FuncName) + "(").str());
+ Editor.insertAfterToken(Call->getEndLoc(), ")");
+ }
}
bool walkToExprPre(Expr *E) override {
@@ -805,7 +828,7 @@
handleFuncRename(FD, Fn, Args);
handleTypeHoist(FD, CE, Args);
handleSpecialCases(FD, CE, Args);
- handleStringRepresentableArg(FD, Args);
+ handleStringRepresentableArg(FD, Args, CE);
}
break;
}
@@ -815,7 +838,7 @@
handleFuncRename(FD, DSC->getFn(), Args);
handleFunctionCallToPropertyChange(FD, DSC->getFn(), Args);
handleSpecialCases(FD, CE, Args);
- handleStringRepresentableArg(FD, Args);
+ handleStringRepresentableArg(FD, Args, CE);
}
break;
}
@@ -824,7 +847,7 @@
if (auto FD = CCE->getFn()->getReferencedDecl().getDecl()) {
auto *CE = CCE->getFn();
handleFuncRename(FD, CE, Args);
- handleStringRepresentableArg(FD, Args);
+ handleStringRepresentableArg(FD, Args, CE);
}
break;
}
diff --git a/lib/Migrator/EditorAdapter.cpp b/lib/Migrator/EditorAdapter.cpp
index 6b99711..ee77d52 100644
--- a/lib/Migrator/EditorAdapter.cpp
+++ b/lib/Migrator/EditorAdapter.cpp
@@ -29,6 +29,8 @@
bool
EditorAdapter::cacheReplacement(CharSourceRange Range, StringRef Text) const {
+ if (!CacheEnabled)
+ return false;
unsigned SwiftBufferID, Offset;
std::tie(SwiftBufferID, Offset) = getLocInfo(Range.getStart());
Replacement R { Offset, Range.getByteLength(), Text };
diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp
index d1f626d..64fcfc2 100644
--- a/lib/ParseSIL/ParseSIL.cpp
+++ b/lib/ParseSIL/ParseSIL.cpp
@@ -2979,10 +2979,21 @@
SILType Ty;
Identifier ToToken;
SourceLoc ToLoc;
- bool guaranteed = true;
- if (Opcode == SILInstructionKind::ConvertEscapeToNoEscapeInst)
- if(parseSILOptional(guaranteed, *this, "not_guaranteed"))
+ bool not_guaranteed = false;
+ bool escaped = false;
+ if (Opcode == SILInstructionKind::ConvertEscapeToNoEscapeInst) {
+ StringRef attrName;
+ if (parseSILOptional(attrName, *this)) {
+ if (attrName.equals("escaped"))
+ escaped = true;
+ else if (attrName.equals("not_guaranteed"))
+ not_guaranteed = true;
+ else
+ return true;
+ }
+ if (parseSILOptional(escaped, *this, "escaped"))
return true;
+ }
if (parseTypedValueRef(Val, B) ||
parseSILIdentifier(ToToken, ToLoc,
diag::expected_tok_in_sil_instr, "to") ||
@@ -3016,7 +3027,8 @@
ResultVal = B.createConvertFunction(InstLoc, Val, Ty);
break;
case SILInstructionKind::ConvertEscapeToNoEscapeInst:
- ResultVal = B.createConvertEscapeToNoEscape(InstLoc, Val, Ty, guaranteed);
+ ResultVal = B.createConvertEscapeToNoEscape(InstLoc, Val, Ty, escaped,
+ !not_guaranteed);
break;
case SILInstructionKind::AddressToPointerInst:
ResultVal = B.createAddressToPointer(InstLoc, Val, Ty);
diff --git a/lib/SIL/Linker.cpp b/lib/SIL/Linker.cpp
index 9f64ff5..9dc4c7a 100644
--- a/lib/SIL/Linker.cpp
+++ b/lib/SIL/Linker.cpp
@@ -10,6 +10,45 @@
//
//===----------------------------------------------------------------------===//
+/// \file The SIL linker walks the call graph beginning at a starting function,
+/// deserializing functions, vtables and witness tables.
+///
+/// The behavior of the linker is controlled by a LinkMode value. The LinkMode
+/// has three possible values:
+///
+/// - LinkNone: The linker does not deserialize anything. This is only used for
+/// debugging and testing purposes, and never during normal operation.
+///
+/// - LinkNormal: The linker deserializes bodies for declarations that must be
+/// emitted into the client because they do not have definitions available
+/// externally. This includes:
+///
+/// - witness tables for imported conformances
+///
+/// - functions with shared linkage
+///
+/// - LinkAll: All reachable functions (including public functions) are
+/// deserialized, including public functions.
+///
+/// The primary entry point into the linker is the SILModule::linkFunction()
+/// function, which recursively walks the call graph starting from the given
+/// function.
+///
+/// In the mandatory pipeline (-Onone), the linker is invoked from the mandatory
+/// SIL linker pass, which pulls in just enough to allow us to emit code, using
+/// LinkNormal mode.
+///
+/// In the performance pipeline, after guaranteed optimizations but before
+/// performance optimizations, the 'performance SILLinker' pass links
+/// transitively all reachable functions, to uncover optimization opportunities
+/// that might be missed from deserializing late. The performance pipeline uses
+/// LinkAll mode.
+///
+/// *NOTE*: In LinkAll mode, we deserialize all vtables and witness tables,
+/// even those with public linkage. This is not strictly necessary, since the
+/// devirtualizer deserializes vtables and witness tables as needed. However,
+/// doing so early creates more opportunities for optimization.
+
#define DEBUG_TYPE "sil-linker"
#include "Linker.h"
#include "llvm/ADT/Statistic.h"
@@ -55,18 +94,29 @@
if (!F->isExternalDeclaration())
return;
- if (isLinkAll() || hasSharedVisibility(F->getLinkage()))
+ // In the performance pipeline, we deserialize all reachable functions.
+ if (isLinkAll())
+ return addFunctionToWorklist(F);
+
+ // Otherwise, make sure to deserialize shared functions; we need to
+ // emit them into the client binary since they're not available
+ // externally.
+ if (hasSharedVisibility(F->getLinkage()))
+ return addFunctionToWorklist(F);
+
+ // Functions with PublicNonABI linkage are deserialized as having
+ // HiddenExternal linkage when they are declarations, then they
+ // become SharedExternal after the body has been deserialized.
+ // So try deserializing HiddenExternal functions too.
+ if (F->getLinkage() == SILLinkage::HiddenExternal)
return addFunctionToWorklist(F);
}
/// Process F, recursively deserializing any thing F may reference.
bool SILLinkerVisitor::processFunction(SILFunction *F) {
- if (Mode == LinkingMode::LinkNone)
- return false;
-
// If F is a declaration, first deserialize it.
if (F->isExternalDeclaration()) {
- addFunctionToWorklist(F);
+ maybeAddFunctionToWorklist(F);
} else {
Worklist.push_back(F);
}
diff --git a/lib/SIL/SILInstructions.cpp b/lib/SIL/SILInstructions.cpp
index dec0573..60f1565 100644
--- a/lib/SIL/SILInstructions.cpp
+++ b/lib/SIL/SILInstructions.cpp
@@ -1998,7 +1998,8 @@
ConvertEscapeToNoEscapeInst *ConvertEscapeToNoEscapeInst::create(
SILDebugLocation DebugLoc, SILValue Operand, SILType Ty, SILFunction &F,
- SILOpenedArchetypesState &OpenedArchetypes, bool isLifetimeGuaranteed) {
+ SILOpenedArchetypesState &OpenedArchetypes, bool isEscapedByUser,
+ bool isLifetimeGuaranteed) {
SILModule &Mod = F.getModule();
SmallVector<SILValue, 8> TypeDependentOperands;
collectTypeDependentOperands(TypeDependentOperands, OpenedArchetypes, F,
@@ -2006,8 +2007,9 @@
unsigned size =
totalSizeToAlloc<swift::Operand>(1 + TypeDependentOperands.size());
void *Buffer = Mod.allocateInst(size, alignof(ConvertEscapeToNoEscapeInst));
- auto *CFI = ::new (Buffer) ConvertEscapeToNoEscapeInst(
- DebugLoc, Operand, TypeDependentOperands, Ty, isLifetimeGuaranteed);
+ auto *CFI = ::new (Buffer)
+ ConvertEscapeToNoEscapeInst(DebugLoc, Operand, TypeDependentOperands, Ty,
+ isEscapedByUser, isLifetimeGuaranteed);
// If we do not have lowered SIL, make sure that are not performing
// ABI-incompatible conversions.
//
diff --git a/lib/SIL/SILOwnershipVerifier.cpp b/lib/SIL/SILOwnershipVerifier.cpp
index bd49d6c..c0fd911 100644
--- a/lib/SIL/SILOwnershipVerifier.cpp
+++ b/lib/SIL/SILOwnershipVerifier.cpp
@@ -1431,6 +1431,9 @@
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(GepRaw)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Gep)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(GetTailAddr)
+BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(PerformInstantaneousReadAccess)
+BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(BeginUnpairedModifyAccess)
+BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(EndUnpairedAccess)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(CondFail)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(FixLifetime)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(IsUnique)
diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp
index baaecac..db3b52f 100644
--- a/lib/SIL/SILPrinter.cpp
+++ b/lib/SIL/SILPrinter.cpp
@@ -1436,6 +1436,7 @@
}
void visitConvertEscapeToNoEscapeInst(ConvertEscapeToNoEscapeInst *CI) {
*this << (CI->isLifetimeGuaranteed() ? "" : "[not_guaranteed] ")
+ << (CI->isEscapedByUser() ? "[escaped] " : "")
<< getIDAndType(CI->getOperand()) << " to " << CI->getType();
}
void visitThinFunctionToPointerInst(ThinFunctionToPointerInst *CI) {
@@ -2215,6 +2216,14 @@
/// Pretty-print the SILBasicBlock to the designated stream.
void SILBasicBlock::print(raw_ostream &OS) const {
SILPrintContext Ctx(OS);
+
+ // Print the debug scope (and compute if we didn't do it already).
+ auto &SM = this->getParent()->getModule().getASTContext().SourceMgr;
+ for (auto &I : *this) {
+ SILPrinter P(Ctx);
+ P.printDebugScope(I.getDebugScope(), SM);
+ }
+
SILPrinter(Ctx).print(this);
}
@@ -2681,7 +2690,7 @@
if (!WholeModuleMode && !(D->getDeclContext() == AssociatedDeclContext))
continue;
if ((isa<ValueDecl>(D) || isa<OperatorDecl>(D) ||
- isa<ExtensionDecl>(D)) &&
+ isa<ExtensionDecl>(D) || isa<ImportDecl>(D)) &&
!D->isImplicit()) {
if (isa<AccessorDecl>(D))
continue;
diff --git a/lib/SIL/SILProfiler.cpp b/lib/SIL/SILProfiler.cpp
index 6f0a738..6a6f755 100644
--- a/lib/SIL/SILProfiler.cpp
+++ b/lib/SIL/SILProfiler.cpp
@@ -26,7 +26,8 @@
using namespace swift;
-static bool isClosureWithBody(AbstractClosureExpr *ACE) {
+/// Check if a closure has a body.
+static bool doesClosureHaveBody(AbstractClosureExpr *ACE) {
if (auto *CE = dyn_cast<ClosureExpr>(ACE))
return CE->getBody();
if (auto *autoCE = dyn_cast<AutoClosureExpr>(ACE))
@@ -34,79 +35,43 @@
return false;
}
+/// Check whether a root AST node is unmapped, i.e not profiled.
static bool isUnmapped(ASTNode N) {
if (auto *E = N.dyn_cast<Expr *>()) {
auto *CE = dyn_cast<AbstractClosureExpr>(E);
- return !CE || (!isa<AutoClosureExpr>(CE) && CE->isImplicit()) ||
- !isClosureWithBody(CE);
+
+ // Only map closure expressions with bodies.
+ if (!CE || !doesClosureHaveBody(CE))
+ return true;
+
+ // Don't map implicit closures, unless they're autoclosures.
+ if (!isa<AutoClosureExpr>(CE) && CE->isImplicit())
+ return true;
+
+ return false;
}
auto *D = N.get<Decl *>();
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
+ // Don't map functions without bodies.
if (!AFD->getBody())
return true;
+ // Map all *structors, even if they are implicit.
+ if (isa<ConstructorDecl>(D) || isa<DestructorDecl>(D))
+ return false;
+
+ // Map implicit getters.
if (auto *accessor = dyn_cast<AccessorDecl>(AFD))
if (accessor->isImplicit() && accessor->isGetter())
return false;
}
- if (isa<ConstructorDecl>(D) || isa<DestructorDecl>(D))
- return false;
+ // Skip any remaining implicit, or otherwise unsupported decls.
+ if (D->isImplicit() || isa<EnumCaseDecl>(D))
+ return true;
- return D->isImplicit() || isa<EnumCaseDecl>(D);
-}
-
-/// A simple heuristic to determine whether \p E contains a definition of a
-/// closure. This is not complete, but it suffices to cheaply filter away some
-/// redundant coverage mappings.
-static bool containsClosure(Expr *E) {
- Expr *candidateExpr = E;
- if (auto *ce = dyn_cast<CallExpr>(E))
- candidateExpr = ce->getDirectCallee();
- return dyn_cast_or_null<AbstractClosureExpr>(candidateExpr);
-}
-
-/// Walk the non-static initializers in \p PBD.
-static void walkPatternForProfiling(PatternBindingDecl *PBD, ASTWalker &Walker,
- bool AllowClosures = true) {
- if (PBD && !PBD->isStatic())
- for (auto E : PBD->getPatternList())
- if (E.getInit())
- if (AllowClosures || !containsClosure(E.getInit()))
- E.getInit()->walk(Walker);
-}
-
-/// Walk the AST of \c Root and related nodes that are relevant for profiling.
-static void walkFunctionForProfiling(AbstractFunctionDecl *Root,
- ASTWalker &Walker) {
- Root->walk(Walker);
-
- // We treat non-closure member initializers as part of the constructor for
- // profiling.
- if (auto *CD = dyn_cast<ConstructorDecl>(Root)) {
- auto *NominalType =
- CD->getDeclContext()->getAsNominalTypeOrNominalTypeExtensionContext();
- for (auto *Member : NominalType->getMembers()) {
- // Find pattern binding declarations that have initializers.
- if (auto *PBD = dyn_cast<PatternBindingDecl>(Member))
- walkPatternForProfiling(PBD, Walker, /*AllowClosures=*/false);
- }
- }
-}
-
-/// Walk \p D for profiling.
-static void walkForProfiling(ASTNode N, ASTWalker &Walker) {
- if (auto *D = N.dyn_cast<Decl *>()) {
- if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D))
- walkFunctionForProfiling(AFD, Walker);
- else if (auto *PBD = dyn_cast<PatternBindingDecl>(D))
- walkPatternForProfiling(PBD, Walker);
- else if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(D))
- TLCD->walk(Walker);
- } else if (auto *E = N.dyn_cast<Expr *>()) {
- cast<AbstractClosureExpr>(E)->walk(Walker);
- }
+ return false;
}
namespace swift {
@@ -123,27 +88,43 @@
return !SF || SF->ASTStage >= SourceFile::TypeChecked;
}
+/// Check whether a mapped AST node requires a new profiler.
+static bool canCreateProfilerForAST(ASTNode N) {
+ assert(hasASTBeenTypeChecked(N) && "Cannot use this AST for profiling");
+
+ if (auto *D = N.dyn_cast<Decl *>()) {
+ // Any mapped function may be profiled. There's an exception for
+ // constructors because all of the constructors for a type share a single
+ // profiler.
+ if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D))
+ return !isa<ConstructorDecl>(AFD);
+
+ if (isa<TopLevelCodeDecl>(D))
+ return true;
+
+ if (isa<NominalTypeDecl>(D))
+ return true;
+ } else {
+ auto *E = N.get<Expr *>();
+ if (isa<AbstractClosureExpr>(E))
+ return true;
+ }
+ return false;
+}
+
SILProfiler *SILProfiler::create(SILModule &M, ForDefinition_t forDefinition,
ASTNode N) {
// Avoid generating profiling state for declarations.
if (!forDefinition)
return nullptr;
- assert(hasASTBeenTypeChecked(N) && "Cannot use this AST for code coverage");
-
- if (auto *D = N.dyn_cast<Decl *>()) {
- assert(isa<AbstractFunctionDecl>(D) ||
- isa<TopLevelCodeDecl>(D) && "Cannot create profiler");
- } else if (auto *E = N.dyn_cast<Expr *>()) {
- assert(isa<AbstractClosureExpr>(E) && "Cannot create profiler");
- } else {
- llvm_unreachable("Invalid AST node for profiling");
- }
-
const auto &Opts = M.getOptions();
if (!doesASTRequireProfiling(M, N) && Opts.UseProfile.empty())
return nullptr;
+ if (!canCreateProfilerForAST(N))
+ llvm_unreachable("Invalid AST node for profiling");
+
auto *Buf = M.allocate<SILProfiler>(1);
auto *SP = ::new (Buf) SILProfiler(M, N, Opts.EmitProfileCoverageMapping);
SP->assignRegionCounters();
@@ -152,6 +133,15 @@
namespace {
+/// Walk the non-static initializers in \p PBD.
+static void walkPatternForProfiling(PatternBindingDecl *PBD,
+ ASTWalker &Walker) {
+ if (PBD && !PBD->isStatic())
+ for (auto E : PBD->getPatternList())
+ if (E.getInit())
+ E.getInit()->walk(Walker);
+}
+
/// Special logic for handling closure visitation.
///
/// To prevent a closure from being mapped twice, avoid recursively walking
@@ -170,25 +160,35 @@
/// An ASTWalker that maps ASTNodes to profiling counters.
struct MapRegionCounters : public ASTWalker {
/// The next counter value to assign.
- unsigned NextCounter;
+ unsigned NextCounter = 0;
/// The map of statements to counters.
llvm::DenseMap<ASTNode, unsigned> &CounterMap;
+ /// A flag indicating whether we're walking a nominal type.
+ bool WithinNominalType = false;
+
MapRegionCounters(llvm::DenseMap<ASTNode, unsigned> &CounterMap)
- : NextCounter(0), CounterMap(CounterMap) {}
+ : CounterMap(CounterMap) {}
bool walkToDeclPre(Decl *D) override {
if (isUnmapped(D))
return false;
+
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
- bool FirstDecl = Parent.isNull();
- if (FirstDecl)
+ // Don't map a nested function unless it's a constructor.
+ bool continueWalk = Parent.isNull() || isa<ConstructorDecl>(AFD);
+ if (continueWalk)
CounterMap[AFD->getBody()] = NextCounter++;
- return FirstDecl;
- }
- if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(D))
+ return continueWalk;
+ } else if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
CounterMap[TLCD->getBody()] = NextCounter++;
+ } else if (isa<NominalTypeDecl>(D)) {
+ bool continueWalk = Parent.isNull();
+ if (continueWalk)
+ WithinNominalType = true;
+ return continueWalk;
+ }
return true;
}
@@ -560,7 +560,11 @@
/// \brief A stack of active repeat-while loops.
std::vector<RepeatWhileStmt *> RepeatWhileStack;
- CounterExpr *ExitCounter;
+ CounterExpr *ExitCounter = nullptr;
+
+ Stmt *ImplicitTopLevelBody = nullptr;
+
+ NominalTypeDecl *ParentNominalType = nullptr;
/// \brief Return true if \c Node has an associated counter.
bool hasCounter(ASTNode Node) { return CounterMap.count(Node); }
@@ -762,19 +766,40 @@
bool walkToDeclPre(Decl *D) override {
if (isUnmapped(D))
return false;
+
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(D)) {
- bool FirstDecl = Parent.isNull();
- if (FirstDecl)
- assignCounter(AFD->getBody());
- return FirstDecl;
- }
- else if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(D))
+ // Don't map a nested function unless it's a constructor.
+ bool continueWalk = Parent.isNull() || isa<ConstructorDecl>(AFD);
+ if (continueWalk) {
+ CounterExpr &funcCounter = assignCounter(AFD->getBody());
+
+ if (isa<ConstructorDecl>(AFD))
+ addToCounter(ParentNominalType, funcCounter);
+ }
+ return continueWalk;
+ } else if (auto *TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
assignCounter(TLCD->getBody());
+ ImplicitTopLevelBody = TLCD->getBody();
+ } else if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
+ bool continueWalk = Parent.isNull();
+ if (continueWalk) {
+ ParentNominalType = NTD;
+ assignCounter(NTD, CounterExpr::Zero());
+ pushRegion(NTD);
+ }
+ return continueWalk;
+ }
+ return true;
+ }
+
+ bool walkToDeclPost(Decl *D) override {
+ if (isa<TopLevelCodeDecl>(D))
+ ImplicitTopLevelBody = nullptr;
return true;
}
std::pair<bool, Stmt *> walkToStmtPre(Stmt *S) override {
- if (S->isImplicit())
+ if (S->isImplicit() && S != ImplicitTopLevelBody)
return {true, S};
if (!RegionStack.empty())
@@ -835,7 +860,7 @@
}
Stmt *walkToStmtPost(Stmt *S) override {
- if (S->isImplicit())
+ if (S->isImplicit() && S != ImplicitTopLevelBody)
return S;
if (isa<BraceStmt>(S)) {
@@ -907,11 +932,8 @@
return Result;
} else if (auto *IE = dyn_cast<IfExpr>(E)) {
CounterExpr &ThenCounter = assignCounter(IE->getThenExpr());
- if (RegionStack.empty())
- assignCounter(IE->getElseExpr());
- else
- assignCounter(IE->getElseExpr(),
- CounterExpr::Sub(getCurrentCounter(), ThenCounter));
+ assignCounter(IE->getElseExpr(),
+ CounterExpr::Sub(getCurrentCounter(), ThenCounter));
}
if (hasCounter(E))
@@ -951,6 +973,16 @@
return {};
}
+static void walkTopLevelNodeForProfiling(ASTNode Root, ASTWalker &Walker) {
+ Root.walk(Walker);
+
+ // Visit extensions when walking through a nominal type.
+ auto *NTD = dyn_cast_or_null<NominalTypeDecl>(Root.dyn_cast<Decl *>());
+ if (NTD)
+ for (ExtensionDecl *ED : NTD->getExtensions())
+ ED->walk(Walker);
+}
+
void SILProfiler::assignRegionCounters() {
const auto &SM = M.getASTContext().SourceMgr;
@@ -970,23 +1002,23 @@
TLCD->getStartLoc().printLineAndColumn(OS, SM);
CurrentFuncLinkage = FormalLinkage::HiddenUnique;
} else {
- llvm_unreachable("Unsupported decl");
+ auto *NTD = cast<NominalTypeDecl>(D);
+ llvm::raw_string_ostream OS{CurrentFuncName};
+ OS << "__ntd_" << NTD->getNameStr() << "_";
+ NTD->getStartLoc().printLineAndColumn(OS, SM);
+ CurrentFuncLinkage = FormalLinkage::HiddenUnique;
}
} else {
- auto *E = Root.get<Expr *>();
- if (auto *CE = dyn_cast<AbstractClosureExpr>(E)) {
- CurrentFuncName = SILDeclRef(CE).mangle();
- CurrentFuncLinkage = FormalLinkage::HiddenUnique;
- } else {
- llvm_unreachable("Unsupported expr");
- }
+ auto *CE = cast<AbstractClosureExpr>(Root.get<Expr *>());
+ CurrentFuncName = SILDeclRef(CE).mangle();
+ CurrentFuncLinkage = FormalLinkage::HiddenUnique;
}
PGOFuncName = llvm::getPGOFuncName(
CurrentFuncName, getEquivalentPGOLinkage(CurrentFuncLinkage),
CurrentFileName);
- walkForProfiling(Root, Mapper);
+ walkTopLevelNodeForProfiling(Root, Mapper);
NumRegionCounters = Mapper.NextCounter;
// TODO: Mapper needs to calculate a function hash as it goes.
@@ -994,7 +1026,7 @@
if (EmitCoverageMapping) {
CoverageMapping Coverage(SM);
- walkForProfiling(Root, Coverage);
+ walkTopLevelNodeForProfiling(Root, Coverage);
CovMap =
Coverage.emitSourceRegions(M, CurrentFuncName, PGOFuncName, PGOFuncHash,
RegionCounterMap, CurrentFileName);
@@ -1012,7 +1044,7 @@
}
PGOMapping pgoMapper(RegionLoadedCounterMap, LoadedCounts,
RegionCondToParentMap);
- walkForProfiling(Root, pgoMapper);
+ walkTopLevelNodeForProfiling(Root, pgoMapper);
}
}
diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp
index 13ab1e0..0ac3d43 100644
--- a/lib/SIL/SILVerifier.cpp
+++ b/lib/SIL/SILVerifier.cpp
@@ -62,6 +62,9 @@
"verify-di-holes",
llvm::cl::init(true));
+static llvm::cl::opt<bool> SkipConvertEscapeToNoescapeAttributes(
+ "verify-skip-convert-escape-to-noescape-attributes", llvm::cl::init(false));
+
// The verifier is basically all assertions, so don't compile it with NDEBUG to
// prevent release builds from triggering spurious unused variable warnings.
@@ -1418,14 +1421,17 @@
SILFunction *RefF = FRI->getReferencedFunction();
- // A direct reference to a shared_external declaration is an error; we
- // should have deserialized a body.
- if (RefF->isExternalDeclaration()) {
- require(SingleFunction ||
- !hasSharedVisibility(RefF->getLinkage()) ||
- RefF->hasForeignBody(),
- "external declarations of SILFunctions with shared visibility is "
- "not allowed");
+ // In canonical SIL, direct reference to a shared_external declaration
+ // is an error; we should have deserialized a body. In raw SIL, we may
+ // not have deserialized the body yet.
+ if (F.getModule().getStage() >= SILStage::Canonical) {
+ if (RefF->isExternalDeclaration()) {
+ require(SingleFunction ||
+ !hasSharedVisibility(RefF->getLinkage()) ||
+ RefF->hasForeignBody(),
+ "external declarations of SILFunctions with shared visibility is "
+ "not allowed");
+ }
}
// A direct reference to a non-public or shared but not fragile function
@@ -3520,6 +3526,18 @@
requireABICompatibleFunctionTypes(
opTI, resTI->getWithExtInfo(resTI->getExtInfo().withNoEscape(false)),
"convert_escape_to_noescape cannot change function ABI");
+
+ // After mandatory passes convert_escape_to_noescape should not have the
+ // '[not_guaranteed]' or '[escaped]' attributes.
+ if (!SkipConvertEscapeToNoescapeAttributes &&
+ F.getModule().getStage() != SILStage::Raw) {
+ require(!ICI->isEscapedByUser(),
+ "convert_escape_to_noescape [escaped] not "
+ "allowed after mandatory passes");
+ require(ICI->isLifetimeGuaranteed(),
+ "convert_escape_to_noescape [not_guaranteed] not "
+ "allowed after mandatory passes");
+ }
}
void checkThinFunctionToPointerInst(ThinFunctionToPointerInst *CI) {
diff --git a/lib/SIL/ValueOwnershipKindClassifier.cpp b/lib/SIL/ValueOwnershipKindClassifier.cpp
index d201e3f..3813009 100644
--- a/lib/SIL/ValueOwnershipKindClassifier.cpp
+++ b/lib/SIL/ValueOwnershipKindClassifier.cpp
@@ -475,6 +475,9 @@
CONSTANT_OWNERSHIP_BUILTIN(Trivial, GepRaw)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Gep)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, GetTailAddr)
+CONSTANT_OWNERSHIP_BUILTIN(Trivial, PerformInstantaneousReadAccess)
+CONSTANT_OWNERSHIP_BUILTIN(Trivial, BeginUnpairedModifyAccess)
+CONSTANT_OWNERSHIP_BUILTIN(Trivial, EndUnpairedAccess)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, OnFastPath)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, IsUnique)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, IsUniqueOrPinned)
diff --git a/lib/SILGen/Cleanup.h b/lib/SILGen/Cleanup.h
index 6d66c18..28dc213 100644
--- a/lib/SILGen/Cleanup.h
+++ b/lib/SILGen/Cleanup.h
@@ -129,7 +129,6 @@
friend class CleanupStateRestorationScope;
friend class SharedBorrowFormalEvaluation;
friend class FormalEvaluationScope;
- friend class PostponedCleanup;
public:
CleanupManager(SILGenFunction &SGF)
diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp
index 7c462eb..ff77f9c 100644
--- a/lib/SILGen/SILGen.cpp
+++ b/lib/SILGen/SILGen.cpp
@@ -488,6 +488,20 @@
constant.isCurried;
}
+SILProfiler *
+SILGenModule::getOrCreateProfilerForConstructors(NominalTypeDecl *decl) {
+ assert(decl && "No nominal type for constructor lookup");
+
+ const auto &Opts = M.getOptions();
+ if (!Opts.GenerateProfile && Opts.UseProfile.empty())
+ return nullptr;
+
+ SILProfiler *&profiler = constructorProfilers[decl];
+ if (!profiler)
+ profiler = SILProfiler::create(M, ForDefinition, decl);
+ return profiler;
+}
+
SILFunction *SILGenModule::getFunction(SILDeclRef constant,
ForDefinition_t forDefinition) {
// If we already emitted the function, return it (potentially preparing it
@@ -737,42 +751,45 @@
return;
SILDeclRef constant(decl);
+ DeclContext *declCtx = decl->getDeclContext();
bool ForCoverageMapping = doesASTRequireProfiling(M, decl);
- if (decl->getDeclContext()->getAsClassOrClassExtensionContext()) {
+ if (auto *clsDecl = declCtx->getAsClassOrClassExtensionContext()) {
// Class constructors have separate entry points for allocation and
// initialization.
emitOrDelayFunction(
- *this, constant,
- [this, constant, decl](SILFunction *f) {
+ *this, constant, [this, constant, decl](SILFunction *f) {
preEmitFunction(constant, decl, f, decl);
PrettyStackTraceSILFunction X("silgen emitConstructor", f);
- f->createProfiler(decl, ForDefinition);
SILGenFunction(*this, *f).emitClassConstructorAllocator(decl);
postEmitFunction(constant, f);
- },
- /*forceEmission=*/ForCoverageMapping);
+ });
// If this constructor was imported, we don't need the initializing
// constructor to be emitted.
if (!decl->hasClangNode()) {
SILDeclRef initConstant(decl, SILDeclRef::Kind::Initializer);
- emitOrDelayFunction(*this, initConstant,
- [this,initConstant,decl](SILFunction *initF){
- preEmitFunction(initConstant, decl, initF, decl);
- PrettyStackTraceSILFunction X("silgen constructor initializer", initF);
- SILGenFunction(*this, *initF).emitClassConstructorInitializer(decl);
- postEmitFunction(initConstant, initF);
- });
+ emitOrDelayFunction(
+ *this, initConstant,
+ [this, initConstant, decl, clsDecl](SILFunction *initF) {
+ preEmitFunction(initConstant, decl, initF, decl);
+ PrettyStackTraceSILFunction X("silgen constructor initializer",
+ initF);
+ initF->setProfiler(getOrCreateProfilerForConstructors(clsDecl));
+ SILGenFunction(*this, *initF).emitClassConstructorInitializer(decl);
+ postEmitFunction(initConstant, initF);
+ },
+ /*forceEmission=*/ForCoverageMapping);
}
} else {
// Struct and enum constructors do everything in a single function.
+ auto *nomDecl = declCtx->getAsNominalTypeOrNominalTypeExtensionContext();
emitOrDelayFunction(
- *this, constant, [this, constant, decl](SILFunction *f) {
+ *this, constant, [this, constant, decl, nomDecl](SILFunction *f) {
preEmitFunction(constant, decl, f, decl);
PrettyStackTraceSILFunction X("silgen emitConstructor", f);
- f->createProfiler(decl, ForDefinition);
+ f->setProfiler(getOrCreateProfilerForConstructors(nomDecl));
SILGenFunction(*this, *f).emitValueConstructor(decl);
postEmitFunction(constant, f);
});
@@ -975,9 +992,16 @@
auto *init = pbdEntry.getInit();
SILDeclRef constant(var, SILDeclRef::Kind::StoredPropertyInitializer);
- emitOrDelayFunction(*this, constant, [this,constant,init](SILFunction *f) {
+ emitOrDelayFunction(*this, constant, [this,constant,init,var](SILFunction *f) {
preEmitFunction(constant, init, f, init);
PrettyStackTraceSILFunction X("silgen emitStoredPropertyInitialization", f);
+
+ // Inherit a profiler instance from the constructor.
+ auto *nominalDecl =
+ var->getDeclContext()->getAsNominalTypeOrNominalTypeExtensionContext();
+ if (nominalDecl)
+ f->setProfiler(getOrCreateProfilerForConstructors(nominalDecl));
+
SILGenFunction(*this, *f).emitGeneratorFunction(constant, init);
postEmitFunction(constant, f);
});
diff --git a/lib/SILGen/SILGen.h b/lib/SILGen/SILGen.h
index c6c1c3a..66ae0b9 100644
--- a/lib/SILGen/SILGen.h
+++ b/lib/SILGen/SILGen.h
@@ -96,6 +96,10 @@
/// The most recent conformance...
NormalProtocolConformance *lastEmittedConformance = nullptr;
+ /// Profiler instances for constructors, grouped by associated nominal type.
+ /// Each profiler is shared by all member initializers for a nominal type.
+ llvm::DenseMap<NominalTypeDecl *, SILProfiler *> constructorProfilers;
+
SILFunction *emitTopLevelFunction(SILLocation Loc);
size_t anonymousSymbolCounter = 0;
@@ -435,6 +439,9 @@
/// Emit a property descriptor for the given storage decl if it needs one.
void tryEmitPropertyDescriptor(AbstractStorageDecl *decl);
+
+ /// Get or create the profiler instance for a nominal type's constructors.
+ SILProfiler *getOrCreateProfilerForConstructors(NominalTypeDecl *decl);
private:
/// Emit the deallocator for a class that uses the objc allocator.
diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp
index e143dbe..a370fd7 100644
--- a/lib/SILGen/SILGenApply.cpp
+++ b/lib/SILGen/SILGenApply.cpp
@@ -259,6 +259,8 @@
const Kind kind;
+ bool isMaterializeForSet = false;
+
// Move, don't copy.
Callee(const Callee &) = delete;
Callee &operator=(const Callee &) = delete;
@@ -3674,7 +3676,7 @@
SGF, calleeTypeInfo, uncurriedSites.back().Loc, uncurriedContext);
ArgumentScope argScope(SGF, uncurriedSites.back().Loc);
- PostponedCleanup postpone(SGF);
+
// Emit the arguments.
SmallVector<ManagedValue, 4> uncurriedArgs;
Optional<SILLocation> uncurriedLoc;
@@ -3695,11 +3697,20 @@
auto mv = callee.getFnValue(SGF, isCurried, borrowedSelf);
+ // Materialize for set could temporarily escape its arguments.
+ if (callee.isMaterializeForSet) {
+ auto indices = ArrayRef<ManagedValue>(uncurriedArgs).slice(2);
+ for (auto index : indices) {
+ auto *toNoEscape = dyn_cast<ConvertEscapeToNoEscapeInst>(index.getValue());
+ if (!toNoEscape) continue;
+ toNoEscape->setEscapedByUser();
+ }
+ }
// Emit the uncurried call.
firstLevelResult.value = SGF.emitApply(
std::move(resultPlan), std::move(argScope), uncurriedLoc.getValue(), mv,
callee.getSubstitutions(), uncurriedArgs, calleeTypeInfo, options,
- uncurriedContext, postpone);
+ uncurriedContext);
firstLevelResult.foreignSelf = calleeTypeInfo.foreignSelf;
return firstLevelResult;
}
@@ -4024,7 +4035,6 @@
ResultPlanPtr resultPtr =
ResultPlanBuilder::computeResultPlan(SGF, calleeTypeInfo, loc, context);
ArgumentScope argScope(SGF, loc);
- PostponedCleanup postpone(SGF);
std::move(extraSites[i])
.emit(SGF, origParamType, paramLowering, siteArgs, delayedArgs,
@@ -4035,7 +4045,7 @@
result = SGF.emitApply(std::move(resultPtr), std::move(argScope), loc,
functionMV, {}, siteArgs, calleeTypeInfo,
- ApplyOptions::None, context, postpone);
+ ApplyOptions::None, context);
}
return std::move(result);
@@ -4088,8 +4098,7 @@
ManagedValue fn, SubstitutionList subs,
ArrayRef<ManagedValue> args,
const CalleeTypeInfo &calleeTypeInfo,
- ApplyOptions options, SGFContext evalContext,
- PostponedCleanup &postponedCleanup) {
+ ApplyOptions options, SGFContext evalContext) {
auto substFnType = calleeTypeInfo.substFnType;
auto substResultType = calleeTypeInfo.substResultType;
@@ -4150,7 +4159,6 @@
// Emit the raw application.
loc.decodeDebugLoc(SGM.M.getASTContext().SourceMgr);
- postponedCleanup.end();
SILValue rawDirectResult = emitRawApply(
*this, loc, fn, subs, args, substFnType, options, indirectResultAddrs);
@@ -4271,9 +4279,8 @@
ResultPlanPtr resultPlan = ResultPlanBuilder::computeResultPlan(
*this, calleeTypeInfo, loc, evalContext);
ArgumentScope argScope(*this, loc);
- PostponedCleanup postpone(*this);
return emitApply(std::move(resultPlan), std::move(argScope), loc, fn, {},
- args, calleeTypeInfo, options, evalContext, postpone);
+ args, calleeTypeInfo, options, evalContext);
}
/// Emit either an 'apply' or a 'try_apply', with the error branch of
@@ -4463,10 +4470,8 @@
ResultPlanPtr resultPlan =
ResultPlanBuilder::computeResultPlan(*this, calleeTypeInfo, loc, ctx);
ArgumentScope argScope(*this, loc);
- PostponedCleanup postpone(*this);
return emitApply(std::move(resultPlan), std::move(argScope), loc, mv, subs,
- finalArgs, calleeTypeInfo, ApplyOptions::None, ctx,
- postpone);
+ finalArgs, calleeTypeInfo, ApplyOptions::None, ctx);
}
static StringRef
@@ -5121,6 +5126,8 @@
materializeForSet,
substitutions, selfValue,
isSuper, isDirectUse);
+ callee.isMaterializeForSet = true;
+
bool hasSelf = (bool)selfValue;
auto accessType = callee.getSubstFormalType();
diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp
index 8466b22..ff595a4 100644
--- a/lib/SILGen/SILGenBridging.cpp
+++ b/lib/SILGen/SILGenBridging.cpp
@@ -241,12 +241,11 @@
ResultPlanPtr resultPlan =
ResultPlanBuilder::computeResultPlan(SGF, calleeTypeInfo, loc, context);
ArgumentScope argScope(SGF, loc);
- PostponedCleanup postpone(SGF);
RValue result =
SGF.emitApply(std::move(resultPlan), std::move(argScope), loc,
ManagedValue::forUnmanaged(witnessRef), subs,
{objcValue, ManagedValue::forUnmanaged(metatypeValue)},
- calleeTypeInfo, ApplyOptions::None, context, postpone);
+ calleeTypeInfo, ApplyOptions::None, context);
return std::move(result).getAsSingleValue(SGF, loc);
}
@@ -940,8 +939,8 @@
// Handle the escaping to noescape conversion.
assert(loweredFuncTy->isNoEscape());
- return B.createConvertEscapeToNoEscape(loc, thunkedFn,
- SILType::getPrimitiveObjectType(loweredFuncTy));
+ return B.createConvertEscapeToNoEscape(
+ loc, thunkedFn, SILType::getPrimitiveObjectType(loweredFuncTy), false);
}
static ManagedValue emitCBridgedToNativeValue(SILGenFunction &SGF,
@@ -1760,11 +1759,10 @@
ResultPlanPtr resultPlan = ResultPlanBuilder::computeResultPlan(
*this, calleeTypeInfo, fd, context);
ArgumentScope argScope(*this, fd);
- PostponedCleanup postpone(*this);
ManagedValue resultMV =
emitApply(std::move(resultPlan), std::move(argScope), fd,
ManagedValue::forUnmanaged(fn), subs, args, calleeTypeInfo,
- ApplyOptions::None, context, postpone)
+ ApplyOptions::None, context)
.getAsSingleValue(*this, fd);
if (indirectResult) {
diff --git a/lib/SILGen/SILGenBuilder.cpp b/lib/SILGen/SILGenBuilder.cpp
index c4f4353..87a517b 100644
--- a/lib/SILGen/SILGenBuilder.cpp
+++ b/lib/SILGen/SILGenBuilder.cpp
@@ -209,7 +209,7 @@
ManagedValue SILGenBuilder::createConvertEscapeToNoEscape(
SILLocation loc, ManagedValue fn, SILType resultTy,
- bool postponeToNoEscapeCleanup) {
+ bool isEscapedByUser) {
auto fnType = fn.getType().castTo<SILFunctionType>();
auto resultFnType = resultTy.castTo<SILFunctionType>();
@@ -221,14 +221,9 @@
SILFunctionTypeRepresentation::Thick &&
!fnType->isNoEscape() && resultFnType->isNoEscape() &&
"Expect a escaping to noescape conversion");
-
- SILValue fnValue = postponeToNoEscapeCleanup
- ? fn.ensurePlusOne(SGF, loc).forward(SGF)
- : fn.getValue();
- SILValue result = createConvertEscapeToNoEscape(loc, fnValue, resultTy,
- postponeToNoEscapeCleanup);
- if (postponeToNoEscapeCleanup)
- getSILGenFunction().enterPostponedCleanup(fnValue);
+ SILValue fnValue = fn.getValue();
+ SILValue result = createConvertEscapeToNoEscape(
+ loc, fnValue, resultTy, isEscapedByUser, false);
return ManagedValue::forTrivialObjectRValue(result);
}
diff --git a/lib/SILGen/SILGenBuilder.h b/lib/SILGen/SILGenBuilder.h
index a59d8fe..82e216b 100644
--- a/lib/SILGen/SILGenBuilder.h
+++ b/lib/SILGen/SILGenBuilder.h
@@ -364,7 +364,7 @@
ManagedValue
createConvertEscapeToNoEscape(SILLocation loc, ManagedValue fn,
SILType resultTy,
- bool postponeToNoEscapeCleanup = true);
+ bool isEscapedByUser);
using SILBuilder::createStore;
/// Forward \p value into \p address.
diff --git a/lib/SILGen/SILGenBuiltin.cpp b/lib/SILGen/SILGenBuiltin.cpp
index f8953fe..59cc412 100644
--- a/lib/SILGen/SILGenBuiltin.cpp
+++ b/lib/SILGen/SILGenBuiltin.cpp
@@ -517,6 +517,90 @@
return ManagedValue::forUnmanaged(addr);
}
+/// Specialized emitter for Builtin.beginUnpairedModifyAccess.
+static ManagedValue emitBuiltinBeginUnpairedModifyAccess(SILGenFunction &SGF,
+ SILLocation loc,
+ SubstitutionList substitutions,
+ ArrayRef<ManagedValue> args,
+ SGFContext C) {
+ assert(substitutions.size() == 1 &&
+ "Builtin.beginUnpairedModifyAccess should have one substitution");
+ assert(args.size() == 3 &&
+ "beginUnpairedModifyAccess should be given three arguments");
+
+ SILType elemTy = SGF.getLoweredType(substitutions[0].getReplacement());
+ SILValue addr = SGF.B.createPointerToAddress(loc, args[0].getUnmanagedValue(),
+ elemTy.getAddressType(),
+ /*strict*/ true,
+ /*invariant*/ false);
+
+ SILType valueBufferTy =
+ SGF.getLoweredType(SGF.getASTContext().TheUnsafeValueBufferType);
+
+ SILValue buffer = SGF.B.createPointerToAddress(loc, args[1].getUnmanagedValue(),
+ valueBufferTy.getAddressType(),
+ /*strict*/ true,
+ /*invariant*/ false);
+ SGF.B.createBeginUnpairedAccess(loc, addr, buffer, SILAccessKind::Modify,
+ SILAccessEnforcement::Dynamic,
+ /*noNestedConflict*/ false);
+
+ return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
+}
+
+/// Specialized emitter for Builtin.performInstantaneousReadAccess
+static ManagedValue emitBuiltinPerformInstantaneousReadAccess(SILGenFunction &SGF,
+ SILLocation loc,
+ SubstitutionList substitutions,
+ ArrayRef<ManagedValue> args,
+ SGFContext C) {
+ assert(substitutions.size() == 1 &&
+ "Builtin.performInstantaneousReadAccess should have one substitution");
+ assert(args.size() == 2 &&
+ "Builtin.performInstantaneousReadAccess should be given "
+ "two arguments");
+
+ SILType elemTy = SGF.getLoweredType(substitutions[0].getReplacement());
+ SILValue addr = SGF.B.createPointerToAddress(loc, args[0].getUnmanagedValue(),
+ elemTy.getAddressType(),
+ /*strict*/ true,
+ /*invariant*/ false);
+
+ // Begin and then immediately end a read access. No nested conflict is
+ // possible because there are no instructions between the begin and the
+ // end of the access.
+ SILValue access = SGF.B.createBeginAccess(loc, addr, SILAccessKind::Read,
+ SILAccessEnforcement::Dynamic,
+ /*noNestedConflict*/ true);
+ SGF.B.createEndAccess(loc, access, /*aborted*/ false);
+
+ return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
+}
+
+/// Specialized emitter for Builtin.endUnpairedAccessModifyAccess.
+static ManagedValue emitBuiltinEndUnpairedAccess(SILGenFunction &SGF,
+ SILLocation loc,
+ SubstitutionList substitutions,
+ ArrayRef<ManagedValue> args,
+ SGFContext C) {
+ assert(substitutions.size() == 0 &&
+ "Builtin.endUnpairedAccess should have no substitutions");
+ assert(args.size() == 1 &&
+ "endUnpairedAccess should be given one argument");
+
+ SILType valueBufferTy =
+ SGF.getLoweredType(SGF.getASTContext().TheUnsafeValueBufferType);
+
+ SILValue buffer = SGF.B.createPointerToAddress(loc, args[0].getUnmanagedValue(),
+ valueBufferTy.getAddressType(),
+ /*strict*/ true,
+ /*invariant*/ false);
+ SGF.B.createEndUnpairedAccess(loc, buffer, SILAccessEnforcement::Dynamic,
+ /*aborted*/ false);
+
+ return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
+}
+
/// Specialized emitter for Builtin.condfail.
static ManagedValue emitBuiltinCondFail(SILGenFunction &SGF,
SILLocation loc,
diff --git a/lib/SILGen/SILGenDecl.cpp b/lib/SILGen/SILGenDecl.cpp
index 21c297f..ebf4264 100644
--- a/lib/SILGen/SILGenDecl.cpp
+++ b/lib/SILGen/SILGenDecl.cpp
@@ -1289,51 +1289,6 @@
return Cleanups.getTopCleanup();
}
-PostponedCleanup::PostponedCleanup(SILGenFunction &sgf, bool recursive)
- : depth(sgf.Cleanups.innermostScope), SGF(sgf),
- previouslyActiveCleanup(sgf.CurrentlyActivePostponedCleanup),
- active(true), applyRecursively(recursive) {
- SGF.CurrentlyActivePostponedCleanup = this;
-}
-
-PostponedCleanup::PostponedCleanup(SILGenFunction &sgf)
- : depth(sgf.Cleanups.innermostScope), SGF(sgf),
- previouslyActiveCleanup(sgf.CurrentlyActivePostponedCleanup),
- active(true),
- applyRecursively(previouslyActiveCleanup
- ? previouslyActiveCleanup->applyRecursively
- : false) {
- SGF.CurrentlyActivePostponedCleanup = this;
-}
-
-PostponedCleanup::~PostponedCleanup() {
- if (active) {
- end();
- }
-}
-
-void PostponedCleanup::end() {
- if (previouslyActiveCleanup && applyRecursively &&
- previouslyActiveCleanup->applyRecursively) {
- previouslyActiveCleanup->deferredCleanups.append(deferredCleanups.begin(),
- deferredCleanups.end());
- }
-
- SGF.CurrentlyActivePostponedCleanup = previouslyActiveCleanup;
- active = false;
-}
-
-void PostponedCleanup::postponeCleanup(CleanupHandle cleanup,
- SILValue forValue) {
- deferredCleanups.push_back(std::make_pair(cleanup, forValue));
-}
-
-void SILGenFunction::enterPostponedCleanup(SILValue forValue) {
- auto handle = enterDestroyCleanup(forValue);
- if (CurrentlyActivePostponedCleanup)
- CurrentlyActivePostponedCleanup->postponeCleanup(handle, forValue);
-}
-
namespace {
/// A cleanup that deinitializes an opaque existential container
/// before a value has been stored into it, or after its value was taken.
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index fbb86e7..df5da72 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -368,7 +368,6 @@
// Handle the special case of copying an lvalue.
if (auto load = dyn_cast<LoadExpr>(E)) {
FormalEvaluationScope writeback(*this);
- PostponedCleanup postpone(*this);
auto lv = emitLValue(load->getSubExpr(), AccessKind::Read);
emitCopyLValueInto(E, std::move(lv), I);
return;
@@ -920,7 +919,6 @@
// Any writebacks for this access are tightly scoped.
FormalEvaluationScope scope(*this);
- PostponedCleanup postpone(*this);
// If this is a decl that we have an lvalue for, produce and return it.
ValueDecl *decl = declRef.getDecl();
@@ -1400,7 +1398,6 @@
RValue RValueEmitter::visitLoadExpr(LoadExpr *E, SGFContext C) {
// Any writebacks here are tightly scoped.
FormalEvaluationScope writeback(SGF);
- PostponedCleanup postpone(SGF);
LValue lv = SGF.emitLValue(E->getSubExpr(), AccessKind::Read);
// We can't load at immediate +0 from the lvalue without deeper analysis,
// since the access will be immediately ended and might invalidate the value
@@ -2091,9 +2088,7 @@
result = convertFunctionRepresentation(SGF, e, result, srcRepTy, srcTy);
if (srcTy != destTy) {
- bool postponeToNoEscapeCleanup = !isa<BindOptionalExpr>(e->getSubExpr());
- result = SGF.emitTransformedValue(e, result, srcTy, destTy, SGFContext(),
- postponeToNoEscapeCleanup);
+ result = SGF.emitTransformedValue(e, result, srcTy, destTy, SGFContext());
}
if (destTy != destRepTy)
@@ -2577,7 +2572,6 @@
// Any writebacks for this access are tightly scoped.
FormalEvaluationScope scope(SGF);
- PostponedCleanup postpone(SGF);
LValue lv = SGF.emitLValue(E, AccessKind::Read);
// We can't load at +0 without further analysis, since the formal access into
@@ -2599,7 +2593,6 @@
RValue RValueEmitter::visitSubscriptExpr(SubscriptExpr *E, SGFContext C) {
// Any writebacks for this access are tightly scoped.
FormalEvaluationScope scope(SGF);
- PostponedCleanup postpone(SGF);
LValue lv = SGF.emitLValue(E, AccessKind::Read);
// We can't load at +0 without further analysis, since the formal access into
@@ -2654,9 +2647,8 @@
ResultPlanPtr resultPtr =
ResultPlanBuilder::computeResultPlan(*this, calleeTypeInfo, loc, C);
ArgumentScope argScope(*this, loc);
- PostponedCleanup postpone(*this);
return emitApply(std::move(resultPtr), std::move(argScope), loc, fnRef, subs,
- {}, calleeTypeInfo, ApplyOptions::None, C, postpone);
+ {}, calleeTypeInfo, ApplyOptions::None, C);
}
RValue SILGenFunction::emitApplyOfStoredPropertyInitializer(
@@ -2678,9 +2670,8 @@
ResultPlanPtr resultPlan =
ResultPlanBuilder::computeResultPlan(*this, calleeTypeInfo, loc, C);
ArgumentScope argScope(*this, loc);
- PostponedCleanup postpone(*this);
return emitApply(std::move(resultPlan), std::move(argScope), loc, fnRef, subs,
- {}, calleeTypeInfo, ApplyOptions::None, C, postpone);
+ {}, calleeTypeInfo, ApplyOptions::None, C);
}
static void emitTupleShuffleExprInto(RValueEmitter &emitter,
@@ -3561,7 +3552,6 @@
auto equalsResultPlan = ResultPlanBuilder::computeResultPlan(subSGF,
equalsInfo, loc, SGFContext());
ArgumentScope argScope(subSGF, loc);
- PostponedCleanup postpone(subSGF);
SmallVector<Substitution, 1> equatableSubListBuf;
equatableProtocol->getGenericSignature()
->getSubstitutions(equatableSub, equatableSubListBuf);
@@ -3570,8 +3560,7 @@
loc, ManagedValue::forUnmanaged(equalsWitness),
C.AllocateCopy(equatableSubListBuf),
{lhsArg, rhsArg, metatyValue},
- equalsInfo, ApplyOptions::None, SGFContext(),
- postpone)
+ equalsInfo, ApplyOptions::None, SGFContext())
.getUnmanagedSingleValue(subSGF, loc);
}
@@ -3700,13 +3689,11 @@
auto hashResultPlan = ResultPlanBuilder::computeResultPlan(subSGF,
hashInfo, loc, SGFContext());
ArgumentScope argScope(subSGF, loc);
- PostponedCleanup postpone(subSGF);
hashCode =
subSGF
.emitApply(std::move(hashResultPlan), std::move(argScope), loc,
ManagedValue::forUnmanaged(hashWitness), hashableSub,
- {arg}, hashInfo, ApplyOptions::None, SGFContext(),
- postpone)
+ {arg}, hashInfo, ApplyOptions::None, SGFContext())
.getUnmanagedSingleValue(subSGF, loc);
}
}
@@ -4313,7 +4300,6 @@
// Get newSelf, forward the cleanup for newSelf and clean everything else
// up.
FormalEvaluationScope Scope(SGF);
- PostponedCleanup postpone(SGF);
ManagedValue newSelfWithCleanup =
SGF.emitRValueAsSingleValue(E->getSubExpr());
@@ -4867,7 +4853,6 @@
if (dest->getType()->isEqual(srcLoad->getSubExpr()->getType())) {
assert(!dest->getType()->is<TupleType>());
FormalEvaluationScope writeback(SGF);
- PostponedCleanup postpone(SGF);
auto destLV = SGF.emitLValue(dest, AccessKind::Write);
auto srcLV = SGF.emitLValue(srcLoad->getSubExpr(), AccessKind::Read);
SGF.emitAssignLValueToLValue(loc, std::move(srcLV), std::move(destLV));
@@ -4889,14 +4874,12 @@
}
FormalEvaluationScope writeback(SGF);
- PostponedCleanup postpone(SGF);
LValue destLV = SGF.emitLValue(dest, AccessKind::Write);
SGF.emitAssignToLValue(loc, src, std::move(destLV));
return;
}
FormalEvaluationScope writeback(SGF);
- PostponedCleanup postpone(SGF);
// Produce a flattened queue of LValues.
SmallVector<Optional<LValue>, 4> destLVs;
@@ -5700,7 +5683,6 @@
RValue RValueEmitter::visitArrayToPointerExpr(ArrayToPointerExpr *E,
SGFContext C) {
FormalEvaluationScope writeback(SGF);
- PostponedCleanup postpone(SGF);
auto subExpr = E->getSubExpr();
auto accessInfo = SGF.getArrayAccessInfo(E->getType(),
@@ -5885,7 +5867,6 @@
if (E->getType()->hasLValueType()) {
// Emit the l-value, but don't perform an access.
FormalEvaluationScope scope(*this);
- PostponedCleanup postpone(*this);
emitLValue(E, AccessKind::Read);
return;
}
@@ -5894,7 +5875,6 @@
// (which could materialize a potentially expensive value with cleanups).
if (auto *LE = dyn_cast<LoadExpr>(E)) {
FormalEvaluationScope scope(*this);
- PostponedCleanup postpone(*this);
LValue lv = emitLValue(LE->getSubExpr(), AccessKind::Read);
// If loading from the lvalue is guaranteed to have no side effects, we
diff --git a/lib/SILGen/SILGenFunction.h b/lib/SILGen/SILGenFunction.h
index fb77e77..df211b6 100644
--- a/lib/SILGen/SILGenFunction.h
+++ b/lib/SILGen/SILGenFunction.h
@@ -43,7 +43,6 @@
class ResultPlan;
using ResultPlanPtr = std::unique_ptr<ResultPlan>;
class ArgumentScope;
-class PostponedCleanup;
class Scope;
enum class ApplyOptions : unsigned {
@@ -248,10 +247,6 @@
/// \brief The current context where formal evaluation cleanups are managed.
FormalEvaluationContext FormalEvalContext;
- /// Currently active postponed cleanups.
- PostponedCleanup *CurrentlyActivePostponedCleanup = nullptr;
- void enterPostponedCleanup(SILValue forValue);
-
/// \brief Values to end dynamic access enforcement on. A hack for
/// materializeForSet.
struct UnpairedAccesses {
@@ -1305,7 +1300,7 @@
SILLocation loc, ManagedValue fn, SubstitutionList subs,
ArrayRef<ManagedValue> args,
const CalleeTypeInfo &calleeTypeInfo, ApplyOptions options,
- SGFContext evalContext, PostponedCleanup &cleanup);
+ SGFContext evalContext);
RValue emitApplyOfDefaultArgGenerator(SILLocation loc,
ConcreteDeclRef defaultArgsOwner,
@@ -1617,8 +1612,7 @@
ManagedValue emitTransformedValue(SILLocation loc, ManagedValue input,
CanType inputType,
CanType outputType,
- SGFContext ctx = SGFContext(),
- bool postponeToNoEscapeCleanup = true);
+ SGFContext ctx = SGFContext());
/// Most general form of the above.
ManagedValue emitTransformedValue(SILLocation loc, ManagedValue input,
@@ -1626,8 +1620,7 @@
CanType inputSubstType,
AbstractionPattern outputOrigType,
CanType outputSubstType,
- SGFContext ctx = SGFContext(),
- bool postponeToNoEscapeCleanup = true);
+ SGFContext ctx = SGFContext());
RValue emitTransformedValue(SILLocation loc, RValue &&input,
AbstractionPattern inputOrigType,
CanType inputSubstType,
@@ -1869,37 +1862,6 @@
}
};
-/// Utility class to facilitate posponment of cleanup of @noescape
-/// partial_apply arguments into the 'right' scope.
-///
-/// If a Postponed cleanup is active at the end of a scope. The scope will
-/// actively push the cleanup into its surrounding scope.
-class PostponedCleanup {
- friend SILGenFunction;
- friend Scope;
-
- SmallVector<std::pair<CleanupHandle, SILValue>, 16> deferredCleanups;
- CleanupsDepth depth;
- SILGenFunction &SGF;
- PostponedCleanup *previouslyActiveCleanup;
- bool active;
- bool applyRecursively;
-
- void postponeCleanup(CleanupHandle cleanup, SILValue forValue);
-public:
- PostponedCleanup(SILGenFunction &SGF);
- PostponedCleanup(SILGenFunction &SGF, bool applyRecursively);
- ~PostponedCleanup();
-
- void end();
-
- PostponedCleanup() = delete;
- PostponedCleanup(const PostponedCleanup &) = delete;
- PostponedCleanup &operator=(const PostponedCleanup &) = delete;
- PostponedCleanup &operator=(PostponedCleanup &&other) = delete;
- PostponedCleanup(PostponedCleanup &&) = delete;
-};
-
} // end namespace Lowering
} // end namespace swift
diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp
index 16af207..5d81218 100644
--- a/lib/SILGen/SILGenLValue.cpp
+++ b/lib/SILGen/SILGenLValue.cpp
@@ -1243,9 +1243,6 @@
SILValue buffer =
SGF.emitTemporaryAllocation(loc, getTypeOfRValue());
- // Postpone cleanup for noescape closures.
- PostponedCleanup postpone(SGF, true);
-
// Clone the component without cloning the indices. We don't actually
// consume them in writeback().
std::unique_ptr<LogicalPathComponent> clonedComponent(
@@ -1303,7 +1300,6 @@
// access for stored properties with didSet.
pushWriteback(SGF, loc, std::move(clonedComponent), base, materialized);
- postpone.end();
return ManagedValue::forLValue(materialized.temporary.getValue());
}
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index bbc0ea5..052e590 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -136,8 +136,7 @@
CanType inputSubstType,
AbstractionPattern outputOrigType,
CanType outputSubstType,
- SGFContext ctxt,
- bool postponeToNoEscapeCleanup = true);
+ SGFContext ctxt);
/// Transform a metatype value.
ManagedValue transformMetatype(ManagedValue fn,
@@ -160,8 +159,7 @@
CanAnyFunctionType inputSubstType,
AbstractionPattern outputOrigType,
CanAnyFunctionType outputSubstType,
- const TypeLowering &expectedTL,
- bool postponeToNoEscapeCleanup = true);
+ const TypeLowering &expectedTL);
};
} // end anonymous namespace
;
@@ -358,8 +356,7 @@
CanType inputSubstType,
AbstractionPattern outputOrigType,
CanType outputSubstType,
- SGFContext ctxt,
- bool postponeToNoEscapeCleanup) {
+ SGFContext ctxt) {
// Look through inout types.
if (isa<InOutType>(inputSubstType))
inputSubstType = CanType(inputSubstType->getInOutObjectType());
@@ -443,8 +440,7 @@
return transformFunction(v,
inputOrigType, inputFnType,
outputOrigType, outputFnType,
- expectedTL,
- postponeToNoEscapeCleanup);
+ expectedTL);
}
// - tuples of transformable values
@@ -2937,8 +2933,8 @@
// Handle the escaping to noescape conversion.
assert(expectedType->isNoEscape());
- return SGF.B.createConvertEscapeToNoEscape(loc, thunkedFn,
- SILType::getPrimitiveObjectType(expectedType));
+ return SGF.B.createConvertEscapeToNoEscape(
+ loc, thunkedFn, SILType::getPrimitiveObjectType(expectedType), false);
}
static CanSILFunctionType buildWithoutActuallyEscapingThunkType(
@@ -3045,8 +3041,7 @@
CanAnyFunctionType inputSubstType,
AbstractionPattern outputOrigType,
CanAnyFunctionType outputSubstType,
- const TypeLowering &expectedTL,
- bool postponeToNoEscapeCleanup) {
+ const TypeLowering &expectedTL) {
assert(fn.getType().isObject() &&
"expected input to emitTransformedFunctionValue to be loaded");
@@ -3105,8 +3100,7 @@
} else if (newFnType != expectedFnType) {
// Escaping to noescape conversion.
SILType resTy = SILType::getPrimitiveObjectType(expectedFnType);
- fn = SGF.B.createConvertEscapeToNoEscape(Loc, fn, resTy,
- postponeToNoEscapeCleanup);
+ fn = SGF.B.createConvertEscapeToNoEscape(Loc, fn, resTy, false);
}
return fn;
@@ -3202,12 +3196,11 @@
SILGenFunction::emitTransformedValue(SILLocation loc, ManagedValue v,
CanType inputType,
CanType outputType,
- SGFContext ctxt,
- bool postponeToNoEscapeCleanup) {
+ SGFContext ctxt) {
return emitTransformedValue(loc, v,
AbstractionPattern(inputType), inputType,
AbstractionPattern(outputType), outputType,
- ctxt, postponeToNoEscapeCleanup);
+ ctxt);
}
ManagedValue
@@ -3216,14 +3209,12 @@
CanType inputSubstType,
AbstractionPattern outputOrigType,
CanType outputSubstType,
- SGFContext ctxt,
- bool postponeToNoEscapeCleanup) {
+ SGFContext ctxt) {
return Transform(*this, loc).transform(v,
inputOrigType,
inputSubstType,
outputOrigType,
- outputSubstType, ctxt,
- postponeToNoEscapeCleanup);
+ outputSubstType, ctxt);
}
RValue
diff --git a/lib/SILGen/Scope.cpp b/lib/SILGen/Scope.cpp
index 1fc5c9d..0606c59 100644
--- a/lib/SILGen/Scope.cpp
+++ b/lib/SILGen/Scope.cpp
@@ -122,26 +122,6 @@
void Scope::popImpl() {
SmallVector<SILValue, 16> cleanupsToPropagateToOuterScope;
- // Deactivate any postpone cleanups in the current scope.
- if (currentlyActivePostponedCleanup) {
- bool inScope;
- do {
- inScope = false;
- auto &deferredCleanups =
- currentlyActivePostponedCleanup->deferredCleanups;
- if (deferredCleanups.empty())
- break;
- auto &top = deferredCleanups.back();
- auto topCleanupDepth = top.first.getDepth();
- if (topCleanupDepth > depth.getDepth()) {
- cleanups.forwardCleanup(top.first);
- cleanupsToPropagateToOuterScope.push_back(top.second);
- deferredCleanups.pop_back();
- inScope = true;
- }
- } while (inScope);
- }
-
cleanups.stack.checkIterator(depth);
cleanups.stack.checkIterator(cleanups.innermostScope);
assert(cleanups.innermostScope == depth && "popping scopes out of order");
@@ -150,14 +130,4 @@
cleanups.endScope(depth, loc);
cleanups.stack.checkIterator(cleanups.innermostScope);
cleanups.popTopDeadCleanups(cleanups.innermostScope);
-
- // Propagate the cleanup to the current parent scope.
- for (auto valueToCleanup : cleanupsToPropagateToOuterScope) {
- auto handle = cleanups.SGF.enterDestroyCleanup(valueToCleanup);
- // Propagate cleanup to parent Scope.
- if (currentlyActivePostponedCleanup->depth.getDepth() < depth.getDepth()) {
- currentlyActivePostponedCleanup->deferredCleanups.push_back(
- std::make_pair(handle, valueToCleanup));
- }
- }
}
diff --git a/lib/SILGen/Scope.h b/lib/SILGen/Scope.h
index 8b67e71..89ce3c8 100644
--- a/lib/SILGen/Scope.h
+++ b/lib/SILGen/Scope.h
@@ -31,14 +31,11 @@
CleanupsDepth depth;
CleanupsDepth savedInnermostScope;
CleanupLocation loc;
- PostponedCleanup *currentlyActivePostponedCleanup;
public:
explicit Scope(CleanupManager &cleanups, CleanupLocation loc)
: cleanups(cleanups), depth(cleanups.getCleanupsDepth()),
- savedInnermostScope(cleanups.innermostScope), loc(loc),
- currentlyActivePostponedCleanup(
- cleanups.SGF.CurrentlyActivePostponedCleanup) {
+ savedInnermostScope(cleanups.innermostScope), loc(loc) {
assert(depth.isValid());
cleanups.stack.checkIterator(cleanups.innermostScope);
cleanups.innermostScope = depth;
diff --git a/lib/SILOptimizer/Analysis/AliasAnalysis.cpp b/lib/SILOptimizer/Analysis/AliasAnalysis.cpp
index 5b2d77f..385b016 100644
--- a/lib/SILOptimizer/Analysis/AliasAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/AliasAnalysis.cpp
@@ -652,8 +652,8 @@
if (!EA->canEscapeTo(Ptr, FAS))
return false;
- SideEffectAnalysis::FunctionEffects ApplyEffects;
- SEA->getEffects(ApplyEffects, FAS);
+ FunctionSideEffects ApplyEffects;
+ SEA->getCalleeEffects(ApplyEffects, FAS);
auto &GlobalEffects = ApplyEffects.getGlobalEffects();
if (ApplyEffects.mayReadRC() || GlobalEffects.mayRelease())
diff --git a/lib/SILOptimizer/Analysis/MemoryBehavior.cpp b/lib/SILOptimizer/Analysis/MemoryBehavior.cpp
index 17ebb80..0b255a6 100644
--- a/lib/SILOptimizer/Analysis/MemoryBehavior.cpp
+++ b/lib/SILOptimizer/Analysis/MemoryBehavior.cpp
@@ -237,8 +237,8 @@
MemBehavior MemoryBehaviorVisitor::visitApplyInst(ApplyInst *AI) {
- SideEffectAnalysis::FunctionEffects ApplyEffects;
- SEA->getEffects(ApplyEffects, AI);
+ FunctionSideEffects ApplyEffects;
+ SEA->getCalleeEffects(ApplyEffects, AI);
MemBehavior Behavior = MemBehavior::None;
diff --git a/lib/SILOptimizer/Analysis/SideEffectAnalysis.cpp b/lib/SILOptimizer/Analysis/SideEffectAnalysis.cpp
index 28fb7d0..26e83a0 100644
--- a/lib/SILOptimizer/Analysis/SideEffectAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/SideEffectAnalysis.cpp
@@ -2,7 +2,7 @@
//
// This source file is part of the Swift.org open source project
//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
@@ -19,12 +19,183 @@
using namespace swift;
-using FunctionEffects = SideEffectAnalysis::FunctionEffects;
-using Effects = SideEffectAnalysis::Effects;
+// -----------------------------------------------------------------------------
+// GenericFunctionEffectAnalysis
+// -----------------------------------------------------------------------------
+
+template <typename FunctionEffects>
+void GenericFunctionEffectAnalysis<FunctionEffects>::initialize(
+ SILPassManager *PM) {
+ BCA = PM->getAnalysis<BasicCalleeAnalysis>();
+}
+
+template <typename FunctionEffects>
+void GenericFunctionEffectAnalysis<FunctionEffects>::invalidate() {
+ functionInfoMap.clear();
+ allocator.DestroyAll();
+ DEBUG(llvm::dbgs() << "invalidate all\n");
+}
+
+template <typename FunctionEffects>
+void GenericFunctionEffectAnalysis<FunctionEffects>::invalidate(
+ SILFunction *F, InvalidationKind K) {
+ if (FunctionInfo *FInfo = functionInfoMap.lookup(F)) {
+ DEBUG(llvm::dbgs() << " invalidate " << FInfo->F->getName() << '\n');
+ invalidateIncludingAllCallers(FInfo);
+ }
+}
+
+template <typename FunctionEffects>
+void GenericFunctionEffectAnalysis<FunctionEffects>::getCalleeEffects(
+ FunctionEffects &calleeEffects, FullApplySite fullApply) {
+ if (calleeEffects.summarizeCall(fullApply))
+ return;
+
+ auto callees = BCA->getCalleeList(fullApply);
+ if (!callees.allCalleesVisible() ||
+ // @callee_owned function calls implicitly release the context, which
+ // may call deinits of boxed values.
+ // TODO: be less conservative about what destructors might be called.
+ fullApply.getOrigCalleeType()->isCalleeConsumed()) {
+ calleeEffects.setWorstEffects();
+ return;
+ }
+
+ // We can see all the callees, so merge the effects from all of them.
+ for (auto *callee : callees)
+ calleeEffects.mergeFrom(getEffects(callee));
+}
+
+template <typename FunctionEffects>
+void GenericFunctionEffectAnalysis<FunctionEffects>::analyzeFunction(
+ FunctionInfo *functionInfo, FunctionOrder &bottomUpOrder,
+ int recursionDepth) {
+ functionInfo->needUpdateCallers = true;
+
+ if (bottomUpOrder.prepareForVisiting(functionInfo))
+ return;
+
+ auto *F = functionInfo->F;
+ if (functionInfo->functionEffects.summarizeFunction(F))
+ return;
+
+ DEBUG(llvm::dbgs() << " >> analyze " << F->getName() << '\n');
+
+ // Check all instructions of the function
+ for (auto &BB : *F) {
+ for (auto &I : BB) {
+ if (auto fullApply = FullApplySite::isa(&I))
+ analyzeCall(functionInfo, fullApply, bottomUpOrder, recursionDepth);
+ else
+ functionInfo->functionEffects.analyzeInstruction(&I);
+ }
+ }
+ DEBUG(llvm::dbgs() << " << finished " << F->getName() << '\n');
+}
+
+template <typename FunctionEffects>
+void GenericFunctionEffectAnalysis<FunctionEffects>::analyzeCall(
+ FunctionInfo *functionInfo, FullApplySite fullApply,
+ FunctionOrder &bottomUpOrder, int recursionDepth) {
+
+ FunctionEffects applyEffects;
+ if (applyEffects.summarizeCall(fullApply)) {
+ functionInfo->functionEffects.mergeFromApply(applyEffects, fullApply);
+ return;
+ }
+
+ if (recursionDepth >= MaxRecursionDepth) {
+ functionInfo->functionEffects.setWorstEffects();
+ return;
+ }
+ CalleeList callees = BCA->getCalleeList(fullApply);
+ if (!callees.allCalleesVisible() ||
+ // @callee_owned function calls implicitly release the context, which
+ // may call deinits of boxed values.
+ // TODO: be less conservative about what destructors might be called.
+ fullApply.getOrigCalleeType()->isCalleeConsumed()) {
+ functionInfo->functionEffects.setWorstEffects();
+ return;
+ }
+ // Derive the effects of the apply from the known callees.
+ // Defer merging callee effects until the callee is scheduled
+ for (SILFunction *callee : callees) {
+ FunctionInfo *calleeInfo = getFunctionInfo(callee);
+ calleeInfo->addCaller(functionInfo, fullApply);
+ if (!calleeInfo->isVisited()) {
+ // Recursively visit the called function.
+ analyzeFunction(calleeInfo, bottomUpOrder, recursionDepth + 1);
+ bottomUpOrder.tryToSchedule(calleeInfo);
+ }
+ }
+}
+
+template <typename FunctionEffects>
+void GenericFunctionEffectAnalysis<FunctionEffects>::recompute(
+ FunctionInfo *initialInfo) {
+ allocNewUpdateID();
+
+ DEBUG(llvm::dbgs() << "recompute function-effect analysis with UpdateID "
+ << getCurrentUpdateID() << '\n');
+
+ // Collect and analyze all functions to recompute, starting at initialInfo.
+ FunctionOrder bottomUpOrder(getCurrentUpdateID());
+ analyzeFunction(initialInfo, bottomUpOrder, 0);
+
+ // Build the bottom-up order.
+ bottomUpOrder.tryToSchedule(initialInfo);
+ bottomUpOrder.finishScheduling();
+
+ // Second step: propagate the side-effect information up the call-graph until
+ // it stabilizes.
+ bool needAnotherIteration;
+ do {
+ DEBUG(llvm::dbgs() << "new iteration\n");
+ needAnotherIteration = false;
+
+ for (FunctionInfo *functionInfo : bottomUpOrder) {
+ if (!functionInfo->needUpdateCallers)
+ continue;
+
+ DEBUG(llvm::dbgs() << " update callers of " << functionInfo->F->getName()
+ << '\n');
+ functionInfo->needUpdateCallers = false;
+
+ // Propagate the function effects to all callers.
+ for (const auto &E : functionInfo->getCallers()) {
+ assert(E.isValid());
+
+ // Only include callers which we are actually recomputing.
+ if (!bottomUpOrder.wasRecomputedWithCurrentUpdateID(E.Caller))
+ continue;
+
+ DEBUG(llvm::dbgs() << " merge into caller " << E.Caller->F->getName()
+ << '\n');
+
+ if (E.Caller->functionEffects.mergeFromApply(
+ functionInfo->functionEffects, FullApplySite(E.FAS))) {
+ E.Caller->needUpdateCallers = true;
+ if (!E.Caller->isScheduledAfter(functionInfo)) {
+ // This happens if we have a cycle in the call-graph.
+ needAnotherIteration = true;
+ }
+ }
+ }
+ }
+ } while (needAnotherIteration);
+}
+
+// Instantiate template members.
+template class swift::GenericFunctionEffectAnalysis<FunctionSideEffects>;
+
+// -----------------------------------------------------------------------------
+// FunctionSideEffects
+// -----------------------------------------------------------------------------
+
using MemoryBehavior = SILInstruction::MemoryBehavior;
MemoryBehavior
-FunctionEffects::getMemBehavior(RetainObserveKind ScanKind) const {
+FunctionSideEffects::getMemBehavior(RetainObserveKind ScanKind) const {
bool Observe = (ScanKind == RetainObserveKind::ObserveRetains);
if ((Observe && mayAllocObjects()) || mayReadRC())
@@ -46,7 +217,7 @@
return Behavior;
}
-bool FunctionEffects::mergeFrom(const FunctionEffects &RHS) {
+bool FunctionSideEffects::mergeFrom(const FunctionSideEffects &RHS) {
bool Changed = mergeFlags(RHS);
Changed |= GlobalEffects.mergeFrom(RHS.GlobalEffects);
Changed |= LocalEffects.mergeFrom(RHS.LocalEffects);
@@ -64,33 +235,26 @@
return Changed;
}
-bool FunctionEffects::mergeFromApply(
- const FunctionEffects &ApplyEffects, FullApplySite FAS) {
- return mergeFromApply(ApplyEffects, FAS.getInstruction());
-}
-
-bool FunctionEffects::mergeFromApply(
- const FunctionEffects &ApplyEffects, SILInstruction *AS) {
+bool FunctionSideEffects::mergeFromApply(
+ const FunctionSideEffects &ApplyEffects, FullApplySite FAS) {
bool Changed = mergeFlags(ApplyEffects);
Changed |= GlobalEffects.mergeFrom(ApplyEffects.GlobalEffects);
- auto FAS = FullApplySite::isa(AS);
- unsigned numCallerArgs = FAS ? FAS.getNumArguments() : 1;
+ unsigned numCallerArgs = FAS.getNumArguments();
unsigned numCalleeArgs = ApplyEffects.ParamEffects.size();
assert(numCalleeArgs >= numCallerArgs);
for (unsigned Idx = 0; Idx < numCalleeArgs; Idx++) {
// Map the callee argument effects to parameters of this function.
// If there are more callee parameters than arguments it means that the
// callee is the result of a partial_apply.
- Effects *E = (Idx < numCallerArgs ? getEffectsOn(FAS ? FAS.getArgument(Idx) : AS->getOperand(Idx)) :
- &GlobalEffects);
+ FunctionSideEffectFlags *E = (Idx < numCallerArgs
+ ? getEffectsOn(FAS.getArgument(Idx))
+ : &GlobalEffects);
Changed |= E->mergeFrom(ApplyEffects.ParamEffects[Idx]);
}
return Changed;
}
-void FunctionEffects::dump() const {
- llvm::errs() << *this << '\n';
-}
+void FunctionSideEffects::dump() const { llvm::errs() << *this << '\n'; }
static SILValue skipAddrProjections(SILValue V) {
for (;;) {
@@ -130,7 +294,7 @@
llvm_unreachable("there is no escape from an infinite loop");
}
-Effects *FunctionEffects::getEffectsOn(SILValue Addr) {
+FunctionSideEffectFlags *FunctionSideEffects::getEffectsOn(SILValue Addr) {
SILValue BaseAddr = skipValueProjections(skipAddrProjections(Addr));
switch (BaseAddr->getKind()) {
case swift::ValueKind::SILFunctionArgument: {
@@ -152,17 +316,18 @@
return &GlobalEffects;
}
-bool SideEffectAnalysis::getDefinedEffects(FunctionEffects &Effects,
- SILFunction *F) {
+// Return true if the given function has defined effects that were successfully
+// recorded in this FunctionSideEffects object.
+bool FunctionSideEffects::setDefinedEffects(SILFunction *F) {
if (F->hasSemanticsAttr("arc.programtermination_point")) {
- Effects.Traps = true;
+ Traps = true;
return true;
}
switch (F->getEffectsKind()) {
case EffectsKind::ReleaseNone:
- Effects.GlobalEffects.Reads = true;
- Effects.GlobalEffects.Writes = true;
- Effects.GlobalEffects.Releases = false;
+ GlobalEffects.Reads = true;
+ GlobalEffects.Writes = true;
+ GlobalEffects.Releases = false;
return true;
case EffectsKind::ReadNone:
return true;
@@ -171,7 +336,7 @@
// the release inside the callee may call a deinit, which itself can do
// anything.
if (!F->hasOwnedParameters()) {
- Effects.GlobalEffects.Reads = true;
+ GlobalEffects.Reads = true;
return true;
}
break;
@@ -182,10 +347,34 @@
return false;
}
-bool SideEffectAnalysis::getSemanticEffects(FunctionEffects &FE,
- ArraySemanticsCall ASC) {
+// Return true if this function's effects have been fully summarized in this
+// FunctionSideEffects object without visiting its body.
+bool FunctionSideEffects::summarizeFunction(SILFunction *F) {
+ assert(ParamEffects.empty() && "Expect uninitialized effects.");
+ if (!F->empty())
+ ParamEffects.resize(F->getArguments().size());
+
+ // Handle @effects attributes
+ if (setDefinedEffects(F)) {
+ DEBUG(llvm::dbgs() << " -- has defined effects " << F->getName() << '\n');
+ return true;
+ }
+
+ if (!F->isDefinition()) {
+ // We can't assume anything about external functions.
+ DEBUG(llvm::dbgs() << " -- is external " << F->getName() << '\n');
+ setWorstEffects();
+ return true;
+ }
+ return false;
+}
+
+// Return true if the side effects of this semantic call are fully known without
+// visiting the callee and have been recorded in this FunctionSideEffects
+// object.
+bool FunctionSideEffects::setSemanticEffects(ArraySemanticsCall ASC) {
assert(ASC.hasSelf());
- auto &SelfEffects = FE.ParamEffects[FE.ParamEffects.size() - 1];
+ auto &SelfEffects = ParamEffects[ParamEffects.size() - 1];
// Currently we only handle array semantics.
// TODO: also handle other semantic functions.
@@ -205,7 +394,7 @@
if (!ASC.mayHaveBridgedObjectElementType()) {
SelfEffects.Reads = true;
SelfEffects.Releases |= !ASC.hasGuaranteedSelf();
- FE.Traps = true;
+ Traps = true;
return true;
}
return false;
@@ -218,7 +407,7 @@
->getOrigCalleeConv()
.getNumIndirectSILResults())) {
assert(!ASC.hasGetElementDirectResult());
- FE.ParamEffects[i].Writes = true;
+ ParamEffects[i].Writes = true;
}
return true;
}
@@ -240,9 +429,9 @@
case ArrayCallKind::kMakeMutable:
if (!ASC.mayHaveBridgedObjectElementType()) {
SelfEffects.Writes = true;
- FE.GlobalEffects.Releases = true;
- FE.AllocsObjects = true;
- FE.ReadsRC = true;
+ GlobalEffects.Releases = true;
+ AllocsObjects = true;
+ ReadsRC = true;
return true;
}
return false;
@@ -252,290 +441,134 @@
}
}
-void SideEffectAnalysis::analyzeFunction(FunctionInfo *FInfo,
- FunctionOrder &BottomUpOrder,
- int RecursionDepth) {
- FInfo->NeedUpdateCallers = true;
+// Summarize the callee side effects of a call instruction using this
+// FunctionSideEffects object without analyzing the callee function bodies or
+// scheduling the callees for bottom-up propagation.
+//
+// Return true if this call-site's effects are summarized without visiting the
+// callee.
+bool FunctionSideEffects::summarizeCall(FullApplySite fullApply) {
+ assert(ParamEffects.empty() && "Expect uninitialized effects.");
+ ParamEffects.resize(fullApply.getNumArguments());
- if (BottomUpOrder.prepareForVisiting(FInfo))
- return;
-
- // Handle @effects attributes
- if (getDefinedEffects(FInfo->FE, FInfo->F)) {
- DEBUG(llvm::dbgs() << " -- has defined effects " <<
- FInfo->F->getName() << '\n');
- return;
- }
-
- if (!FInfo->F->isDefinition()) {
- // We can't assume anything about external functions.
- DEBUG(llvm::dbgs() << " -- is external " << FInfo->F->getName() << '\n');
- FInfo->FE.setWorstEffects();
- return;
- }
-
- DEBUG(llvm::dbgs() << " >> analyze " << FInfo->F->getName() << '\n');
-
- // Check all instructions of the function
- for (auto &BB : *FInfo->F) {
- for (auto &I : BB) {
- analyzeInstruction(FInfo, &I, BottomUpOrder, RecursionDepth);
+ // Is this a call to a semantics function?
+ if (auto apply = dyn_cast<ApplyInst>(fullApply.getInstruction())) {
+ ArraySemanticsCall ASC(apply);
+ if (ASC && ASC.hasSelf()) {
+ if (setSemanticEffects(ASC))
+ return true;
}
}
- DEBUG(llvm::dbgs() << " << finished " << FInfo->F->getName() << '\n');
+
+ if (SILFunction *SingleCallee = fullApply.getReferencedFunction()) {
+ // Does the function have any @effects?
+ if (setDefinedEffects(SingleCallee))
+ return true;
+ }
+ return false;
}
-void SideEffectAnalysis::analyzeInstruction(FunctionInfo *FInfo,
- SILInstruction *I,
- FunctionOrder &BottomUpOrder,
- int RecursionDepth) {
- if (FullApplySite FAS = FullApplySite::isa(I)) {
- // Is this a call to a semantics function?
- if (auto apply = dyn_cast<ApplyInst>(FAS.getInstruction())) {
- ArraySemanticsCall ASC(apply);
- if (ASC && ASC.hasSelf()) {
- FunctionEffects ApplyEffects(FAS.getNumArguments());
- if (getSemanticEffects(ApplyEffects, ASC)) {
- FInfo->FE.mergeFromApply(ApplyEffects, FAS);
- return;
- }
- }
- }
-
- if (SILFunction *SingleCallee = FAS.getReferencedFunction()) {
- // Does the function have any @effects?
- if (getDefinedEffects(FInfo->FE, SingleCallee))
- return;
- }
-
- if (RecursionDepth < MaxRecursionDepth) {
- CalleeList Callees = BCA->getCalleeList(FAS);
- if (Callees.allCalleesVisible() &&
- // @callee_owned function calls implicitly release the context, which
- // may call deinits of boxed values.
- // TODO: be less conservative about what destructors might be called.
- !FAS.getOrigCalleeType()->isCalleeConsumed()) {
- // Derive the effects of the apply from the known callees.
- for (SILFunction *Callee : Callees) {
- FunctionInfo *CalleeInfo = getFunctionInfo(Callee);
- CalleeInfo->addCaller(FInfo, FAS);
- if (!CalleeInfo->isVisited()) {
- // Recursively visit the called function.
- analyzeFunction(CalleeInfo, BottomUpOrder, RecursionDepth + 1);
- BottomUpOrder.tryToSchedule(CalleeInfo);
- }
- }
- return;
- }
- }
- // Be conservative for everything else.
- FInfo->FE.setWorstEffects();
- return;
- }
+void FunctionSideEffects::analyzeInstruction(SILInstruction *I) {
// Handle some kind of instructions specially.
switch (I->getKind()) {
- case SILInstructionKind::FixLifetimeInst:
- // A fix_lifetime instruction acts like a read on the operand. Retains can move after it
- // but the last release can't move before it.
- FInfo->FE.getEffectsOn(I->getOperand(0))->Reads = true;
- return;
- case SILInstructionKind::AllocStackInst:
- case SILInstructionKind::DeallocStackInst:
- return;
- case SILInstructionKind::StrongRetainInst:
- case SILInstructionKind::StrongRetainUnownedInst:
- case SILInstructionKind::RetainValueInst:
- case SILInstructionKind::UnownedRetainInst:
- FInfo->FE.getEffectsOn(I->getOperand(0))->Retains = true;
- return;
- case SILInstructionKind::StrongReleaseInst:
- case SILInstructionKind::ReleaseValueInst:
- case SILInstructionKind::UnownedReleaseInst:
- FInfo->FE.getEffectsOn(I->getOperand(0))->Releases = true;
- return;
- case SILInstructionKind::UnconditionalCheckedCastInst:
- FInfo->FE.getEffectsOn(cast<UnconditionalCheckedCastInst>(I)->getOperand())->Reads = true;
- FInfo->FE.Traps = true;
- return;
- case SILInstructionKind::LoadInst:
- FInfo->FE.getEffectsOn(cast<LoadInst>(I)->getOperand())->Reads = true;
- return;
- case SILInstructionKind::StoreInst:
- FInfo->FE.getEffectsOn(cast<StoreInst>(I)->getDest())->Writes = true;
- return;
- case SILInstructionKind::CondFailInst:
- FInfo->FE.Traps = true;
- return;
- case SILInstructionKind::PartialApplyInst: {
- FInfo->FE.AllocsObjects = true;
- auto *PAI = cast<PartialApplyInst>(I);
- auto Args = PAI->getArguments();
- auto Params = PAI->getSubstCalleeType()->getParameters();
- Params = Params.slice(Params.size() - Args.size(), Args.size());
- for (unsigned Idx : indices(Args)) {
- if (isIndirectFormalParameter(Params[Idx].getConvention()))
- FInfo->FE.getEffectsOn(Args[Idx])->Reads = true;
- }
- return;
+ case SILInstructionKind::FixLifetimeInst:
+ // A fix_lifetime instruction acts like a read on the operand. Retains can
+ // move after it but the last release can't move before it.
+ getEffectsOn(I->getOperand(0))->Reads = true;
+ return;
+ case SILInstructionKind::AllocStackInst:
+ case SILInstructionKind::DeallocStackInst:
+ return;
+ case SILInstructionKind::StrongRetainInst:
+ case SILInstructionKind::StrongRetainUnownedInst:
+ case SILInstructionKind::RetainValueInst:
+ case SILInstructionKind::UnownedRetainInst:
+ getEffectsOn(I->getOperand(0))->Retains = true;
+ return;
+ case SILInstructionKind::StrongReleaseInst:
+ case SILInstructionKind::ReleaseValueInst:
+ case SILInstructionKind::UnownedReleaseInst:
+ getEffectsOn(I->getOperand(0))->Releases = true;
+ return;
+ case SILInstructionKind::UnconditionalCheckedCastInst:
+ getEffectsOn(cast<UnconditionalCheckedCastInst>(I)->getOperand())->Reads =
+ true;
+ Traps = true;
+ return;
+ case SILInstructionKind::LoadInst:
+ getEffectsOn(cast<LoadInst>(I)->getOperand())->Reads = true;
+ return;
+ case SILInstructionKind::StoreInst:
+ getEffectsOn(cast<StoreInst>(I)->getDest())->Writes = true;
+ return;
+ case SILInstructionKind::CondFailInst:
+ Traps = true;
+ return;
+ case SILInstructionKind::PartialApplyInst: {
+ AllocsObjects = true;
+ auto *PAI = cast<PartialApplyInst>(I);
+ auto Args = PAI->getArguments();
+ auto Params = PAI->getSubstCalleeType()->getParameters();
+ Params = Params.slice(Params.size() - Args.size(), Args.size());
+ for (unsigned Idx : indices(Args)) {
+ if (isIndirectFormalParameter(Params[Idx].getConvention()))
+ getEffectsOn(Args[Idx])->Reads = true;
}
- case SILInstructionKind::BuiltinInst: {
- auto *BInst = cast<BuiltinInst>(I);
- auto &BI = BInst->getBuiltinInfo();
- switch (BI.ID) {
- case BuiltinValueKind::IsUnique:
- // TODO: derive this information in a more general way, e.g. add it
- // to Builtins.def
- FInfo->FE.ReadsRC = true;
- break;
- case BuiltinValueKind::CondUnreachable:
- FInfo->FE.Traps = true;
- return;
- default:
- break;
- }
- const IntrinsicInfo &IInfo = BInst->getIntrinsicInfo();
- if (IInfo.ID == llvm::Intrinsic::trap) {
- FInfo->FE.Traps = true;
- return;
- }
- // Detailed memory effects of builtins are handled below by checking the
- // memory behavior of the instruction.
+ return;
+ }
+ case SILInstructionKind::BuiltinInst: {
+ auto *BInst = cast<BuiltinInst>(I);
+ auto &BI = BInst->getBuiltinInfo();
+ switch (BI.ID) {
+ case BuiltinValueKind::IsUnique:
+ // TODO: derive this information in a more general way, e.g. add it
+ // to Builtins.def
+ ReadsRC = true;
break;
- }
+ case BuiltinValueKind::CondUnreachable:
+ Traps = true;
+ return;
default:
break;
+ }
+ const IntrinsicInfo &IInfo = BInst->getIntrinsicInfo();
+ if (IInfo.ID == llvm::Intrinsic::trap) {
+ Traps = true;
+ return;
+ }
+ // Detailed memory effects of builtins are handled below by checking the
+ // memory behavior of the instruction.
+ break;
+ }
+ default:
+ break;
}
if (isa<AllocationInst>(I)) {
// Excluding AllocStackInst (which is handled above).
- FInfo->FE.AllocsObjects = true;
+ AllocsObjects = true;
}
// Check the general memory behavior for instructions we didn't handle above.
switch (I->getMemoryBehavior()) {
- case MemoryBehavior::None:
- break;
- case MemoryBehavior::MayRead:
- FInfo->FE.GlobalEffects.Reads = true;
- break;
- case MemoryBehavior::MayWrite:
- FInfo->FE.GlobalEffects.Writes = true;
- break;
- case MemoryBehavior::MayReadWrite:
- FInfo->FE.GlobalEffects.Reads = true;
- FInfo->FE.GlobalEffects.Writes = true;
- break;
- case MemoryBehavior::MayHaveSideEffects:
- FInfo->FE.setWorstEffects();
- break;
+ case MemoryBehavior::None:
+ break;
+ case MemoryBehavior::MayRead:
+ GlobalEffects.Reads = true;
+ break;
+ case MemoryBehavior::MayWrite:
+ GlobalEffects.Writes = true;
+ break;
+ case MemoryBehavior::MayReadWrite:
+ GlobalEffects.Reads = true;
+ GlobalEffects.Writes = true;
+ break;
+ case MemoryBehavior::MayHaveSideEffects:
+ setWorstEffects();
+ break;
}
if (I->mayTrap())
- FInfo->FE.Traps = true;
-}
-
-void SideEffectAnalysis::initialize(SILPassManager *PM) {
- BCA = PM->getAnalysis<BasicCalleeAnalysis>();
-}
-
-void SideEffectAnalysis::recompute(FunctionInfo *Initial) {
- allocNewUpdateID();
-
- DEBUG(llvm::dbgs() << "recompute side-effect analysis with UpdateID " <<
- getCurrentUpdateID() << '\n');
-
- // Collect and analyze all functions to recompute, starting at Initial.
- FunctionOrder BottomUpOrder(getCurrentUpdateID());
- analyzeFunction(Initial, BottomUpOrder, 0);
-
- // Build the bottom-up order.
- BottomUpOrder.tryToSchedule(Initial);
- BottomUpOrder.finishScheduling();
-
- // Second step: propagate the side-effect information up the call-graph until
- // it stabilizes.
- bool NeedAnotherIteration;
- do {
- DEBUG(llvm::dbgs() << "new iteration\n");
- NeedAnotherIteration = false;
-
- for (FunctionInfo *FInfo : BottomUpOrder) {
- if (FInfo->NeedUpdateCallers) {
- DEBUG(llvm::dbgs() << " update callers of " << FInfo->F->getName() <<
- '\n');
- FInfo->NeedUpdateCallers = false;
-
- // Propagate the side-effects to all callers.
- for (const auto &E : FInfo->getCallers()) {
- assert(E.isValid());
-
- // Only include callers which we are actually recomputing.
- if (BottomUpOrder.wasRecomputedWithCurrentUpdateID(E.Caller)) {
- DEBUG(llvm::dbgs() << " merge into caller " <<
- E.Caller->F->getName() << '\n');
-
- if (E.Caller->FE.mergeFromApply(FInfo->FE, E.FAS)) {
- E.Caller->NeedUpdateCallers = true;
- if (!E.Caller->isScheduledAfter(FInfo)) {
- // This happens if we have a cycle in the call-graph.
- NeedAnotherIteration = true;
- }
- }
- }
- }
- }
- }
- } while (NeedAnotherIteration);
-}
-
-void SideEffectAnalysis::getEffects(FunctionEffects &ApplyEffects, FullApplySite FAS) {
- assert(ApplyEffects.ParamEffects.empty() &&
- "Not using a new ApplyEffects?");
- ApplyEffects.ParamEffects.resize(FAS.getNumArguments());
-
- // Is this a call to a semantics function?
- if (auto apply = dyn_cast<ApplyInst>(FAS.getInstruction())) {
- ArraySemanticsCall ASC(apply);
- if (ASC && ASC.hasSelf()) {
- if (getSemanticEffects(ApplyEffects, ASC))
- return;
- }
- }
-
- if (SILFunction *SingleCallee = FAS.getReferencedFunction()) {
- // Does the function have any @effects?
- if (getDefinedEffects(ApplyEffects, SingleCallee))
- return;
- }
-
- auto Callees = BCA->getCalleeList(FAS);
- if (!Callees.allCalleesVisible() ||
- // @callee_owned function calls implicitly release the context, which
- // may call deinits of boxed values.
- // TODO: be less conservative about what destructors might be called.
- FAS.getOrigCalleeType()->isCalleeConsumed()) {
- ApplyEffects.setWorstEffects();
- return;
- }
-
- // We can see all the callees. So we just merge the effects from all of
- // them.
- for (auto *Callee : Callees) {
- const FunctionEffects &CalleeFE = getEffects(Callee);
- ApplyEffects.mergeFrom(CalleeFE);
- }
-}
-
-void SideEffectAnalysis::invalidate() {
- Function2Info.clear();
- Allocator.DestroyAll();
- DEBUG(llvm::dbgs() << "invalidate all\n");
-}
-
-void SideEffectAnalysis::invalidate(SILFunction *F, InvalidationKind K) {
- if (FunctionInfo *FInfo = Function2Info.lookup(F)) {
- DEBUG(llvm::dbgs() << " invalidate " << FInfo->F->getName() << '\n');
- invalidateIncludingAllCallers(FInfo);
- }
+ Traps = true;
}
SILAnalysis *swift::createSideEffectAnalysis(SILModule *M) {
diff --git a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
index 6beb3d7..2614281 100644
--- a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
+++ b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
@@ -663,7 +663,7 @@
auto *Cvt = cast<ConvertEscapeToNoEscapeInst>(calleeValue);
calleeValue = cloneCalleeConversion(Cvt->getOperand(), NewClosure, Builder);
return Builder.createConvertEscapeToNoEscape(
- CallSiteDesc.getLoc(), calleeValue, Cvt->getType(), true);
+ CallSiteDesc.getLoc(), calleeValue, Cvt->getType(), false, true);
}
/// \brief Populate the body of the cloned closure, modifying instructions as
diff --git a/lib/SILOptimizer/LoopTransforms/LICM.cpp b/lib/SILOptimizer/LoopTransforms/LICM.cpp
index 00ad534..e0ec846 100644
--- a/lib/SILOptimizer/LoopTransforms/LICM.cpp
+++ b/lib/SILOptimizer/LoopTransforms/LICM.cpp
@@ -59,8 +59,8 @@
/// alias with any memory which is read by \p AI.
static bool mayWriteTo(AliasAnalysis *AA, SideEffectAnalysis *SEA,
WriteSet &MayWrites, ApplyInst *AI) {
- SideEffectAnalysis::FunctionEffects E;
- SEA->getEffects(E, AI);
+ FunctionSideEffects E;
+ SEA->getCalleeEffects(E, AI);
assert(E.getMemBehavior(RetainObserveKind::IgnoreRetains) <=
SILInstruction::MemoryBehavior::MayRead &&
"apply should only read from memory");
@@ -495,8 +495,8 @@
if (auto *AI = dyn_cast<ApplyInst>(&Inst)) {
// In contrast to load instructions, we first collect all read-only
// function calls and add them later to SafeReads.
- SideEffectAnalysis::FunctionEffects E;
- SEA->getEffects(E, AI);
+ FunctionSideEffects E;
+ SEA->getCalleeEffects(E, AI);
auto MB = E.getMemBehavior(RetainObserveKind::ObserveRetains);
if (MB <= SILInstruction::MemoryBehavior::MayRead)
diff --git a/lib/SILOptimizer/Mandatory/CMakeLists.txt b/lib/SILOptimizer/Mandatory/CMakeLists.txt
index 6eeef3a..b4c29d5 100644
--- a/lib/SILOptimizer/Mandatory/CMakeLists.txt
+++ b/lib/SILOptimizer/Mandatory/CMakeLists.txt
@@ -2,6 +2,7 @@
Mandatory/AccessEnforcementSelection.cpp
Mandatory/AccessMarkerElimination.cpp
Mandatory/AddressLowering.cpp
+ Mandatory/ConstantPropagation.cpp
Mandatory/DefiniteInitialization.cpp
Mandatory/DIMemoryUseCollector.cpp
Mandatory/DIMemoryUseCollectorOwnership.cpp
@@ -10,8 +11,9 @@
Mandatory/DiagnoseStaticExclusivity.cpp
Mandatory/DiagnoseUnreachable.cpp
Mandatory/GuaranteedARCOpts.cpp
+ Mandatory/IRGenPrepare.cpp
Mandatory/MandatoryInlining.cpp
Mandatory/PredictableMemOpt.cpp
- Mandatory/ConstantPropagation.cpp
Mandatory/SemanticARCOpts.cpp
+ Mandatory/ClosureLifetimeFixup.cpp
PARENT_SCOPE)
diff --git a/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp b/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp
new file mode 100644
index 0000000..8493ac7
--- /dev/null
+++ b/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp
@@ -0,0 +1,374 @@
+//===--- ClosureLifetimeFixup.cpp - Fixup the lifetime of closures --------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "closure-lifetime-fixup"
+
+#include "swift/SIL/DebugUtils.h"
+#include "swift/SIL/InstructionUtils.h"
+#include "swift/SIL/SILArgument.h"
+#include "swift/SIL/SILBuilder.h"
+#include "swift/SIL/SILInstruction.h"
+#include "swift/SILOptimizer/PassManager/Passes.h"
+#include "swift/SILOptimizer/PassManager/Transforms.h"
+#include "swift/SILOptimizer/Utils/CFG.h"
+#include "swift/SILOptimizer/Utils/Local.h"
+
+#include "llvm/Support/CommandLine.h"
+
+llvm::cl::opt<bool> DisableConvertEscapeToNoEscapeSwitchEnumPeephole(
+ "sil-disable-convert-escape-to-noescape-switch-peephole",
+ llvm::cl::init(false),
+ llvm::cl::desc(
+ "Disable the convert_escape_to_noescape switch enum peephole. "),
+ llvm::cl::Hidden);
+
+using namespace swift;
+
+static SILBasicBlock *getOptionalDiamondSuccessor(SwitchEnumInst *SEI) {
+ auto numSuccs = SEI->getNumSuccessors();
+ if (numSuccs != 2)
+ return nullptr;
+ auto *SuccSome = SEI->getCase(0).second;
+ auto *SuccNone = SEI->getCase(1).second;
+ if (SuccSome->args_size() != 1)
+ std::swap(SuccSome, SuccNone);
+
+ if (SuccSome->args_size() != 1 || SuccNone->args_size() != 0)
+ return nullptr;
+
+ auto *Succ = SuccSome->getSingleSuccessorBlock();
+ if (!Succ)
+ return nullptr;
+
+ if (SuccNone == Succ)
+ return Succ;
+
+ SuccNone = SuccNone->getSingleSuccessorBlock();
+ if (SuccNone == Succ)
+ return Succ;
+
+ SuccNone = SuccNone->getSingleSuccessorBlock();
+ if (SuccNone == Succ)
+ return Succ;
+
+ return nullptr;
+}
+
+/// Extend the lifetime of the convert_escape_to_noescape's operand to the end
+/// of the function.
+static void extendLifetimeToEndOfFunction(SILFunction &Fn,
+ ConvertEscapeToNoEscapeInst *Cvt) {
+ auto EscapingClosure = Cvt->getOperand();
+ auto EscapingClosureTy = EscapingClosure->getType();
+ auto OptionalEscapingClosureTy = SILType::getOptionalType(EscapingClosureTy);
+ auto loc = RegularLocation::getAutoGeneratedLocation();
+
+ SILBuilderWithScope B(Cvt);
+ auto NewCvt = B.createConvertEscapeToNoEscape(
+ Cvt->getLoc(), Cvt->getOperand(), Cvt->getType(), false, true);
+ Cvt->replaceAllUsesWith(NewCvt);
+ Cvt->eraseFromParent();
+ Cvt = NewCvt;
+
+ // Create an alloc_stack Optional<() -> ()> at the beginning of the function.
+ AllocStackInst *Slot;
+ auto &Context = Cvt->getModule().getASTContext();
+ {
+ SILBuilderWithScope B(Fn.getEntryBlock()->begin());
+ Slot = B.createAllocStack(loc, OptionalEscapingClosureTy);
+ auto *NoneDecl = Context.getOptionalNoneDecl();
+ // Store None to it.
+ B.createStore(
+ loc, B.createEnum(loc, SILValue(), NoneDecl, OptionalEscapingClosureTy),
+ Slot, StoreOwnershipQualifier::Init);
+ }
+ // Insert a copy before the convert_escape_to_noescape and store it to the
+ // alloc_stack location.
+ {
+ SILBuilderWithScope B(Cvt);
+ auto *SomeDecl = Context.getOptionalSomeDecl();
+ B.createDestroyAddr(loc, Slot);
+ auto ClosureCopy = B.createCopyValue(loc, EscapingClosure);
+ B.createStore(
+ loc,
+ B.createEnum(loc, ClosureCopy, SomeDecl, OptionalEscapingClosureTy),
+ Slot, StoreOwnershipQualifier::Init);
+ }
+ // Insert destroys at the function exits.
+ SmallVector<SILBasicBlock *, 4> ExitingBlocks;
+ Fn.findExitingBlocks(ExitingBlocks);
+ for (auto *Exit : ExitingBlocks) {
+ auto *Term = Exit->getTerminator();
+ SILBuilderWithScope B(Term);
+ B.setInsertionPoint(Term);
+ B.createDestroyAddr(loc, Slot);
+ B.createDeallocStack(loc, Slot);
+ }
+}
+
+static SILInstruction *lookThroughRebastractionUsers(
+ SILInstruction *Inst,
+ llvm::DenseMap<SILInstruction *, SILInstruction *> &Memoized) {
+
+ if (Inst == nullptr)
+ return nullptr;
+
+ // Try a cached lookup.
+ auto Res = Memoized.find(Inst);
+ if (Res != Memoized.end())
+ return Res->second;
+
+ // Cache recursive results.
+ auto memoizeResult = [&] (SILInstruction *from, SILInstruction *toResult) {
+ Memoized[from] = toResult;
+ return toResult;
+ };
+
+ // If we have a convert_function, just look at its user.
+ if (auto *Cvt = dyn_cast<ConvertFunctionInst>(Inst))
+ return memoizeResult(Inst, lookThroughRebastractionUsers(
+ getSingleNonDebugUser(Cvt), Memoized));
+ if (auto *Cvt = dyn_cast<ConvertEscapeToNoEscapeInst>(Inst))
+ return memoizeResult(Inst, lookThroughRebastractionUsers(
+ getSingleNonDebugUser(Cvt), Memoized));
+
+ // If we have a partial_apply user look at its single (non release) user.
+ auto *PA = dyn_cast<PartialApplyInst>(Inst);
+ if (!PA) return Inst;
+
+ SILInstruction *SingleNonDebugNonRefCountUser = nullptr;
+ for (auto *Usr : getNonDebugUses(PA)) {
+ auto *I = Usr->getUser();
+ if (onlyAffectsRefCount(I))
+ continue;
+ if (SingleNonDebugNonRefCountUser) {
+ SingleNonDebugNonRefCountUser = nullptr;
+ break;
+ }
+ SingleNonDebugNonRefCountUser = I;
+ }
+
+ return memoizeResult(Inst, lookThroughRebastractionUsers(
+ SingleNonDebugNonRefCountUser, Memoized));
+}
+
+static bool tryExtendLifetimeToLastUse(
+ ConvertEscapeToNoEscapeInst *Cvt,
+ llvm::DenseMap<SILInstruction *, SILInstruction *> &Memoized) {
+ // Don't optimize converts that might have been escaped by the function call
+ // (materializeForSet 'escapes' its arguments into the writeback buffer).
+ if (Cvt->isEscapedByUser())
+ return false;
+
+ // If there is a single user that is an apply this is simple: extend the
+ // lifetime of the operand until after the apply.
+ auto SingleUser = lookThroughRebastractionUsers(Cvt, Memoized);
+ if (!SingleUser)
+ return false;
+
+ // Handle an apply.
+ if (auto SingleApplyUser = FullApplySite::isa(SingleUser)) {
+ // FIXME: Don't know how-to handle begin_apply/end_apply yet.
+ if (auto *Begin =
+ dyn_cast<BeginApplyInst>(SingleApplyUser.getInstruction())) {
+ return false;
+ }
+
+ auto loc = RegularLocation::getAutoGeneratedLocation();
+
+ // Insert a copy at the convert_escape_to_noescape [not_guaranteed] and
+ // change the instruction to the guaranteed form.
+ auto EscapingClosure = Cvt->getOperand();
+ {
+ SILBuilderWithScope B(Cvt);
+ auto NewCvt = B.createConvertEscapeToNoEscape(
+ Cvt->getLoc(), Cvt->getOperand(), Cvt->getType(), false, true);
+ Cvt->replaceAllUsesWith(NewCvt);
+ Cvt->eraseFromParent();
+ Cvt = NewCvt;
+ }
+
+ SILBuilderWithScope B2(Cvt);
+ auto ClosureCopy = B2.createCopyValue(loc, EscapingClosure);
+
+ // Insert a destroy after the apply.
+ if (auto *Apply = dyn_cast<ApplyInst>(SingleApplyUser.getInstruction())) {
+ auto InsertPt = std::next(SILBasicBlock::iterator(Apply));
+ SILBuilderWithScope B3(InsertPt);
+ B3.createDestroyValue(loc, ClosureCopy);
+
+ } else if (auto *Try =
+ dyn_cast<TryApplyInst>(SingleApplyUser.getInstruction())) {
+ for (auto *SuccBB : Try->getSuccessorBlocks()) {
+ SILBuilderWithScope B3(SuccBB->begin());
+ B3.createDestroyValue(loc, ClosureCopy);
+ }
+ } else {
+ llvm_unreachable("Unknown FullApplySite instruction kind");
+ }
+ return true;
+ }
+ return false;
+}
+
+/// Ensure the lifetime of the closure accross an
+///
+/// optional<@escaping () -> ()> to
+/// optional<@noescape @convention(block) () -> ()>
+///
+/// conversion and its use.
+///
+/// The pattern this is looking for
+/// switch_enum %closure
+/// / \
+/// convert_escape_to_noescape nil
+/// switch_enum
+/// / \
+/// convertToBlock nil
+/// \ /
+/// (%convertOptionalBlock :)
+/// We will insert a copy_value of the original %closure before the two
+/// diamonds. And a destroy of %closure at the last destroy of
+/// %convertOptionalBlock.
+static bool trySwitchEnumPeephole(ConvertEscapeToNoEscapeInst *Cvt) {
+ // Don't optimize converts that might have been escaped by the function call
+ // (materializeForSet 'escapes' its arguments into the writeback buffer).
+ if (Cvt->isEscapedByUser())
+ return false;
+
+ auto *blockArg = dyn_cast<SILArgument>(Cvt->getOperand());
+ if (!blockArg)
+ return false;
+ auto *PredBB = Cvt->getParent()->getSinglePredecessorBlock();
+ if (!PredBB)
+ return false;
+ auto *ConvertSuccessorBlock = Cvt->getParent()->getSingleSuccessorBlock();
+ if (!ConvertSuccessorBlock)
+ return false;
+ auto *SwitchEnum1 = dyn_cast<SwitchEnumInst>(PredBB->getTerminator());
+ if (!SwitchEnum1)
+ return false;
+ auto *DiamondSucc = getOptionalDiamondSuccessor(SwitchEnum1);
+ if (!DiamondSucc)
+ return false;
+ auto *SwitchEnum2 = dyn_cast<SwitchEnumInst>(DiamondSucc->getTerminator());
+ if (!SwitchEnum2)
+ return false;
+ auto *DiamondSucc2 = getOptionalDiamondSuccessor(SwitchEnum2);
+ if (!DiamondSucc2)
+ return false;
+ if (DiamondSucc2->getNumArguments() != 1)
+ return false;
+
+ // Look for the last and only destroy.
+ SILInstruction *onlyDestroy = [&]() -> SILInstruction * {
+ SILInstruction *lastDestroy = nullptr;
+ for (auto *Use : DiamondSucc2->getArgument(0)->getUses()) {
+ SILInstruction *Usr = Use->getUser();
+ if (isa<ReleaseValueInst>(Usr) || isa<StrongReleaseInst>(Usr) ||
+ isa<DestroyValueInst>(Usr)) {
+ if (lastDestroy)
+ return nullptr;
+ lastDestroy = Usr;
+ }
+ }
+ return lastDestroy;
+ }();
+ if (!onlyDestroy)
+ return false;
+
+ // Replace the convert_escape_to_noescape instruction.
+ {
+ SILBuilderWithScope B(Cvt);
+ auto NewCvt = B.createConvertEscapeToNoEscape(
+ Cvt->getLoc(), Cvt->getOperand(), Cvt->getType(), false, true);
+ Cvt->replaceAllUsesWith(NewCvt);
+ Cvt->eraseFromParent();
+ Cvt = NewCvt;
+ }
+
+ // Extend the lifetime.
+ SILBuilderWithScope B(SwitchEnum1);
+ auto loc = RegularLocation::getAutoGeneratedLocation();
+ auto copy =
+ B.createCopyValue(loc, SwitchEnum1->getOperand());
+ B.setInsertionPoint(onlyDestroy);
+ B.createDestroyValue(loc, copy);
+ return true;
+}
+
+static bool fixupConvertEscapeToNoEscapeLifetime(SILFunction &Fn) {
+ bool Changed = false;
+
+ // tryExtendLifetimeToLastUse uses a cache of recursive instruction use
+ // queries.
+ llvm::DenseMap<SILInstruction *, SILInstruction *> MemoizedQueries;
+
+ for (auto &BB : Fn) {
+ auto I = BB.begin();
+ while (I != BB.end()) {
+ SILInstruction *Inst = &*I;
+ ++I;
+ auto *Cvt = dyn_cast<ConvertEscapeToNoEscapeInst>(Inst);
+ if (!Cvt || Cvt->isLifetimeGuaranteed())
+ continue;
+
+ // First try to peephole a known pattern.
+ if (!DisableConvertEscapeToNoEscapeSwitchEnumPeephole &&
+ trySwitchEnumPeephole(Cvt)) {
+ Changed |= true;
+ continue;
+ }
+
+ if (tryExtendLifetimeToLastUse(Cvt, MemoizedQueries)) {
+ Changed |= true;
+ continue;
+ }
+
+ // Otherwise, extend the lifetime of the operand to the end of the
+ // function.
+ extendLifetimeToEndOfFunction(Fn, Cvt);
+ Changed |= true;
+ }
+ }
+ return Changed;
+}
+
+/// Fix-up the lifetime of the escaping closure argument of
+/// convert_escape_to_noescape [not_guaranteed] instructions.
+///
+/// convert_escape_to_noescape [not_guaranteed] assume that someone guarantees
+/// the lifetime of the operand for the duration of the trivial closure result.
+/// SILGen does not guarantee this for '[not_guaranteed]' instructions so we
+/// ensure it here.
+namespace {
+class ClosureLifetimeFixup : public SILFunctionTransform {
+
+ /// The entry point to the transformation.
+ void run() override {
+ // Don't rerun diagnostics on deserialized functions.
+ if (getFunction()->wasDeserializedCanonical())
+ return;
+
+ // Fixup lifetimes of optional convertEscapeToNoEscape.
+ if (fixupConvertEscapeToNoEscapeLifetime(*getFunction()))
+ invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
+ DEBUG(getFunction()->verify());
+
+ }
+
+};
+} // end anonymous namespace
+
+SILTransform *swift::createClosureLifetimeFixup() {
+ return new ClosureLifetimeFixup();
+}
diff --git a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
index bc5b5a4..3d3a29e 100644
--- a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
+++ b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
@@ -2952,210 +2952,6 @@
return Changed;
}
-static SILBasicBlock *getOptionalDiamondSuccessor(SwitchEnumInst *SEI) {
- auto numSuccs = SEI->getNumSuccessors();
- if (numSuccs != 2)
- return nullptr;
- auto *SuccSome = SEI->getCase(0).second;
- auto *SuccNone = SEI->getCase(1).second;
- if (SuccSome->args_size() != 1)
- std::swap(SuccSome, SuccNone);
-
- if (SuccSome->args_size() != 1 || SuccNone->args_size() != 0)
- return nullptr;
-
- auto *Succ = SuccSome->getSingleSuccessorBlock();
- if (!Succ)
- return nullptr;
-
- if (SuccNone == Succ)
- return Succ;
-
- SuccNone = SuccNone->getSingleSuccessorBlock();
- if (SuccNone == Succ)
- return Succ;
-
- SuccNone = SuccNone->getSingleSuccessorBlock();
- if (SuccNone == Succ)
- return Succ;
-
- return nullptr;
-}
-
-/// Extend the lifetime of the convert_escape_to_noescape's operand to the end
-/// of the function.
-void extendLifetimeToEndOfFunction(SILFunction &Fn,
- ConvertEscapeToNoEscapeInst *Cvt) {
- auto EscapingClosure = Cvt->getOperand();
- auto EscapingClosureTy = EscapingClosure->getType();
- auto OptionalEscapingClosureTy = SILType::getOptionalType(EscapingClosureTy);
- auto loc = RegularLocation::getAutoGeneratedLocation();
-
- SILBuilderWithScope B(Cvt);
- auto NewCvt = B.createConvertEscapeToNoEscape(
- Cvt->getLoc(), Cvt->getOperand(), Cvt->getType(), true);
- Cvt->replaceAllUsesWith(NewCvt);
- Cvt->eraseFromParent();
- Cvt = NewCvt;
-
- // Create an alloc_stack Optional<() -> ()> at the beginning of the function.
- AllocStackInst *Slot;
- auto &Context = Cvt->getModule().getASTContext();
- {
- SILBuilderWithScope B(Fn.getEntryBlock()->begin());
- Slot = B.createAllocStack(loc, OptionalEscapingClosureTy);
- auto *NoneDecl = Context.getOptionalNoneDecl();
- // Store None to it.
- B.createStore(
- loc, B.createEnum(loc, SILValue(), NoneDecl, OptionalEscapingClosureTy),
- Slot, StoreOwnershipQualifier::Init);
- }
- // Insert a copy before the convert_escape_to_noescape and store it to the
- // alloc_stack location.
- {
- SILBuilderWithScope B(Cvt);
- auto *SomeDecl = Context.getOptionalSomeDecl();
- B.createDestroyAddr(loc, Slot);
- auto ClosureCopy = B.createCopyValue(loc, EscapingClosure);
- B.createStore(
- loc,
- B.createEnum(loc, ClosureCopy, SomeDecl, OptionalEscapingClosureTy),
- Slot, StoreOwnershipQualifier::Init);
- }
- // Insert destroys at the function exits.
- SmallVector<SILBasicBlock *, 4> ExitingBlocks;
- Fn.findExitingBlocks(ExitingBlocks);
- for (auto *Exit : ExitingBlocks) {
- auto *Term = Exit->getTerminator();
- SILBuilderWithScope B(Term);
- B.setInsertionPoint(Term);
- B.createDestroyAddr(loc, Slot);
- B.createDeallocStack(loc, Slot);
- }
-}
-
-/// Ensure the lifetime of the closure accross an
-///
-/// optional<@escaping () -> ()> to
-/// optional<@noescape @convention(block) () -> ()>
-///
-/// conversion and its use.
-///
-/// The pattern this is looking for
-/// switch_enum %closure
-/// / \
-/// convert_escape_to_noescape nil
-/// switch_enum
-/// / \
-/// convertToBlock nil
-/// \ /
-/// (%convertOptionalBlock :)
-/// We will insert a copy_value of the original %closure before the two
-/// diamonds. And a destroy of %closure at the last destroy of
-/// %convertOptionalBlock.
-static bool trySwitchEnumPeephole(ConvertEscapeToNoEscapeInst *Cvt) {
- auto *blockArg = dyn_cast<SILArgument>(Cvt->getOperand());
- if (!blockArg)
- return false;
- auto *PredBB = Cvt->getParent()->getSinglePredecessorBlock();
- if (!PredBB)
- return false;
- auto *ConvertSuccessorBlock = Cvt->getParent()->getSingleSuccessorBlock();
- if (!ConvertSuccessorBlock)
- return false;
- auto *SwitchEnum1 = dyn_cast<SwitchEnumInst>(PredBB->getTerminator());
- if (!SwitchEnum1)
- return false;
- auto *DiamondSucc = getOptionalDiamondSuccessor(SwitchEnum1);
- if (!DiamondSucc)
- return false;
- auto *SwitchEnum2 = dyn_cast<SwitchEnumInst>(DiamondSucc->getTerminator());
- if (!SwitchEnum2)
- return false;
- auto *DiamondSucc2 = getOptionalDiamondSuccessor(SwitchEnum2);
- if (!DiamondSucc2)
- return false;
- if (DiamondSucc2->getNumArguments() != 1)
- return false;
-
- // Look for the last and only destroy.
- SILInstruction *onlyDestroy = [&]() -> SILInstruction * {
- SILInstruction *lastDestroy = nullptr;
- for (auto *Use : DiamondSucc2->getArgument(0)->getUses()) {
- SILInstruction *Usr = Use->getUser();
- if (isa<ReleaseValueInst>(Usr) || isa<StrongReleaseInst>(Usr) ||
- isa<DestroyValueInst>(Usr)) {
- if (lastDestroy)
- return nullptr;
- lastDestroy = Usr;
- }
- }
- return lastDestroy;
- }();
- if (!onlyDestroy)
- return false;
-
- // Replace the convert_escape_to_noescape instruction.
- {
- SILBuilderWithScope B(Cvt);
- auto NewCvt = B.createConvertEscapeToNoEscape(
- Cvt->getLoc(), Cvt->getOperand(), Cvt->getType(), true);
- Cvt->replaceAllUsesWith(NewCvt);
- Cvt->eraseFromParent();
- Cvt = NewCvt;
- }
-
- // Extend the lifetime.
- SILBuilderWithScope B(SwitchEnum1);
- auto loc = RegularLocation::getAutoGeneratedLocation();
- auto copy =
- B.createCopyValue(loc, SwitchEnum1->getOperand());
- B.setInsertionPoint(onlyDestroy);
- B.createDestroyValue(loc, copy);
- return true;
-}
-
-llvm::cl::opt<bool> DIDisableConvertEscapeToNoEscapeSwitchEnumPeephole(
- "sil-di-disable-convert-escape-to-noescape-switch-peephole",
- llvm::cl::init(false),
- llvm::cl::desc(
- "Disable the convert_escape_to_noescape switch enum peephole. "),
- llvm::cl::Hidden);
-
-/// Fix-up the lifetime of the escaping closure argument of
-/// convert_escape_to_noescape [not_guaranteed] instructions.
-///
-/// convert_escape_to_noescape [not_guaranteed] assume that someone guarantees
-/// the lifetime of the operand for the duration of the trivial closure result.
-/// SILGen does not guarantee this for '[not_guaranteed]' instructions so we
-/// ensure it here.
-static bool fixupConvertEscapeToNoEscapeLifetime(SILFunction &Fn) {
- bool Changed = false;
- for (auto &BB : Fn) {
- auto I = BB.begin();
- while (I != BB.end()) {
- SILInstruction *Inst = &*I;
- ++I;
- auto *Cvt = dyn_cast<ConvertEscapeToNoEscapeInst>(Inst);
- if (!Cvt || Cvt->isLifetimeGuaranteed())
- continue;
-
- // First try to peephole a known pattern.
- if (!DIDisableConvertEscapeToNoEscapeSwitchEnumPeephole &&
- trySwitchEnumPeephole(Cvt)) {
- Changed |= true;
- continue;
- }
-
- // Otherwise, extend the lifetime of the operand to the end of the
- // function.
- extendLifetimeToEndOfFunction(Fn, Cvt);
- Changed |= true;
- }
- }
- return Changed;
-}
-
namespace {
/// Perform definitive initialization analysis and promote alloc_box uses into
/// SSA registers for later SSA-based dataflow passes.
@@ -3178,10 +2974,6 @@
if (lowerRawSILOperations(*getFunction()))
invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
- // Fixup lifetimes of optional convertEscapeToNoEscape.
- if (fixupConvertEscapeToNoEscapeLifetime(*getFunction()))
- invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
-
}
};
diff --git a/lib/SILOptimizer/Mandatory/IRGenPrepare.cpp b/lib/SILOptimizer/Mandatory/IRGenPrepare.cpp
new file mode 100644
index 0000000..ee9f4c3
--- /dev/null
+++ b/lib/SILOptimizer/Mandatory/IRGenPrepare.cpp
@@ -0,0 +1,83 @@
+//===--- IRGenPrepare.cpp -------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+///
+/// Cleanup SIL to make it suitable for IRGen.
+///
+/// We perform the following canonicalizations:
+///
+/// 1. We remove calls to Builtin.staticReport(), which are not needed post SIL.
+///
+//===----------------------------------------------------------------------===//
+
+#include "swift/SILOptimizer/PassManager/Passes.h"
+#include "swift/SIL/SILFunction.h"
+#include "swift/SIL/SILInstruction.h"
+#include "swift/SIL/SILModule.h"
+#include "swift/SILOptimizer/Utils/Local.h"
+#include "swift/SILOptimizer/PassManager/Transforms.h"
+
+using namespace swift;
+
+static bool cleanFunction(SILFunction &fn) {
+ bool madeChange = false;
+
+ for (auto &bb : fn) {
+ for (auto i = bb.begin(), e = bb.end(); i != e;) {
+ // Make sure there is no iterator invalidation if the inspected
+ // instruction gets removed from the block.
+ SILInstruction *inst = &*i;
+ ++i;
+
+ // Remove calls to Builtin.staticReport().
+ auto *bi = dyn_cast<BuiltinInst>(inst);
+ if (!bi) {
+ continue;
+ }
+
+ const BuiltinInfo &bInfo = bi->getBuiltinInfo();
+ if (bInfo.ID != BuiltinValueKind::StaticReport) {
+ continue;
+ }
+
+ // The call to the builtin should get removed before we reach
+ // IRGen.
+ recursivelyDeleteTriviallyDeadInstructions(bi, /* Force */ true);
+ madeChange = true;
+ }
+ }
+
+ return madeChange;
+}
+
+//===----------------------------------------------------------------------===//
+// Top Level Entrypoint
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+class IRGenPrepare : public SILFunctionTransform {
+ void run() override {
+ bool shouldInvalidate = cleanFunction(*getFunction());
+ if (!shouldInvalidate)
+ return;
+ invalidateAnalysis(SILAnalysis::InvalidationKind::Instructions);
+ }
+};
+
+} // end anonymous namespace
+
+
+SILTransform *swift::createIRGenPrepare() {
+ return new IRGenPrepare();
+}
diff --git a/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp b/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp
index 0fd434d..6895c54 100644
--- a/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp
+++ b/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp
@@ -259,8 +259,7 @@
static SILFunction *getCalleeFunction(
SILFunction *F, FullApplySite AI, bool &IsThick,
SmallVectorImpl<std::pair<SILValue, ParameterConvention>> &CaptureArgs,
- SmallVectorImpl<SILValue> &FullArgs, PartialApplyInst *&PartialApply,
- SILModule::LinkingMode Mode) {
+ SmallVectorImpl<SILValue> &FullArgs, PartialApplyInst *&PartialApply) {
IsThick = false;
PartialApply = nullptr;
CaptureArgs.clear();
@@ -404,17 +403,19 @@
return nullptr;
}
- // If CalleeFunction is a declaration, see if we can load it. If we fail to
- // load it, bail.
- if (CalleeFunction->empty()
- && !AI.getModule().linkFunction(CalleeFunction, Mode))
- return nullptr;
-
// If the CalleeFunction is a not-transparent definition, we can not process
// it.
if (CalleeFunction->isTransparent() == IsNotTransparent)
return nullptr;
+ // If CalleeFunction is a declaration, see if we can load it.
+ if (CalleeFunction->empty())
+ AI.getModule().loadFunction(CalleeFunction);
+
+ // If we fail to load it, bail.
+ if (CalleeFunction->empty())
+ return nullptr;
+
if (F->isSerialized() &&
!CalleeFunction->hasValidLinkageForFragileInline()) {
if (!CalleeFunction->hasValidLinkageForFragileRef()) {
@@ -462,7 +463,6 @@
/// \returns true if successful, false if failed due to circular inlining.
static bool
runOnFunctionRecursively(SILFunction *F, FullApplySite AI,
- SILModule::LinkingMode Mode,
DenseFunctionSet &FullyInlinedSet,
ImmutableFunctionSet::Factory &SetFactory,
ImmutableFunctionSet CurrentInliningSet,
@@ -510,13 +510,13 @@
bool IsThick;
PartialApplyInst *PAI;
SILFunction *CalleeFunction = getCalleeFunction(
- F, InnerAI, IsThick, CaptureArgs, FullArgs, PAI, Mode);
+ F, InnerAI, IsThick, CaptureArgs, FullArgs, PAI);
if (!CalleeFunction)
continue;
// Then recursively process it first before trying to inline it.
- if (!runOnFunctionRecursively(CalleeFunction, InnerAI, Mode,
+ if (!runOnFunctionRecursively(CalleeFunction, InnerAI,
FullyInlinedSet, SetFactory,
CurrentInliningSet, CHA)) {
// If we failed due to circular inlining, then emit some notes to
@@ -619,25 +619,12 @@
//===----------------------------------------------------------------------===//
namespace {
-/// MandatoryInlining reruns on deserialized functions for two reasons, both
-/// unrelated to mandatory inlining:
-///
-/// 1. It recursively visits the entire call tree rooted at transparent
-/// functions. This has the effect of linking all reachable functions. If they
-/// aren't linked until the explicit SILLinker pass, then they don't benefit
-/// from rerunning optimizations like PredictableMemOps. Ideally we wouldn't
-/// need to rerun PredictableMemOps and wouldn't need to eagerly link anything
-/// in the mandatory pipeline.
-///
-/// 2. It may devirtualize non-transparent methods. It's not clear whether we
-/// really need to devirtualize this early without actually inlining, but it can
-/// unblock other optimizations in the mandatory pipeline.
+
class MandatoryInlining : public SILModuleTransform {
/// The entry point to the transformation.
void run() override {
ClassHierarchyAnalysis *CHA = getAnalysis<ClassHierarchyAnalysis>();
SILModule *M = getModule();
- SILModule::LinkingMode Mode = getOptions().LinkMode;
bool ShouldCleanup = !getOptions().DebugSerialization;
DenseFunctionSet FullyInlinedSet;
ImmutableFunctionSet::Factory SetFactory;
@@ -647,21 +634,15 @@
if (F.isThunk())
continue;
+ // Skip deserialized functions.
+ if (F.wasDeserializedCanonical())
+ continue;
+
runOnFunctionRecursively(&F,
- FullApplySite(static_cast<ApplyInst*>(nullptr)),
- Mode, FullyInlinedSet,
- SetFactory, SetFactory.getEmptySet(), CHA);
+ FullApplySite(), FullyInlinedSet, SetFactory,
+ SetFactory.getEmptySet(), CHA);
}
- // Make sure that we de-serialize all transparent functions,
- // even if we didn't inline them for some reason.
- // Transparent functions are not available externally, so we
- // have to generate code for them.
- for (auto &F : *M) {
- if (F.isTransparent())
- M->linkFunction(&F, Mode);
- }
-
if (!ShouldCleanup)
return;
diff --git a/lib/SILOptimizer/PassManager/PassPipeline.cpp b/lib/SILOptimizer/PassManager/PassPipeline.cpp
index bd46d84..98bcfae 100644
--- a/lib/SILOptimizer/PassManager/PassPipeline.cpp
+++ b/lib/SILOptimizer/PassManager/PassPipeline.cpp
@@ -88,8 +88,10 @@
P.addNoReturnFolding();
P.addMarkUninitializedFixup();
P.addDefiniteInitialization();
+ P.addClosureLifetimeFixup();
P.addOwnershipModelEliminator();
P.addMandatoryInlining();
+ P.addMandatorySILLinker();
P.addPredictableMemoryOptimizations();
// Diagnostic ConstantPropagation must be rerun on deserialized functions
@@ -222,6 +224,10 @@
// Split up operations on stack-allocated aggregates (struct, tuple).
P.addSROA();
+ // Re-run predictable memory optimizations, since previous optimization
+ // passes sometimes expose oppotunities here.
+ P.addPredictableMemoryOptimizations();
+
// Promote stack allocations to values.
P.addMem2Reg();
@@ -314,7 +320,7 @@
static void addPerfDebugSerializationPipeline(SILPassPipelinePlan &P) {
P.startPipeline("Performance Debug Serialization");
- P.addSILLinker();
+ P.addPerformanceSILLinker();
}
static void addPerfEarlyModulePassPipeline(SILPassPipelinePlan &P) {
@@ -324,7 +330,7 @@
// we do not spend time optimizing them.
P.addDeadFunctionElimination();
// Start by cloning functions from stdlib.
- P.addSILLinker();
+ P.addPerformanceSILLinker();
// Cleanup after SILGen: remove trivial copies to temporaries.
P.addTempRValueOpt();
@@ -344,7 +350,7 @@
static void addMidModulePassesStackPromotePassPipeline(SILPassPipelinePlan &P) {
P.startPipeline("MidModulePasses+StackPromote");
P.addDeadFunctionElimination();
- P.addSILLinker();
+ P.addPerformanceSILLinker();
P.addDeadObjectElimination();
P.addGlobalPropertyOpt();
@@ -456,7 +462,7 @@
SILPassPipelinePlan::getLoweringPassPipeline() {
SILPassPipelinePlan P;
P.startPipeline("Address Lowering");
- P.addSILCleanup();
+ P.addIRGenPrepare();
P.addAddressLowering();
return P;
diff --git a/lib/SILOptimizer/Transforms/CMakeLists.txt b/lib/SILOptimizer/Transforms/CMakeLists.txt
index 0f454d8..49d140e 100644
--- a/lib/SILOptimizer/Transforms/CMakeLists.txt
+++ b/lib/SILOptimizer/Transforms/CMakeLists.txt
@@ -23,7 +23,6 @@
Transforms/RedundantOverflowCheckRemoval.cpp
Transforms/ReleaseDevirtualizer.cpp
Transforms/RemovePin.cpp
- Transforms/SILCleanup.cpp
Transforms/SILCodeMotion.cpp
Transforms/SILLowerAggregateInstrs.cpp
Transforms/SILMem2Reg.cpp
diff --git a/lib/SILOptimizer/Transforms/CSE.cpp b/lib/SILOptimizer/Transforms/CSE.cpp
index 4f7c206..85f5a62 100644
--- a/lib/SILOptimizer/Transforms/CSE.cpp
+++ b/lib/SILOptimizer/Transforms/CSE.cpp
@@ -874,8 +874,8 @@
// We can CSE function calls which do not read or write memory and don't
// have any other side effects.
- SideEffectAnalysis::FunctionEffects Effects;
- SEA->getEffects(Effects, AI);
+ FunctionSideEffects Effects;
+ SEA->getCalleeEffects(Effects, AI);
// Note that the function also may not contain any retains. And there are
// functions which are read-none and have a retain, e.g. functions which
diff --git a/lib/SILOptimizer/Transforms/Devirtualizer.cpp b/lib/SILOptimizer/Transforms/Devirtualizer.cpp
index e37210f..2ddd68a 100644
--- a/lib/SILOptimizer/Transforms/Devirtualizer.cpp
+++ b/lib/SILOptimizer/Transforms/Devirtualizer.cpp
@@ -93,11 +93,9 @@
assert(CalleeFn && "Expected devirtualized callee!");
// We need to ensure that we link after devirtualizing in order to pull in
- // everything we reference from another module. This is especially important
- // for transparent functions, because if transparent functions are not
- // inlined for some reason, we need to generate code for them.
- // Note that functions, which are only referenced from witness/vtables, are
- // not linked upfront by the SILLinker.
+ // everything we reference from another module, which may expose optimization
+ // opportunities and is also needed for correctness if we reference functions
+ // with non-public linkage. See lib/SIL/Linker.cpp for details.
if (!CalleeFn->isDefinition())
F.getModule().linkFunction(CalleeFn, SILModule::LinkingMode::LinkAll);
diff --git a/lib/SILOptimizer/Transforms/SILCleanup.cpp b/lib/SILOptimizer/Transforms/SILCleanup.cpp
deleted file mode 100644
index 3fd0d64..0000000
--- a/lib/SILOptimizer/Transforms/SILCleanup.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-//===--- SILCleanup.cpp - Removes diagnostics instructions ----------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-//
-//===----------------------------------------------------------------------===//
-//
-// Cleanup SIL to make it suitable for IRGen. Specifically, removes the calls to
-// Builtin.staticReport(), which are not needed post SIL.
-//
-// FIXME: This pass is mandatory so should probably be in
-// SILOptimizer/Mandatory.
-//
-//===----------------------------------------------------------------------===//
-
-#include "swift/SILOptimizer/PassManager/Passes.h"
-#include "swift/SIL/SILFunction.h"
-#include "swift/SIL/SILInstruction.h"
-#include "swift/SIL/SILModule.h"
-#include "swift/SILOptimizer/Utils/Local.h"
-#include "swift/SILOptimizer/PassManager/Transforms.h"
-
-using namespace swift;
-
-static void cleanFunction(SILFunction &Fn) {
- for (auto &BB : Fn) {
- auto I = BB.begin(), E = BB.end();
- while (I != E) {
- // Make sure there is no iterator invalidation if the inspected
- // instruction gets removed from the block.
- SILInstruction *Inst = &*I;
- ++I;
-
- // Remove calls to Builtin.staticReport().
- if (auto *BI = dyn_cast<BuiltinInst>(Inst)) {
- const BuiltinInfo &B = BI->getBuiltinInfo();
- if (B.ID == BuiltinValueKind::StaticReport) {
- // The call to the builtin should get removed before we reach
- // IRGen.
- recursivelyDeleteTriviallyDeadInstructions(BI, /* Force */true);
- }
- }
- }
- }
-}
-
-namespace {
-class SILCleanup : public swift::SILFunctionTransform {
-
- /// The entry point to the transformation.
- void run() override {
- cleanFunction(*getFunction());
- invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
- }
-
-};
-} // end anonymous namespace
-
-
-SILTransform *swift::createSILCleanup() {
- return new SILCleanup();
-}
diff --git a/lib/SILOptimizer/UtilityPasses/Link.cpp b/lib/SILOptimizer/UtilityPasses/Link.cpp
index 06c094b..bf080a3 100644
--- a/lib/SILOptimizer/UtilityPasses/Link.cpp
+++ b/lib/SILOptimizer/UtilityPasses/Link.cpp
@@ -25,11 +25,15 @@
/// Copies code from the standard library into the user program to enable
/// optimizations.
class SILLinker : public SILModuleTransform {
+ SILModule::LinkingMode LinkMode;
+
+public:
+ explicit SILLinker(SILModule::LinkingMode LinkMode) : LinkMode(LinkMode) {}
void run() override {
SILModule &M = *getModule();
for (auto &Fn : M)
- if (M.linkFunction(&Fn, SILModule::LinkingMode::LinkAll))
+ if (M.linkFunction(&Fn, LinkMode))
invalidateAnalysis(&Fn, SILAnalysis::InvalidationKind::Everything);
}
@@ -37,6 +41,10 @@
} // end anonymous namespace
-SILTransform *swift::createSILLinker() {
- return new SILLinker();
+SILTransform *swift::createMandatorySILLinker() {
+ return new SILLinker(SILModule::LinkingMode::LinkNormal);
+}
+
+SILTransform *swift::createPerformanceSILLinker() {
+ return new SILLinker(SILModule::LinkingMode::LinkAll);
}
diff --git a/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp b/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp
index bf98cea..86c69a3 100644
--- a/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp
+++ b/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp
@@ -852,8 +852,8 @@
// If a call has only constant arguments and the call is pure, i.e. has
// no side effects, then we should always inline it.
// This includes arguments which are objects initialized with constant values.
- SideEffectAnalysis::FunctionEffects ApplyEffects;
- SEA->getEffects(ApplyEffects, AI);
+ FunctionSideEffects ApplyEffects;
+ SEA->getCalleeEffects(ApplyEffects, AI);
auto GE = ApplyEffects.getGlobalEffects();
if (GE.mayRead() || GE.mayWrite() || GE.mayRetain() || GE.mayRelease())
return false;
diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt
index db1ed26..c01fb95 100644
--- a/lib/Sema/CMakeLists.txt
+++ b/lib/Sema/CMakeLists.txt
@@ -27,7 +27,6 @@
DerivedConformances.cpp
ITCDecl.cpp
ITCNameLookup.cpp
- ITCType.cpp
InstrumenterSupport.cpp
IterativeTypeChecker.cpp
MiscDiagnostics.cpp
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index c8ebc30..4da4ffa 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -543,6 +543,25 @@
/// look-through.
Expr *coerceImplicitlyUnwrappedOptionalToValue(Expr *expr, Type objTy);
+ /// Peephole an array upcast.
+ void peepholeArrayUpcast(ArrayExpr *expr, Type toType, bool bridged,
+ Type elementType,
+ ConstraintLocatorBuilder locator);
+
+ /// Peephole a dictionary upcast.
+ void peepholeDictionaryUpcast(DictionaryExpr *expr, Type toType,
+ bool bridged, Type keyType,
+ Type valueType,
+ ConstraintLocatorBuilder locator);
+
+ /// Try to peephole the collection upcast, eliminating the need for
+ /// a separate collection-upcast expression.
+ ///
+ /// \returns true if the peephole operation succeeded, in which case
+ /// \c expr already subsumes the upcast.
+ bool peepholeCollectionUpcast(Expr *expr, Type toType, bool bridged,
+ ConstraintLocatorBuilder locator);
+
/// \brief Build a collection upcast expression.
///
/// \param bridged Whether this is a bridging conversion, meaning that the
@@ -2946,9 +2965,9 @@
expr->getAccessSemantics());
}
- Expr *visitArrayExpr(ArrayExpr *expr) {
- Type openedType = cs.getType(expr);
- Type arrayTy = simplifyType(openedType);
+ /// "Finish" an array expression by filling in the semantic expression.
+ ArrayExpr *finishArrayExpr(ArrayExpr *expr) {
+ Type arrayTy = cs.getType(expr);
auto &tc = cs.getTypeChecker();
ProtocolDecl *arrayProto
@@ -2987,7 +3006,7 @@
first = false;
continue;
- }
+ }
typeElements.push_back(cs.getType(elt));
names.push_back(Identifier());
@@ -2997,13 +3016,13 @@
assert(isa<TupleType>(argType.getPointer()));
Expr *arg =
- TupleExpr::create(tc.Context, SourceLoc(),
- expr->getElements(),
- names,
- { },
- SourceLoc(), /*HasTrailingClosure=*/false,
- /*Implicit=*/true,
- argType);
+ TupleExpr::create(tc.Context, SourceLoc(),
+ expr->getElements(),
+ names,
+ { },
+ SourceLoc(), /*HasTrailingClosure=*/false,
+ /*Implicit=*/true,
+ argType);
cs.cacheExprTypes(arg);
@@ -3018,7 +3037,14 @@
cs.cacheExprTypes(result);
expr->setSemanticExpr(result);
+ return expr;
+ }
+
+ Expr *visitArrayExpr(ArrayExpr *expr) {
+ Type openedType = cs.getType(expr);
+ Type arrayTy = simplifyType(openedType);
cs.setType(expr, arrayTy);
+ if (!finishArrayExpr(expr)) return nullptr;
// If the array element type was defaulted, note that in the expression.
if (solution.DefaultedConstraints.count(cs.getConstraintLocator(expr)))
@@ -3027,11 +3053,11 @@
return expr;
}
- Expr *visitDictionaryExpr(DictionaryExpr *expr) {
- Type openedType = cs.getType(expr);
- Type dictionaryTy = simplifyType(openedType);
- auto &tc = cs.getTypeChecker();
+ /// "Finish" a dictionary expression by filling in the semantic expression.
+ DictionaryExpr *finishDictionaryExpr(DictionaryExpr *expr) {
+ Type dictionaryTy = cs.getType(expr);
+ auto &tc = cs.getTypeChecker();
ProtocolDecl *dictionaryProto
= tc.getProtocol(expr->getLoc(),
KnownProtocolKind::ExpressibleByDictionaryLiteral);
@@ -3068,7 +3094,7 @@
first = false;
continue;
- }
+ }
typeElements.push_back(cs.getType(elt));
names.push_back(Identifier());
@@ -3101,7 +3127,14 @@
cs.cacheExprTypes(result);
expr->setSemanticExpr(result);
+ return expr;
+ }
+
+ Expr *visitDictionaryExpr(DictionaryExpr *expr) {
+ Type openedType = cs.getType(expr);
+ Type dictionaryTy = simplifyType(openedType);
cs.setType(expr, dictionaryTy);
+ if (!finishDictionaryExpr(expr)) return nullptr;
// If the dictionary key or value type was defaulted, note that in the
// expression.
@@ -6201,14 +6234,38 @@
}
}
+/// Build the conversion of an element in a collection upcast.
+static Expr *buildElementConversion(ExprRewriter &rewriter,
+ SourceLoc srcLoc,
+ Type srcType,
+ Type destType,
+ bool bridged,
+ ConstraintLocatorBuilder locator,
+ Expr *element) {
+ auto &cs = rewriter.getConstraintSystem();
+
+ auto &tc = rewriter.getConstraintSystem().getTypeChecker();
+ if (bridged &&
+ tc.typeCheckCheckedCast(srcType, destType,
+ CheckedCastContextKind::None, cs.DC,
+ SourceLoc(), nullptr, SourceRange())
+ != CheckedCastKind::Coercion) {
+ if (auto conversion =
+ rewriter.buildObjCBridgeExpr(element, destType, locator))
+ return conversion;
+ }
+
+ return rewriter.coerceToType(element, destType, locator);
+}
+
static CollectionUpcastConversionExpr::ConversionPair
-buildElementConversion(ExprRewriter &rewriter,
- SourceLoc srcLoc,
- Type srcCollectionType,
- Type destCollectionType,
- bool bridged,
- ConstraintLocatorBuilder locator,
- unsigned typeArgIndex) {
+buildOpaqueElementConversion(ExprRewriter &rewriter,
+ SourceLoc srcLoc,
+ Type srcCollectionType,
+ Type destCollectionType,
+ bool bridged,
+ ConstraintLocatorBuilder locator,
+ unsigned typeArgIndex) {
// We don't need this stuff unless we've got generalized casts.
Type srcType = srcCollectionType->castTo<BoundGenericType>()
->getGenericArgs()[typeArgIndex];
@@ -6220,35 +6277,138 @@
ASTContext &ctx = cs.getASTContext();
auto opaque =
rewriter.cs.cacheType(new (ctx) OpaqueValueExpr(srcLoc, srcType));
- Expr *conversion = nullptr;
- auto &tc = rewriter.getConstraintSystem().getTypeChecker();
- if (bridged &&
- tc.typeCheckCheckedCast(srcType, destType,
- CheckedCastContextKind::None, cs.DC,
- SourceLoc(), nullptr, SourceRange())
- != CheckedCastKind::Coercion) {
- conversion = rewriter.buildObjCBridgeExpr(opaque, destType,
- locator.withPathElement(
- ConstraintLocator::PathElement::getGenericArgument(typeArgIndex)));
- }
-
- if (!conversion) {
- conversion = rewriter.coerceToType(opaque, destType,
- locator.withPathElement(
- ConstraintLocator::PathElement::getGenericArgument(typeArgIndex)));
- }
+ Expr *conversion =
+ buildElementConversion(rewriter, srcLoc, srcType, destType, bridged,
+ locator.withPathElement(
+ ConstraintLocator::PathElement::getGenericArgument(
+ typeArgIndex)),
+ opaque);
return { opaque, conversion };
}
-Expr *ExprRewriter::buildCollectionUpcastExpr(Expr *expr, Type toType,
- bool bridged,
- ConstraintLocatorBuilder locator) {
+void ExprRewriter::peepholeArrayUpcast(ArrayExpr *expr, Type toType,
+ bool bridged, Type elementType,
+ ConstraintLocatorBuilder locator) {
+ // Update the type of the array literal.
+ cs.setType(expr, toType);
+
+ // Convert the elements.
+ ConstraintLocatorBuilder innerLocator =
+ locator.withPathElement(
+ ConstraintLocator::PathElement::getGenericArgument(0));
+ for (auto &element : expr->getElements()) {
+ if (auto newElement = buildElementConversion(*this, expr->getLoc(),
+ cs.getType(element),
+ elementType,
+ bridged, innerLocator,
+ element)) {
+ element = newElement;
+ }
+ }
+
+ (void)finishArrayExpr(expr);
+}
+
+void ExprRewriter::peepholeDictionaryUpcast(DictionaryExpr *expr,
+ Type toType, bool bridged,
+ Type keyType, Type valueType,
+ ConstraintLocatorBuilder locator) {
+ // Update the type of the dictionary literal.
+ cs.setType(expr, toType);
+
+ ConstraintLocatorBuilder keyLocator =
+ locator.withPathElement(
+ ConstraintLocator::PathElement::getGenericArgument(0));
+ ConstraintLocatorBuilder valueLocator =
+ locator.withPathElement(
+ ConstraintLocator::PathElement::getGenericArgument(1));
+
+ // Convert the elements.
+ TupleTypeElt tupleTypeElts[2] = { keyType, valueType };
+ auto tupleType = TupleType::get(tupleTypeElts, cs.getASTContext());
+ for (auto element : expr->getElements()) {
+ if (auto tuple = dyn_cast<TupleExpr>(element)) {
+ auto key = tuple->getElement(0);
+ if (auto newKey = buildElementConversion(*this, expr->getLoc(),
+ cs.getType(key), keyType,
+ bridged, valueLocator, key))
+ tuple->setElement(0, newKey);
+
+ auto value = tuple->getElement(1);
+ if (auto newValue = buildElementConversion(*this, expr->getLoc(),
+ cs.getType(value), valueType,
+ bridged, valueLocator,
+ value)) {
+ tuple->setElement(1, newValue);
+ }
+
+ cs.setType(tuple, tupleType);
+ }
+ }
+
+ (void)finishDictionaryExpr(expr);
+}
+
+bool ExprRewriter::peepholeCollectionUpcast(Expr *expr, Type toType,
+ bool bridged,
+ ConstraintLocatorBuilder locator) {
+ // Recurse into parenthesized expressions.
+ if (auto paren = dyn_cast<ParenExpr>(expr)) {
+ // If we can't peephole the subexpression, we're done.
+ if (!peepholeCollectionUpcast(paren->getSubExpr(), toType, bridged,
+ locator))
+ return false;
+
+ // Update the type of this expression.
+ cs.setType(paren, ParenType::get(cs.getASTContext(),
+ cs.getType(paren->getSubExpr())));
+ return true;
+ }
+
+ // Array literals.
+ if (auto arrayLiteral = dyn_cast<ArrayExpr>(expr)) {
+ if (Optional<Type> elementType = ConstraintSystem::isArrayType(toType)) {
+ peepholeArrayUpcast(arrayLiteral, toType, bridged, *elementType, locator);
+ return true;
+ }
+
+ if (Optional<Type> elementType = ConstraintSystem::isSetType(toType)) {
+ peepholeArrayUpcast(arrayLiteral, toType, bridged, *elementType, locator);
+ return true;
+ }
+
+ return false;
+ }
+
+ // Dictionary literals.
+ if (auto dictLiteral = dyn_cast<DictionaryExpr>(expr)) {
+ if (auto elementType = ConstraintSystem::isDictionaryType(toType)) {
+ peepholeDictionaryUpcast(dictLiteral, toType, bridged,
+ elementType->first, elementType->second,
+ locator);
+ return true;
+ }
+
+ return false;
+ }
+
+ return false;
+}
+
+Expr *ExprRewriter::buildCollectionUpcastExpr(
+ Expr *expr, Type toType,
+ bool bridged,
+ ConstraintLocatorBuilder locator) {
+ if (peepholeCollectionUpcast(expr, toType, bridged, locator))
+ return expr;
+
ASTContext &ctx = cs.getASTContext();
// Build the first value conversion.
- auto conv = buildElementConversion(*this, expr->getLoc(), cs.getType(expr),
- toType, bridged, locator, 0);
+ auto conv =
+ buildOpaqueElementConversion(*this, expr->getLoc(), cs.getType(expr),
+ toType, bridged, locator, 0);
// For single-parameter collections, form the upcast.
if (ConstraintSystem::isArrayType(toType) ||
@@ -6261,8 +6421,9 @@
"Unhandled collection upcast");
// Build the second value conversion.
- auto conv2 = buildElementConversion(*this, expr->getLoc(), cs.getType(expr),
- toType, bridged, locator, 1);
+ auto conv2 =
+ buildOpaqueElementConversion(*this, expr->getLoc(), cs.getType(expr),
+ toType, bridged, locator, 1);
return cs.cacheType(
new (ctx) CollectionUpcastConversionExpr(expr, toType, conv, conv2));
diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp
index 85a0f27..e807468 100644
--- a/lib/Sema/DerivedConformanceCodable.cpp
+++ b/lib/Sema/DerivedConformanceCodable.cpp
@@ -767,7 +767,7 @@
encodeDecl->setInterfaceType(interfaceType);
encodeDecl->setValidationStarted();
- encodeDecl->setAccess(target->getFormalAccess());
+ encodeDecl->copyFormalAccessFrom(target, /*sourceIsParentContext*/true);
tc.Context.addSynthesizedDecl(encodeDecl);
@@ -1106,7 +1106,7 @@
initDecl->setInterfaceType(interfaceType);
initDecl->setValidationStarted();
initDecl->setInitializerInterfaceType(initializerType);
- initDecl->setAccess(target->getFormalAccess());
+ initDecl->copyFormalAccessFrom(target, /*sourceIsParentContext*/true);
tc.Context.addSynthesizedDecl(initDecl);
diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp
index 9e6db9f..cbba981 100644
--- a/lib/Sema/DerivedConformanceEquatableHashable.cpp
+++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp
@@ -655,7 +655,7 @@
FunctionType::ExtInfo());
}
eqDecl->setInterfaceType(interfaceTy);
- eqDecl->copyFormalAccessFrom(typeDecl);
+ eqDecl->copyFormalAccessFrom(typeDecl, /*sourceIsParentContext*/true);
eqDecl->setValidationStarted();
tc.Context.addSynthesizedDecl(eqDecl);
@@ -1044,7 +1044,7 @@
getterDecl->setInterfaceType(interfaceType);
getterDecl->setValidationStarted();
- getterDecl->copyFormalAccessFrom(typeDecl);
+ getterDecl->copyFormalAccessFrom(typeDecl, /*sourceIsParentContext*/true);
// Finish creating the property.
hashValueDecl->setImplicit();
@@ -1052,7 +1052,7 @@
hashValueDecl->setValidationStarted();
hashValueDecl->makeComputed(SourceLoc(), getterDecl,
nullptr, nullptr, SourceLoc());
- hashValueDecl->copyFormalAccessFrom(typeDecl);
+ hashValueDecl->copyFormalAccessFrom(typeDecl, /*sourceIsParentContext*/true);
Pattern *hashValuePat = new (C) NamedPattern(hashValueDecl, /*implicit*/true);
hashValuePat->setType(intType);
diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp
index 37ef181..dfdb730 100644
--- a/lib/Sema/DerivedConformanceRawRepresentable.cpp
+++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp
@@ -340,7 +340,7 @@
}
initDecl->setInterfaceType(allocIfaceType);
initDecl->setInitializerInterfaceType(initIfaceType);
- initDecl->copyFormalAccessFrom(enumDecl);
+ initDecl->copyFormalAccessFrom(enumDecl, /*sourceIsParentContext*/true);
initDecl->setValidationStarted();
tc.Context.addSynthesizedDecl(initDecl);
diff --git a/lib/Sema/DerivedConformances.cpp b/lib/Sema/DerivedConformances.cpp
index e7d056e..c2b44b9 100644
--- a/lib/Sema/DerivedConformances.cpp
+++ b/lib/Sema/DerivedConformances.cpp
@@ -303,7 +303,7 @@
/*IsCaptureList*/false, SourceLoc(), name,
propertyContextType, parentDC);
propDecl->setImplicit();
- propDecl->copyFormalAccessFrom(typeDecl);
+ propDecl->copyFormalAccessFrom(typeDecl, /*sourceIsParentContext*/true);
propDecl->setInterfaceType(propertyInterfaceType);
propDecl->setValidationStarted();
diff --git a/lib/Sema/ITCType.cpp b/lib/Sema/ITCType.cpp
deleted file mode 100644
index 598fbb6..0000000
--- a/lib/Sema/ITCType.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-//===--- ITCType.cpp - Iterative Type Checker for Types -------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the portions of the IterativeTypeChecker
-// class that involve types.
-//
-//===----------------------------------------------------------------------===//
-#include "GenericTypeResolver.h"
-#include "TypeChecker.h"
-#include "swift/Sema/IterativeTypeChecker.h"
-#include "swift/AST/ASTContext.h"
-#include "swift/AST/ASTWalker.h"
-#include "swift/AST/Decl.h"
-using namespace swift;
-
-//===----------------------------------------------------------------------===//
-// Type resolution.
-//===----------------------------------------------------------------------===//
-bool IterativeTypeChecker::isResolveTypeReprSatisfied(
- std::tuple<TypeRepr *, DeclContext *, unsigned> payload) {
- auto typeRepr = std::get<0>(payload);
- auto options = static_cast<TypeResolutionOptions>(std::get<2>(payload));
-
- // FIXME: Introduce a bit indicating when everything in the TypeRepr
- // has been name-bound, which indicates that we can always compute a
- // structural type.
- struct FindUnboundTypeRepr : public ASTWalker {
- TypeResolutionOptions Options;
-
- // Whether we've found an unbound type.
- bool HasUnbound = false;
-
- FindUnboundTypeRepr(TypeResolutionOptions options) : Options(options) { }
-
- bool walkToTypeReprPre(TypeRepr *T) override {
- // If we already found an unbound type, we're done.
- if (HasUnbound) return false;
-
- if (auto ident = dyn_cast<ComponentIdentTypeRepr>(T)) {
- if (!ident->isBound()) {
- HasUnbound = true;
- return false;
- }
-
- // If we're only looking to resolve the structure of the type,
- // don't walk into generic arguments. They don't affect the
- // structure.
- if (Options.contains(TypeResolutionFlags::ResolveStructure) &&
- isa<GenericIdentTypeRepr>(ident))
- return false;
- }
-
- // Keep walking.
- return true;
- }
- } findUnboundTypeRepr(options);
-
- typeRepr->walk(findUnboundTypeRepr);
- return findUnboundTypeRepr.HasUnbound;
-}
-
-void IterativeTypeChecker::processResolveTypeRepr(
- std::tuple<TypeRepr *, DeclContext *, unsigned> payload,
- UnsatisfiedDependency unsatisfiedDependency) {
- auto typeRepr = std::get<0>(payload);
- auto dc = std::get<1>(payload);
- auto options = static_cast<TypeResolutionOptions>(std::get<2>(payload));
-
- // FIXME: TypeChecker::resolveType() is mostly non-ad-hoc-recursive
- // when given an UnsatisfiedDependency.
- TC.resolveType(typeRepr, dc, options, nullptr, &unsatisfiedDependency);
-}
-
-bool IterativeTypeChecker::breakCycleForResolveTypeRepr(
- std::tuple<TypeRepr *, DeclContext *, unsigned> payload) {
- std::get<0>(payload)->setInvalid();
- return true;
-}
-
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index 2c6ae5c..6d02cec 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -185,7 +185,7 @@
void visitAlignmentAttr(AlignmentAttr *attr) {
// Alignment must be a power of two.
- unsigned value = attr->Value;
+ auto value = attr->getValue();
if (value == 0 || (value & (value - 1)) != 0)
TC.diagnose(attr->getLocation(), diag::alignment_not_power_of_two);
}
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index f7de22e..3d3aae9 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -7605,7 +7605,7 @@
&& "Decl parsing must prevent destructors outside of types!");
checkDeclAttributesEarly(DD);
- DD->copyFormalAccessFrom(enclosingClass);
+ DD->copyFormalAccessFrom(enclosingClass, /*sourceIsParentContext*/true);
configureImplicitSelf(*this, DD);
diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp
index 8ced660..0ed25a7 100644
--- a/lib/Sema/TypeCheckStmt.cpp
+++ b/lib/Sema/TypeCheckStmt.cpp
@@ -377,6 +377,7 @@
template<typename StmtTy>
bool typeCheckStmt(StmtTy *&S) {
+ PrettyStackTraceStmt trace(TC.Context, "type-checking", S);
StmtTy *S2 = cast_or_null<StmtTy>(visit(S));
if (S2 == nullptr)
return true;
@@ -821,7 +822,7 @@
// Type-check the subject expression.
Expr *subjectExpr = S->getSubjectExpr();
auto resultTy = TC.typeCheckExpression(subjectExpr, DC);
- auto hadError = !resultTy;
+ auto limitExhaustivityChecks = !resultTy;
if (Expr *newSubjectExpr = TC.coerceToRValue(subjectExpr))
subjectExpr = newSubjectExpr;
S->setSubjectExpr(subjectExpr);
@@ -856,7 +857,7 @@
// Coerce the pattern to the subject's type.
if (!subjectType || TC.coercePatternToType(pattern, DC, subjectType,
TypeResolutionFlags::InExpression)) {
- hadError = true;
+ limitExhaustivityChecks = true;
// If that failed, mark any variables binding pieces of the pattern
// as invalid to silence follow-on errors.
@@ -907,7 +908,7 @@
}
// Check the guard expression, if present.
if (auto *guard = labelItem.getGuardExpr()) {
- hadError |= TC.typeCheckCondition(guard, DC);
+ limitExhaustivityChecks |= TC.typeCheckCondition(guard, DC);
labelItem.setGuardExpr(guard);
}
}
@@ -920,11 +921,13 @@
TC.diagnose(caseBlock->getLoc(),
diag::unknown_case_multiple_patterns)
.highlight(caseBlock->getCaseLabelItems()[1].getSourceRange());
+ limitExhaustivityChecks = true;
}
- if (!caseBlock->isDefault() && FallthroughDest != nullptr) {
- TC.diagnose(caseBlock->getLoc(),
- diag::unknown_case_must_be_last);
+ if (FallthroughDest != nullptr) {
+ if (!caseBlock->isDefault())
+ TC.diagnose(caseBlock->getLoc(), diag::unknown_case_must_be_last);
+ limitExhaustivityChecks = true;
}
const CaseLabelItem &labelItem = caseBlock->getCaseLabelItems().front();
@@ -981,13 +984,13 @@
// Type-check the body statements.
PreviousFallthrough = nullptr;
Stmt *body = caseBlock->getBody();
- hadError |= typeCheckStmt(body);
+ limitExhaustivityChecks |= typeCheckStmt(body);
caseBlock->setBody(body);
previousBlock = caseBlock;
}
if (!S->isImplicit()) {
- TC.checkSwitchExhaustiveness(S, DC, /*limitChecking*/hadError);
+ TC.checkSwitchExhaustiveness(S, DC, limitExhaustivityChecks);
}
return S;
diff --git a/lib/Sema/TypeCheckSwitchStmt.cpp b/lib/Sema/TypeCheckSwitchStmt.cpp
index 6a221cd..d2a448d 100644
--- a/lib/Sema/TypeCheckSwitchStmt.cpp
+++ b/lib/Sema/TypeCheckSwitchStmt.cpp
@@ -1219,7 +1219,7 @@
SmallVector<Space, 4> spaces;
for (auto *caseBlock : Switch->getCases()) {
if (caseBlock->hasUnknownAttr()) {
- assert(unknownCase == nullptr);
+ assert(unknownCase == nullptr && "multiple unknown cases");
unknownCase = caseBlock;
continue;
}
@@ -1345,10 +1345,25 @@
// Decide whether we want an error or a warning.
auto mainDiagType = diag::non_exhaustive_switch;
- if (!uncovered.isEmpty() && unknownCase) {
- assert(defaultReason == RequiresDefault::No);
- mainDiagType = diag::non_exhaustive_switch_warn;
+ if (unknownCase) {
+ switch (defaultReason) {
+ case RequiresDefault::EmptySwitchBody:
+ llvm_unreachable("there's an @unknown case; the body can't be empty");
+ case RequiresDefault::No:
+ if (!uncovered.isEmpty())
+ mainDiagType = diag::non_exhaustive_switch_warn;
+ break;
+ case RequiresDefault::UncoveredSwitch:
+ case RequiresDefault::SpaceTooLarge:
+ TC.diagnose(startLoc, diag::non_exhaustive_switch);
+ TC.diagnose(unknownCase->getLoc(),
+ diag::non_exhaustive_switch_drop_unknown)
+ .fixItRemoveChars(unknownCase->getStartLoc(),
+ unknownCase->getLoc());
+ return;
+ }
}
+
switch (uncovered.checkDowngradeToWarning()) {
case DowngradeToWarning::No:
break;
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 8ec7f1b..3d34299 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -2277,8 +2277,8 @@
}
for (auto &fieldRepr : repr->getFields()) {
- auto fieldTy = resolveType(fieldRepr.FieldType, options);
- fields.push_back({fieldTy->getCanonicalType(), fieldRepr.Mutable});
+ auto fieldTy = resolveType(fieldRepr.getFieldType(), options);
+ fields.push_back({fieldTy->getCanonicalType(), fieldRepr.isMutable()});
}
}
diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp
index 670f821..11a919d 100644
--- a/lib/Serialization/DeserializeSIL.cpp
+++ b/lib/Serialization/DeserializeSIL.cpp
@@ -1107,11 +1107,12 @@
assert(RecordKind == SIL_ONE_TYPE_ONE_OPERAND &&
"Layout should be OneTypeOneOperand.");
bool isLifetimeGuaranteed = Attr & 0x01;
+ bool isEscaped = Attr & 0x02;
ResultVal = Builder.createConvertEscapeToNoEscape(
Loc,
getLocalValue(ValID, getSILType(MF->getType(TyID2),
(SILValueCategory)TyCategory2)),
- getSILType(MF->getType(TyID), (SILValueCategory)TyCategory),
+ getSILType(MF->getType(TyID), (SILValueCategory)TyCategory), isEscaped,
isLifetimeGuaranteed);
break;
}
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index 006469b..0219e97 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -2232,7 +2232,7 @@
auto abbrCode = DeclTypeAbbrCodes[AlignmentDeclAttrLayout::Code];
AlignmentDeclAttrLayout::emitRecord(Out, ScratchRecord, abbrCode,
theAlignment->isImplicit(),
- theAlignment->Value);
+ theAlignment->getValue());
return;
}
diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp
index 5c670b8..3aafb45 100644
--- a/lib/Serialization/SerializeSIL.cpp
+++ b/lib/Serialization/SerializeSIL.cpp
@@ -252,7 +252,7 @@
void writeIndexTables();
void writeConversionLikeInstruction(const SingleValueInstruction *I,
- bool guaranteed);
+ bool guaranteed, bool escaped);
void writeOneTypeLayout(SILInstructionKind valueKind, SILType type);
void writeOneTypeOneOperandLayout(SILInstructionKind valueKind,
unsigned attrs,
@@ -601,10 +601,11 @@
/// Write an instruction that looks exactly like a conversion: all
/// important information is encoded in the operand and the result type.
void SILSerializer::writeConversionLikeInstruction(
- const SingleValueInstruction *I, bool guaranteed) {
+ const SingleValueInstruction *I, bool guaranteed, bool escaped) {
assert(I->getNumOperands() - I->getTypeDependentOperands().size() == 1);
- writeOneTypeOneOperandLayout(I->getKind(), guaranteed ? 1 : 0, I->getType(),
- I->getOperand(0));
+ writeOneTypeOneOperandLayout(I->getKind(),
+ (guaranteed ? 1 : 0) | (escaped ? 2 : 0),
+ I->getType(), I->getOperand(0));
}
void
@@ -1473,10 +1474,13 @@
case SILInstructionKind::ObjCExistentialMetatypeToObjectInst:
case SILInstructionKind::ProjectBlockStorageInst: {
bool guaranteed = false;
- if (SI.getKind() == SILInstructionKind::ConvertEscapeToNoEscapeInst)
+ bool escaped = false;
+ if (SI.getKind() == SILInstructionKind::ConvertEscapeToNoEscapeInst) {
+ escaped = cast<ConvertEscapeToNoEscapeInst>(SI).isEscapedByUser();
guaranteed = cast<ConvertEscapeToNoEscapeInst>(SI).isLifetimeGuaranteed();
+ }
writeConversionLikeInstruction(cast<SingleValueInstruction>(&SI),
- guaranteed);
+ guaranteed, escaped);
break;
}
case SILInstructionKind::PointerToAddressInst: {
diff --git a/stdlib/public/SDK/Foundation/Decimal.swift b/stdlib/public/SDK/Foundation/Decimal.swift
index 8af713e..6e0cd4b 100644
--- a/stdlib/public/SDK/Foundation/Decimal.swift
+++ b/stdlib/public/SDK/Foundation/Decimal.swift
@@ -59,6 +59,7 @@
public mutating func formTruncatingRemainder(dividingBy other: Decimal) { fatalError("Decimal does not yet fully adopt FloatingPoint") }
public mutating func negate() {
+ guard _length != 0 else { return }
_isNegative = _isNegative == 0 ? 1 : 0
}
diff --git a/stdlib/public/SwiftRemoteMirror/CMakeLists.txt b/stdlib/public/SwiftRemoteMirror/CMakeLists.txt
index 93255e9..af4a8e9 100644
--- a/stdlib/public/SwiftRemoteMirror/CMakeLists.txt
+++ b/stdlib/public/SwiftRemoteMirror/CMakeLists.txt
@@ -1,6 +1,3 @@
-# HACK: Force this library to build with undefined symbols.
-string(REGEX REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
-
# libswiftRemoteMirror.dylib should not have runtime dependencies; it's
# always built as a shared library.
if(SWIFT_BUILD_DYNAMIC_STDLIB OR SWIFT_BUILD_REMOTE_MIRROR)
diff --git a/stdlib/public/core/ClosedRange.swift b/stdlib/public/core/ClosedRange.swift
index c95fc7d..df64925 100644
--- a/stdlib/public/core/ClosedRange.swift
+++ b/stdlib/public/core/ClosedRange.swift
@@ -498,6 +498,7 @@
@available(*, deprecated, renamed: "ClosedRange.Index")
public typealias ClosedRangeIndex<T> = ClosedRange<T>.Index where T: Strideable, T.Stride: SignedInteger
-@available(*, deprecated, renamed: "ClosedRange")
+
+@available(*, deprecated: 4.2, renamed: "ClosedRange")
public typealias CountableClosedRange<Bound: Strideable> = ClosedRange<Bound>
where Bound.Stride : SignedInteger
diff --git a/stdlib/public/core/NewtypeWrapper.swift b/stdlib/public/core/NewtypeWrapper.swift
index fe74178..08aa9f9 100644
--- a/stdlib/public/core/NewtypeWrapper.swift
+++ b/stdlib/public/core/NewtypeWrapper.swift
@@ -15,11 +15,16 @@
/// attribute.
public protocol _SwiftNewtypeWrapper : RawRepresentable { }
-extension _SwiftNewtypeWrapper where Self.RawValue : Hashable {
+extension _SwiftNewtypeWrapper where Self: Hashable, Self.RawValue : Hashable {
@inlinable // FIXME(sil-serialize-all)
public var hashValue: Int {
return rawValue.hashValue
}
+
+ @inlinable // FIXME(sil-serialize-all)
+ public func _hash(into hasher: inout _Hasher) {
+ hasher.append(rawValue)
+ }
}
#if _runtime(_ObjC)
diff --git a/stdlib/public/core/Range.swift b/stdlib/public/core/Range.swift
index bac7c3e..b7aac8d 100644
--- a/stdlib/public/core/Range.swift
+++ b/stdlib/public/core/Range.swift
@@ -907,3 +907,7 @@
@available(*, deprecated, renamed: "Range")
public typealias CountableRange<Bound: Strideable> = Range<Bound>
where Bound.Stride : SignedInteger
+
+@available(*, deprecated: 4.2, renamed: "PartialRangeFrom")
+public typealias CountablePartialRangeFrom<Bound: Strideable> = PartialRangeFrom<Bound>
+ where Bound.Stride : SignedInteger
diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp
index 517e449..4bedefe 100644
--- a/stdlib/public/runtime/MetadataLookup.cpp
+++ b/stdlib/public/runtime/MetadataLookup.cpp
@@ -1031,7 +1031,7 @@
// Call the associated type access function.
// TODO: can we just request abstract metadata? If so, do we have
// a responsibility to try to finish it later?
- return ((const AssociatedTypeAccessFunction * const *)witnessTable)[*assocTypeReqIndex]
+ return ((AssociatedTypeAccessFunction * const *)witnessTable)[*assocTypeReqIndex]
(MetadataState::Complete, base, witnessTable).Value;
});
diff --git a/stdlib/public/stubs/MathStubs.cpp b/stdlib/public/stubs/MathStubs.cpp
index f6bc8f2..9f8de55 100644
--- a/stdlib/public/stubs/MathStubs.cpp
+++ b/stdlib/public/stubs/MathStubs.cpp
@@ -29,9 +29,29 @@
#define SWIFT_MODE_TI
#endif
+typedef int si_int;
typedef int di_int SWIFT_MODE_DI;
typedef int ti_int SWIFT_MODE_TI;
+typedef unsigned su_int;
+typedef unsigned du_int SWIFT_MODE_DI;
+typedef unsigned tu_int SWIFT_MODE_TI;
+
+typedef union
+{
+ tu_int all;
+ struct
+ {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ du_int low;
+ du_int high;
+#else
+ du_int high;
+ du_int low;
+#endif /* __BYTE_ORDER__ == __LITTLE_ENDIAN__ */
+ }s;
+} utwords;
+
extern "C" {
// Although this builtin is provided by clang rt builtins,
@@ -142,5 +162,265 @@
#endif
+#if defined(_WIN32)
+
+tu_int
+__udivmodti4(tu_int a, tu_int b, tu_int* rem)
+{
+ const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT;
+ const unsigned n_utword_bits = sizeof(tu_int) * CHAR_BIT;
+ utwords n;
+ n.all = a;
+ utwords d;
+ d.all = b;
+ utwords q;
+ utwords r;
+ unsigned sr;
+ /* special cases, X is unknown, K != 0 */
+ if (n.s.high == 0)
+ {
+ if (d.s.high == 0)
+ {
+ /* 0 X
+ * ---
+ * 0 X
+ */
+ if (rem)
+ *rem = n.s.low % d.s.low;
+ return n.s.low / d.s.low;
+ }
+ /* 0 X
+ * ---
+ * K X
+ */
+ if (rem)
+ *rem = n.s.low;
+ return 0;
+ }
+ /* n.s.high != 0 */
+ if (d.s.low == 0)
+ {
+ if (d.s.high == 0)
+ {
+ /* K X
+ * ---
+ * 0 0
+ */
+ if (rem)
+ *rem = n.s.high % d.s.low;
+ return n.s.high / d.s.low;
+ }
+ /* d.s.high != 0 */
+ if (n.s.low == 0)
+ {
+ /* K 0
+ * ---
+ * K 0
+ */
+ if (rem)
+ {
+ r.s.high = n.s.high % d.s.high;
+ r.s.low = 0;
+ *rem = r.all;
+ }
+ return n.s.high / d.s.high;
+ }
+ /* K K
+ * ---
+ * K 0
+ */
+ if ((d.s.high & (d.s.high - 1)) == 0) /* if d is a power of 2 */
+ {
+ if (rem)
+ {
+ r.s.low = n.s.low;
+ r.s.high = n.s.high & (d.s.high - 1);
+ *rem = r.all;
+ }
+ return n.s.high >> __builtin_ctzll(d.s.high);
+ }
+ /* K K
+ * ---
+ * K 0
+ */
+ sr = __builtin_clzll(d.s.high) - __builtin_clzll(n.s.high);
+ /* 0 <= sr <= n_udword_bits - 2 or sr large */
+ if (sr > n_udword_bits - 2)
+ {
+ if (rem)
+ *rem = n.all;
+ return 0;
+ }
+ ++sr;
+ /* 1 <= sr <= n_udword_bits - 1 */
+ /* q.all = n.all << (n_utword_bits - sr); */
+ q.s.low = 0;
+ q.s.high = n.s.low << (n_udword_bits - sr);
+ /* r.all = n.all >> sr; */
+ r.s.high = n.s.high >> sr;
+ r.s.low = (n.s.high << (n_udword_bits - sr)) | (n.s.low >> sr);
+ }
+ else /* d.s.low != 0 */
+ {
+ if (d.s.high == 0)
+ {
+ /* K X
+ * ---
+ * 0 K
+ */
+ if ((d.s.low & (d.s.low - 1)) == 0) /* if d is a power of 2 */
+ {
+ if (rem)
+ *rem = n.s.low & (d.s.low - 1);
+ if (d.s.low == 1)
+ return n.all;
+ sr = __builtin_ctzll(d.s.low);
+ q.s.high = n.s.high >> sr;
+ q.s.low = (n.s.high << (n_udword_bits - sr)) | (n.s.low >> sr);
+ return q.all;
+ }
+ /* K X
+ * ---
+ * 0 K
+ */
+ sr = 1 + n_udword_bits + __builtin_clzll(d.s.low)
+ - __builtin_clzll(n.s.high);
+ /* 2 <= sr <= n_utword_bits - 1
+ * q.all = n.all << (n_utword_bits - sr);
+ * r.all = n.all >> sr;
+ */
+ if (sr == n_udword_bits)
+ {
+ q.s.low = 0;
+ q.s.high = n.s.low;
+ r.s.high = 0;
+ r.s.low = n.s.high;
+ }
+ else if (sr < n_udword_bits) // 2 <= sr <= n_udword_bits - 1
+ {
+ q.s.low = 0;
+ q.s.high = n.s.low << (n_udword_bits - sr);
+ r.s.high = n.s.high >> sr;
+ r.s.low = (n.s.high << (n_udword_bits - sr)) | (n.s.low >> sr);
+ }
+ else // n_udword_bits + 1 <= sr <= n_utword_bits - 1
+ {
+ q.s.low = n.s.low << (n_utword_bits - sr);
+ q.s.high = (n.s.high << (n_utword_bits - sr)) |
+ (n.s.low >> (sr - n_udword_bits));
+ r.s.high = 0;
+ r.s.low = n.s.high >> (sr - n_udword_bits);
+ }
+ }
+ else
+ {
+ /* K X
+ * ---
+ * K K
+ */
+ sr = __builtin_clzll(d.s.high) - __builtin_clzll(n.s.high);
+ /*0 <= sr <= n_udword_bits - 1 or sr large */
+ if (sr > n_udword_bits - 1)
+ {
+ if (rem)
+ *rem = n.all;
+ return 0;
+ }
+ ++sr;
+ /* 1 <= sr <= n_udword_bits
+ * q.all = n.all << (n_utword_bits - sr);
+ * r.all = n.all >> sr;
+ */
+ q.s.low = 0;
+ if (sr == n_udword_bits)
+ {
+ q.s.high = n.s.low;
+ r.s.high = 0;
+ r.s.low = n.s.high;
+ }
+ else
+ {
+ r.s.high = n.s.high >> sr;
+ r.s.low = (n.s.high << (n_udword_bits - sr)) | (n.s.low >> sr);
+ q.s.high = n.s.low << (n_udword_bits - sr);
+ }
+ }
+ }
+ /* Not a special case
+ * q and r are initialized with:
+ * q.all = n.all << (n_utword_bits - sr);
+ * r.all = n.all >> sr;
+ * 1 <= sr <= n_utword_bits - 1
+ */
+ su_int carry = 0;
+ for (; sr > 0; --sr)
+ {
+ /* r:q = ((r:q) << 1) | carry */
+ r.s.high = (r.s.high << 1) | (r.s.low >> (n_udword_bits - 1));
+ r.s.low = (r.s.low << 1) | (q.s.high >> (n_udword_bits - 1));
+ q.s.high = (q.s.high << 1) | (q.s.low >> (n_udword_bits - 1));
+ q.s.low = (q.s.low << 1) | carry;
+ /* carry = 0;
+ * if (r.all >= d.all)
+ * {
+ * r.all -= d.all;
+ * carry = 1;
+ * }
+ */
+ const ti_int s = (ti_int)(d.all - r.all - 1) >> (n_utword_bits - 1);
+ carry = s & 1;
+ r.all -= d.all & s;
+ }
+ q.all = (q.all << 1) | carry;
+ if (rem)
+ *rem = r.all;
+ return q.all;
+}
+
+SWIFT_RUNTIME_STDLIB_INTERFACE
+tu_int
+__udivti3(tu_int a, tu_int b)
+{
+ return __udivmodti4(a, b, NULL);
+}
+
+SWIFT_RUNTIME_STDLIB_INTERFACE
+tu_int
+__umodti3(tu_int a, tu_int b)
+{
+ tu_int r;
+ __udivmodti4(a, b, &r);
+ return r;
+}
+
+SWIFT_RUNTIME_STDLIB_INTERFACE
+ti_int
+__divti3(ti_int a, ti_int b)
+{
+ const int bits_in_tword_m1 = (int)(sizeof(ti_int) * CHAR_BIT) - 1;
+ ti_int s_a = a >> bits_in_tword_m1; /* s_a = a < 0 ? -1 : 0 */
+ ti_int s_b = b >> bits_in_tword_m1; /* s_b = b < 0 ? -1 : 0 */
+ a = (a ^ s_a) - s_a; /* negate if s_a == -1 */
+ b = (b ^ s_b) - s_b; /* negate if s_b == -1 */
+ s_a ^= s_b; /* sign of quotient */
+ return (__udivmodti4(a, b, (tu_int*)0) ^ s_a) - s_a; /* negate if s_a == -1 */
+}
+
+SWIFT_RUNTIME_STDLIB_INTERFACE
+ti_int
+__modti3(ti_int a, ti_int b)
+{
+ const int bits_in_tword_m1 = (int)(sizeof(ti_int) * CHAR_BIT) - 1;
+ ti_int s = b >> bits_in_tword_m1; /* s = b < 0 ? -1 : 0 */
+ b = (b ^ s) - s; /* negate if s == -1 */
+ s = a >> bits_in_tword_m1; /* s = a < 0 ? -1 : 0 */
+ a = (a ^ s) - s; /* negate if s == -1 */
+ tu_int r;
+ __udivmodti4(a, b, &r);
+ return ((ti_int)r ^ s) - s; /* negate if s == -1 */
+}
+
+#endif
+
}
diff --git a/test/ClangImporter/Inputs/pch-bridging-header-with-another-bridging-header/app.h b/test/ClangImporter/Inputs/pch-bridging-header-with-another-bridging-header/app.h
new file mode 100644
index 0000000..154f4ef
--- /dev/null
+++ b/test/ClangImporter/Inputs/pch-bridging-header-with-another-bridging-header/app.h
@@ -0,0 +1,5 @@
+#include "has_warning.h"
+
+static inline int app_function(int x) {
+ return x + 27;
+}
diff --git a/test/ClangImporter/Inputs/pch-bridging-header-with-another-bridging-header/has_warning.h b/test/ClangImporter/Inputs/pch-bridging-header-with-another-bridging-header/has_warning.h
new file mode 100644
index 0000000..b516ee9
--- /dev/null
+++ b/test/ClangImporter/Inputs/pch-bridging-header-with-another-bridging-header/has_warning.h
@@ -0,0 +1,6 @@
+#ifndef HAS_WARNING_H
+#define HAS_WARNING_H
+
+#warning "warning in bridging header"
+
+#endif
diff --git a/test/ClangImporter/Inputs/pch-bridging-header-with-another-bridging-header/unit-tests.h b/test/ClangImporter/Inputs/pch-bridging-header-with-another-bridging-header/unit-tests.h
new file mode 100644
index 0000000..a78913e
--- /dev/null
+++ b/test/ClangImporter/Inputs/pch-bridging-header-with-another-bridging-header/unit-tests.h
@@ -0,0 +1 @@
+#include "has_warning.h"
diff --git a/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKit.framework/Headers/SKWidget.h b/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKit.framework/Headers/SKWidget.h
new file mode 100644
index 0000000..dd99ff7
--- /dev/null
+++ b/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKit.framework/Headers/SKWidget.h
@@ -0,0 +1 @@
+#import <SomeKitCore/SKWidget.h>
diff --git a/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKit.framework/Headers/SomeKit.h b/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKit.framework/Headers/SomeKit.h
new file mode 100644
index 0000000..17a4cc8
--- /dev/null
+++ b/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKit.framework/Headers/SomeKit.h
@@ -0,0 +1 @@
+#import <SomeKit/SKWidget.h>
diff --git a/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKit.framework/Modules/module.modulemap b/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKit.framework/Modules/module.modulemap
new file mode 100644
index 0000000..ae4b276
--- /dev/null
+++ b/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKit.framework/Modules/module.modulemap
@@ -0,0 +1,6 @@
+framework module SomeKit {
+ umbrella header "SomeKit.h"
+ module * {
+ export *
+ }
+}
diff --git a/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKit.framework/SomeKit.tbd b/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKit.framework/SomeKit.tbd
new file mode 100644
index 0000000..fcb8b10
--- /dev/null
+++ b/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKit.framework/SomeKit.tbd
@@ -0,0 +1 @@
+// dummy file to trigger autolink
diff --git a/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKitCore.framework/Headers/SKWidget.h b/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKitCore.framework/Headers/SKWidget.h
new file mode 100644
index 0000000..0370e85
--- /dev/null
+++ b/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKitCore.framework/Headers/SKWidget.h
@@ -0,0 +1,27 @@
+@import ObjectiveC;
+@import Foundation;
+
+@interface SKWidget : NSObject
+- (void)someObjCMethod;
+@end
+
+@interface SKWidget(ObjCAPI)
+- (void)someObjCExtensionMethod;
+@property (readwrite,strong,nonnull) NSObject *anObject;
+@end
+
+@interface NSObject (SKWidget)
+- (void)doSomethingWithWidget:(nonnull SKWidget *)widget;
+@end
+
+extern NSString * _Nonnull const SKWidgetErrorDomain;
+typedef enum __attribute__((ns_error_domain(SKWidgetErrorDomain))) __attribute__((swift_name("SKWidget.Error"))) SKWidgetErrorCode : NSInteger {
+ SKWidgetErrorNone = 0,
+ SKWidgetErrorBoom = 1
+} SKWidgetErrorCode;
+
+@interface SKWidget(Erroneous)
+- (SKWidgetErrorCode)getCurrentError;
+@end
+
+extern void someKitGlobalFunc(void);
diff --git a/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKitCore.framework/Headers/SomeKitCore.h b/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKitCore.framework/Headers/SomeKitCore.h
new file mode 100644
index 0000000..dd99ff7
--- /dev/null
+++ b/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKitCore.framework/Headers/SomeKitCore.h
@@ -0,0 +1 @@
+#import <SomeKitCore/SKWidget.h>
diff --git a/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKitCore.framework/Modules/module.modulemap b/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKitCore.framework/Modules/module.modulemap
new file mode 100644
index 0000000..30f9770
--- /dev/null
+++ b/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKitCore.framework/Modules/module.modulemap
@@ -0,0 +1,7 @@
+framework module SomeKitCore {
+ umbrella header "SomeKitCore.h"
+ export_as SomeKit
+ module * {
+ export *
+ }
+}
diff --git a/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKitCore.framework/SomeKitCore.tbd b/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKitCore.framework/SomeKitCore.tbd
new file mode 100644
index 0000000..fcb8b10
--- /dev/null
+++ b/test/ClangImporter/Inputs/privateframeworks/withprivate-autolink/SomeKitCore.framework/SomeKitCore.tbd
@@ -0,0 +1 @@
+// dummy file to trigger autolink
diff --git a/test/ClangImporter/pch-bridging-header-with-another-bridging-header.swift b/test/ClangImporter/pch-bridging-header-with-another-bridging-header.swift
new file mode 100644
index 0000000..63d2326
--- /dev/null
+++ b/test/ClangImporter/pch-bridging-header-with-another-bridging-header.swift
@@ -0,0 +1,21 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-build-swift -emit-module -import-objc-header %S/Inputs/pch-bridging-header-with-another-bridging-header/app.h -I %S/Inputs/pch-bridging-header-with-another-bridging-header -module-name App -emit-module-path %t/App.swiftmodule %S/../Inputs/empty.swift
+// RUN: llvm-bcanalyzer -dump %t/App.swiftmodule | %FileCheck %s
+
+// CHECK: IMPORTED_HEADER{{.*}}Inputs/pch-bridging-header-with-another-bridging-header/app.h
+
+// Now load the app-module-with-bridging-header along with another bridging
+// header that we precompile. This is going to the frontend directly to make
+// sure we validate PCH inputs (because -pch-disable-validation wasn't passed).
+// This is deliberately run twice to test what happens when the PCH is already
+// there. (It used to crash.)
+
+// RUN: cp %S/Inputs/pch-bridging-header-with-another-bridging-header/unit-tests.h %t/unit-tests.h
+// RUN: %target-swift-frontend -typecheck -pch-output-dir %t -import-objc-header %t/unit-tests.h -I %S/Inputs/pch-bridging-header-with-another-bridging-header -I %t %s
+// RUN: %target-swift-frontend -typecheck -pch-output-dir %t -import-objc-header %t/unit-tests.h -I %S/Inputs/pch-bridging-header-with-another-bridging-header -I %t %s
+// RUN: echo >> %t/unit-tests.h
+// RUN: %target-swift-frontend -typecheck -pch-output-dir %t -import-objc-header %t/unit-tests.h -I %S/Inputs/pch-bridging-header-with-another-bridging-header -I %t %s
+
+import App
+
+_ = app_function(2)
\ No newline at end of file
diff --git a/test/ClangImporter/private_frameworks_autolink.swift b/test/ClangImporter/private_frameworks_autolink.swift
new file mode 100644
index 0000000..545b180
--- /dev/null
+++ b/test/ClangImporter/private_frameworks_autolink.swift
@@ -0,0 +1,16 @@
+// RUN: %empty-directory(%t)
+
+// FIXME: BEGIN -enable-source-import hackaround
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource) -emit-module -o %t %clang-importer-sdk-path/swift-modules/CoreGraphics.swift
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-module -o %t %clang-importer-sdk-path/swift-modules/Foundation.swift
+// FIXME: END -enable-source-import hackaround
+
+// Check that the autolink information is appropriate (do not link against SomeKitCore).
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-ir -o %t/private_frameworks_autolink.ll -F %S/Inputs/privateframeworks/withprivate-autolink %s
+// RUN: %FileCheck %s < %t/private_frameworks_autolink.ll
+// CHECK-NOT: !{!"-framework", !"SomeKitCore"}
+
+// REQUIRES: objc_interop
+
+import SomeKitCore
+import SomeKit
diff --git a/test/ClangImporter/private_frameworks_autolink2.swift b/test/ClangImporter/private_frameworks_autolink2.swift
new file mode 100644
index 0000000..7d09ba9
--- /dev/null
+++ b/test/ClangImporter/private_frameworks_autolink2.swift
@@ -0,0 +1,16 @@
+// RUN: %empty-directory(%t)
+
+// FIXME: BEGIN -enable-source-import hackaround
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource) -emit-module -o %t %clang-importer-sdk-path/swift-modules/CoreGraphics.swift
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-module -o %t %clang-importer-sdk-path/swift-modules/Foundation.swift
+// FIXME: END -enable-source-import hackaround
+
+// Check that the autolink information is appropriate (do not link against SomeKitCore).
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-ir -o %t/private_frameworks_autolink2.ll -F %S/Inputs/privateframeworks/withprivate-autolink %s
+// RUN: %FileCheck %s < %t/private_frameworks_autolink2.ll
+// CHECK-NOT: !{!"-framework", !"SomeKit"}
+// CHECK: !{!"-framework", !"SomeKitCore"}
+
+// REQUIRES: objc_interop
+
+import SomeKitCore
diff --git a/test/Compatibility/exhaustive_switch.swift b/test/Compatibility/exhaustive_switch.swift
index 9e0b392..a3d3e57 100644
--- a/test/Compatibility/exhaustive_switch.swift
+++ b/test/Compatibility/exhaustive_switch.swift
@@ -473,6 +473,21 @@
case (.case10, _): return true
}
+ switch (OverlyLargeSpaceEnum.case1, OverlyLargeSpaceEnum.case2) { // expected-error {{switch must be exhaustive}}
+ case (.case0, _): return true
+ case (.case1, _): return true
+ case (.case2, _): return true
+ case (.case3, _): return true
+ case (.case4, _): return true
+ case (.case5, _): return true
+ case (.case6, _): return true
+ case (.case7, _): return true
+ case (.case8, _): return true
+ case (.case9, _): return true
+ case (.case10, _): return true
+ @unknown default: return false // expected-note {{remove '@unknown' to handle remaining values}} {{3-12=}}
+ }
+
// No diagnostic
switch (OverlyLargeSpaceEnum.case1, OverlyLargeSpaceEnum.case2) {
@@ -526,6 +541,10 @@
case .two: return true
case .three: return true
}
+
+ // Make sure we haven't just stopped emitting diagnostics.
+ switch OverlyLargeSpaceEnum.case1 { // expected-error {{switch must be exhaustive}} expected-note 12 {{add missing case}} expected-note {{handle unknown values}}
+ }
}
indirect enum InfinitelySized {
diff --git a/test/Constraints/rdar39209245.swift b/test/Constraints/rdar39209245.swift
new file mode 100644
index 0000000..b7e15d5
--- /dev/null
+++ b/test/Constraints/rdar39209245.swift
@@ -0,0 +1,15 @@
+// RUN: %target-typecheck-verify-swift
+
+struct S: Hashable {
+ let e: E?
+}
+
+enum E: Hashable {
+ case foo
+ case bar
+}
+
+let a = S(e: .foo)
+let b = S(e: .bar)
+
+_ = a == b
diff --git a/test/DebugInfo/DumpDeclFromMangledName.swift b/test/DebugInfo/DumpDeclFromMangledName.swift
index 154afd3..4b8bcef 100644
--- a/test/DebugInfo/DumpDeclFromMangledName.swift
+++ b/test/DebugInfo/DumpDeclFromMangledName.swift
@@ -7,6 +7,22 @@
// RUN: sed -ne '/--->/s/^.*---> *//p' < %S/Inputs/decl-reconstr-names.txt > %t.check
// RUN: %target-build-swift -emit-executable %s -g -o %t/DeclReconstr -emit-module
+
+// Input validation tests.
+// RUN: not %lldb-moduleimport-test patatino 2>&1 | %FileCheck %s \
+// RUN: --check-prefix=INVALID-INPUT
+// INVALID-INPUT: patatino does not exists, exiting.
+
+// RUN: not %lldb-moduleimport-test %t/DeclReconstr \
+// RUN: --decl-from-mangled=patatino 2>&1 | \
+// RUN: %FileCheck %s --check-prefix=INVALID-DECL
+// INVALID-DECL: patatino does not exists, exiting.
+
+// RUN: not %lldb-moduleimport-test %t/DeclReconstr \
+// RUN: --type-from-mangled=patatino 2>&1 | \
+// RUN: %FileCheck %s --check-prefix=INVALID-TYPE
+// INVALID-TYPE: patatino does not exists, exiting.
+
// RUN: %lldb-moduleimport-test %t/DeclReconstr \
// RUN: -decl-from-mangled=%t.input > %t.output 2>&1
// RUN: diff %t.check %t.output
diff --git a/test/DebugInfo/LinetableArtificialFn.swift b/test/DebugInfo/LinetableArtificialFn.swift
deleted file mode 100644
index 4f985ff..0000000
--- a/test/DebugInfo/LinetableArtificialFn.swift
+++ /dev/null
@@ -1,34 +0,0 @@
-// RUN: %target-swift-frontend %s -emit-ir -g -o - -disable-sil-linking | %FileCheck %s
-
-// Verify that a helper function that is generated on-the-fly does
-// not mess up the linetable of the calling function.
-// CHECK: store i2048 10, i2048* [[STKLOC:%.*]], align
-// CHECK: call swiftcc {{(i32|i64)}} @"$SSi22_builtinIntegerLiteralSiBi2048__tcfC"(i2048* {{.*}} [[STKLOC]]
-// CHECK: store {{(i32|i64)}} {{.*}}getelementptr
-// CHECK: store {{(i32|i64)}} {{.*}}getelementptr{{.*}}, !dbg ![[DBG:[0-9]+]]
-// CHECK-NOT: ![[DBG]] = !{i32 0, i32 0,
-
-class TurnBasedPolicy {
-
- typealias Rules = (onWin : Int, onHint : Int, onLose : Int, onWrongGuess: Int, numAttempts : Int, numHints : Int, secretRange : (Int, Int))
-
- init (r : Rules) {
- self.rules = r
- }
- var rules : Rules
- var secret = 0
- var attempts = 0
- var hints = 0
- var hintedRange = (0, 0)
-}
-
-var easyPolicy : TurnBasedPolicy.Rules = (
- onWin : 2,
- onHint : -1,
- onLose : -2,
- onWrongGuess : 0,
- numAttempts : 7,
- numHints : 7,
- secretRange : (1,10)
-)
-
diff --git a/test/DebugInfo/basic.swift b/test/DebugInfo/basic.swift
index d9b6bbb..4755a0f 100644
--- a/test/DebugInfo/basic.swift
+++ b/test/DebugInfo/basic.swift
@@ -20,8 +20,6 @@
// --------------------------------------------------------------------
// Now check that we do generate line+scope info with -g.
// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s
-// RUN: %target-swift-frontend %s -emit-ir -g -o - -disable-sil-linking \
-// RUN: | %FileCheck %s --check-prefix=CHECK-NOSIL
// --------------------------------------------------------------------
// Currently -gdwarf-types should give the same results as -g.
// RUN: %target-swift-frontend %s -emit-ir -gdwarf-types -o - | %FileCheck %s
@@ -49,10 +47,7 @@
// CHECK-DAG: !DILexicalBlock({{.*}} line: [[@LINE-1]]
// Transparent inlined multiply:
// CHECK-DAG: smul{{.*}}, !dbg ![[MUL:[0-9]+]]
- // CHECK-DAG: [[MUL]] = !DILocation(line: [[@LINE+4]], column: 16,
- // Runtime call to multiply function:
- // CHECK-NOSIL: @"$Ss5Int64V1moiyA2B_ABtFZ{{.*}}, !dbg ![[MUL:[0-9]+]]
- // CHECK-NOSIL: [[MUL]] = !DILocation(line: [[@LINE+1]], column: 16,
+ // CHECK-DAG: [[MUL]] = !DILocation(line: [[@LINE+1]], column: 16,
return a*b
} else {
// CHECK-DAG: ![[PARENT:[0-9]+]] = distinct !DILexicalBlock({{.*}} line: [[@LINE-1]], column: 13)
diff --git a/test/IRGen/objc_super.swift b/test/IRGen/objc_super.swift
index 5cd6f84..c8b86cb 100644
--- a/test/IRGen/objc_super.swift
+++ b/test/IRGen/objc_super.swift
@@ -76,7 +76,7 @@
class PartialApply : Gizmo {
// CHECK: define hidden swiftcc void @"$S10objc_super12PartialApplyC4frobyyF"([[PARTIAL_APPLY_CLASS]]* swiftself) {{.*}} {
override func frob() {
- // CHECK: call swiftcc void @"$S10objc_super8acceptFnyyyyXEF"(i8* bitcast (void (%swift.refcounted*)* [[PARTIAL_FORWARDING_THUNK:@"\$[A-Za-z0-9_]+"]] to i8*), %swift.opaque* %7)
+ // CHECK: call swiftcc void @"$S10objc_super8acceptFnyyyyXEF"(i8* bitcast (void (%swift.refcounted*)* [[PARTIAL_FORWARDING_THUNK:@"\$[A-Za-z0-9_]+"]] to i8*), %swift.opaque* %{{[0-9]+}})
acceptFn(super.frob)
}
// CHECK: }
diff --git a/test/IRGen/outlined_copy_addr.swift b/test/IRGen/outlined_copy_addr.swift
index a4973b4..b68a57b 100644
--- a/test/IRGen/outlined_copy_addr.swift
+++ b/test/IRGen/outlined_copy_addr.swift
@@ -18,9 +18,33 @@
var elem2: BaseStruct<Element>
}
-// CHECK-LABEL: define hidden swiftcc void @"$S11outcopyaddr010StructWithbc4BaseB0V4elemAA0bcdB0VyxGvg"(%T11outcopyaddr014StructWithBaseB0V.0* noalias nocapture sret, %swift.type* %"StructWithStructWithBaseStruct<T>", %T11outcopyaddr010StructWithbc4BaseB0V* noalias nocapture swiftself)
-// CHECK: call %T11outcopyaddr014StructWithBaseB0V.0* @"$S11outcopyaddr014StructWithBaseB0VyxGAA9ChildProtRzlWOc"
+// CHECK-LABEL: define hidden swiftcc void @"$S11outcopyaddr010StructWithbc4BaseB0V4elemAA0bcdB0VyxGvg"(%T11outcopyaddr014StructWithBaseB0V.4* noalias nocapture sret, %swift.type* %"StructWithStructWithBaseStruct<T>", %T11outcopyaddr010StructWithbc4BaseB0V* noalias nocapture swiftself)
+// CHECK: call %T11outcopyaddr014StructWithBaseB0V.4* @"$S11outcopyaddr014StructWithBaseB0VyxGAA9ChildProtRzlWOc"
public struct StructWithStructWithBaseStruct<T: ChildProt> {
public typealias Element = T
let elem: StructWithBaseStruct<Element>
}
+
+protocol P { }
+
+class OtherPrivate<T> { }
+
+struct OtherInternal<T> {
+ var myPrivate: OtherPrivate<T>? = nil
+}
+
+struct MyPrivate<T: P> {
+ var otherHelper: OtherInternal<T>? = nil
+
+ // CHECK-LABEL: define hidden swiftcc {{i32|i64}} @"$S11outcopyaddr9MyPrivateVyACyxGxcfC"(%swift.opaque* noalias nocapture, %swift.type* %T, i8** %T.P) {{.*}} {
+ // CHECK: call %T11outcopyaddr9MyPrivateV* @"$S11outcopyaddr9MyPrivateVyxGAA1PRzlWOh"(%T11outcopyaddr9MyPrivateV* %self)
+ // CHECK: ret
+ init(_: T) { }
+}
+
+extension P {
+ func foo(data: Any) {
+ _ = MyPrivate(data as! Self)
+ }
+}
+
diff --git a/test/IRGen/same_type_constraints.swift b/test/IRGen/same_type_constraints.swift
index a8ca7fe..881ac82 100644
--- a/test/IRGen/same_type_constraints.swift
+++ b/test/IRGen/same_type_constraints.swift
@@ -1,6 +1,12 @@
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-ir -primary-file %s -disable-objc-attr-requires-foundation-module | %FileCheck %s
// RUN: %target-swift-frontend -Osize -assume-parsing-unqualified-ownership-sil -emit-ir -primary-file %s -disable-objc-attr-requires-foundation-module | %FileCheck %s --check-prefix=OSIZE
+// Ensure that same-type constraints between generic arguments get reflected
+// correctly in the type context descriptor.
+// CHECK-LABEL: @"$S21same_type_constraints4SG11VA2A2P2Rzq_RszrlE13InnerTEqualsUVMn" =
+// T U(==T) V padding
+// CHECK-SAME: , i8 -128, i8 0, i8 -128, i8 0,
+
// <rdar://problem/21665983> IRGen crash with protocol extension involving same-type constraint to X<T>
public struct DefaultFoo<T> {
var t: T?
@@ -16,7 +22,8 @@
}
}
-// CHECK: define{{( protected)?}} swiftcc void @"$S21same_type_constraints1PPA2A10DefaultFooVyxG0E0RtzrlE3fooAFyF"
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S21same_type_constraints1PPA2A10DefaultFooVyxG0E0RtzrlE3fooAFyF"
// <rdar://26873036> IRGen crash with derived class declaring same-type constraint on constrained associatedtype.
public class C1<T: Equatable> { }
@@ -62,3 +69,40 @@
// OSIZE: define internal swiftcc i8** @"$S21same_type_constraints12GenericKlazzCyxq_GAA1EAA4Data_AA0F4TypePWT"(%swift.type* %"GenericKlazz<T, R>.Data", %swift.type* nocapture readonly %"GenericKlazz<T, R>", i8** nocapture readnone %"GenericKlazz<T, R>.E") [[ATTRS:#[0-9]+]] {
// OSIZE: [[ATTRS]] = {{{.*}}noinline
+
+// Check that same-typing two generic parameters together lowers correctly.
+
+protocol P1 {}
+protocol P2 {}
+protocol P3 {}
+struct ConformsToP1: P1 {}
+struct ConformsToP2: P2 {}
+struct ConformsToP3: P3 {}
+
+struct SG11<T: P1, U: P2> {}
+
+struct ConformsToP1AndP2 : P1, P2 { }
+
+extension SG11 where U == T {
+ struct InnerTEqualsU<V: P3> { }
+}
+
+extension SG11 where T == ConformsToP1 {
+ struct InnerTEqualsConformsToP1<V: P3> { }
+}
+
+extension SG11 where U == ConformsToP2 {
+ struct InnerUEqualsConformsToP2<V: P3> { }
+}
+
+func inner1() -> Any.Type {
+ return SG11<ConformsToP1AndP2, ConformsToP1AndP2>.InnerTEqualsU<ConformsToP3>.self
+}
+
+func inner2() -> Any.Type {
+ return SG11<ConformsToP1, ConformsToP2>.InnerTEqualsConformsToP1<ConformsToP3>.self
+}
+
+func inner3() -> Any.Type {
+ return SG11<ConformsToP1, ConformsToP2>.InnerTEqualsConformsToP1<ConformsToP3>.self
+}
diff --git a/test/Migrator/Inputs/Cities.swift b/test/Migrator/Inputs/Cities.swift
index b7ae3d2..7c6f5a1 100644
--- a/test/Migrator/Inputs/Cities.swift
+++ b/test/Migrator/Inputs/Cities.swift
@@ -36,8 +36,20 @@
public class Container {
public var Value: String = ""
+ public var attrDict: [String: Any] = [:]
+ public var attrArr: [String] = []
public func addingAttributes(_ input: [String: Any]) {}
public func adding(attributes: [String: Any]) {}
public func adding(optionalAttributes: [String: Any]?) {}
public init(optionalAttributes: [String: Any]?) {}
+ public func adding(attrArray: [String]) {}
+ public init(optionalAttrArray: [String]?) {}
+ public func add(single: String) {}
+ public func add(singleOptional: String?) {}
+ public func getAttrArray() -> [String] { return [] }
+ public func getOptionalAttrArray() -> [String]? { return [] }
+ public func getAttrDictionary() -> [String: Any] { return [:] }
+ public func getOptionalAttrDictionary() -> [String: Any]? { return nil }
+ public func getSingleAttr() -> String { return "" }
+ public func getOptionalSingleAttr() -> String? { return nil }
}
diff --git a/test/Migrator/Inputs/string-representable.json b/test/Migrator/Inputs/string-representable.json
index 947a889..9c24902 100644
--- a/test/Migrator/Inputs/string-representable.json
+++ b/test/Migrator/Inputs/string-representable.json
@@ -54,4 +54,136 @@
"RightComment": "SimpleAttribute",
"ModuleName": "Cities"
},
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "ArrayMemberUpdate",
+ "ChildIndex": "1",
+ "LeftUsr": "s:6Cities9ContainerC6adding9attrArrayySaySSG_tF",
+ "LeftComment": "",
+ "RightUsr": "",
+ "RightComment": "SimpleAttribute",
+ "ModuleName": "Cities"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "OptionalArrayMemberUpdate",
+ "ChildIndex": "1",
+ "LeftUsr": "s:6Cities9ContainerC17optionalAttrArrayACSaySSGSg_tcfc",
+ "LeftComment": "",
+ "RightUsr": "",
+ "RightComment": "SimpleAttribute",
+ "ModuleName": "Cities"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "SimpleStringRepresentableUpdate",
+ "ChildIndex": "1",
+ "LeftUsr": "s:6Cities9ContainerC3add6singleySS_tF",
+ "LeftComment": "",
+ "RightUsr": "",
+ "RightComment": "SimpleAttribute",
+ "ModuleName": "Cities"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "SimpleOptionalStringRepresentableUpdate",
+ "ChildIndex": "1",
+ "LeftUsr": "s:6Cities9ContainerC3add14singleOptionalySSSg_tF",
+ "LeftComment": "",
+ "RightUsr": "",
+ "RightComment": "SimpleAttribute",
+ "ModuleName": "Cities"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "SimpleStringRepresentableUpdate",
+ "ChildIndex": "0",
+ "LeftUsr": "s:6Cities9ContainerC13getSingleAttrSSyF",
+ "LeftComment": "",
+ "RightUsr": "",
+ "RightComment": "SimpleAttribute",
+ "ModuleName": "Cities"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "SimpleOptionalStringRepresentableUpdate",
+ "ChildIndex": "0",
+ "LeftUsr": "s:6Cities9ContainerC21getOptionalSingleAttrSSSgyF",
+ "LeftComment": "",
+ "RightUsr": "",
+ "RightComment": "SimpleAttribute",
+ "ModuleName": "Cities"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "ArrayMemberUpdate",
+ "ChildIndex": "0",
+ "LeftUsr": "s:6Cities9ContainerC12getAttrArraySaySSGyF",
+ "LeftComment": "",
+ "RightUsr": "",
+ "RightComment": "SimpleAttribute",
+ "ModuleName": "Cities"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "OptionalArrayMemberUpdate",
+ "ChildIndex": "0",
+ "LeftUsr": "s:6Cities9ContainerC20getOptionalAttrArraySaySSGSgyF",
+ "LeftComment": "",
+ "RightUsr": "",
+ "RightComment": "SimpleAttribute",
+ "ModuleName": "Cities"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "OptionalDictionaryKeyUpdate",
+ "ChildIndex": "0",
+ "LeftUsr": "s:6Cities9ContainerC25getOptionalAttrDictionarys0F0VySSypGSgyF",
+ "LeftComment": "",
+ "RightUsr": "",
+ "RightComment": "SimpleAttribute",
+ "ModuleName": "Cities"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Function",
+ "NodeAnnotation": "DictionaryKeyUpdate",
+ "ChildIndex": "0",
+ "LeftUsr": "s:6Cities9ContainerC17getAttrDictionarys0E0VySSypGyF",
+ "LeftComment": "",
+ "RightUsr": "",
+ "RightComment": "SimpleAttribute",
+ "ModuleName": "Cities"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Var",
+ "NodeAnnotation": "DictionaryKeyUpdate",
+ "ChildIndex": "0",
+ "LeftUsr": "s:6Cities9ContainerC8attrDicts10DictionaryVySSypGvp",
+ "LeftComment": "",
+ "RightUsr": "",
+ "RightComment": "SimpleAttribute",
+ "ModuleName": "Cities"
+ },
+ {
+ "DiffItemKind": "CommonDiffItem",
+ "NodeKind": "Var",
+ "NodeAnnotation": "ArrayMemberUpdate",
+ "ChildIndex": "0",
+ "LeftUsr": "s:6Cities9ContainerC7attrArrSaySSGvp",
+ "LeftComment": "",
+ "RightUsr": "",
+ "RightComment": "SimpleAttribute",
+ "ModuleName": "Cities"
+ },
]
diff --git a/test/Migrator/string-representable.swift b/test/Migrator/string-representable.swift
index 20d5dee..94fe882 100644
--- a/test/Migrator/string-representable.swift
+++ b/test/Migrator/string-representable.swift
@@ -13,5 +13,21 @@
c.adding(attributes: ["a": 1, "a": 2, "a": 3])
c.adding(optionalAttributes: ["a": 1, "a": 2, "a": 3])
_ = Container(optionalAttributes: nil)
+ _ = Container(optionalAttrArray: nil)
+ c.adding(attrArray: ["key1", "key2"])
+ c.add(single: "")
+ c.add(singleOptional: nil)
+ _ = c.getAttrDictionary()
+ _ = c.getOptionalAttrDictionary()
+ _ = c.getSingleAttr()
+ _ = c.getOptionalSingleAttr()
+ _ = c.getAttrArray()
+ _ = c.getOptionalAttrArray()
+
+ c.addingAttributes(c.getAttrDictionary())
+ c.adding(optionalAttributes: c.getAttrDictionary())
+
+ c.attrDict = ["a": "b", "a": "b", "a": "b"]
+ c.attrArr = ["key1", "key2"]
return c.Value
}
diff --git a/test/Migrator/string-representable.swift.expected b/test/Migrator/string-representable.swift.expected
index 0957441..7dee8cd 100644
--- a/test/Migrator/string-representable.swift.expected
+++ b/test/Migrator/string-representable.swift.expected
@@ -7,27 +7,103 @@
import Cities
func foo(_ c: Container) -> String {
- c.Value = NewAttribute(rawValue: "")
- c.addingAttributes(converToCitiesContainerAttributeDictionary(["a": "b", "a": "b", "a": "b"]))
- c.addingAttributes(converToCitiesContainerAttributeDictionary(["a": "b", "a": "b", "a": "b"]))
- c.adding(attributes: converToSimpleAttributeDictionary(["a": 1, "a": 2, "a": 3]))
- c.adding(optionalAttributes: converToOptionalSimpleAttributeDictionary(["a": 1, "a": 2, "a": 3]))
- _ = Container(optionalAttributes: converToOptionalSimpleAttributeDictionary(nil))
+ c.Value = convertToNewAttribute("")
+ c.addingAttributes(convertToCitiesContainerAttributeDictionary(["a": "b", "a": "b", "a": "b"]))
+ c.addingAttributes(convertToCitiesContainerAttributeDictionary(["a": "b", "a": "b", "a": "b"]))
+ c.adding(attributes: convertToSimpleAttributeDictionary(["a": 1, "a": 2, "a": 3]))
+ c.adding(optionalAttributes: convertToOptionalSimpleAttributeDictionary(["a": 1, "a": 2, "a": 3]))
+ _ = Container(optionalAttributes: convertToOptionalSimpleAttributeDictionary(nil))
+ _ = Container(optionalAttrArray: convertToOptionalSimpleAttributeArray(nil))
+ c.adding(attrArray: convertToSimpleAttributeArray(["key1", "key2"]))
+ c.add(single: convertToSimpleAttribute(""))
+ c.add(singleOptional: convertToOptionalSimpleAttribute(nil))
+ _ = convertFromSimpleAttributeDictionary(c.getAttrDictionary())
+ _ = convertFromOptionalSimpleAttributeDictionary(c.getOptionalAttrDictionary())
+ _ = convertFromSimpleAttribute(c.getSingleAttr())
+ _ = convertFromOptionalSimpleAttribute(c.getOptionalSingleAttr())
+ _ = convertFromSimpleAttributeArray(c.getAttrArray())
+ _ = convertFromOptionalSimpleAttributeArray(c.getOptionalAttrArray())
+
+ c.addingAttributes(convertToCitiesContainerAttributeDictionary(convertFromSimpleAttributeDictionary(c.getAttrDictionary())))
+ c.adding(optionalAttributes: convertToOptionalSimpleAttributeDictionary(convertFromSimpleAttributeDictionary(c.getAttrDictionary())))
+
+ c.attrDict = convertToSimpleAttributeDictionary(["a": "b", "a": "b", "a": "b"])
+ c.attrArr = convertToSimpleAttributeArray(["key1", "key2"])
return c.Value.rawValue
}
// Helper function inserted by Swift 4.2 migrator.
-fileprivate func converToCitiesContainerAttributeDictionary(_ input: [String: Any]) -> [Cities.Container.Attribute: Any] {
+fileprivate func convertToNewAttribute(_ input: String) -> NewAttribute {
+ return NewAttribute(rawValue: input)
+}
+
+// Helper function inserted by Swift 4.2 migrator.
+fileprivate func convertToCitiesContainerAttributeDictionary(_ input: [String: Any]) -> [Cities.Container.Attribute: Any] {
return Dictionary(uniqueKeysWithValues: input.map { key, value in (Cities.Container.Attribute(rawValue: key), value)})
}
// Helper function inserted by Swift 4.2 migrator.
-fileprivate func converToSimpleAttributeDictionary(_ input: [String: Any]) -> [SimpleAttribute: Any] {
+fileprivate func convertToSimpleAttributeDictionary(_ input: [String: Any]) -> [SimpleAttribute: Any] {
return Dictionary(uniqueKeysWithValues: input.map { key, value in (SimpleAttribute(rawValue: key), value)})
}
// Helper function inserted by Swift 4.2 migrator.
-fileprivate func converToOptionalSimpleAttributeDictionary(_ input: [String: Any]?) -> [SimpleAttribute: Any]? {
+fileprivate func convertToOptionalSimpleAttributeDictionary(_ input: [String: Any]?) -> [SimpleAttribute: Any]? {
guard let input = input else { return nil }
return Dictionary(uniqueKeysWithValues: input.map { key, value in (SimpleAttribute(rawValue: key), value)})
}
+
+// Helper function inserted by Swift 4.2 migrator.
+fileprivate func convertToOptionalSimpleAttributeArray(_ input: [String]?) -> [SimpleAttribute]? {
+ guard let input = input else { return nil }
+ return input.map { key in SimpleAttribute(key) }
+}
+
+// Helper function inserted by Swift 4.2 migrator.
+fileprivate func convertToSimpleAttributeArray(_ input: [String]) -> [SimpleAttribute] {
+ return input.map { key in SimpleAttribute(key) }
+}
+
+// Helper function inserted by Swift 4.2 migrator.
+fileprivate func convertToSimpleAttribute(_ input: String) -> SimpleAttribute {
+ return SimpleAttribute(rawValue: input)
+}
+
+// Helper function inserted by Swift 4.2 migrator.
+fileprivate func convertToOptionalSimpleAttribute(_ input: String?) -> SimpleAttribute? {
+ guard let input = input else { return nil }
+ return SimpleAttribute(rawValue: input)
+}
+
+// Helper function inserted by Swift 4.2 migrator.
+fileprivate func convertFromSimpleAttributeDictionary(_ input: [SimpleAttribute: Any]) -> [String: Any] {
+ return Dictionary(uniqueKeysWithValues: input.map {key, value in (key.rawValue, value)})
+}
+
+// Helper function inserted by Swift 4.2 migrator.
+fileprivate func convertFromOptionalSimpleAttributeDictionary(_ input: [SimpleAttribute: Any]?) -> [String: Any]? {
+ guard let input = input else { return nil }
+ return Dictionary(uniqueKeysWithValues: input.map {key, value in (key.rawValue, value)})
+}
+
+// Helper function inserted by Swift 4.2 migrator.
+fileprivate func convertFromSimpleAttribute(_ input: SimpleAttribute) -> String {
+ return input.rawValue
+}
+
+// Helper function inserted by Swift 4.2 migrator.
+fileprivate func convertFromOptionalSimpleAttribute(_ input: SimpleAttribute?) -> String? {
+ guard let input = input else { return nil }
+ return input.rawValue
+}
+
+// Helper function inserted by Swift 4.2 migrator.
+fileprivate func convertFromSimpleAttributeArray(_ input: [SimpleAttribute]) -> [String] {
+ return input.map { key in key.rawValue }
+}
+
+// Helper function inserted by Swift 4.2 migrator.
+fileprivate func convertFromOptionalSimpleAttributeArray(_ input: [SimpleAttribute]?) -> [String]? {
+ guard let input = input else { return nil }
+ return input.map { key in key.rawValue }
+}
diff --git a/test/Parse/switch.swift b/test/Parse/switch.swift
index e3945f6..08368cd 100644
--- a/test/Parse/switch.swift
+++ b/test/Parse/switch.swift
@@ -427,12 +427,12 @@
break
}
-switch Whatever.Thing { // expected-warning {{switch must be exhaustive}} expected-note{{add missing case: '.Thing'}}
+switch Whatever.Thing {
@unknown case _, _: // expected-error {{'@unknown' cannot be applied to multiple patterns}}
break
}
-switch Whatever.Thing { // expected-warning {{switch must be exhaustive}} expected-note{{add missing case: '.Thing'}}
+switch Whatever.Thing {
@unknown case _, _, _: // expected-error {{'@unknown' cannot be applied to multiple patterns}}
break
}
@@ -522,3 +522,90 @@
case _:
break
}
+
+switch x { // expected-error {{switch must be exhaustive}}
+case 1:
+ break
+@unknown case _: // expected-note {{remove '@unknown' to handle remaining values}} {{1-10=}}
+ break
+}
+
+switch x { // expected-error {{switch must be exhaustive}}
+@unknown case _: // expected-note {{remove '@unknown' to handle remaining values}} {{1-10=}}
+ break
+}
+
+switch x { // expected-error {{switch must be exhaustive}}
+@unknown default: // expected-note {{remove '@unknown' to handle remaining values}} {{1-10=}}
+ break
+}
+
+switch Whatever.Thing {
+case .Thing:
+ break
+@unknown case _: // expected-error {{'@unknown' can only be applied to the last case in a switch}}
+ break
+@unknown case _:
+ break
+}
+
+switch Whatever.Thing {
+case .Thing:
+ break
+@unknown case _: // expected-error {{'@unknown' can only be applied to the last case in a switch}}
+ break
+@unknown default:
+ break
+}
+
+switch Whatever.Thing {
+case .Thing:
+ break
+@unknown default:
+ break
+@unknown default: // expected-error {{additional 'case' blocks cannot appear after the 'default' block of a 'switch'}}
+ break
+}
+
+switch Whatever.Thing {
+@unknown case _: // expected-error {{'@unknown' can only be applied to the last case in a switch}}
+ break
+@unknown case _:
+ break
+}
+
+switch Whatever.Thing {
+@unknown case _: // expected-error {{'@unknown' can only be applied to the last case in a switch}}
+ break
+@unknown default:
+ break
+}
+
+switch Whatever.Thing {
+@unknown default:
+ break
+@unknown default: // expected-error {{additional 'case' blocks cannot appear after the 'default' block of a 'switch'}}
+ break
+}
+
+
+switch x {
+@unknown case _: // expected-error {{'@unknown' can only be applied to the last case in a switch}}
+ break
+@unknown case _:
+ break
+}
+
+switch x {
+@unknown case _: // expected-error {{'@unknown' can only be applied to the last case in a switch}}
+ break
+@unknown default:
+ break
+}
+
+switch x {
+@unknown default:
+ break
+@unknown default: // expected-error {{additional 'case' blocks cannot appear after the 'default' block of a 'switch'}}
+ break
+}
diff --git a/test/Reflection/typeref_decoding_asan.swift b/test/Reflection/typeref_decoding_asan.swift
new file mode 100644
index 0000000..3532397
--- /dev/null
+++ b/test/Reflection/typeref_decoding_asan.swift
@@ -0,0 +1,732 @@
+// REQUIRES: asan_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-build-swift %S/Inputs/ConcreteTypes.swift %S/Inputs/GenericTypes.swift %S/Inputs/Protocols.swift %S/Inputs/Extensions.swift %S/Inputs/Closures.swift -parse-as-library -emit-module -emit-library -module-name TypesToReflect -sanitize=address -o %t/libTypesToReflect.%target-dylib-extension
+// RUN: %target-swift-reflection-dump -binary-filename %t/libTypesToReflect.%target-dylib-extension | %FileCheck %s
+
+// CHECK: FIELDS:
+// CHECK: =======
+// CHECK: TypesToReflect.Box
+// CHECK: ------------------
+// CHECK: item: A
+// CHECK: (generic_type_parameter depth=0 index=0)
+
+// CHECK: TypesToReflect.C
+// CHECK: ----------------
+// CHECK: aClass: TypesToReflect.C
+// CHECK: (class TypesToReflect.C)
+
+// CHECK: aStruct: TypesToReflect.S
+// CHECK: (struct TypesToReflect.S)
+
+// CHECK: anEnum: TypesToReflect.E
+// CHECK: (enum TypesToReflect.E)
+
+// CHECK: aTuple: (TypesToReflect.C, TypesToReflect.S, TypesToReflect.E, Swift.Int)
+// CHECK: (tuple
+// CHECK: (class TypesToReflect.C)
+// CHECK: (struct TypesToReflect.S)
+// CHECK: (enum TypesToReflect.E)
+// CHECK: (struct Swift.Int))
+
+// CHECK: aTupleWithLabels: (a: TypesToReflect.C, s: TypesToReflect.S, e: TypesToReflect.E)
+// CHECK: (tuple
+// CHECK: (class TypesToReflect.C)
+// CHECK: (struct TypesToReflect.S)
+// CHECK: (enum TypesToReflect.E))
+
+// CHECK: aMetatype: TypesToReflect.C.Type
+// CHECK: (metatype
+// CHECK: (class TypesToReflect.C))
+
+// CHECK: aFunction: (TypesToReflect.C, TypesToReflect.S, TypesToReflect.E, Swift.Int) -> Swift.Int
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (class TypesToReflect.C)
+// CHECK: (struct TypesToReflect.S)
+// CHECK: (enum TypesToReflect.E)
+// CHECK: (struct Swift.Int)
+// CHECK: (result
+// CHECK: (struct Swift.Int))
+
+// CHECK: aFunctionWithVarArgs: (TypesToReflect.C, TypesToReflect.S...) -> ()
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (class TypesToReflect.C)
+// CHECK: (variadic
+// CHECK: (struct TypesToReflect.S))
+// CHECK: (result
+// CHECK: (tuple))
+
+// CHECK: aFunctionWithInout1: (inout TypesToReflect.C) -> ()
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (inout
+// CHECK: (class TypesToReflect.C))
+// CHECK: (result
+// CHECK: (tuple))
+
+// CHECK: aFunctionWithInout2: (TypesToReflect.C, inout Swift.Int) -> ()
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (class TypesToReflect.C)
+// CHECK: (inout
+// CHECK: (struct Swift.Int))
+// CHECK: (result
+// CHECK: (tuple))
+
+// CHECK: aFunctionWithInout3: (inout TypesToReflect.C, inout Swift.Int) -> ()
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (inout
+// CHECK: (class TypesToReflect.C))
+// CHECK: (inout
+// CHECK: (struct Swift.Int))
+// CHECK: (result
+// CHECK: (tuple))
+
+// CHECK: aFunctionWithShared: (__shared TypesToReflect.C) -> ()
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (shared
+// CHECK: (class TypesToReflect.C))
+// CHECK: (result
+// CHECK: (tuple))
+
+// CHECK: TypesToReflect.S.NestedS
+// CHECK: ------------------------
+// CHECK: aField: Swift.Int
+// CHECK: (struct Swift.Int)
+
+// CHECK: TypesToReflect.S
+// CHECK: ----------------
+// CHECK: aClass: TypesToReflect.C
+// CHECK: (class TypesToReflect.C)
+
+// CHECK: aStruct: TypesToReflect.Box<TypesToReflect.S>
+// CHECK: (bound_generic_class TypesToReflect.Box
+// CHECK: (struct TypesToReflect.S))
+
+// CHECK: anEnum: TypesToReflect.Box<TypesToReflect.E>
+// CHECK: (bound_generic_class TypesToReflect.Box
+// CHECK: (enum TypesToReflect.E))
+
+// CHECK: aTuple: (TypesToReflect.C, TypesToReflect.Box<TypesToReflect.S>, TypesToReflect.Box<TypesToReflect.E>, Swift.Int)
+// CHECK: (tuple
+// CHECK: (class TypesToReflect.C)
+// CHECK: (bound_generic_class TypesToReflect.Box
+// CHECK: (struct TypesToReflect.S))
+// CHECK: (bound_generic_class TypesToReflect.Box
+// CHECK: (enum TypesToReflect.E))
+// CHECK: (struct Swift.Int))
+
+// CHECK: aMetatype: TypesToReflect.C.Type
+// CHECK: (metatype
+// CHECK: (class TypesToReflect.C))
+
+// CHECK: aFunction: (TypesToReflect.C, TypesToReflect.S, TypesToReflect.E, Swift.Int) -> Swift.Int
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (class TypesToReflect.C)
+// CHECK: (struct TypesToReflect.S)
+// CHECK: (enum TypesToReflect.E)
+// CHECK: (struct Swift.Int)
+// CHECK: (result
+// CHECK: (struct Swift.Int))
+
+// CHECK: aFunctionWithThinRepresentation: @convention(thin) () -> ()
+// CHECK: (function convention=thin
+// CHECK: (tuple))
+
+// CHECK: aFunctionWithCRepresentation: @convention(c) () -> ()
+// CHECK: (function convention=c
+// CHECK: (tuple))
+
+// CHECK: TypesToReflect.E
+// CHECK: ----------------
+// CHECK: Class: TypesToReflect.C
+// CHECK: (class TypesToReflect.C)
+
+// CHECK: Struct: TypesToReflect.S
+// CHECK: (struct TypesToReflect.S)
+
+// CHECK: Enum: TypesToReflect.E
+// CHECK: (enum TypesToReflect.E)
+
+// CHECK: Function: (TypesToReflect.C, TypesToReflect.S, TypesToReflect.E, Swift.Int) -> ()
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (class TypesToReflect.C)
+// CHECK: (struct TypesToReflect.S)
+// CHECK: (enum TypesToReflect.E)
+// CHECK: (struct Swift.Int)
+// CHECK: (result
+// CHECK: (tuple))
+
+// CHECK: Tuple: (TypesToReflect.C, TypesToReflect.S, Swift.Int)
+// CHECK: (tuple
+// CHECK: (class TypesToReflect.C)
+// CHECK: (struct TypesToReflect.S)
+// CHECK: (struct Swift.Int))
+
+// CHECK: IndirectTuple: (TypesToReflect.C, TypesToReflect.S, TypesToReflect.E, Swift.Int)
+// CHECK: (tuple
+// CHECK: (class TypesToReflect.C)
+// CHECK: (struct TypesToReflect.S)
+// CHECK: (enum TypesToReflect.E)
+// CHECK: (struct Swift.Int))
+
+// CHECK: NestedStruct: TypesToReflect.S.NestedS
+// CHECK: (struct TypesToReflect.S.NestedS
+// CHECK: (struct TypesToReflect.S))
+
+// CHECK: Metatype
+
+// CHECK: EmptyCase
+
+// CHECK: TypesToReflect.References
+// CHECK: -------------------------
+// CHECK: strongRef: TypesToReflect.C
+// CHECK: (class TypesToReflect.C)
+
+// CHECK: weakRef: weak Swift.Optional<TypesToReflect.C>
+// CHECK: (weak_storage
+// CHECK: (bound_generic_enum Swift.Optional
+// CHECK: (class TypesToReflect.C)))
+
+// CHECK: unownedRef: unowned TypesToReflect.C
+// CHECK: (unowned_storage
+// CHECK: (class TypesToReflect.C))
+
+// CHECK: unownedUnsafeRef: unowned(unsafe) TypesToReflect.C
+// CHECK: (unmanaged_storage
+// CHECK: (class TypesToReflect.C))
+
+// CHECK: TypesToReflect.C1
+// CHECK: -----------------
+// CHECK: aClass: TypesToReflect.C1<A>
+// CHECK: (bound_generic_class TypesToReflect.C1
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: aStruct: TypesToReflect.S1<A>
+// CHECK: (bound_generic_struct TypesToReflect.S1
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: anEnum: TypesToReflect.E1<A>
+// CHECK: (bound_generic_enum TypesToReflect.E1
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: function: (TypesToReflect.C1<A>) -> (TypesToReflect.S1<A>) -> (TypesToReflect.E1<A>) -> Swift.Int
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (bound_generic_class TypesToReflect.C1
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (result
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (bound_generic_struct TypesToReflect.S1
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (result
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (bound_generic_enum TypesToReflect.E1
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (result
+// CHECK: (struct Swift.Int))))
+
+// CHECK: tuple: (TypesToReflect.C1<A>, TypesToReflect.S1<A>, TypesToReflect.E1<A>, Swift.Int)
+// CHECK: (tuple
+// CHECK: (bound_generic_class TypesToReflect.C1
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (bound_generic_struct TypesToReflect.S1
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (bound_generic_enum TypesToReflect.E1
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (struct Swift.Int))
+
+// CHECK: dependentMember: A
+// CHECK: (generic_type_parameter depth=0 index=0)
+
+// CHECK: TypesToReflect.C2
+// CHECK: -----------------
+// CHECK: aClass: TypesToReflect.C1<A>
+// CHECK: (bound_generic_class TypesToReflect.C1
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: aStruct: TypesToReflect.S1<A>
+// CHECK: (bound_generic_struct TypesToReflect.S1
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: anEnum: TypesToReflect.E1<A>
+// CHECK: (bound_generic_enum TypesToReflect.E1
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: function: (TypesToReflect.C1<A>) -> (TypesToReflect.S1<A>) -> (TypesToReflect.E1<A>) -> Swift.Int
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (bound_generic_class TypesToReflect.C1
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (result
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (bound_generic_struct TypesToReflect.S1
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (result
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (bound_generic_enum TypesToReflect.E1
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (result
+// CHECK: (struct Swift.Int))))
+
+// CHECK: tuple: (TypesToReflect.C2<A>, TypesToReflect.S2<A>, TypesToReflect.E2<A>, Swift.Int)
+// CHECK: (tuple
+// CHECK: (bound_generic_class TypesToReflect.C2
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (bound_generic_struct TypesToReflect.S2
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (bound_generic_enum TypesToReflect.E2
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (struct Swift.Int))
+
+// CHECK: primaryArchetype: A
+// CHECK: (generic_type_parameter depth=0 index=0)
+
+// CHECK: dependentMember1: A.Inner
+// CHECK: (dependent_member protocol=14TypesToReflect2P1P
+// CHECK: (generic_type_parameter depth=0 index=0) member=Inner)
+
+// CHECK: TypesToReflect.C3
+// CHECK: -----------------
+// CHECK: aClass: TypesToReflect.C3<A>
+// CHECK: (bound_generic_class TypesToReflect.C3
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: aStruct: TypesToReflect.S3<A>
+// CHECK: (bound_generic_struct TypesToReflect.S3
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: anEnum: TypesToReflect.E3<A>
+// CHECK: (bound_generic_enum TypesToReflect.E3
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: function: (TypesToReflect.C3<A>) -> (TypesToReflect.S3<A>) -> (TypesToReflect.E3<A>) -> Swift.Int
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (bound_generic_class TypesToReflect.C3
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (result
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (bound_generic_struct TypesToReflect.S3
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (result
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (bound_generic_enum TypesToReflect.E3
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (result
+// CHECK: (struct Swift.Int))))
+
+// CHECK: tuple: (TypesToReflect.C3<A>, TypesToReflect.S3<A>, TypesToReflect.E3<A>, Swift.Int)
+// CHECK: (tuple
+// CHECK: (bound_generic_class TypesToReflect.C3
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (bound_generic_struct TypesToReflect.S3
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (bound_generic_enum TypesToReflect.E3
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (struct Swift.Int))
+
+// CHECK: primaryArchetype: A
+// CHECK: (generic_type_parameter depth=0 index=0)
+
+// CHECK: dependentMember1: A.Outer
+// CHECK: (dependent_member protocol=14TypesToReflect2P2P
+// CHECK: (generic_type_parameter depth=0 index=0) member=Outer)
+
+// CHECK: dependentMember2: A.Outer.Inner
+// CHECK: (dependent_member protocol=14TypesToReflect2P1P
+// CHECK: (dependent_member protocol=14TypesToReflect2P2P
+// CHECK: (generic_type_parameter depth=0 index=0) member=Outer) member=Inner)
+
+// CHECK: TypesToReflect.C4
+// CHECK: -----------------
+// CHECK: TypesToReflect.S1
+// CHECK: -----------------
+// CHECK: aClass: TypesToReflect.C1<A>
+// CHECK: (bound_generic_class TypesToReflect.C1
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: aStruct: TypesToReflect.Box<TypesToReflect.S1<A>>
+// CHECK: (bound_generic_class TypesToReflect.Box
+// CHECK: (bound_generic_struct TypesToReflect.S1
+// CHECK: (generic_type_parameter depth=0 index=0)))
+
+// CHECK: anEnum: TypesToReflect.Box<TypesToReflect.E1<A>>
+// CHECK: (bound_generic_class TypesToReflect.Box
+// CHECK: (bound_generic_enum TypesToReflect.E1
+// CHECK: (generic_type_parameter depth=0 index=0)))
+
+// CHECK: function: (TypesToReflect.C1<A>) -> (TypesToReflect.S1<A>) -> (TypesToReflect.E1<A>) -> Swift.Int
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (bound_generic_class TypesToReflect.C1
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (result
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (bound_generic_struct TypesToReflect.S1
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (result
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (bound_generic_enum TypesToReflect.E1
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (result
+// CHECK: (struct Swift.Int))))
+
+// CHECK: tuple: (TypesToReflect.C1<A>, TypesToReflect.Box<TypesToReflect.S1<A>>, TypesToReflect.Box<TypesToReflect.E1<A>>, Swift.Int)
+// CHECK: (tuple
+// CHECK: (bound_generic_class TypesToReflect.C1
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (bound_generic_class TypesToReflect.Box
+// CHECK: (bound_generic_struct TypesToReflect.S1
+// CHECK: (generic_type_parameter depth=0 index=0)))
+// CHECK: (bound_generic_class TypesToReflect.Box
+// CHECK: (bound_generic_enum TypesToReflect.E1
+// CHECK: (generic_type_parameter depth=0 index=0)))
+// CHECK: (struct Swift.Int))
+
+// CHECK: primaryArchetype: A
+// CHECK: (generic_type_parameter depth=0 index=0)
+
+// CHECK: TypesToReflect.S2
+// CHECK: -----------------
+// CHECK: aClass: TypesToReflect.C2<A>
+// CHECK: (bound_generic_class TypesToReflect.C2
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: aStruct: TypesToReflect.Box<TypesToReflect.S2<A>>
+// CHECK: (bound_generic_class TypesToReflect.Box
+// CHECK: (bound_generic_struct TypesToReflect.S2
+// CHECK: (generic_type_parameter depth=0 index=0)))
+
+// CHECK: anEnum: TypesToReflect.Box<TypesToReflect.E2<A>>
+// CHECK: (bound_generic_class TypesToReflect.Box
+// CHECK: (bound_generic_enum TypesToReflect.E2
+// CHECK: (generic_type_parameter depth=0 index=0)))
+
+// CHECK: function: (TypesToReflect.C2<A>) -> (TypesToReflect.S2<A>) -> (TypesToReflect.E2<A>) -> Swift.Int
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (bound_generic_class TypesToReflect.C2
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (result
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (bound_generic_struct TypesToReflect.S2
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (result
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (bound_generic_enum TypesToReflect.E2
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (result
+// CHECK: (struct Swift.Int))))
+
+// CHECK: tuple: (TypesToReflect.C2<A>, TypesToReflect.Box<TypesToReflect.S2<A>>, TypesToReflect.Box<TypesToReflect.E2<A>>, Swift.Int)
+// CHECK: (tuple
+// CHECK: (bound_generic_class TypesToReflect.C2
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (bound_generic_class TypesToReflect.Box
+// CHECK: (bound_generic_struct TypesToReflect.S2
+// CHECK: (generic_type_parameter depth=0 index=0)))
+// CHECK: (bound_generic_class TypesToReflect.Box
+// CHECK: (bound_generic_enum TypesToReflect.E2
+// CHECK: (generic_type_parameter depth=0 index=0)))
+// CHECK: (struct Swift.Int))
+
+// CHECK: primaryArchetype: A
+// CHECK: (generic_type_parameter depth=0 index=0)
+
+// CHECK: dependentMember1: A.Inner
+// CHECK: (dependent_member protocol=14TypesToReflect2P1P
+// CHECK: (generic_type_parameter depth=0 index=0) member=Inner)
+
+// CHECK: TypesToReflect.S3
+// CHECK: -----------------
+// CHECK: aClass: TypesToReflect.C3<A>
+// CHECK: (bound_generic_class TypesToReflect.C3
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: aStruct: TypesToReflect.Box<TypesToReflect.S3<A>>
+// CHECK: (bound_generic_class TypesToReflect.Box
+// CHECK: (bound_generic_struct TypesToReflect.S3
+// CHECK: (generic_type_parameter depth=0 index=0)))
+
+// CHECK: anEnum: TypesToReflect.Box<TypesToReflect.E3<A>>
+// CHECK: (bound_generic_class TypesToReflect.Box
+// CHECK: (bound_generic_enum TypesToReflect.E3
+// CHECK: (generic_type_parameter depth=0 index=0)))
+
+// CHECK: function: (TypesToReflect.C3<A>) -> (TypesToReflect.S3<A>) -> (TypesToReflect.E3<A>) -> Swift.Int
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (bound_generic_class TypesToReflect.C3
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (result
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (bound_generic_struct TypesToReflect.S3
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (result
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (bound_generic_enum TypesToReflect.E3
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (result
+// CHECK: (struct Swift.Int))))
+
+// CHECK: tuple: (TypesToReflect.C3<A>, TypesToReflect.Box<TypesToReflect.S3<A>>, TypesToReflect.Box<TypesToReflect.E3<A>>, Swift.Int)
+// CHECK: (tuple
+// CHECK: (bound_generic_class TypesToReflect.C3
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (bound_generic_class TypesToReflect.Box
+// CHECK: (bound_generic_struct TypesToReflect.S3
+// CHECK: (generic_type_parameter depth=0 index=0)))
+// CHECK: (bound_generic_class TypesToReflect.Box
+// CHECK: (bound_generic_enum TypesToReflect.E3
+// CHECK: (generic_type_parameter depth=0 index=0)))
+// CHECK: (struct Swift.Int))
+
+// CHECK: primaryArchetype: A
+// CHECK: (generic_type_parameter depth=0 index=0)
+
+// CHECK: dependentMember1: A.Outer
+// CHECK: (dependent_member protocol=14TypesToReflect2P2P
+// CHECK: (generic_type_parameter depth=0 index=0) member=Outer)
+
+// CHECK: dependentMember2: A.Outer.Inner
+// CHECK: (dependent_member protocol=14TypesToReflect2P1P
+// CHECK: (dependent_member protocol=14TypesToReflect2P2P
+// CHECK: (generic_type_parameter depth=0 index=0) member=Outer) member=Inner)
+
+// CHECK: TypesToReflect.S4
+// CHECK: -----------------
+// CHECK: TypesToReflect.E1
+// CHECK: -----------------
+// CHECK: Class: TypesToReflect.C1<A>
+// CHECK: (bound_generic_class TypesToReflect.C1
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: Struct: TypesToReflect.S1<A>
+// CHECK: (bound_generic_struct TypesToReflect.S1
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: Enum: TypesToReflect.E1<A>
+// CHECK: (bound_generic_enum TypesToReflect.E1
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: Int: Swift.Int
+// CHECK: (struct Swift.Int)
+
+// CHECK: Function: (A) -> TypesToReflect.E1<A>
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (generic_type_parameter depth=0 index=0)
+// CHECK: (result
+// CHECK: (bound_generic_enum TypesToReflect.E1
+// CHECK: (generic_type_parameter depth=0 index=0)))
+
+// CHECK: Tuple: (TypesToReflect.C1<A>, TypesToReflect.S1<A>, Swift.Int)
+// CHECK: (tuple
+// CHECK: (bound_generic_class TypesToReflect.C1
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (bound_generic_struct TypesToReflect.S1
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (struct Swift.Int))
+
+// CHECK: Primary: A
+// CHECK: (generic_type_parameter depth=0 index=0)
+
+// CHECK: Metatype: A.Type
+// CHECK: (metatype
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: TypesToReflect.E2
+// CHECK: -----------------
+// CHECK: Class: TypesToReflect.C2<A>
+// CHECK: (bound_generic_class TypesToReflect.C2
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: Struct: TypesToReflect.S2<A>
+// CHECK: (bound_generic_struct TypesToReflect.S2
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: Enum: TypesToReflect.E2<A>
+// CHECK: (bound_generic_enum TypesToReflect.E2
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: Function: (A.Type) -> TypesToReflect.E1<A>
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (metatype
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (result
+// CHECK: (bound_generic_enum TypesToReflect.E1
+// CHECK: (generic_type_parameter depth=0 index=0)))
+
+// CHECK: Tuple: (TypesToReflect.C2<A>, TypesToReflect.S2<A>, Swift.Int)
+// CHECK: (tuple
+// CHECK: (bound_generic_class TypesToReflect.C2
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (bound_generic_struct TypesToReflect.S2
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (struct Swift.Int))
+
+// CHECK: Primary: A
+// CHECK: (generic_type_parameter depth=0 index=0)
+
+// CHECK: DependentMemberInner: A.Inner
+// CHECK: (dependent_member protocol=14TypesToReflect2P1P
+// CHECK: (generic_type_parameter depth=0 index=0) member=Inner)
+
+// CHECK: ExistentialMetatype: A.Type
+// CHECK: (metatype
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: TypesToReflect.E3
+// CHECK: -----------------
+// CHECK: Class: TypesToReflect.C3<A>
+// CHECK: (bound_generic_class TypesToReflect.C3
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: Struct: TypesToReflect.S3<A>
+// CHECK: (bound_generic_struct TypesToReflect.S3
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: Enum: TypesToReflect.E3<A>
+// CHECK: (bound_generic_enum TypesToReflect.E3
+// CHECK: (generic_type_parameter depth=0 index=0))
+
+// CHECK: Function: (A.Type.Type) -> TypesToReflect.E1<A>
+// CHECK: (function
+// CHECK: (parameters
+// CHECK: (metatype
+// CHECK: (metatype
+// CHECK: (generic_type_parameter depth=0 index=0)))
+// CHECK: (result
+// CHECK: (bound_generic_enum TypesToReflect.E1
+// CHECK: (generic_type_parameter depth=0 index=0)))
+
+// CHECK: Tuple: (TypesToReflect.C3<A>, TypesToReflect.S3<A>, Swift.Int)
+// CHECK: (tuple
+// CHECK: (bound_generic_class TypesToReflect.C3
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (bound_generic_struct TypesToReflect.S3
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: (struct Swift.Int))
+
+// CHECK: Primary: A
+// CHECK: (generic_type_parameter depth=0 index=0)
+
+// CHECK: DependentMemberOuter: A.Outer
+// CHECK: (dependent_member protocol=14TypesToReflect2P2P
+// CHECK: (generic_type_parameter depth=0 index=0) member=Outer)
+
+// CHECK: DependentMemberInner: A.Outer.Inner
+// CHECK: (dependent_member protocol=14TypesToReflect2P1P
+// CHECK: (dependent_member protocol=14TypesToReflect2P2P
+// CHECK: (generic_type_parameter depth=0 index=0) member=Outer) member=Inner)
+
+// CHECK: TypesToReflect.E4
+// CHECK: -----------------
+// CHECK: TypesToReflect.P1
+// CHECK: -----------------
+// CHECK: TypesToReflect.P2
+// CHECK: -----------------
+// CHECK: TypesToReflect.P3
+// CHECK: -----------------
+// CHECK: TypesToReflect.P4
+// CHECK: -----------------
+// CHECK: TypesToReflect.ClassBoundP
+// CHECK: --------------------------
+
+// CHECK: TypesToReflect.(FileprivateProtocol in _{{[0-9A-F]+}})
+// CHECK: -------------------------------------------------------------------------
+
+// CHECK: TypesToReflect.HasFileprivateProtocol
+// CHECK: -------------------------------------
+// CHECK: x: TypesToReflect.(FileprivateProtocol in _{{[0-9A-F]+}})
+// CHECK: (protocol_composition
+// CHECK-NEXT: (protocol TypesToReflect.(FileprivateProtocol in _{{[0-9A-F]+}})))
+
+// CHECK: ASSOCIATED TYPES:
+// CHECK: =================
+// CHECK: - TypesToReflect.C1 : TypesToReflect.ClassBoundP
+// CHECK: typealias Inner = A
+// CHECK: (generic_type_parameter depth=0 index=0)
+
+// CHECK: - TypesToReflect.C4 : TypesToReflect.P1
+// CHECK: typealias Inner = A
+// CHECK: (generic_type_parameter depth=0 index=0)
+
+// CHECK: - TypesToReflect.C4 : TypesToReflect.P2
+// CHECK: typealias Outer = A
+// CHECK: (generic_type_parameter depth=0 index=0)
+
+// CHECK: - TypesToReflect.S4 : TypesToReflect.P1
+// CHECK: typealias Inner = A
+// CHECK: (generic_type_parameter depth=0 index=0)
+
+// CHECK: - TypesToReflect.S4 : TypesToReflect.P2
+// CHECK: typealias Outer = A
+// CHECK: (generic_type_parameter depth=0 index=0)
+
+// CHECK: - TypesToReflect.E4 : TypesToReflect.P1
+// CHECK: typealias Inner = A
+// CHECK: (generic_type_parameter depth=0 index=0)
+
+// CHECK: - TypesToReflect.E4 : TypesToReflect.P2
+// CHECK: typealias Outer = B
+// CHECK: (generic_type_parameter depth=0 index=1)
+
+// CHECK: - TypesToReflect.E4 : TypesToReflect.P3
+// CHECK: typealias First = A
+// CHECK: (generic_type_parameter depth=0 index=0)
+
+// CHECK: typealias Second = B
+// CHECK: (generic_type_parameter depth=0 index=1)
+
+// CHECK: - TypesToReflect.S : TypesToReflect.P4
+// CHECK: typealias Result = Swift.Int
+// CHECK: (struct Swift.Int)
+
+// CHECK: BUILTIN TYPES:
+// CHECK: ==============
+
+// CHECK: CAPTURE DESCRIPTORS:
+// CHECK: ====================
+// CHECK: - Capture types:
+// CHECK: (sil_box
+// CHECK: (generic_type_parameter depth=0 index=0))
+// CHECK: - Metadata sources:
+// CHECK: (generic_type_parameter depth=0 index=0)
+// CHECK: (closure_binding index=0)
+// CHECK: (generic_type_parameter depth=0 index=1)
+// CHECK: (closure_binding index=1)
+
+// CHECK: - Capture types:
+// CHECK: (struct Swift.Int)
+// CHECK: - Metadata sources:
+
+// CHECK: - Capture types:
+// CHECK: (bound_generic_class TypesToReflect.C1
+// CHECK: (generic_type_parameter depth=0 index=1))
+// CHECK: - Metadata sources:
+// CHECK: (generic_type_parameter depth=0 index=0)
+// CHECK: (closure_binding index=0)
+// CHECK: (generic_type_parameter depth=0 index=1)
+// CHECK: (generic_argument index=0
+// CHECK: (reference_capture index=0))
+
diff --git a/test/SIL/Parser/basic.sil b/test/SIL/Parser/basic.sil
index 4e0631c..5b3a646 100644
--- a/test/SIL/Parser/basic.sil
+++ b/test/SIL/Parser/basic.sil
@@ -1343,10 +1343,16 @@
}
// CHECK-LABEL: sil @convert_function_trivial
// CHECK: %1 = convert_escape_to_noescape %0 : $@callee_guaranteed (AnyObject) -> Optional<AnyObject> to $@noescape @callee_guaranteed (Optional<AnyObject>) -> AnyObject
+// CHECK: %2 = convert_escape_to_noescape [not_guaranteed] %0 : $@callee_guaranteed (AnyObject) -> Optional<AnyObject> to $@noescape @callee_guaranteed (Optional<AnyObject>) -> AnyObject
+// CHECK: %3 = convert_escape_to_noescape [escaped] %0 : $@callee_guaranteed (AnyObject) -> Optional<AnyObject> to $@noescape @callee_guaranteed (Optional<AnyObject>) -> AnyObject
+// CHECK: %4 = convert_escape_to_noescape [not_guaranteed] [escaped] %0 : $@callee_guaranteed (AnyObject) -> Optional<AnyObject> to $@noescape @callee_guaranteed (Optional<AnyObject>) -> AnyObject
// CHECK: return
sil @convert_function_trivial : $@convention(thin) (@owned @callee_guaranteed (AnyObject) -> Optional<AnyObject>) -> () {
entry(%0 : $@callee_guaranteed (AnyObject) -> Optional<AnyObject>):
%1 = convert_escape_to_noescape %0 : $@callee_guaranteed (AnyObject) -> Optional<AnyObject> to $@noescape @callee_guaranteed (Optional<AnyObject>) -> AnyObject
+ %2 = convert_escape_to_noescape [not_guaranteed] %0 : $@callee_guaranteed (AnyObject) -> Optional<AnyObject> to $@noescape @callee_guaranteed (Optional<AnyObject>) -> AnyObject
+ %3 = convert_escape_to_noescape [escaped] %0 : $@callee_guaranteed (AnyObject) -> Optional<AnyObject> to $@noescape @callee_guaranteed (Optional<AnyObject>) -> AnyObject
+ %4 = convert_escape_to_noescape [not_guaranteed] [escaped] %0 : $@callee_guaranteed (AnyObject) -> Optional<AnyObject> to $@noescape @callee_guaranteed (Optional<AnyObject>) -> AnyObject
return undef : $()
}
diff --git a/test/SIL/Serialization/Inputs/def_public_non_abi.sil b/test/SIL/Serialization/Inputs/def_public_non_abi.sil
index 4010b44..927ccef 100644
--- a/test/SIL/Serialization/Inputs/def_public_non_abi.sil
+++ b/test/SIL/Serialization/Inputs/def_public_non_abi.sil
@@ -1,4 +1,10 @@
+sil non_abi [serialized] @other_public_non_abi_function : $@convention(thin) () -> () {
+ %0 = tuple ()
+ return %0 : $()
+}
+
sil non_abi [serialized] @public_non_abi_function : $@convention(thin) () -> () {
+ %fn = function_ref @other_public_non_abi_function : $@convention(thin) () -> ()
%0 = tuple ()
return %0 : $()
}
\ No newline at end of file
diff --git a/test/SIL/Serialization/deserialize_generic.sil b/test/SIL/Serialization/deserialize_generic.sil
index d4873c2..6e1c1b9 100644
--- a/test/SIL/Serialization/deserialize_generic.sil
+++ b/test/SIL/Serialization/deserialize_generic.sil
@@ -1,7 +1,7 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/def_generic.swift
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -linker -I %t %s | %FileCheck %s
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -performance-linker -I %t %s | %FileCheck %s
// Make sure that SILFunctionType with GenericSignature can match up with
// SILFunctionType deserialized from module.
diff --git a/test/SIL/Serialization/deserialize_generic_marker.sil b/test/SIL/Serialization/deserialize_generic_marker.sil
index 2cb3109..766b322 100644
--- a/test/SIL/Serialization/deserialize_generic_marker.sil
+++ b/test/SIL/Serialization/deserialize_generic_marker.sil
@@ -1,7 +1,7 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/def_generic_marker.swift
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -linker -I %t %s | %FileCheck %s
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -performance-linker -I %t %s | %FileCheck %s
// Make sure that SILFunctionType with GenericSignature can match up with
// SILFunctionType deserialized from module.
diff --git a/test/SIL/Serialization/function_param_convention.sil b/test/SIL/Serialization/function_param_convention.sil
index 80fe6ef..9503baa 100644
--- a/test/SIL/Serialization/function_param_convention.sil
+++ b/test/SIL/Serialization/function_param_convention.sil
@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -parse-sil -sil-inline-threshold 0 %S/Inputs/function_param_convention_input.sil -o %t/FunctionInput.swiftmodule -emit-module -parse-as-library -parse-stdlib -module-name FunctionInput -O
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -I %t -linker %s -o - | %FileCheck %s
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -I %t -performance-linker %s -o - | %FileCheck %s
import Swift
import FunctionInput
diff --git a/test/SIL/Serialization/public_non_abi.sil b/test/SIL/Serialization/public_non_abi.sil
index 68ef9d8..32f14a9 100644
--- a/test/SIL/Serialization/public_non_abi.sil
+++ b/test/SIL/Serialization/public_non_abi.sil
@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/def_public_non_abi.sil
-// RUN: %target-sil-opt -linker -I %t %s | %FileCheck %s
+// RUN: %target-swift-frontend -emit-sil -I %t %s | %FileCheck %s
sil_stage raw
@@ -20,6 +20,11 @@
}
// Make sure the function body is deserialized.
-// CHECK-LABEL: sil shared_external [serialized] [canonical] @public_non_abi_function : $@convention(thin) () -> ()
+// CHECK-LABEL: sil shared_external [serialized] @public_non_abi_function : $@convention(thin) () -> ()
+// CHECK: function_ref @other_public_non_abi_function
// CHECK: return
sil hidden_external [serialized] @public_non_abi_function : $@convention(thin) () -> ()
+
+// Make sure the function body is deserialized.
+// CHECK-LABEL: sil shared_external [serialized] @other_public_non_abi_function : $@convention(thin) () -> ()
+// CHECK: return
\ No newline at end of file
diff --git a/test/SIL/Serialization/shared_function_serialization.sil b/test/SIL/Serialization/shared_function_serialization.sil
index c784fb7..afcf991 100644
--- a/test/SIL/Serialization/shared_function_serialization.sil
+++ b/test/SIL/Serialization/shared_function_serialization.sil
@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend %S/Inputs/shared_function_serialization_input.swift -o %t/Swift.swiftmodule -emit-module -parse-as-library -parse-stdlib -module-link-name swiftCore -module-name Swift -O
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -I %t -linker -inline %s -o - | %FileCheck %s
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -I %t -performance-linker -inline %s -o - | %FileCheck %s
// CHECK: sil private @top_level_code
// CHECK: sil public_external [serialized] @$Ss1XVABycfC{{.*}}
diff --git a/test/SIL/Serialization/vtable_deserialization.swift b/test/SIL/Serialization/vtable_deserialization.swift
index fb2862e..8efc0eb 100644
--- a/test/SIL/Serialization/vtable_deserialization.swift
+++ b/test/SIL/Serialization/vtable_deserialization.swift
@@ -11,13 +11,10 @@
Class.firstMethod()
-// For now, we also deserialize the body of firstMethod(), even though it
-// is not transparent.
-// CHECK-LABEL: sil public_external [serialized] @$S28vtable_deserialization_input5ClassC11firstMethodyyFZ : $@convention(method) (@thick Class.Type) -> () {
-// OPT-LABEL: sil public_external @$S28vtable_deserialization_input5ClassC11firstMethodyyFZ : $@convention(method) (@thick Class.Type) -> () {
+// The methods should not be deserialized in the mandatory pipeline.
-// The other two methods should not be deserialized in the mandatory
-// pipeline.
+// CHECK-LABEL: sil [serialized] @$S28vtable_deserialization_input5ClassC11firstMethodyyFZ : $@convention(method) (@thick Class.Type) -> (){{$}}
+// OPT-LABEL: sil public_external @$S28vtable_deserialization_input5ClassC11firstMethodyyFZ : $@convention(method) (@thick Class.Type) -> () {
// CHECK-LABEL: sil [serialized] @$S28vtable_deserialization_input5ClassC12secondMethodyyFZ : $@convention(method) (@thick Class.Type) -> (){{$}}
// OPT-LABEL: sil public_external @$S28vtable_deserialization_input5ClassC12secondMethodyyFZ : $@convention(method) (@thick Class.Type) -> () {
diff --git a/test/SILGen/auto_closures.swift b/test/SILGen/auto_closures.swift
index 5390dbe..3d69064 100644
--- a/test/SILGen/auto_closures.swift
+++ b/test/SILGen/auto_closures.swift
@@ -16,7 +16,7 @@
func test_auto_closure_with_capture(_ x: Bool) -> Bool {
// CHECK: [[CLOSURE:%.*]] = function_ref @$S13auto_closures05test_A21_closure_with_capture
// CHECK: [[WITHCAPTURE:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE]](
- // CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[WITHCAPTURE]]
+ // CHECK: [[CVT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[WITHCAPTURE]]
// CHECK: [[RET:%.*]] = apply {{%.*}}([[CVT]])
// CHECK: return [[RET]]
return call_auto_closure(x)
@@ -42,7 +42,7 @@
// CHECK: [[AUTOCLOSURE_FUNC:%.*]] = function_ref @$S13auto_closures3SubC1xAA4BoolVvgAFyXKfu_ : $@convention(thin) (@guaranteed Sub) -> Bool
// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
// CHECK: [[AUTOCLOSURE:%.*]] = partial_apply [callee_guaranteed] [[AUTOCLOSURE_FUNC]]([[SELF_COPY]])
- // CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[AUTOCLOSURE]]
+ // CHECK: [[CVT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[AUTOCLOSURE]]
// CHECK: [[AUTOCLOSURE_CONSUMER:%.*]] = function_ref @$S13auto_closures05call_A8_closureyAA4BoolVADyXKF : $@convention(thin)
// CHECK: [[RET:%.*]] = apply [[AUTOCLOSURE_CONSUMER]]([[CVT]])
// CHECK: return [[RET]] : $Bool
diff --git a/test/SILGen/builtins.swift b/test/SILGen/builtins.swift
index 3261aa3..588c682 100644
--- a/test/SILGen/builtins.swift
+++ b/test/SILGen/builtins.swift
@@ -369,6 +369,35 @@
return Builtin.getTailAddr_Word(start, i, ty1, ty2)
}
+// CHECK-LABEL: sil hidden @$S8builtins25beginUnpairedModifyAccess{{[_0-9a-zA-Z]*}}F
+// CHECK: [[P2A_ADDR:%.*]] = pointer_to_address %0
+// CHECK: [[P2A_SCRATCH:%.*]] = pointer_to_address %1
+// CHECK: begin_unpaired_access [modify] [dynamic] [[P2A_ADDR]] : $*T1, [[P2A_SCRATCH]] : $*Builtin.UnsafeValueBuffer
+// CHECK: [[RESULT:%.*]] = tuple ()
+// CHECK: [[RETURN:%.*]] = tuple ()
+// CHECK: return [[RETURN]] : $()
+// CHECK: } // end sil function '$S8builtins25beginUnpairedModifyAccess{{[_0-9a-zA-Z]*}}F'
+func beginUnpairedModifyAccess<T1>(address: Builtin.RawPointer, scratch: Builtin.RawPointer, ty1: T1.Type) {
+ Builtin.beginUnpairedModifyAccess(address, scratch, ty1);
+}
+
+// CHECK-LABEL: sil hidden @$S8builtins17endUnpairedAccess{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Builtin.RawPointer) -> () {
+// CHECK: [[P2A_ADDR:%.*]] = pointer_to_address %0
+// CHECK: end_unpaired_access [dynamic] [[P2A_ADDR]]
+// CHECK: } // end sil function '$S8builtins17endUnpairedAccess{{[_0-9a-zA-Z]*}}F'
+func endUnpairedAccess(address: Builtin.RawPointer) {
+ Builtin.endUnpairedAccess(address)
+}
+
+// CHECK-LABEL: sil hidden @$S8builtins30performInstantaneousReadAccess{{[_0-9a-zA-Z]*}}F
+// CHECK: [[P2A_ADDR:%.*]] = pointer_to_address %0
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [no_nested_conflict] [[P2A_ADDR]] : $*T1
+// CHECK-NEXT: end_access [[ACCESS]] : $*T1
+// CHECK: } // end sil function '$S8builtins30performInstantaneousReadAccess{{[_0-9a-zA-Z]*}}F'
+func performInstantaneousReadAccess<T1>(address: Builtin.RawPointer, scratch: Builtin.RawPointer, ty1: T1.Type) {
+ Builtin.performInstantaneousReadAccess(address, ty1);
+}
+
// CHECK-LABEL: sil hidden @$S8builtins8condfail{{[_0-9a-zA-Z]*}}F
func condfail(_ i: Builtin.Int1) {
Builtin.condfail(i)
diff --git a/test/SILGen/closures.swift b/test/SILGen/closures.swift
index 1a38391..ca8fd5f 100644
--- a/test/SILGen/closures.swift
+++ b/test/SILGen/closures.swift
@@ -614,9 +614,9 @@
// CHECK: [[INNER:%.*]] = function_ref @[[INNER_FUNC_2:\$S8closures8SuperSubC1fyyFyycfU_yyKXKfu_]] : $@convention(thin) (@guaranteed SuperSub) -> @error Error
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[INNER]]([[ARG_COPY]])
- // CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[PA]]
+ // CHECK: [[CVT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PA]]
// CHECK: [[REABSTRACT_PA:%.*]] = partial_apply [callee_guaranteed] {{.*}}([[CVT]])
- // CHECK: [[REABSTRACT_CVT:%.*]] = convert_escape_to_noescape [[REABSTRACT_PA]]
+ // CHECK: [[REABSTRACT_CVT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[REABSTRACT_PA]]
// CHECK: [[TRY_APPLY_AUTOCLOSURE:%.*]] = function_ref @$Ss2qqoiyxxSg_xyKXKtKlF : $@convention(thin) <τ_0_0> (@in_guaranteed Optional<τ_0_0>, @noescape @callee_guaranteed () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error)
// CHECK: try_apply [[TRY_APPLY_AUTOCLOSURE]]<()>({{.*}}, {{.*}}, [[REABSTRACT_CVT]]) : $@convention(thin) <τ_0_0> (@in_guaranteed Optional<τ_0_0>, @noescape @callee_guaranteed () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error), normal [[NORMAL_BB:bb1]], error [[ERROR_BB:bb2]]
// CHECK: [[NORMAL_BB]]{{.*}}
@@ -646,9 +646,9 @@
// CHECK: [[INNER:%.*]] = function_ref @[[INNER_FUNC_2:\$S8closures8SuperSubC1g.*]] : $@convention(thin) (@guaranteed SuperSub) -> @error Error
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[INNER]]([[ARG_COPY]])
- // CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[PA]] : $@callee_guaranteed () -> @error Error to $@noescape @callee_guaranteed () -> @error Error
+ // CHECK: [[CVT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PA]] : $@callee_guaranteed () -> @error Error to $@noescape @callee_guaranteed () -> @error Error
// CHECK: [[REABSTRACT_PA:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[CVT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> @error Error) -> (@out (), @error Error)
- // CHECK: [[REABSTRACT_CVT:%.*]] = convert_escape_to_noescape [[REABSTRACT_PA]]
+ // CHECK: [[REABSTRACT_CVT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[REABSTRACT_PA]]
// CHECK: [[TRY_APPLY_FUNC:%.*]] = function_ref @$Ss2qqoiyxxSg_xyKXKtKlF : $@convention(thin) <τ_0_0> (@in_guaranteed Optional<τ_0_0>, @noescape @callee_guaranteed () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error)
// CHECK: try_apply [[TRY_APPLY_FUNC]]<()>({{.*}}, {{.*}}, [[REABSTRACT_CVT]]) : $@convention(thin) <τ_0_0> (@in_guaranteed Optional<τ_0_0>, @noescape @callee_guaranteed () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error), normal [[NORMAL_BB:bb1]], error [[ERROR_BB:bb2]]
// CHECK: [[NORMAL_BB]]{{.*}}
@@ -694,7 +694,7 @@
// CHECK: destroy_value [[SELF]]
// -- closure takes unowned ownership
// CHECK: [[OUTER_CLOSURE:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[UNOWNED_SELF2_COPY]])
-// CHECK: [[OUTER_CONVERT:%.*]] = convert_escape_to_noescape [[OUTER_CLOSURE]]
+// CHECK: [[OUTER_CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[OUTER_CLOSURE]]
// -- call consumes closure
// -- strong +1, unowned +1
// CHECK: [[INNER_CLOSURE:%.*]] = apply [[OUTER_CONVERT]]
diff --git a/test/SILGen/coverage_class.swift b/test/SILGen/coverage_class.swift
index d27df0a..97fee71 100644
--- a/test/SILGen/coverage_class.swift
+++ b/test/SILGen/coverage_class.swift
@@ -3,7 +3,8 @@
class C {
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_class.C.foo
func foo() {}
- // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_class.C.__allocating_init
+ // CHECK: sil_coverage_map {{.*}}// __ntd_C_line:[[@LINE-3]]:1
+ // CHECK-NEXT: [[@LINE+1]]:10 -> [[@LINE+1]]:12
init() {}
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_class.C.__deallocating_deinit
deinit {}
@@ -17,7 +18,7 @@
struct S {
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_class.S.foo
func foo() {}
- // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_class.S.init
+ // CHECK: sil_coverage_map {{.*}}// __ntd_S_line:[[@LINE-3]]:1
init() {}
}
@@ -25,6 +26,16 @@
case X, Y, Z
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_class.E.foo
func foo() {}
- // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_class.E.init
+ // CHECK: sil_coverage_map {{.*}}// __ntd_E_line:[[@LINE-4]]:1
+ // CHECK-NEXT: [[@LINE+1]]:10 -> [[@LINE+1]]:23
init() { self = .Y }
}
+
+var g1: Bool = true
+
+struct S2 {
+ // CHECK: sil_coverage_map {{.*}}// __ntd_S2_line:[[@LINE-1]]:1
+ // CHECK-NEXT: [[@LINE+2]]:22 -> [[@LINE+2]]:23 : 0
+ // CHECK-NEXT: [[@LINE+1]]:26 -> [[@LINE+1]]:27 : (1 - 0)
+ var m1: Int = g1 ? 0 : 1
+}
diff --git a/test/SILGen/coverage_closures.swift b/test/SILGen/coverage_closures.swift
index 837e662..6fdf8d9 100644
--- a/test/SILGen/coverage_closures.swift
+++ b/test/SILGen/coverage_closures.swift
@@ -3,15 +3,10 @@
// rdar://39200851: Closure in init method covered twice
class C2 {
-// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_closures.C2.__allocating_init()
-// CHECK-NEXT: [[@LINE+7]]:10 -> [[@LINE+11]]:4 : 0
-// CHECK-NEXT: }
-
-// CHECK-LABEL: sil_coverage_map {{.*}}// closure #1 () -> () in coverage_closures.C2.init()
-// CHECK-NEXT: [[@LINE+4]]:13 -> [[@LINE+6]]:6 : 0
-// CHECK-NEXT: }
-
init() {
+// CHECK-LABEL: sil_coverage_map {{.*}}// closure #1 () -> () in coverage_closures.C2.init()
+// CHECK-NEXT: [[@LINE+2]]:13 -> [[@LINE+4]]:6 : 0
+// CHECK-NEXT: }
let _ = { () in
print("hello")
}
diff --git a/test/SILGen/coverage_exceptions.swift b/test/SILGen/coverage_exceptions.swift
index e0c68fb..c434f82 100644
--- a/test/SILGen/coverage_exceptions.swift
+++ b/test/SILGen/coverage_exceptions.swift
@@ -5,17 +5,6 @@
case Err2
}
-struct S {
- // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_catch.S.init
- init() {
- do {
- throw SomeErr.Err1
- } catch {
- // CHECK: [[@LINE-1]]:13 -> [[@LINE+1]]:6 : 2
- } // CHECK: [[@LINE]]:6 -> [[@LINE+1]]:4 : 1
- }
-}
-
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_catch.bar
func bar() throws {
// CHECK-NEXT: [[@LINE-1]]:19 -> [[@LINE+2]]:2 : 0
@@ -62,3 +51,14 @@
}
foo()
+
+struct S {
+ // CHECK: sil_coverage_map {{.*}}// __ntd_S_line:[[@LINE-1]]
+ init() {
+ do {
+ throw SomeErr.Err1
+ } catch {
+ // CHECK: [[@LINE-1]]:13 -> [[@LINE+1]]:6 : 2
+ } // CHECK: [[@LINE]]:6 -> [[@LINE+1]]:4 : 1
+ }
+}
diff --git a/test/SILGen/coverage_member_closure.swift b/test/SILGen/coverage_member_closure.swift
index 21af473..4e2b022 100644
--- a/test/SILGen/coverage_member_closure.swift
+++ b/test/SILGen/coverage_member_closure.swift
@@ -1,13 +1,6 @@
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -emit-sil -module-name coverage_member_closure %s | %FileCheck %s
class C {
- // CHECK-LABEL: sil_coverage_map {{.*}}// coverage_member_closure.C.__allocating_init
- init() {
- if (false) { // CHECK: [[@LINE]]:16 -> [[@LINE+2]]:6 : 1
- // ...
- }
- }
-
// Closures in members receive their own coverage mapping.
// CHECK: sil_coverage_map {{.*}} $S23coverage_member_closure1CC17completionHandleryySS_SaySSGtcvpfiySS_AEtcfU_
// CHECK: [[@LINE+1]]:55 -> [[@LINE+1]]:79 : 0
diff --git a/test/SILGen/coverage_smoke.swift b/test/SILGen/coverage_smoke.swift
index 1303d7a..31d4918 100644
--- a/test/SILGen/coverage_smoke.swift
+++ b/test/SILGen/coverage_smoke.swift
@@ -35,7 +35,7 @@
deinit {}
}
-// CHECK-MAIN: Maximum function count: 3
+// CHECK-MAIN: Maximum function count: 4
func main() {
// CHECK-COV: {{ *}}[[@LINE+1]]|{{ *}}1{{.*}}f_public
f_public()
@@ -85,9 +85,69 @@
let _ = use_auto_closure(true) // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}3
}
+class Class2 {
+ var field: Int
+ init(field: Int) {
+ if field > 0 {
+ self.field = 0 // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}1
+ } else {
+ self.field = 1 // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}3
+ }
+ }
+}
+
+extension Class2 {
+ convenience init() {
+ self.init(field: 0) // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}1
+ }
+}
+
+class SubClass1: Class2 {
+ override init(field: Int) {
+ super.init(field: field) // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}1
+ }
+}
+
+struct Struct1 {
+ var field: Int
+ init(field: Int) {
+ if field > 0 {
+ self.field = 0 // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}1
+ } else {
+ self.field = 1 // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}1
+ }
+ }
+}
+
+extension Struct1 {
+ init() {
+ self.init(field: 0) // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}1
+ }
+}
+
+var g2: Int = 0
+
+class Class3 {
+ var m1 = g2 == 0
+ ? "false" // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}1
+ : "true"; // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}1
+}
+
main() // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}1
foo() // CHECK-COV: {{ *}}[[@LINE]]|{{ *}}1
call_closure()
call_auto_closure()
+let _ = Class2(field: 0)
+let _ = Class2(field: 1)
+let _ = Class2()
+let _ = SubClass1(field: 0)
+
+let _ = Class3()
+g2 = 1
+let _ = Class3()
+
+let _ = Struct1(field: 1)
+let _ = Struct1()
+
// CHECK-REPORT: TOTAL {{.*}} 100.00% {{.*}} 100.00%
diff --git a/test/SILGen/coverage_ternary.swift b/test/SILGen/coverage_ternary.swift
index 6eb7b1d..a32b612 100644
--- a/test/SILGen/coverage_ternary.swift
+++ b/test/SILGen/coverage_ternary.swift
@@ -1,6 +1,6 @@
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -profile-generate -profile-coverage-mapping -emit-sorted-sil -emit-sil -module-name coverage_ternary %s | %FileCheck %s
-// CHECK-LABEL: sil hidden @$S16coverage_ternary3barCACycfC
+// CHECK-LABEL: sil hidden @$S16coverage_ternary3barCACycfc
// CHECK-NOT: return
// CHECK: builtin "int_instrprof_increment"
@@ -8,13 +8,7 @@
// CHECK-NOT: return
// CHECK: builtin "int_instrprof_increment"
-// rdar://problem/23256795 - Avoid crash if an if_expr has no parent
-// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_ternary.bar.__allocating_init
-class bar {
- var m1 = 0 == 1
- ? "false" // CHECK: [[@LINE]]:16 -> [[@LINE]]:23 : 1
- : "true"; // CHECK: [[@LINE]]:16 -> [[@LINE]]:22 : 0
-}
+var flag: Int = 0
// CHECK-LABEL: sil_coverage_map {{.*}}// coverage_ternary.foo
func foo(_ x : Int32) -> Int32 {
@@ -27,5 +21,13 @@
foo(2)
foo(3)
+// rdar://problem/23256795 - Avoid crash if an if_expr has no parent
+// CHECK: sil_coverage_map {{.*}}// __ntd_bar_line:[[@LINE+1]]
+class bar {
+ var m1 = flag == 0
+ ? "false" // CHECK: [[@LINE]]:16 -> [[@LINE]]:23 : 0
+ : "true"; // CHECK: [[@LINE]]:16 -> [[@LINE]]:22 : (1 - 0)
+}
+
// Note: We didn't instantiate bar, but we still expect to see instrumentation
// for its *structors, and coverage mapping information for it.
diff --git a/test/SILGen/coverage_toplevel.swift b/test/SILGen/coverage_toplevel.swift
index 8e7c26b..ca1bc48 100644
--- a/test/SILGen/coverage_toplevel.swift
+++ b/test/SILGen/coverage_toplevel.swift
@@ -17,7 +17,7 @@
// CHECK: sil_coverage_map{{.*}}__tlcd_line:[[@LINE+3]]:1
// CHECK-NEXT: [[@LINE+2]]:17 -> [[@LINE+2]]:18 : 1
-// CHECK-NEXT: [[@LINE+1]]:21 -> [[@LINE+1]]:22 : 0
+// CHECK-NEXT: [[@LINE+1]]:21 -> [[@LINE+1]]:22 : (0 - 1)
var i2 = true ? 1 : 0;
// CHECK: sil_coverage_map{{.*}}__tlcd_line:[[@LINE+4]]:1
diff --git a/test/SILGen/default_arguments.swift b/test/SILGen/default_arguments.swift
index 044e6d4..c0996e8 100644
--- a/test/SILGen/default_arguments.swift
+++ b/test/SILGen/default_arguments.swift
@@ -227,11 +227,11 @@
// CHECK-NEXT: function_ref reabstraction thunk helper from @escaping @callee_guaranteed (@in_guaranteed Swift.Int, @in_guaranteed Swift.Int) -> (@unowned Swift.Bool) to @escaping @callee_guaranteed (@unowned Swift.Int, @unowned Swift.Int) -> (@unowned Swift.Bool)
// CHECK-NEXT: [[THUNK:%.*]] = function_ref @$SS2iSbIegnnd_S2iSbIegyyd_TR : $@convention(thin) (Int, Int, @guaranteed @callee_guaranteed (@in_guaranteed Int, @in_guaranteed Int) -> Bool) -> Bool
// CHECK-NEXT: [[FN:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[RESULT]]) : $@convention(thin) (Int, Int, @guaranteed @callee_guaranteed (@in_guaranteed Int, @in_guaranteed Int) -> Bool) -> Bool
-// CHECK-NEXT: [[CONV_FN:%.*]] = convert_escape_to_noescape [[FN]]
+// CHECK-NEXT: [[CONV_FN:%.*]] = convert_escape_to_noescape [not_guaranteed] [[FN]]
// function_ref reabstraction thunk helper from @callee_guaranteed (@unowned Swift.Int, @unowned Swift.Int) -> (@unowned Swift.Bool) to @callee_guaranteed (@in_guaranteed Swift.Int, @in_guaranteed Swift.Int) -> (@unowned Swift.Bool)
// CHECK: [[THUNK:%.*]] = function_ref @$SS2iSbIgyyd_S2iSbIegnnd_TR : $@convention(thin) (@in_guaranteed Int, @in_guaranteed Int, @noescape @callee_guaranteed (Int, Int) -> Bool) -> Bool
// CHECK-NEXT: [[FN:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[CONV_FN]]) : $@convention(thin) (@in_guaranteed Int, @in_guaranteed Int, @noescape @callee_guaranteed (Int, Int) -> Bool) -> Bool
-// CHECK-NEXT: [[CONV_FN:%.*]] = convert_escape_to_noescape [[FN]]
+// CHECK-NEXT: [[CONV_FN:%.*]] = convert_escape_to_noescape [not_guaranteed] [[FN]]
// CHECK: [[INITFN:%[0-9]+]] = function_ref @$S17default_arguments25ReabstractDefaultArgumentC{{[_0-9a-zA-Z]*}}fC
// CHECK-NEXT: apply [[INITFN]]<Int>([[CONV_FN]],
@@ -320,25 +320,25 @@
// CHECK: [[F:%.*]] = function_ref @$S17default_arguments15throwingDefault7closureySbyKXE_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error)
// CHECK: [[C:%.*]] = apply [[F]]() : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error)
-// CHECK: [[E:%.*]] = convert_escape_to_noescape [[C]]
+// CHECK: [[E:%.*]] = convert_escape_to_noescape [not_guaranteed] [[C]]
// CHECK: [[R:%.*]] = function_ref @$S17default_arguments15throwingDefault7closureySbyKXE_tKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Bool, @error Error)) -> @error Error
// CHECK: try_apply [[R]]([[E]])
// CHECK: [[F:%.*]] = function_ref @$S17default_arguments26throwingAutoclosureDefault7closureySbyKXK_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error)
// CHECK: [[C:%.*]] = apply [[F]]() : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error)
-// CHECK: [[E:%.*]] = convert_escape_to_noescape [[C]]
+// CHECK: [[E:%.*]] = convert_escape_to_noescape [not_guaranteed] [[C]]
// CHECK: [[R:%.*]] = function_ref @$S17default_arguments26throwingAutoclosureDefault7closureySbyKXK_tKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Bool, @error Error)) -> @error Error
// CHECK: try_apply [[R]]([[E]])
// CHECK: [[F:%.*]] = function_ref @$S17default_arguments0A3Arg7closureySbyXE_tFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> Bool
// CHECK: [[C:%.*]] = apply [[F]]() : $@convention(thin) () -> @owned @callee_guaranteed () -> Bool
-// CHECK: [[E:%.*]] = convert_escape_to_noescape [[C]]
+// CHECK: [[E:%.*]] = convert_escape_to_noescape [not_guaranteed] [[C]]
// CHECK: [[R:%.*]] = function_ref @$S17default_arguments0A3Arg7closureySbyXE_tF : $@convention(thin) (@noescape @callee_guaranteed () -> Bool) -> ()
// CHECK: apply [[R]]([[E]])
// CHECK: [[F:%.*]] = function_ref @$S17default_arguments21autoclosureDefaultArg7closureySbyXK_tFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> Boo
// CHECK: [[C:%.*]] = apply [[F]]() : $@convention(thin) () -> @owned @callee_guaranteed () -> Bool
-// CHECK: [[E:%.*]] = convert_escape_to_noescape [[C]]
+// CHECK: [[E:%.*]] = convert_escape_to_noescape [not_guaranteed] [[C]]
// CHECK: [[R:%.*]] = function_ref @$S17default_arguments21autoclosureDefaultArg7closureySbyXK_tF : $@convention(thin) (@noescape @callee_guaranteed () -> Bool) -> ()
// CHECK: apply [[R]]([[E]])
diff --git a/test/SILGen/function_conversion.swift b/test/SILGen/function_conversion.swift
index b0922a8..09af86f 100644
--- a/test/SILGen/function_conversion.swift
+++ b/test/SILGen/function_conversion.swift
@@ -628,16 +628,16 @@
// CHECK: [[FN:%.*]] = function_ref @$SSays11AnyHashableVGSgIegg_Say19function_conversion1BCGSgIegg_TR : $@convention(thin) (@guaranteed Optional<Array<B>>, @guaranteed @callee_guaranteed (@guaranteed Optional<Array<AnyHashable>>) -> ()) -> ()
// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[FN]](%{{[0-9]+}}) : $@convention(thin) (@guaranteed Optional<Array<B>>, @guaranteed @callee_guaranteed (@guaranteed Optional<Array<AnyHashable>>) -> ()) -> ()
- // CHECK: convert_escape_to_noescape [[PA]] : $@callee_guaranteed (@guaranteed Optional<Array<B>>) -> () to $@noescape @callee_guaranteed (@guaranteed Optional<Array<B>>) -> ()
+ // CHECK: convert_escape_to_noescape [not_guaranteed] [[PA]] : $@callee_guaranteed (@guaranteed Optional<Array<B>>) -> () to $@noescape @callee_guaranteed (@guaranteed Optional<Array<B>>) -> ()
bar_arr(type: B.self, fn_arr)
// CHECK: [[FN:%.*]] = function_ref @$Ss10DictionaryVys11AnyHashableVSiGIegg_ABy19function_conversion1BCSiGIegg_TR : $@convention(thin) (@guaranteed Dictionary<B, Int>, @guaranteed @callee_guaranteed (@guaranteed Dictionary<AnyHashable, Int>) -> ()) -> ()
// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[FN]](%{{[0-9]+}}) : $@convention(thin) (@guaranteed Dictionary<B, Int>, @guaranteed @callee_guaranteed (@guaranteed Dictionary<AnyHashable, Int>) -> ()) -> ()
- // CHECK: convert_escape_to_noescape [[PA]] : $@callee_guaranteed (@guaranteed Dictionary<B, Int>) -> () to $@noescape @callee_guaranteed (@guaranteed Dictionary<B, Int>) -> ()
+ // CHECK: convert_escape_to_noescape [not_guaranteed] [[PA]] : $@callee_guaranteed (@guaranteed Dictionary<B, Int>) -> () to $@noescape @callee_guaranteed (@guaranteed Dictionary<B, Int>) -> ()
bar_map(type: B.self, fn_map)
// CHECK: [[FN:%.*]] = function_ref @$Ss3SetVys11AnyHashableVGIegg_ABy19function_conversion1BCGIegg_TR : $@convention(thin) (@guaranteed Set<B>, @guaranteed @callee_guaranteed (@guaranteed Set<AnyHashable>) -> ()) -> ()
// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[FN]](%{{[0-9]+}}) : $@convention(thin) (@guaranteed Set<B>, @guaranteed @callee_guaranteed (@guaranteed Set<AnyHashable>) -> ()) -> ()
- // CHECK: convert_escape_to_noescape [[PA]] : $@callee_guaranteed (@guaranteed Set<B>) -> () to $@noescape @callee_guaranteed (@guaranteed Set<B>) -> ()
+ // CHECK: convert_escape_to_noescape [not_guaranteed] [[PA]] : $@callee_guaranteed (@guaranteed Set<B>) -> () to $@noescape @callee_guaranteed (@guaranteed Set<B>) -> ()
bar_set(type: B.self, fn_set)
}
diff --git a/test/SILGen/functions.swift b/test/SILGen/functions.swift
index f6333e1..c7b4892 100644
--- a/test/SILGen/functions.swift
+++ b/test/SILGen/functions.swift
@@ -348,7 +348,7 @@
// CHECK: [[FUNC_THIN:%[0-9]+]] = function_ref @$S9functions19standalone_function{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
// CHECK: [[FUNC_THICK:%[0-9]+]] = thin_to_thick_function [[FUNC_THIN]]
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[FUNC_THICK]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[FUNC_THICK]]
// CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
// CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
// CHECK: [[READJ:%.*]] = begin_access [read] [unknown] [[JADDR]]
@@ -359,7 +359,7 @@
// CHECK: [[FUNC_THIN:%[0-9]+]] = function_ref @$S9functions19standalone_function{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
// CHECK: [[FUNC_THICK:%.*]] = thin_to_thick_function [[FUNC_THIN]]
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[FUNC_THICK]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[FUNC_THICK]]
// CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
// CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
// CHECK: [[READJ:%.*]] = begin_access [read] [unknown] [[JADDR]]
diff --git a/test/SILGen/guaranteed_closure_context.swift b/test/SILGen/guaranteed_closure_context.swift
index 91306be..f5884a1 100644
--- a/test/SILGen/guaranteed_closure_context.swift
+++ b/test/SILGen/guaranteed_closure_context.swift
@@ -60,7 +60,7 @@
// CHECK: [[IMMUTABLE_RETAINABLE_COPY:%.*]] = copy_value [[IMMUTABLE_RETAINABLE]]
// CHECK: [[IMMUTABLE_AO_BOX:%.*]] = alloc_box ${ var P }
// CHECK: [[CLOSURE:%.*]] = partial_apply {{.*}}([[MUTABLE_TRIVIAL_BOX_COPY]], [[MUTABLE_RETAINABLE_BOX_COPY]], [[MUTABLE_ADDRESS_ONLY_BOX_COPY]], [[IMMUTABLE_TRIVIAL]], [[IMMUTABLE_RETAINABLE_COPY]], [[IMMUTABLE_AO_BOX]])
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[CLOSURE]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[CLOSURE]]
// CHECK: apply {{.*}}[[CONVERT]]
// CHECK-NOT: copy_value [[MUTABLE_TRIVIAL_BOX]]
diff --git a/test/SILGen/objc_blocks_bridging.swift b/test/SILGen/objc_blocks_bridging.swift
index c5d8d0a..7b1508a 100644
--- a/test/SILGen/objc_blocks_bridging.swift
+++ b/test/SILGen/objc_blocks_bridging.swift
@@ -15,7 +15,7 @@
// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
// CHECK: [[THUNK:%.*]] = function_ref @$SS2iIyByd_S2iIegyd_TR
// CHECK: [[BRIDGED:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[ARG1_COPY]])
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[BRIDGED]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[BRIDGED]]
// CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
// CHECK: [[NATIVE:%.*]] = function_ref @$S20objc_blocks_bridging3FooC3foo{{[_0-9a-zA-Z]*}}F : $@convention(method) (@noescape @callee_guaranteed (Int) -> Int, Int, @guaranteed Foo) -> Int
// CHECK: apply [[NATIVE]]([[CONVERT]], {{.*}}, [[BORROWED_SELF_COPY]])
@@ -32,7 +32,7 @@
// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
// CHECK: [[THUNK:%.*]] = function_ref @$SSo8NSStringCABIyBya_S2SIeggo_TR
// CHECK: [[BRIDGED:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[BLOCK_COPY]])
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[BRIDGED]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[BRIDGED]]
// CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
// CHECK: [[NATIVE:%.*]] = function_ref @$S20objc_blocks_bridging3FooC3bar{{[_0-9a-zA-Z]*}}F : $@convention(method) (@noescape @callee_guaranteed (@guaranteed String) -> @owned String, @guaranteed String, @guaranteed Foo) -> @owned String
// CHECK: apply [[NATIVE]]([[CONVERT]], {{%.*}}, [[BORROWED_SELF_COPY]])
@@ -56,7 +56,7 @@
// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
// CHECK: [[THUNK:%.*]] = function_ref @$SSo8NSStringCSgACIyBya_SSSgADIeggo_TR
// CHECK: [[BRIDGED:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[BLOCK_COPY]])
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[BRIDGED]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[BRIDGED]]
// CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
// CHECK: [[NATIVE:%.*]] = function_ref @$S20objc_blocks_bridging3FooC3bas{{[_0-9a-zA-Z]*}}F : $@convention(method) (@noescape @callee_guaranteed (@guaranteed Optional<String>) -> @owned Optional<String>, @guaranteed Optional<String>, @guaranteed Foo) -> @owned Optional<String>
// CHECK: apply [[NATIVE]]([[CONVERT]], {{%.*}}, [[BORROWED_SELF_COPY]])
@@ -112,7 +112,7 @@
) -> (Int, String, String?, String?) {
// CHECK: bb0([[ARG0:%.*]] : @guaranteed $Foo, [[ARG1:%.*]] : @guaranteed $@callee_guaranteed (Int) -> Int, [[ARG2:%.*]] : @guaranteed $@callee_guaranteed (@guaranteed String) -> @owned String, [[ARG3:%.*]] : @guaranteed $@callee_guaranteed (@guaranteed Optional<String>) -> @owned Optional<String>):
// CHECK: [[CLOSURE_COPY:%.*]] = copy_value [[ARG1]]
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[CLOSURE_COPY]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[CLOSURE_COPY]]
// CHECK: [[F_BLOCK_STORAGE:%.*]] = alloc_stack $@block_storage
// CHECK: [[F_BLOCK_CAPTURE:%.*]] = project_block_storage [[F_BLOCK_STORAGE]]
// CHECK: store [[CONVERT]] to [trivial] [[F_BLOCK_CAPTURE]]
@@ -147,7 +147,7 @@
// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SS2iIgyd_SiIegyd_S2iIyByd_SiIeyByd_TR
// CHECK: [[BLOCK_COPY:%.*]] = copy_block [[ORIG_BLOCK:%.*]] :
// CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[BLOCK_COPY]])
-// CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[CLOSURE]]
+// CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[CLOSURE]]
// CHECK: [[RESULT:%.*]] = apply {{%.*}}([[CONVERT]])
// CHECK: return [[RESULT]]
diff --git a/test/SILGen/objc_bridging_any.swift b/test/SILGen/objc_bridging_any.swift
index bf79086..264ca2a 100644
--- a/test/SILGen/objc_bridging_any.swift
+++ b/test/SILGen/objc_bridging_any.swift
@@ -464,7 +464,7 @@
// CHECK-NEXT: [[SELF_COPY:%.*]] = copy_value [[SELF]]
// CHECK: [[THUNK_FN:%.*]] = function_ref @$SyXlIyBy_ypIegn_TR
// CHECK-NEXT: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]([[BLOCK_COPY]])
- // CHECK-NEXT: [[THUNK_CVT:%.*]] = convert_escape_to_noescape [[THUNK]]
+ // CHECK-NEXT: [[THUNK_CVT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[THUNK]]
// CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[METHOD:%.*]] = function_ref @$S17objc_bridging_any12SwiftIdLoverC017methodTakingBlockH3AnyyyyypXEF
@@ -543,7 +543,7 @@
// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[THUNK_FN:%.*]] = function_ref @$SyXlIyBa_ypIegr_TR
// CHECK-NEXT: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]([[BLOCK_COPY]])
- // CHECK-NEXT: [[THUNK_CVT:%.*]] = convert_escape_to_noescape [[THUNK]]
+ // CHECK-NEXT: [[THUNK_CVT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[THUNK]]
// CHECK-NEXT: [[BORROWED_ANY_COPY:%.*]] = begin_borrow [[ANY_COPY]]
// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[METHOD:%.*]] = function_ref @$S17objc_bridging_any12SwiftIdLoverC29methodTakingBlockReturningAnyyyypyXEF
diff --git a/test/SILGen/partial_apply_super.swift b/test/SILGen/partial_apply_super.swift
index 42d2bd4..3c7b250 100644
--- a/test/SILGen/partial_apply_super.swift
+++ b/test/SILGen/partial_apply_super.swift
@@ -37,7 +37,7 @@
// CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
// CHECK: [[SUPER_METHOD:%.*]] = function_ref @$S19partial_apply_super6ParentC6methodyyFTcTd : $@convention(thin) (@guaranteed Parent) -> @owned @callee_guaranteed () -> ()
// CHECK: [[PARTIAL_APPLY:%.*]] = apply [[SUPER_METHOD]]([[BORROWED_CASTED_SELF_COPY]]) : $@convention(thin) (@guaranteed Parent) -> @owned @callee_guaranteed () -> ()
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_APPLY]]
// CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: } // end sil function '$S19partial_apply_super5ChildC6methodyyF'
@@ -49,7 +49,7 @@
// CHECK: [[CASTED_SELF:%.*]] = upcast %0 : $@thick Child.Type to $@thick Parent.Type
// CHECK: [[SUPER_METHOD:%.*]] = function_ref @$S19partial_apply_super6ParentC11classMethodyyFZTcTd : $@convention(thin) (@thick Parent.Type) -> @owned @callee_guaranteed () -> ()
// CHECK: [[PARTIAL_APPLY:%.*]] = apply [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(thin) (@thick Parent.Type) -> @owned @callee_guaranteed () -> ()
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_APPLY]]
// CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: } // end sil function '$S19partial_apply_super5ChildC11classMethodyyFZ'
@@ -64,7 +64,7 @@
// CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
// CHECK: [[SUPER_METHOD:%.*]] = function_ref @$S19partial_apply_super6ParentC11finalMethodyyFTc : $@convention(thin) (@guaranteed Parent) -> @owned @callee_guaranteed () -> ()
// CHECK: [[APPLIED_SELF:%.*]] = apply [[SUPER_METHOD]]([[BORROWED_CASTED_SELF_COPY]]) : $@convention(thin) (@guaranteed Parent) -> @owned @callee_guaranteed () -> ()
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[APPLIED_SELF]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[APPLIED_SELF]]
// CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: } // end sil function '$S19partial_apply_super5ChildC20callFinalSuperMethodyyF'
@@ -77,7 +77,7 @@
// CHECK: [[CASTED_SELF:%.*]] = upcast [[ARG]] : $@thick Child.Type to $@thick Parent.Type
// CHECK: [[SUPER_METHOD:%.*]] = function_ref @$S19partial_apply_super6ParentC16finalClassMethodyyFZTc : $@convention(thin) (@thick Parent.Type) -> @owned @callee_guaranteed () -> ()
// CHECK: [[APPLIED_SELF:%.*]] = apply [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(thin) (@thick Parent.Type) -> @owned @callee_guaranteed () -> ()
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[APPLIED_SELF]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[APPLIED_SELF]]
// CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: } // end sil function '$S19partial_apply_super5ChildC25callFinalSuperClassMethodyyFZ'
@@ -97,7 +97,7 @@
// CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
// CHECK: [[SUPER_METHOD:%.*]] = function_ref @$S19partial_apply_super13GenericParentC6methodyyFTcTd : $@convention(thin) <τ_0_0> (@guaranteed GenericParent<τ_0_0>) -> @owned @callee_guaranteed () -> ()
// CHECK: [[PARTIAL_APPLY:%.*]] = apply [[SUPER_METHOD]]<A>([[BORROWED_CASTED_SELF_COPY]]) : $@convention(thin) <τ_0_0> (@guaranteed GenericParent<τ_0_0>) -> @owned @callee_guaranteed () -> ()
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_APPLY]]
// CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: } // end sil function '$S19partial_apply_super12GenericChildC6methodyyF'
@@ -109,7 +109,7 @@
// CHECK: [[CASTED_SELF:%.*]] = upcast %0 : $@thick GenericChild<A>.Type to $@thick GenericParent<A>.Type
// CHECK: [[SUPER_METHOD:%.*]] = function_ref @$S19partial_apply_super13GenericParentC11classMethodyyFZTcTd : $@convention(thin) <τ_0_0> (@thick GenericParent<τ_0_0>.Type) -> @owned @callee_guaranteed () -> ()
// CHECK: [[PARTIAL_APPLY:%.*]] = apply [[SUPER_METHOD]]<A>([[CASTED_SELF]]) : $@convention(thin) <τ_0_0> (@thick GenericParent<τ_0_0>.Type) -> @owned @callee_guaranteed () -> ()
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_APPLY]]
// CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: } // end sil function '$S19partial_apply_super12GenericChildC11classMethodyyFZ'
@@ -133,7 +133,7 @@
// turn on +0.
// CHECK: [[SUPER_METHOD:%.*]] = super_method [[DOWNCAST_BORROWED_CASTED_SELF_COPY]] : $OutsideParent, #OutsideParent.method!1 : (OutsideParent) -> () -> (), $@convention(method) (@guaranteed OutsideParent) -> ()
// CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(method) (@guaranteed OutsideParent) -> ()
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_APPLY]]
// CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: } // end sil function '$S19partial_apply_super25ChildToFixedOutsideParentC6methodyyF'
@@ -145,7 +145,7 @@
// CHECK: [[CASTED_SELF:%.*]] = upcast %0 : $@thick ChildToFixedOutsideParent.Type to $@thick OutsideParent.Type
// CHECK: [[SUPER_METHOD:%.*]] = super_method %0 : $@thick ChildToFixedOutsideParent.Type, #OutsideParent.classMethod!1 : (OutsideParent.Type) -> () -> (), $@convention(method) (@thick OutsideParent.Type) -> (){{.*}}
// CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(method) (@thick OutsideParent.Type) -> ()
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_APPLY]]
// CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: } // end sil function '$S19partial_apply_super25ChildToFixedOutsideParentC11classMethodyyFZ'
@@ -166,7 +166,7 @@
// CHECK: [[SUPER_METHOD:%.*]] = super_method [[DOWNCAST_BORROWED_CASTED_SELF_COPY]] : $ResilientOutsideParent, #ResilientOutsideParent.method!1 : (ResilientOutsideParent) -> () -> (), $@convention(method) (@guaranteed ResilientOutsideParent) -> ()
// CHECK: end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
// CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(method) (@guaranteed ResilientOutsideParent) -> ()
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_APPLY]]
// CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: } // end sil function '$S19partial_apply_super29ChildToResilientOutsideParentC6methodyyF'
@@ -178,7 +178,7 @@
// CHECK: [[CASTED_SELF:%.*]] = upcast %0 : $@thick ChildToResilientOutsideParent.Type to $@thick ResilientOutsideParent.Type
// CHECK: [[SUPER_METHOD:%.*]] = super_method %0 : $@thick ChildToResilientOutsideParent.Type, #ResilientOutsideParent.classMethod!1 : (ResilientOutsideParent.Type) -> () -> (), $@convention(method) (@thick ResilientOutsideParent.Type) -> ()
// CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(method) (@thick ResilientOutsideParent.Type) -> ()
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_APPLY]]
// CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: } // end sil function '$S19partial_apply_super29ChildToResilientOutsideParentC11classMethodyyFZ'
@@ -199,7 +199,7 @@
// CHECK: [[SUPER_METHOD:%.*]] = super_method [[DOWNCAST_BORROWED_CASTED_SELF_COPY]] : $OutsideChild, #OutsideChild.method!1 : (OutsideChild) -> () -> (), $@convention(method) (@guaranteed OutsideChild) -> ()
// CHECK: end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
// CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(method) (@guaranteed OutsideChild) -> ()
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_APPLY]]
// CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: } // end sil function '$S19partial_apply_super29GrandchildToFixedOutsideChildC6methodyyF'
@@ -211,7 +211,7 @@
// CHECK: [[CASTED_SELF:%.*]] = upcast %0 : $@thick GrandchildToFixedOutsideChild.Type to $@thick OutsideChild.Type
// CHECK: [[SUPER_METHOD:%.*]] = super_method %0 : $@thick GrandchildToFixedOutsideChild.Type, #OutsideChild.classMethod!1 : (OutsideChild.Type) -> () -> (), $@convention(method) (@thick OutsideChild.Type) -> ()
// CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(method) (@thick OutsideChild.Type) -> ()
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_APPLY]]
// CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: } // end sil function '$S19partial_apply_super29GrandchildToFixedOutsideChildC11classMethodyyFZ'
@@ -232,7 +232,7 @@
// CHECK: [[SUPER_METHOD:%.*]] = super_method [[DOWNCAST_BORROWED_CASTED_SELF_COPY]] : $ResilientOutsideChild, #ResilientOutsideChild.method!1 : (ResilientOutsideChild) -> () -> (), $@convention(method) (@guaranteed ResilientOutsideChild) -> ()
// CHEC: end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
// CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(method) (@guaranteed ResilientOutsideChild) -> ()
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_APPLY]]
// CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: } // end sil function '$S19partial_apply_super33GrandchildToResilientOutsideChildC6methodyyF'
@@ -244,7 +244,7 @@
// CHECK: [[CASTED_SELF:%.*]] = upcast %0 : $@thick GrandchildToResilientOutsideChild.Type to $@thick ResilientOutsideChild.Type
// CHECK: [[SUPER_METHOD:%.*]] = super_method %0 : $@thick GrandchildToResilientOutsideChild.Type, #ResilientOutsideChild.classMethod!1 : (ResilientOutsideChild.Type) -> () -> (), $@convention(method) (@thick ResilientOutsideChild.Type) -> ()
// CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(method) (@thick ResilientOutsideChild.Type) -> ()
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_APPLY]]
// CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: } // end sil function '$S19partial_apply_super33GrandchildToResilientOutsideChildC11classMethodyyFZ'
@@ -265,7 +265,7 @@
// CHECK: [[SUPER_METHOD:%.*]] = super_method [[DOWNCAST_BORROWED_CASTED_SELF_COPY]] : $GenericOutsideParent<A>, #GenericOutsideParent.method!1 : <A> (GenericOutsideParent<A>) -> () -> (), $@convention(method) <τ_0_0> (@guaranteed GenericOutsideParent<τ_0_0>) -> ()
// CHECK: end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
// CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]<A>([[CASTED_SELF_COPY]]) : $@convention(method) <τ_0_0> (@guaranteed GenericOutsideParent<τ_0_0>) -> ()
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_APPLY]]
// CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: } // end sil function '$S19partial_apply_super019GenericChildToFixedD13OutsideParentC6methodyyF'
@@ -277,7 +277,7 @@
// CHECK: [[CASTED_SELF:%.*]] = upcast %0 : $@thick GenericChildToFixedGenericOutsideParent<A>.Type to $@thick GenericOutsideParent<A>.Type
// CHECK: [[SUPER_METHOD:%.*]] = super_method %0 : $@thick GenericChildToFixedGenericOutsideParent<A>.Type, #GenericOutsideParent.classMethod!1 : <A> (GenericOutsideParent<A>.Type) -> () -> (), $@convention(method) <τ_0_0> (@thick GenericOutsideParent<τ_0_0>.Type) -> ()
// CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]<A>([[CASTED_SELF]]) : $@convention(method) <τ_0_0> (@thick GenericOutsideParent<τ_0_0>.Type) -> ()
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_APPLY]]
// CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: } // end sil function '$S19partial_apply_super019GenericChildToFixedD13OutsideParentC11classMethodyyFZ'
@@ -298,7 +298,7 @@
// CHECK: [[SUPER_METHOD:%.*]] = super_method [[DOWNCAST_BORROWED_CASTED_SELF_COPY]] : $ResilientGenericOutsideParent<A>, #ResilientGenericOutsideParent.method!1 : <A> (ResilientGenericOutsideParent<A>) -> () -> (), $@convention(method) <τ_0_0> (@guaranteed ResilientGenericOutsideParent<τ_0_0>) -> ()
// CHECK: end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
// CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]<A>([[CASTED_SELF_COPY]]) : $@convention(method) <τ_0_0> (@guaranteed ResilientGenericOutsideParent<τ_0_0>) -> ()
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_APPLY]]
// CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: } // end sil function '$S19partial_apply_super023GenericChildToResilientD13OutsideParentC6methodyyF'
@@ -310,7 +310,7 @@
// CHECK: [[CASTED_SELF:%.*]] = upcast %0 : $@thick GenericChildToResilientGenericOutsideParent<A>.Type to $@thick ResilientGenericOutsideParent<A>.Type
// CHECK: [[SUPER_METHOD:%.*]] = super_method %0 : $@thick GenericChildToResilientGenericOutsideParent<A>.Type, #ResilientGenericOutsideParent.classMethod!1 : <A> (ResilientGenericOutsideParent<A>.Type) -> () -> (), $@convention(method) <τ_0_0> (@thick ResilientGenericOutsideParent<τ_0_0>.Type) -> ()
// CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]<A>([[CASTED_SELF]]) : $@convention(method) <τ_0_0> (@thick ResilientGenericOutsideParent<τ_0_0>.Type) -> ()
- // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_APPLY]]
// CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
// CHECK: } // end sil function '$S19partial_apply_super023GenericChildToResilientD13OutsideParentC11classMethodyyFZ'
diff --git a/test/SILGen/reabstract.swift b/test/SILGen/reabstract.swift
index 2266f20..08df15a 100644
--- a/test/SILGen/reabstract.swift
+++ b/test/SILGen/reabstract.swift
@@ -1,5 +1,6 @@
// RUN: %target-swift-frontend -module-name reabstract -Xllvm -sil-full-demangle -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+// RUN: %target-swift-frontend -module-name reabstract -Xllvm -sil-full-demangle -emit-sil -enable-sil-ownership %s | %FileCheck %s --check-prefix=MANDATORY
func takeFn<T>(_ f : (T) -> T?) {}
func liftOptional(_ x : Int) -> Int? { return x }
@@ -13,19 +14,41 @@
// CHECK: reabstract.liftOptional
// CHECK-NEXT: [[T1:%.*]] = function_ref @$S10reabstract12liftOptional{{[_0-9a-zA-Z]*}}F
// CHECK-NEXT: [[T2:%.*]] = thin_to_thick_function [[T1]]
-// CHECK-NEXT: [[CVT:%.*]] = convert_escape_to_noescape [[T2]]
+// CHECK-NEXT: [[CVT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[T2]]
// CHECK-NEXT: reabstraction thunk
// CHECK-NEXT: [[T3:%.*]] = function_ref [[THUNK:@.*]] :
// CHECK-NEXT: [[T4:%.*]] = partial_apply [callee_guaranteed] [[T3]]([[CVT]])
-// CHECK-NEXT: [[CVT:%.*]] = convert_escape_to_noescape [[T4]]
+// CHECK-NEXT: [[CVT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[T4]]
+// CHECK: destroy_value [[T4]]
+// CHECK-NEXT: destroy_value [[T2]]
// CHECK: [[T0:%.*]] = function_ref @$S10reabstract6takeFn{{[_0-9a-zA-Z]*}}F
// CHECK-NEXT: apply [[T0]]<Int>([[CVT]])
-// CHECK-NEXT: destroy_value [[T2]]
-// CHECK-NEXT: destroy_value [[T4]]
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
// CHECK-NEXT: } // end sil function '$S10reabstract5test0yyF'
+// MANDATORY: sil hidden @$S10reabstract5test0yyF : $@convention(thin) () -> () {
+// Emit a generalized reference to liftOptional.
+// TODO: just emit a globalized thunk
+// MANDATORY: reabstract.liftOptional
+// MANDATORY-NEXT: [[T1:%.*]] = function_ref @$S10reabstract12liftOptional{{[_0-9a-zA-Z]*}}F
+// MANDATORY-NEXT: [[T2:%.*]] = thin_to_thick_function [[T1]]
+// MANDATORY-NEXT: strong_retain [[T2]]
+// MANDATORY-NEXT: [[CVT:%.*]] = convert_escape_to_noescape [[T2]]
+// MANDATORY-NEXT: //{{.*}}reabstraction thunk
+// MANDATORY-NEXT: [[T3:%.*]] = function_ref [[THUNK:@.*]] :
+// MANDATORY-NEXT: [[T4:%.*]] = partial_apply [callee_guaranteed] [[T3]]([[CVT]])
+// MANDATORY-NEXT: [[CVT:%.*]] = convert_escape_to_noescape [[T4]]
+// MANDATORY-NEXT: strong_release [[T2]]
+// MANDATORY-NEXT: // function_ref
+// MANDATORY-NEXT: [[T0:%.*]] = function_ref @$S10reabstract6takeFn{{[_0-9a-zA-Z]*}}F
+// MANDATORY-NEXT: apply [[T0]]<Int>([[CVT]])
+// MANDATORY-NEXT: strong_release [[T4]]
+// MANDATORY-NEXT: strong_release [[T2]]
+// MANDATORY-NEXT: tuple ()
+// MANDATORY-NEXT: return
+// MANDATORY-NEXT: } // end sil function '$S10reabstract5test0yyF'
+
// CHECK: sil shared [transparent] [serializable] [reabstraction_thunk] [[THUNK]] : $@convention(thin) (@in_guaranteed Int, @noescape @callee_guaranteed (Int) -> Optional<Int>) -> @out Optional<Int> {
// CHECK: [[T0:%.*]] = load [trivial] %1 : $*Int
// CHECK-NEXT: [[T1:%.*]] = apply %2([[T0]])
diff --git a/test/SILGen/rethrows.swift b/test/SILGen/rethrows.swift
index 0239d4d..d77971b 100644
--- a/test/SILGen/rethrows.swift
+++ b/test/SILGen/rethrows.swift
@@ -17,11 +17,13 @@
// CHECK: [[NORMAL]]([[RESULT_T0:%.*]] : $Int):
// FIXME - SR-6979: We should be able to eliminate this strong_release.
// CHECK-NEXT: strong_release [[T0]]
+// CHECK-NEXT: strong_release [[T0]]
// CHECK-NEXT: [[T1:%.*]] = tuple ()
// CHECK-NEXT: return [[T1]]
// CHECK: [[ERROR]]([[RESULT_T0:%.*]] : $Error):
// FIXME - SR-6979: We should be able to eliminate this strong_release.
// CHECK-NEXT: strong_release [[T0]]
+// CHECK-NEXT: strong_release [[T0]]
// CHECK-NEXT: throw [[RESULT_T0]]
func test0() throws {
try rethrower(thrower)
@@ -47,9 +49,11 @@
// CHECK: try_apply [[RETHROWER]]([[CVT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]]
// CHECK: [[NORMAL]]([[RESULT:%.*]] : $Int):
// CHECK-NEXT: strong_release [[T0]]
+// CHECK-NEXT: strong_release [[T0]]
// CHECK-NEXT: return [[RESULT]]
// CHECK: [[ERROR]]([[ERROR:%.*]] : $Error):
// CHECK-NEXT: strong_release [[T0]]
+// CHECK-NEXT: strong_release [[T0]]
// CHECK-NEXT: throw [[ERROR]]
func test1() throws {
try rethrower { try rethrower(thrower) }
@@ -64,9 +68,11 @@
// CHECK: try_apply [[RETHROWER]]([[T2]]) : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]]
// CHECK: [[NORMAL]]([[T0:%.*]] : $Int):
// CHECK-NEXT: strong_release [[T1]]
+// CHECK-NEXT: strong_release [[T1]]
// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
// CHECK-NEXT: return [[RESULT]]
// CHECK: [[ERROR]]([[T0:%.*]] : $Error):
+// CHECK-NEXT: strong_release [[T1]]
// CHECK-NEXT: unreachable
func test2() {
rethrower(nonthrower)
diff --git a/test/SILGen/witnesses.swift b/test/SILGen/witnesses.swift
index e1b4f1e..fe4f550 100644
--- a/test/SILGen/witnesses.swift
+++ b/test/SILGen/witnesses.swift
@@ -520,8 +520,8 @@
// CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses18EscapingCovarianceVAA0B3ReqA2aDP1fyyS2icFTW : $@convention(witness_method: EscapingReq) (@guaranteed @callee_guaranteed (Int) -> Int, @in_guaranteed EscapingCovariance) -> ()
// CHECK-NOT: return
-// CHECK: [[COPIED:%.*]] = copy_value %0
-// CHECK: convert_escape_to_noescape [[COPIED]]
+// CHECK: convert_escape_to_noescape [not_guaranteed] %0
+// CHECK: return
struct EscapingCovariance: EscapingReq {
func f(_: (Int) -> Int) { }
}
diff --git a/test/SILOptimizer/Inputs/linker_pass_input.swift b/test/SILOptimizer/Inputs/linker_pass_input.swift
index 8b58310..18fff65 100644
--- a/test/SILOptimizer/Inputs/linker_pass_input.swift
+++ b/test/SILOptimizer/Inputs/linker_pass_input.swift
@@ -2,6 +2,7 @@
@_silgen_name("unknown")
public func unknown() -> ()
+@inline(never)
@inlinable
public func doSomething() {
unknown()
diff --git a/test/SILOptimizer/access_marker_verify.swift b/test/SILOptimizer/access_marker_verify.swift
index 4318270..87ebc96 100644
--- a/test/SILOptimizer/access_marker_verify.swift
+++ b/test/SILOptimizer/access_marker_verify.swift
@@ -969,7 +969,7 @@
// CHECK: mark_uninitialized [rootself] %{{.*}} : ${ var StructWithLayout }
// CHECK: [[PROJ:%.*]] = project_box %{{.*}} : ${ var StructWithLayout }, 0
// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] %{{.*}}([[PROJ]]) : $@convention(thin) (@inout_aliasable StructWithLayout) -> Bool
-// CHECK: [[CLOSURE:%.*]] = convert_escape_to_noescape [[PA]] : $@callee_guaranteed () -> Bool to $@noescape @callee_guaranteed () -> Bool
+// CHECK: [[CLOSURE:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PA]] : $@callee_guaranteed () -> Bool to $@noescape @callee_guaranteed () -> Bool
// call default argument
// CHECK: apply %{{.*}}() : $@convention(thin) () -> StaticString
// call StaticString.init
diff --git a/test/SILOptimizer/access_marker_verify_objc.swift b/test/SILOptimizer/access_marker_verify_objc.swift
index c9f4c07..6d24335 100644
--- a/test/SILOptimizer/access_marker_verify_objc.swift
+++ b/test/SILOptimizer/access_marker_verify_objc.swift
@@ -40,7 +40,7 @@
// function_ref thunk for @callee_unowned @convention(block) (@unowned Int) -> (@unowned Int)
// CHECK: [[THUNK:%.*]] = function_ref @$SS2iIyByd_S2iIegyd_TR : $@convention(thin) (Int, @guaranteed @convention(block) @noescape (Int) -> Int) -> Int
// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[CP]]) : $@convention(thin) (Int, @guaranteed @convention(block) @noescape (Int) -> Int) -> Int
-// CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[PA]] : $@callee_guaranteed (Int) -> Int to $@noescape @callee_guaranteed (Int) -> Int
+// CHECK: [[CVT:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PA]] : $@callee_guaranteed (Int) -> Int to $@noescape @callee_guaranteed (Int) -> Int
// CHECK: [[F:%.*]] = function_ref @$S25access_marker_verify_objc12HasBlockImplC5blockyyS2iXEF : $@convention(method) (@noescape @callee_guaranteed (Int) -> Int, @guaranteed HasBlockImpl) -> ()
// CHECK: %{{.*}} = apply [[F]]([[CVT]], %{{.*}}) : $@convention(method) (@noescape @callee_guaranteed (Int) -> Int, @guaranteed HasBlockImpl) -> ()
// CHECK: return %{{.*}} : $()
diff --git a/test/SILOptimizer/capture_promotion_ownership.swift b/test/SILOptimizer/capture_promotion_ownership.swift
index c74a886..28794f5 100644
--- a/test/SILOptimizer/capture_promotion_ownership.swift
+++ b/test/SILOptimizer/capture_promotion_ownership.swift
@@ -1,9 +1,4 @@
-// RUN: %target-swift-frontend %s -enable-sil-ownership -disable-sil-linking -emit-sil -o - | %FileCheck %s
-
-// NOTE: We add -disable-sil-linking to the compile line to ensure that we have
-// access to declarations for standard library types, but not definitions. This
-// ensures that we are able to safely use standard library types for this test
-// without needing the standard library to be ownership correct in its body.
+// RUN: %target-swift-frontend %s -enable-sil-ownership -emit-sil -o - | %FileCheck %s
class Foo {
func foo() -> Int {
diff --git a/test/SILOptimizer/closure_lifetime_fixup.swift b/test/SILOptimizer/closure_lifetime_fixup.swift
new file mode 100644
index 0000000..c50a4fb
--- /dev/null
+++ b/test/SILOptimizer/closure_lifetime_fixup.swift
@@ -0,0 +1,84 @@
+// RUN: %target-swift-frontend %s -emit-sil -o - | %FileCheck %s
+
+func use_closure(_ c : () -> () ) {
+ c()
+}
+
+func use_closureGeneric<T>(_ c : () -> T ) {
+ _ = c()
+}
+
+public class C {
+ func doIt() {}
+ func returnInt() -> Int { return 0 }
+}
+
+// CHECK-LABEL: sil @$S22closure_lifetime_fixup10testSimple1cyAA1CC_tF : $@convention(thin) (@guaranteed C) -> () {
+// CHECK: bb0([[ARG:%.*]] : $C):
+// CHECK: [[F:%.*]] = function_ref @$S22closure_lifetime_fixup10testSimple1cyAA1CC_tFyyXEfU_
+// CHECK-NEXT: strong_retain [[ARG]] : $C
+// CHECK-NEXT: [[PA:%.*]] = partial_apply [callee_guaranteed] [[F]]([[ARG]]) : $@convention(thin) (@guaranteed C) -> ()
+// CHECK-NEXT: strong_retain [[PA]] : $@callee_guaranteed () -> ()
+// CHECK-NEXT: [[CVT:%.*]] = convert_escape_to_noescape [[PA]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK-NEXT: // function_ref use_closure(_:)
+// CHECK-NEXT: [[F2:%.*]] = function_ref @$S22closure_lifetime_fixup04use_A0yyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+// CHECK-NEXT: apply [[F2]]([[CVT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+// CHECK-NEXT: strong_release [[PA]] : $@callee_guaranteed () -> ()
+// CHECK-NEXT: strong_release [[PA]] : $@callee_guaranteed () -> ()
+// CHECK-NEXT: tuple ()
+// CHECK-NEXT: return {{.*}} : $()
+public func testSimple(c: C) {
+ use_closure { c.doIt() }
+}
+
+// CHECK-LABEL: sil @$S22closure_lifetime_fixup11testGeneric1cyAA1CC_tF : $@convention(thin) (@guaranteed C) -> () {
+// CHECK:bb0([[ARG:%.*]] : $C):
+// CHECK: [[F:%.*]] = function_ref @$S22closure_lifetime_fixup11testGeneric1cyAA1CC_tFSiyXEfU_ : $@convention(thin) (@guaranteed C) -> Int
+// CHECK-NEXT: strong_retain [[ARG]] : $C
+// CHECK-NEXT: [[PA:%.*]] = partial_apply [callee_guaranteed] [[F]]([[ARG]]) : $@convention(thin) (@guaranteed C) -> Int
+// CHECK-NEXT: strong_retain [[PA]] : $@callee_guaranteed () -> Int
+// CHECK-NEXT: [[CVT:%.*]] = convert_escape_to_noescape [[PA]] : $@callee_guaranteed () -> Int to $@noescape @callee_guaranteed () -> Int
+// CHECK-NEXT: // function_ref thunk for @callee_guaranteed () -> (@unowned Int)
+// CHECK-NEXT: [[F:%.*]] = function_ref @$SSiIgd_SiIegr_TR : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> @out Int
+// CHECK-NEXT: [[PA2:%.*]] = partial_apply [callee_guaranteed] [[F]]([[CVT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> @out Int
+// CHECK-NEXT: [[CVT2:%.*]] = convert_escape_to_noescape [[PA2]] : $@callee_guaranteed () -> @out Int to $@noescape @callee_guaranteed () -> @out Int
+// CHECK-NEXT: strong_release [[PA]] : $@callee_guaranteed () -> Int
+// CHECK-NEXT: // function_ref use_closureGeneric<A>(_:)
+// CHECK-NEXT: [[F2:%.*]] = function_ref @$S22closure_lifetime_fixup04use_A7GenericyyxyXElF : $@convention(thin) <τ_0_0> (@noescape @callee_guaranteed () -> @out τ_0_0) -> ()
+// CHECK-NEXT: %12 = apply [[F2]]<Int>([[CVT2]]) : $@convention(thin) <τ_0_0> (@noescape @callee_guaranteed () -> @out τ_0_0) -> ()
+// CHECK-NEXT: strong_release [[PA2]] : $@callee_guaranteed () -> @out Int
+// CHECK-NEXT: strong_release [[PA]] : $@callee_guaranteed () -> Int
+// CHECK-NEXT: tuple ()
+// CHECK-NEXT: return {{.*}} : $()
+
+public func testGeneric(c: C) {
+ use_closureGeneric { return c.returnInt() }
+}
+
+public protocol P {
+ associatedtype Element
+ subscript<U>(a: (Element) -> U, b: (U) -> Element) -> U { get set }
+}
+
+// Make sure we keep the closure alive up until after the write back.
+
+// CHECK-LABEL: sil @$S22closure_lifetime_fixup21testMaterializeForSet1pyxz_tAA1PRzSS7ElementRtzlF : $@convention(thin) <T where T : P, T.Element == String> (@inout T) -> () {
+// CHECK: bb0
+// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[ENUM1:%.*]] = enum $Optional<@callee_guaranteed (@in_guaranteed String) -> @out Int>, #Optional.some!enumelt.1, [[PA1]]
+// CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA1]]
+// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[ENUM2:%.*]] = enum $Optional<@callee_guaranteed (@in_guaranteed Int) -> @out String>, #Optional.some!enumelt.1, [[PA2]]
+// CHECK: [[CVT2:%.*]] = convert_escape_to_noescape [[PA2]]
+// CHECK: [[W:%.*]] = witness_method $T, #P.subscript!materializeForSet.1
+// CHECK: [[BUFFER:%.*]] = apply [[W]]<T, Int>({{.*}}, [[CVT1]], [[CVT2]]
+// CHECK: bb1:
+// CHECK: br bb3
+// CHECK: bb2({{.*}}):
+// CHECK: br bb3
+// CHECK: bb3:
+// CHECK: release_value [[ENUM1]]
+// CHECK: release_value [[ENUM2]]
+public func testMaterializeForSet<T : P>(p: inout T) where T.Element == String {
+ p[{Int($0)!}, {String($0)}] += 1
+}
diff --git a/test/SILOptimizer/definite-init-convert-to-escape.swift b/test/SILOptimizer/definite-init-convert-to-escape.swift
index 74d8d99..f6569ea 100644
--- a/test/SILOptimizer/definite-init-convert-to-escape.swift
+++ b/test/SILOptimizer/definite-init-convert-to-escape.swift
@@ -1,5 +1,5 @@
// RUN: %target-swift-frontend -module-name A -verify -emit-sil -import-objc-header %S/Inputs/Closure.h -disable-objc-attr-requires-foundation-module -enable-sil-ownership %s | %FileCheck %s
-// RUN: %target-swift-frontend -module-name A -verify -emit-sil -import-objc-header %S/Inputs/Closure.h -disable-objc-attr-requires-foundation-module -enable-sil-ownership -Xllvm -sil-di-disable-convert-escape-to-noescape-switch-peephole %s | %FileCheck %s --check-prefix=NOPEEPHOLE
+// RUN: %target-swift-frontend -module-name A -verify -emit-sil -import-objc-header %S/Inputs/Closure.h -disable-objc-attr-requires-foundation-module -enable-sil-ownership -Xllvm -sil-disable-convert-escape-to-noescape-switch-peephole %s | %FileCheck %s --check-prefix=NOPEEPHOLE
// REQUIRES: objc_interop
diff --git a/test/SILOptimizer/hello-world.swift b/test/SILOptimizer/hello-world.swift
new file mode 100644
index 0000000..4e7c19a
--- /dev/null
+++ b/test/SILOptimizer/hello-world.swift
@@ -0,0 +1,6 @@
+// RUN: rm -rf %t && mkdir -p %t/stats
+// RUN: %target-swift-frontend -emit-sil -stats-output-dir %t/stats %s -o /dev/null
+// RUN: %utils/process-stats-dir.py --evaluate 'NumSILGenFunctions < 10' %t/stats
+// RUN: %utils/process-stats-dir.py --evaluate 'NumSILOptFunctions < 10' %t/stats
+
+print("Hello world")
diff --git a/test/SILOptimizer/linker.swift b/test/SILOptimizer/linker.swift
index d411077..7b41bde 100644
--- a/test/SILOptimizer/linker.swift
+++ b/test/SILOptimizer/linker.swift
@@ -1,21 +1,23 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module %S/Inputs/linker_pass_input.swift -o %t/Swift.swiftmodule -parse-stdlib -parse-as-library -module-name Swift -module-link-name swiftCore
-// RUN: %target-swift-frontend %s -O -I %t -sil-debug-serialization -o - -emit-sil | %FileCheck %s
+// RUN: %target-swift-frontend %s -I %t -emit-sil | %FileCheck %s
+// RUN: %target-swift-frontend %s -I %t -O -emit-sil | %FileCheck %s --check-prefix=OPT
-// CHECK: sil public_external [serialized] [canonical] @$Ss11doSomethingyyF : $@convention(thin) () -> () {
+// CHECK: sil [serialized] [noinline] @$Ss11doSomethingyyF : $@convention(thin) () -> (){{$}}
+// OPT: sil public_external [noinline] @$Ss11doSomethingyyF : $@convention(thin) () -> () {
doSomething()
// CHECK: sil @$Ss12doSomething2yyF : $@convention(thin) () -> ()
// CHECK-NOT: return
doSomething2()
-// CHECK: sil public_external [serialized] [noinline] [canonical] @$Ss16callDoSomething3yyF
+// CHECK: sil [serialized] [noinline] @$Ss16callDoSomething3yyF : $@convention(thin) () -> (){{$}}
+// OPT: sil public_external [noinline] @$Ss16callDoSomething3yyF : $@convention(thin) () -> () {
-// CHECK: sil [canonical] @unknown
+// OPT: sil @unknown
-// CHECK: sil [canonical] @$Ss1AVABycfC
+// OPT: sil @$Ss1AVABycfC
-// CHECK: sil [noinline] [canonical] @$Ss12doSomething3yyxlF
-// CHECK-NOT: return
+// OPT: sil [noinline] @$Ss12doSomething3yyxlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> (){{$}}
callDoSomething3()
diff --git a/test/Sema/exhaustive_switch.swift b/test/Sema/exhaustive_switch.swift
index 6333287..8ebbd02 100644
--- a/test/Sema/exhaustive_switch.swift
+++ b/test/Sema/exhaustive_switch.swift
@@ -472,6 +472,21 @@
case (.case10, _): return true
}
+ switch (OverlyLargeSpaceEnum.case1, OverlyLargeSpaceEnum.case2) { // expected-error {{switch must be exhaustive}}
+ case (.case0, _): return true
+ case (.case1, _): return true
+ case (.case2, _): return true
+ case (.case3, _): return true
+ case (.case4, _): return true
+ case (.case5, _): return true
+ case (.case6, _): return true
+ case (.case7, _): return true
+ case (.case8, _): return true
+ case (.case9, _): return true
+ case (.case10, _): return true
+ @unknown default: return false // expected-note {{remove '@unknown' to handle remaining values}} {{3-12=}}
+ }
+
// No diagnostic
switch (OverlyLargeSpaceEnum.case1, OverlyLargeSpaceEnum.case2) {
@@ -525,6 +540,10 @@
case .two: return true
case .three: return true
}
+
+ // Make sure we haven't just stopped emitting diagnostics.
+ switch OverlyLargeSpaceEnum.case1 { // expected-error {{switch must be exhaustive}} expected-note 12 {{add missing case}} expected-note {{handle unknown values}}
+ }
}
indirect enum InfinitelySized {
diff --git a/test/Sema/struct_equatable_hashable_access.swift b/test/Sema/struct_equatable_hashable_access.swift
new file mode 100644
index 0000000..8672c98
--- /dev/null
+++ b/test/Sema/struct_equatable_hashable_access.swift
@@ -0,0 +1,10 @@
+// RUN: %target-swift-frontend -print-ast %s 2>&1 | %FileCheck %s
+
+// Check that synthesized members show up as 'fileprivate', not 'private.
+
+// CHECK-LABEL: private struct PrivateConformer : Hashable {
+private struct PrivateConformer: Hashable {
+ var value: Int
+ // CHECK-DAG: fileprivate var hashValue: Int { get }
+ // CHECK-DAG: @_implements(Equatable, ==(_:_:)) fileprivate static func __derived_struct_equals
+}
diff --git a/test/Serialization/Inputs/def_basic.sil b/test/Serialization/Inputs/def_basic.sil
index 673a9bd..b14ff89 100644
--- a/test/Serialization/Inputs/def_basic.sil
+++ b/test/Serialization/Inputs/def_basic.sil
@@ -1132,37 +1132,23 @@
return %y : $Int
}
-// Make sure we serialize the body of closure even without -sil-serialize-all.
-// CHECK_DECL-LABEL: @partial_apply_with_closure
-sil [transparent] [serialized] [transparent] @partial_apply_with_closure : $@convention(thin) (@owned @callee_owned () -> Bool, @owned String, UnsafePointer<Int8>, Int64) -> () {
+// CHECK-LABEL: @partial_apply_with_closure
+sil [transparent] [serialized] @partial_apply_with_closure : $@convention(thin) (@owned @callee_owned () -> Bool, @owned String, UnsafePointer<Int8>, Int64) -> () {
bb0(%0 : $@callee_owned () -> Bool, %1 : $String, %2 : $UnsafePointer<Int8>, %3 : $Int64):
%17 = function_ref @closure_body : $@convention(thin) (UnsafePointer<Int8>, UnsafePointer<Int8>, Int64) -> ()
-// CHECK_DECL: function_ref @closure_body
+// CHECK: function_ref @closure_body
%18 = partial_apply %17(%2, %3) : $@convention(thin) (UnsafePointer<Int8>, UnsafePointer<Int8>, Int64) -> ()
-// CHECK_DECL: partial_apply
+// CHECK: partial_apply
%30 = tuple ()
return %30 : $()
}
-sil shared [serialized] @closure_body : $@convention(thin) (UnsafePointer<Int8>, UnsafePointer<Int8>, Int64) -> () {
-bb0(%0 : $UnsafePointer<Int8>, %1 : $UnsafePointer<Int8>, %2 : $Int64):
- %3 = function_ref @assert_fail : $@convention(thin) (UnsafePointer<Int8>, UnsafePointer<Int8>, Int64) -> ()
- %4 = apply %3(%0, %1, %2) : $@convention(thin) (UnsafePointer<Int8>, UnsafePointer<Int8>, Int64) -> ()
- %5 = tuple ()
- return %5 : $()
-}
-
-// CHECK_DECL-LABEL: @closure_body : $@convention(thin) (UnsafePointer<Int8>, UnsafePointer<Int8>, Int64) -> () {
-// CHECK_DECL: function_ref @assert_fail
-
-sil [transparent] [serialized] @assert_fail : $@convention(thin) (UnsafePointer<Int8>, UnsafePointer<Int8>, Int64) -> ()
-
// rdar: 15893086
struct GenericStruct<T> {
var x : T
}
-// CHECK-LABEL: @extract_generic_struct
+// CHECK-LABEL: sil public_external [transparent] [serialized] @extract_generic_struct
sil [transparent] [serialized] @extract_generic_struct : $@convention(thin) GenericStruct<Int64> -> Int64 {
entry(%0 : $GenericStruct<Int64>):
// CHECK: %1 = struct_extract %0 : $GenericStruct<Int64>, #GenericStruct.x
@@ -1347,6 +1333,19 @@
}
+sil [transparent] [serialized] @assert_fail : $@convention(thin) (UnsafePointer<Int8>, UnsafePointer<Int8>, Int64) -> ()
+
+sil shared [serialized] @closure_body : $@convention(thin) (UnsafePointer<Int8>, UnsafePointer<Int8>, Int64) -> () {
+bb0(%0 : $UnsafePointer<Int8>, %1 : $UnsafePointer<Int8>, %2 : $Int64):
+ %3 = function_ref @assert_fail : $@convention(thin) (UnsafePointer<Int8>, UnsafePointer<Int8>, Int64) -> ()
+ %4 = apply %3(%0, %1, %2) : $@convention(thin) (UnsafePointer<Int8>, UnsafePointer<Int8>, Int64) -> ()
+ %5 = tuple ()
+ return %5 : $()
+}
+
+// CHECK-LABEL: @closure_body : $@convention(thin) (UnsafePointer<Int8>, UnsafePointer<Int8>, Int64) -> () {
+// CHECK: function_ref @assert_fail
+
sil_vtable [serialized] Foo {
#Foo.subscript!getter.1: @$S3tmp3FooC9subscriptSiSi1x_Si1ytcfg
#Foo.subscript!setter.1: @$S3tmp3FooC9subscriptSiSi1x_Si1ytcfs
diff --git a/test/Serialization/Inputs/def_transparent.swift b/test/Serialization/Inputs/def_transparent.swift
index 73bf8d4..20da66e 100644
--- a/test/Serialization/Inputs/def_transparent.swift
+++ b/test/Serialization/Inputs/def_transparent.swift
@@ -44,7 +44,8 @@
case Right(String)
case Both(Int32, String)
}
-@inlinable
+
+@_transparent
public func do_switch(u u: MaybePair) {
switch u {
case .Neither:
diff --git a/test/Serialization/always_inline.swift b/test/Serialization/always_inline.swift
index 5a354e5..2a8ec45 100644
--- a/test/Serialization/always_inline.swift
+++ b/test/Serialization/always_inline.swift
@@ -1,12 +1,17 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/def_always_inline.swift
// RUN: llvm-bcanalyzer %t/def_always_inline.swiftmodule | %FileCheck %s
-// RUN: %target-swift-frontend -emit-sil -I %t %s | %FileCheck %s -check-prefix=SIL
+// RUN: %target-swift-frontend -emit-sib -I %t %s -o %t/always_inline.sib
+// RUN: %target-sil-opt -performance-linker %t/always_inline.sib -I %t | %FileCheck %s -check-prefix=SIL
// CHECK-NOT: UnknownCode
import def_always_inline
+// SIL-LABEL: sil public_external [serialized] [always_inline] [canonical] @$S17def_always_inline22AlwaysInlineInitStructV1xACSb_tcfC : $@convention(method) (Bool, @thin AlwaysInlineInitStruct.Type) -> AlwaysInlineInitStruct {
+
+// SIL-LABEL: sil public_external [serialized] [always_inline] [canonical] @$S17def_always_inline16testAlwaysInline1xS2b_tF : $@convention(thin) (Bool) -> Bool {
+
// SIL-LABEL: sil @main
// SIL: [[RAW:%.+]] = global_addr @$S13always_inline3rawSbvp : $*Bool
// SIL: [[FUNC:%.+]] = function_ref @$S17def_always_inline16testAlwaysInline1xS2b_tF : $@convention(thin) (Bool) -> Bool
@@ -16,10 +21,5 @@
// SIL: [[FUNC2:%.+]] = function_ref @$S17def_always_inline22AlwaysInlineInitStructV1xACSb_tcfC : $@convention(method) (Bool, @thin AlwaysInlineInitStruct.Type) -> AlwaysInlineInitStruct
// SIL: apply [[FUNC2]]({{%.+}}, {{%.+}}) : $@convention(method) (Bool, @thin AlwaysInlineInitStruct.Type) -> AlwaysInlineInitStruct
-
var a = AlwaysInlineInitStruct(x: false)
-// SIL-LABEL: [always_inline] @$S17def_always_inline16testAlwaysInline1xS2b_tF : $@convention(thin) (Bool) -> Bool
-
-// SIL-LABEL: sil public_external [serialized] [always_inline] @$S17def_always_inline22AlwaysInlineInitStructV1xACSb_tcfC : $@convention(method) (Bool, @thin AlwaysInlineInitStruct.Type) -> AlwaysInlineInitStruct {
-
diff --git a/test/Serialization/basic_sil.swift b/test/Serialization/basic_sil.swift
index 12cbe2e..a81df0e 100644
--- a/test/Serialization/basic_sil.swift
+++ b/test/Serialization/basic_sil.swift
@@ -1,11 +1,8 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -Xfrontend -assume-parsing-unqualified-ownership-sil -emit-module -Xfrontend -disable-diagnostic-passes -force-single-frontend-invocation -o %t/def_basic.swiftmodule %S/Inputs/def_basic.sil
// RUN: llvm-bcanalyzer %t/def_basic.swiftmodule | %FileCheck %s
-// RUN: %target-build-swift -emit-sil -I %t %s | %FileCheck %S/Inputs/def_basic.sil
-
-// RUN: %empty-directory(%t)
-// RUN: %target-build-swift -Xfrontend -assume-parsing-unqualified-ownership-sil -emit-module -Xfrontend -disable-diagnostic-passes -force-single-frontend-invocation -o %t/def_basic.swiftmodule %S/Inputs/def_basic.sil
-// RUN: %target-build-swift -emit-sil -I %t %s | %FileCheck -check-prefix=CHECK_DECL %S/Inputs/def_basic.sil
+// RUN: %target-build-swift -emit-sil -I %t %s -o %t/basic_sil.sil
+// RUN: %target-sil-opt -I %t %t/basic_sil.sil -performance-linker | %FileCheck %S/Inputs/def_basic.sil
// This test currently is written such that no optimizations are assumed.
// REQUIRES: swift_test_mode_optimize_none
diff --git a/test/Serialization/basic_sil_objc.swift b/test/Serialization/basic_sil_objc.swift
index 0a83a07..cfaeaa6 100644
--- a/test/Serialization/basic_sil_objc.swift
+++ b/test/Serialization/basic_sil_objc.swift
@@ -1,7 +1,9 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -Xfrontend %clang-importer-sdk -I %S/../Inputs/clang-importer-sdk/swift-modules -emit-module -Xfrontend -disable-diagnostic-passes -force-single-frontend-invocation -o %t/def_basic_objc.swiftmodule %S/Inputs/def_basic_objc.sil
// RUN: llvm-bcanalyzer %t/def_basic_objc.swiftmodule | %FileCheck %s
-// RUN: %target-build-swift -Xfrontend %clang-importer-sdk -emit-sil -I %t %s | %FileCheck %S/Inputs/def_basic_objc.sil
+
+// RUN: %target-build-swift -Xfrontend %clang-importer-sdk -emit-sil -I %t %s -o %t/basic_sil_objc.sil
+// RUN: %target-sil-opt %t/basic_sil_objc.sil -performance-linker -I %t | %FileCheck %S/Inputs/def_basic_objc.sil
// This test currently is written such that no optimizations are assumed.
// REQUIRES: swift_test_mode_optimize_none
@@ -10,6 +12,7 @@
// CHECK-NOT: UnknownCode
import def_basic_objc
+import Foundation
func test_all() {
serialize_all()
diff --git a/test/Serialization/noinline.swift b/test/Serialization/noinline.swift
index f7d9052..719e076 100644
--- a/test/Serialization/noinline.swift
+++ b/test/Serialization/noinline.swift
@@ -1,12 +1,17 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/def_noinline.swift
// RUN: llvm-bcanalyzer %t/def_noinline.swiftmodule | %FileCheck %s
-// RUN: %target-swift-frontend -emit-sil -I %t %s | %FileCheck %s -check-prefix=SIL
+// RUN: %target-swift-frontend -emit-sib -I %t %s -o %t/noinline.sib
+// RUN: %target-sil-opt -performance-linker %t/noinline.sib -I %t | %FileCheck %s -check-prefix=SIL
// CHECK-NOT: UnknownCode
import def_noinline
+// SIL-LABEL: sil public_external [serialized] [noinline] [canonical] @$S12def_noinline18NoInlineInitStructV1xACSb_tcfC : $@convention(method) (Bool, @thin NoInlineInitStruct.Type) -> NoInlineInitStruct {
+
+// SIL-LABEL: sil public_external [serialized] [noinline] [canonical] @$S12def_noinline12testNoinline1xS2b_tF : $@convention(thin) (Bool) -> Bool {
+
// SIL-LABEL: sil @main
// SIL: [[RAW:%.+]] = global_addr @$S8noinline3rawSbvp : $*Bool
// SIL: [[FUNC:%.+]] = function_ref @$S12def_noinline12testNoinline1xS2b_tF : $@convention(thin) (Bool) -> Bool
@@ -18,7 +23,3 @@
// SIL: apply [[FUNC2]]({{%.+}}, {{%.+}}) : $@convention(method) (Bool, @thin NoInlineInitStruct.Type) -> NoInlineInitStruct
var a = NoInlineInitStruct(x: false)
-
-// SIL-LABEL: [serialized] [noinline] @$S12def_noinline12testNoinline1xS2b_tF : $@convention(thin) (Bool) -> Bool
-
-// SIL-LABEL: sil public_external [serialized] [noinline] @$S12def_noinline18NoInlineInitStructV1xACSb_tcfC : $@convention(method) (Bool, @thin NoInlineInitStruct.Type) -> NoInlineInitStruct {
diff --git a/test/Serialization/sil_partial_apply_ownership.sil b/test/Serialization/sil_partial_apply_ownership.sil
index 09dc7b6..7c6216a 100644
--- a/test/Serialization/sil_partial_apply_ownership.sil
+++ b/test/Serialization/sil_partial_apply_ownership.sil
@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
-// RUN: %target-build-swift -Xfrontend -assume-parsing-unqualified-ownership-sil -emit-module -Xfrontend -disable-diagnostic-passes -force-single-frontend-invocation -o %t/sil_partial_apply_ownership.swiftmodule %s
-// RUN: %target-build-swift -Xfrontend -assume-parsing-unqualified-ownership-sil -emit-sil -I %t %s | %FileCheck %s
+// RUN: %target-build-swift -Xfrontend -assume-parsing-unqualified-ownership-sil -emit-module -Xllvm -verify-skip-convert-escape-to-noescape-attributes -Xfrontend -disable-diagnostic-passes -force-single-frontend-invocation -o %t/sil_partial_apply_ownership.swiftmodule %s
+// RUN: %target-build-swift -Xfrontend -assume-parsing-unqualified-ownership-sil -Xllvm -verify-skip-convert-escape-to-noescape-attributes -emit-sil -I %t %s | %FileCheck %s
import Builtin
@@ -47,12 +47,18 @@
// CHECK-LABEL: sil @partial_apply_convert
// CHECK: convert_escape_to_noescape %{{.*}} : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: convert_escape_to_noescape [not_guaranteed] %
+// CHECK: convert_escape_to_noescape [escaped] %
+// CHECK: convert_escape_to_noescape [not_guaranteed] [escaped] %
sil @partial_apply_convert : $@convention(thin) () -> () {
entry:
%f = function_ref @subject : $@convention(thin) (Builtin.Int64) -> ()
%z = integer_literal $Builtin.Int64, 0
%e = partial_apply [callee_guaranteed] %f(%z) : $@convention(thin) (Builtin.Int64) -> ()
%n = convert_escape_to_noescape %e : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+ %x2 = convert_escape_to_noescape [not_guaranteed] %e : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+ %x3 = convert_escape_to_noescape [escaped] %e : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+ %x4 = convert_escape_to_noescape [not_guaranteed] [escaped] %e : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
%n2 = mark_dependence %n : $@noescape @callee_guaranteed () -> () on %e : $@callee_guaranteed () -> ()
%f2 = function_ref @use : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
apply %f2(%n2) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
diff --git a/test/Serialization/transparent.swift b/test/Serialization/transparent.swift
index b887699..48d7ace 100644
--- a/test/Serialization/transparent.swift
+++ b/test/Serialization/transparent.swift
@@ -2,7 +2,7 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/def_transparent.swift
// RUN: llvm-bcanalyzer %t/def_transparent.swiftmodule | %FileCheck %s
-// RUN: %target-swift-frontend -module-name transparent -emit-sil -I %t %s | tee /tmp/xxx | %FileCheck %s -check-prefix=SIL
+// RUN: %target-swift-frontend -module-name transparent -emit-sil -I %t %s | %FileCheck %s -check-prefix=SIL
// CHECK-NOT: UnknownCode
@@ -40,7 +40,7 @@
test_br()
}
-// SIL-LABEL: sil public_external [serialized] @$S15def_transparent9do_switch1uyAA9MaybePairO_tF : $@convention(thin) (@guaranteed MaybePair) -> () {
+// SIL-LABEL: sil public_external [transparent] [serialized] @$S15def_transparent9do_switch1uyAA9MaybePairO_tF : $@convention(thin) (@guaranteed MaybePair) -> () {
// SIL: bb0(%0 : $MaybePair):
// SIL: retain_value %0 : $MaybePair
// SIL: switch_enum %0 : $MaybePair, case #MaybePair.Neither!enumelt: bb[[CASE1:[0-9]+]], case #MaybePair.Left!enumelt.1: bb[[CASE2:[0-9]+]], case #MaybePair.Right!enumelt.1: bb[[CASE3:[0-9]+]], case #MaybePair.Both!enumelt.1: bb[[CASE4:[0-9]+]]
diff --git a/test/decl/protocol/conforms/self.swift b/test/decl/protocol/conforms/self.swift
index 1aa9fb8..7fe8e4e 100644
--- a/test/decl/protocol/conforms/self.swift
+++ b/test/decl/protocol/conforms/self.swift
@@ -70,3 +70,19 @@
}
extension SeriousClass : HasDefault {}
+
+// https://bugs.swift.org/browse/SR-7428
+
+protocol Node {
+ associatedtype ValueType = Int
+
+ func addChild<ChildType>(_ child: ChildType)
+ where ChildType: Node, ChildType.ValueType == Self.ValueType
+}
+
+extension Node {
+ func addChild<ChildType>(_ child: ChildType)
+ where ChildType: Node, ChildType.ValueType == Self.ValueType {}
+}
+
+class IntNode: Node {}
diff --git a/test/decl/protocol/special/coding/class_codable_inheritance.swift b/test/decl/protocol/special/coding/class_codable_inheritance.swift
index 2f29331..baa2173 100644
--- a/test/decl/protocol/special/coding/class_codable_inheritance.swift
+++ b/test/decl/protocol/special/coding/class_codable_inheritance.swift
@@ -50,3 +50,30 @@
// The synthesized CodingKeys type should not be accessible from outside the
// class.
let _ = SimpleChildClass.CodingKeys.self // expected-error {{'CodingKeys' is inaccessible due to 'private' protection level}}
+
+// Check access level issues around 'private'.
+private class PrivateClass: Codable {
+ var x: Int = 1
+}
+
+private class PrivateClassChild: PrivateClass {}
+
+_ = PrivateClass.init(from:)
+_ = PrivateClass.encode(to:)
+_ = PrivateClassChild.init(from:)
+_ = PrivateClassChild.encode(to:)
+
+_ = PrivateClass.CodingKeys.self // expected-error {{'CodingKeys' is inaccessible due to 'private' protection level}}
+
+// Check access level issues around 'open'.
+open class OpenClass: Codable {
+ var x: Int = 1
+}
+open class OpenClassChild: OpenClass {}
+
+_ = OpenClass.init(from:)
+_ = OpenClass.encode(to:)
+_ = OpenClassChild.init(from:)
+_ = OpenClassChild.encode(to:)
+
+_ = OpenClass.CodingKeys.self // expected-error {{'CodingKeys' is inaccessible due to 'private' protection level}}
diff --git a/test/expr/primary/literal/collection_upcast_opt.swift b/test/expr/primary/literal/collection_upcast_opt.swift
new file mode 100644
index 0000000..d105716
--- /dev/null
+++ b/test/expr/primary/literal/collection_upcast_opt.swift
@@ -0,0 +1,38 @@
+// RUN: %target-typecheck-verify-swift -dump-ast 2> %t.ast
+// RUN: %FileCheck %s < %t.ast
+
+// Verify that upcasts of array literals upcast the individual elements in place
+// rather than introducing a collection_upcast_expr.
+
+protocol P { }
+struct X : P { }
+
+struct TakesArray<T> {
+ init(_: [(T) -> Void]) { }
+}
+
+// CHECK-LABEL: func_decl "arrayUpcast(_:_:)"
+// CHECK: assign_expr
+// CHECK-NOT: collection_upcast_expr
+// CHECK: array_expr type='[(X) -> Void]'
+// CHECK-NEXT: function_conversion_expr implicit type='(X) -> Void'
+// CHECK-NEXT: {{declref_expr.*x1}}
+// CHECK-NEXT: function_conversion_expr implicit type='(X) -> Void'
+// CHECK-NEXT: {{declref_expr.*x2}}
+func arrayUpcast(_ x1: @escaping (P) -> Void, _ x2: @escaping (P) -> Void) {
+ _ = TakesArray<X>([x1, x2])
+}
+
+struct TakesDictionary<T> {
+ init(_: [Int : (T) -> Void]) { }
+}
+
+// CHECK-LABEL: func_decl "dictionaryUpcast(_:_:)"
+// CHECK: assign_expr
+// CHECK-NOT: collection_upcast_expr
+// CHECK: paren_expr type='([Int : (X) -> Void])'
+// CHECK-NOT: collection_upcast_expr
+// CHECK: (dictionary_expr type='[Int : (X) -> Void]'
+func dictionaryUpcast(_ x1: @escaping (P) -> Void, _ x2: @escaping (P) -> Void) {
+ _ = TakesDictionary<X>(([1: x1, 2: x2]))
+}
diff --git a/test/multifile/Inputs/outlined-thunks-other.swift b/test/multifile/Inputs/outlined-thunks-other.swift
new file mode 100644
index 0000000..95da403
--- /dev/null
+++ b/test/multifile/Inputs/outlined-thunks-other.swift
@@ -0,0 +1,5 @@
+private class OtherPrivate<T> { }
+
+struct OtherInternal<T> {
+ fileprivate var myPrivate: OtherPrivate<T>? = nil
+}
diff --git a/test/multifile/outlined-thunks.swift b/test/multifile/outlined-thunks.swift
new file mode 100644
index 0000000..b24a959
--- /dev/null
+++ b/test/multifile/outlined-thunks.swift
@@ -0,0 +1,18 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-build-swift -emit-library -module-name outlined_thunks %S/Inputs/outlined-thunks-other.swift %s
+// RUN: %target-build-swift -emit-library -module-name outlined_thunks -whole-module-optimization %S/Inputs/outlined-thunks-other.swift %s
+
+// rdar://problem/39470607
+
+protocol P { }
+
+private struct MyPrivate<T: P> {
+ private var otherHelper: OtherInternal<T>? = nil
+ init(_: T) { }
+}
+
+extension P {
+ func foo(data: Any) {
+ _ = MyPrivate(data as! Self)
+ }
+}
diff --git a/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L12-14.swift.expected b/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L12-14.swift.expected
index 388f8cf..d57e401 100644
--- a/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L12-14.swift.expected
+++ b/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L12-14.swift.expected
@@ -9,7 +9,9 @@
didSet { print("bye") }
}
-func generic<T>(_: T) -> Int { fatalError() }
+func generic<T>(_: T) -> Int {
+fatalError()
+}
class Foo {
var foo: Int
diff --git a/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L16-49.swift.expected b/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L16-49.swift.expected
index 6ad8406..3ee21a6 100644
--- a/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L16-49.swift.expected
+++ b/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L16-49.swift.expected
@@ -16,25 +16,43 @@
class Foo {
var foo: Int
- var bar: Int { fatalError() }
+ var bar: Int {
+fatalError()
+}
var baz: Int {
- get { fatalError() }
- set { fatalError() }
+ get {
+fatalError()
+}
+ set {
+fatalError()
+}
}
var qux: Int {
- willSet { fatalError() }
- didSet { fatalError() }
+ willSet {
+fatalError()
+}
+ didSet {
+fatalError()
+}
}
- init() { fatalError() }
+ init() {
+fatalError()
+}
- func nonGeneric() -> Int { fatalError() }
+ func nonGeneric() -> Int {
+fatalError()
+}
- func generic<T>(_: T) -> Int { fatalError() }
+ func generic<T>(_: T) -> Int {
+fatalError()
+}
- deinit { fatalError() }
+ deinit {
+fatalError()
+}
}
extension Foo {
diff --git a/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L19-22.swift.expected b/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L19-22.swift.expected
index 0e6dbc5..cd68c9f 100644
--- a/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L19-22.swift.expected
+++ b/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L19-22.swift.expected
@@ -16,7 +16,9 @@
class Foo {
var foo: Int
- var bar: Int { fatalError() }
+ var bar: Int {
+fatalError()
+}
var baz: Int {
get { return 0 }
diff --git a/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L3-5.swift.expected b/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L3-5.swift.expected
index 5d0d2e8..d4ea890 100644
--- a/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L3-5.swift.expected
+++ b/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L3-5.swift.expected
@@ -1,6 +1,8 @@
var foo: Int = 0
-var bar: Int { fatalError() }
+var bar: Int {
+fatalError()
+}
var qux: Int = 0 {
willSet { print("hi") }
diff --git a/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L30-44.swift.expected b/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L30-44.swift.expected
index ed96bab..053b5bc 100644
--- a/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L30-44.swift.expected
+++ b/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L30-44.swift.expected
@@ -27,14 +27,22 @@
var qux: Int {
willSet { print("hi") }
- didSet { fatalError() }
+ didSet {
+fatalError()
+}
}
- init() { fatalError() }
+ init() {
+fatalError()
+}
- func nonGeneric() -> Int { fatalError() }
+ func nonGeneric() -> Int {
+fatalError()
+}
- func generic<T>(_: T) -> Int { fatalError() }
+ func generic<T>(_: T) -> Int {
+fatalError()
+}
deinit {
print("bye")
diff --git a/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L51-59.swift.expected b/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L51-59.swift.expected
index 8a73c00..95bd535 100644
--- a/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L51-59.swift.expected
+++ b/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L51-59.swift.expected
@@ -49,9 +49,13 @@
}
extension Foo {
- func nonGeneric2() -> Int { fatalError() }
+ func nonGeneric2() -> Int {
+fatalError()
+}
- func generic2<T>(_: T) -> Int { fatalError() }
+ func generic2<T>(_: T) -> Int {
+fatalError()
+}
}
diff --git a/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L7-10.swift.expected b/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L7-10.swift.expected
index 02d3f7b..06ce662 100644
--- a/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L7-10.swift.expected
+++ b/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L7-10.swift.expected
@@ -5,8 +5,12 @@
}
var qux: Int = 0 {
- willSet { fatalError() }
- didSet { fatalError() }
+ willSet {
+fatalError()
+}
+ didSet {
+fatalError()
+}
}
func generic<T>(_: T) -> Int {
diff --git a/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L8.swift.expected b/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L8.swift.expected
index f9fa570..68a1e53 100644
--- a/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L8.swift.expected
+++ b/test/refactoring/ReplaceBodiesWithFatalError/Outputs/basic/L8.swift.expected
@@ -5,7 +5,9 @@
}
var qux: Int = 0 {
- willSet { fatalError() }
+ willSet {
+fatalError()
+}
didSet { print("bye") }
}
diff --git a/test/refactoring/ReplaceBodiesWithFatalError/requires-env-var.swift b/test/refactoring/ReplaceBodiesWithFatalError/requires-env-var.swift
new file mode 100644
index 0000000..bd21695
--- /dev/null
+++ b/test/refactoring/ReplaceBodiesWithFatalError/requires-env-var.swift
@@ -0,0 +1,16 @@
+var bar: Int {
+ return 0
+}
+// CHECK-NO-ENV-LABEL: Action begins
+// CHECK-NO-ENV-NEXT: Action ends
+
+// CHECK-ENV-LABEL: Action begins
+// CHECK-ENV-NEXT: Replace Function Bodies With 'fatalError()'
+// CHECK-ENV-NEXT: Action ends
+
+// replace.bodies.with.fatalError/-replace-bodies-with-fatalError should only be
+// found if the appropriate environment variable is set.
+
+// RUN: %refactor -actions -source-filename %s -pos=1:1 -end-pos=3:2 | %FileCheck %s -check-prefix CHECK-NO-ENV
+
+// RUN: env SWIFT_ENABLE_INTERNAL_REFACTORING_ACTIONS=1 %refactor -actions -source-filename %s -pos=1:1 -end-pos=3:2 | %FileCheck %s -check-prefix CHECK-ENV
diff --git a/test/stdlib/TestDecimal.swift b/test/stdlib/TestDecimal.swift
index 00dda26..3d2a304 100644
--- a/test/stdlib/TestDecimal.swift
+++ b/test/stdlib/TestDecimal.swift
@@ -272,6 +272,9 @@
expectEqual(.minus, d.sign)
d.negate()
expectEqual(.plus, d.sign)
+ var e = Decimal(0)
+ e.negate()
+ expectEqual(e, 0)
expectTrue(Decimal(3.5).isEqual(to: Decimal(3.5)))
expectTrue(Decimal.nan.isEqual(to: Decimal.nan))
expectTrue(Decimal(1.28).isLess(than: Decimal(2.24)))
diff --git a/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp b/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp
index 140bedb..1ac528d 100644
--- a/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp
+++ b/tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp
@@ -199,6 +199,28 @@
DumpTypeFromMangled.removeArgument();
InputNames.removeArgument();
+ auto validateInputFile = [](std::string Filename) {
+ if (Filename.empty())
+ return true;
+ if (!llvm::sys::fs::exists(llvm::Twine(Filename))) {
+ llvm::errs() << Filename << " does not exists, exiting.\n";
+ return false;
+ }
+ if (!llvm::sys::fs::is_regular_file(llvm::Twine(Filename))) {
+ llvm::errs() << Filename << " is not a regular file, exiting.\n";
+ return false;
+ }
+ return true;
+ };
+
+ for (auto &InputFilename : InputNames)
+ if (!validateInputFile(InputFilename))
+ return 1;
+ if (!validateInputFile(DumpTypeFromMangled))
+ return 1;
+ if (!validateInputFile(DumpDeclFromMangled))
+ return 1;
+
// Fetch the serialized module bitstreams from the Mach-O files and
// register them with the module loader.
llvm::SmallVector<std::pair<char *, uint64_t>, 8> Modules;
diff --git a/utils/pass-pipeline/src/passes.py b/utils/pass-pipeline/src/passes.py
index 5a28a83..c5e5afd 100644
--- a/utils/pass-pipeline/src/passes.py
+++ b/utils/pass-pipeline/src/passes.py
@@ -40,7 +40,7 @@
PerfInliner = Pass('PerfInliner')
PerformanceConstantPropagation = Pass('PerformanceConstantPropagation')
PredictableMemoryOptimizations = Pass('PredictableMemoryOptimizations')
-SILCleanup = Pass('SILCleanup')
+IRGenPrepare = Pass('IRGenPrepare')
SILCombine = Pass('SILCombine')
SILLinker = Pass('SILLinker')
SROA = Pass('SROA')
@@ -89,7 +89,7 @@
PerfInliner,
PerformanceConstantPropagation,
PredictableMemoryOptimizations,
- SILCleanup,
+ IRGenPrepare,
SILCombine,
SILLinker,
SROA,
diff --git a/validation-test/compiler_crashers_2/0153-rdar39130543.swift b/validation-test/compiler_crashers_2/0153-rdar39130543.swift
new file mode 100644
index 0000000..40d25aa
--- /dev/null
+++ b/validation-test/compiler_crashers_2/0153-rdar39130543.swift
@@ -0,0 +1,21 @@
+// RUN: not --crash %target-swift-frontend %s -emit-ir
+
+protocol P20 { }
+
+protocol P21b {
+ associatedtype T
+
+ func foo(_: (T?) -> Void)
+}
+
+protocol P21a {
+ associatedtype T
+
+ func bar(_: ([T]) -> Void)
+}
+
+extension P21b where Self: P21a, T: P20 {
+ func foo(_: (T?) -> Void) {
+ bar { _ in }
+ }
+}
diff --git a/validation-test/compiler_crashers/28598-issatisfied-request.swift b/validation-test/compiler_crashers_fixed/28598-issatisfied-request.swift
similarity index 84%
rename from validation-test/compiler_crashers/28598-issatisfied-request.swift
rename to validation-test/compiler_crashers_fixed/28598-issatisfied-request.swift
index c7da4d8..b617169 100644
--- a/validation-test/compiler_crashers/28598-issatisfied-request.swift
+++ b/validation-test/compiler_crashers_fixed/28598-issatisfied-request.swift
@@ -5,8 +5,8 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// RUN: not --crash %target-swift-frontend %s -emit-ir
-// REQUIRES: asserts
+// RUN: not %target-swift-frontend %s -emit-ir
+
class a{
let d= <H
class B{extension{protocol A{{
diff --git a/validation-test/compiler_crashers/28778-hasaccessibility-accessibility-not-computed-yet.swift b/validation-test/compiler_crashers_fixed/28778-hasaccessibility-accessibility-not-computed-yet.swift
similarity index 83%
rename from validation-test/compiler_crashers/28778-hasaccessibility-accessibility-not-computed-yet.swift
rename to validation-test/compiler_crashers_fixed/28778-hasaccessibility-accessibility-not-computed-yet.swift
index 6bf0b84..20c2b30 100644
--- a/validation-test/compiler_crashers/28778-hasaccessibility-accessibility-not-computed-yet.swift
+++ b/validation-test/compiler_crashers_fixed/28778-hasaccessibility-accessibility-not-computed-yet.swift
@@ -5,6 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
-// RUN: not --crash %target-swift-frontend %s -emit-ir
+
+// RUN: not %target-swift-frontend %s -emit-ir
extension{let d=r protocol A{{}extension{func<(Int=
diff --git a/validation-test/stdlib/Range.swift.gyb b/validation-test/stdlib/Range.swift.gyb
index 9ae0fdd..bf34c58 100644
--- a/validation-test/stdlib/Range.swift.gyb
+++ b/validation-test/stdlib/Range.swift.gyb
@@ -788,5 +788,11 @@
result)
}
+MiscTestSuite.test("Compatibility typealiases") {
+ let _: CountablePartialRangeFrom = 1...
+ let _: CountableRange = MinimalStrideableValue(3)..<MinimalStrideableValue(3)
+ let _: CountableClosedRange = MinimalStrideableValue(3)...MinimalStrideableValue(3)
+}
+
runAllTests()