Merge branch 'master' into remotemirror-hide-reflection-sections
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 31373ee..55317a8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,7 +6,7 @@
| Contents |
| :--------------------- |
-| [Swift 5.0](#swift-50) |
+| [Swift 4.2](#swift-42) |
| [Swift 4.1](#swift-41) |
| [Swift 4.0](#swift-40) |
| [Swift 3.1](#swift-31) |
@@ -20,7 +20,7 @@
</details>
-Swift 5.0
+Swift 4.2
---------
* Public classes may now have internal `required` initializers. The rule for
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e9281bf..0050546 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -128,7 +128,7 @@
# SWIFT_VERSION is deliberately /not/ cached so that an existing build directory
# can be reused when a new version of Swift comes out (assuming the user hasn't
# manually set it as part of their own CMake configuration).
-set(SWIFT_VERSION "4.1")
+set(SWIFT_VERSION "4.2")
set(SWIFT_VENDOR "" CACHE STRING
"The vendor name of the Swift compiler")
diff --git a/benchmark/utils/DriverUtils.swift b/benchmark/utils/DriverUtils.swift
index f5b5398..74f59d6 100644
--- a/benchmark/utils/DriverUtils.swift
+++ b/benchmark/utils/DriverUtils.swift
@@ -208,14 +208,10 @@
}
if let x = benchArgs.optionalArgsMap["--sleep"] {
- if x.isEmpty {
+ guard let v = Int(x) else {
return .fail("--sleep requires a non-empty integer value")
}
- let v: Int? = Int(x)
- if v == nil {
- return .fail("--sleep requires a non-empty integer value")
- }
- afterRunSleep = v!
+ afterRunSleep = v
}
if let _ = benchArgs.optionalArgsMap["--list"] {
diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake
index 5f191ce..e837cf6 100644
--- a/cmake/modules/AddSwift.cmake
+++ b/cmake/modules/AddSwift.cmake
@@ -183,12 +183,16 @@
if(optimized OR CFLAGS_FORCE_BUILD_OPTIMIZED)
list(APPEND result "-O2")
- # Omit leaf frame pointers on x86.
- if("${CFLAGS_ARCH}" STREQUAL "i386" OR "${CFLAGS_ARCH}" STREQUAL "i686")
- if(NOT SWIFT_COMPILER_IS_MSVC_LIKE)
- list(APPEND result "-momit-leaf-frame-pointer")
- else()
- list(APPEND result "/Oy")
+ # Omit leaf frame pointers on x86 production builds (optimized, no debug
+ # info, and no asserts).
+ is_build_type_with_debuginfo("${CFLAGS_BUILD_TYPE}" debug)
+ if(NOT debug AND NOT CFLAGS_ENABLE_ASSERTIONS)
+ if("${CFLAGS_ARCH}" STREQUAL "i386" OR "${CFLAGS_ARCH}" STREQUAL "i686")
+ if(NOT SWIFT_COMPILER_IS_MSVC_LIKE)
+ list(APPEND result "-momit-leaf-frame-pointer")
+ else()
+ list(APPEND result "/Oy")
+ endif()
endif()
endif()
else()
diff --git a/docs/Serialization.rst b/docs/Serialization.rst
index 9655ecf..57f55ab 100644
--- a/docs/Serialization.rst
+++ b/docs/Serialization.rst
@@ -135,7 +135,7 @@
of ``@_transparent``. The SIL block precedes the AST block because it affects
which AST nodes get serialized.
-- The **SIL index black** contains tables for accessing various SIL entities by
+- The **SIL index block** contains tables for accessing various SIL entities by
their names, along with a mapping of unique IDs for these to the appropriate
bit offsets into the SIL block.
diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h
index aed6000..8c4f7d6 100644
--- a/include/swift/ABI/MetadataValues.h
+++ b/include/swift/ABI/MetadataValues.h
@@ -1021,6 +1021,10 @@
/// Only meaningful for class descriptors.
Class_SuperclassReferenceKind = 12,
Class_SuperclassReferenceKind_width = 2,
+
+ /// Whether the immediate class members in this metadata are allocated
+ /// at negative offsets. For now, we don't use this.
+ Class_AreImmediateMembersNegative = 11,
};
public:
@@ -1037,6 +1041,9 @@
FLAGSET_DEFINE_FLAG_ACCESSORS(Class_HasResilientSuperclass,
class_hasResilientSuperclass,
class_setHasResilientSuperclass)
+ FLAGSET_DEFINE_FLAG_ACCESSORS(Class_AreImmediateMembersNegative,
+ class_areImmediateMembersNegative,
+ class_setAreImmediateMembersNegative)
FLAGSET_DEFINE_FIELD_ACCESSORS(Class_SuperclassReferenceKind,
Class_SuperclassReferenceKind_width,
diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def
index 2bcaf62..9569816 100644
--- a/include/swift/AST/Attr.def
+++ b/include/swift/AST/Attr.def
@@ -214,9 +214,9 @@
NotSerialized | RejectByParser, /* Not serialized */48)
// Also handles unowned and unowned(weak).
-DECL_ATTR(weak, Ownership, OnVar | OnParam | DeclModifier | NotSerialized,
+DECL_ATTR(weak, ReferenceOwnership, OnVar | OnParam | DeclModifier | NotSerialized,
/* Not serialized */49)
-DECL_ATTR_ALIAS(unowned, Ownership)
+DECL_ATTR_ALIAS(unowned, ReferenceOwnership)
DECL_ATTR(effects, Effects, OnFunc | OnConstructor | OnDestructor |
UserInaccessible, 50)
diff --git a/include/swift/AST/Attr.h b/include/swift/AST/Attr.h
index a31a22f..78f21c4 100644
--- a/include/swift/AST/Attr.h
+++ b/include/swift/AST/Attr.h
@@ -105,13 +105,18 @@
bool hasConvention() const { return convention.hasValue(); }
StringRef getConvention() const { return *convention; }
-
- bool hasOwnership() const { return getOwnership() != Ownership::Strong; }
- Ownership getOwnership() const {
- if (has(TAK_sil_weak)) return Ownership::Weak;
- if (has(TAK_sil_unowned)) return Ownership::Unowned;
- if (has(TAK_sil_unmanaged)) return Ownership::Unmanaged;
- return Ownership::Strong;
+
+ bool hasOwnership() const {
+ return getOwnership() != ReferenceOwnership::Strong;
+ }
+ ReferenceOwnership getOwnership() const {
+ if (has(TAK_sil_weak))
+ return ReferenceOwnership::Weak;
+ if (has(TAK_sil_unowned))
+ return ReferenceOwnership::Unowned;
+ if (has(TAK_sil_unmanaged))
+ return ReferenceOwnership::Unmanaged;
+ return ReferenceOwnership::Strong;
}
void clearOwnership() {
@@ -965,24 +970,27 @@
/// Represents weak/unowned/unowned(unsafe) decl modifiers.
-class OwnershipAttr : public DeclAttribute {
- const Ownership ownership;
+class ReferenceOwnershipAttr : public DeclAttribute {
+ const ReferenceOwnership ownership;
+
public:
- OwnershipAttr(SourceRange range, Ownership kind)
- : DeclAttribute(DAK_Ownership, range.Start, range, /*Implicit=*/false),
- ownership(kind) {}
+ ReferenceOwnershipAttr(SourceRange range, ReferenceOwnership kind)
+ : DeclAttribute(DAK_ReferenceOwnership, range.Start, range,
+ /*Implicit=*/false),
+ ownership(kind) {}
- OwnershipAttr(Ownership kind) : OwnershipAttr(SourceRange(), kind) {}
+ ReferenceOwnershipAttr(ReferenceOwnership kind)
+ : ReferenceOwnershipAttr(SourceRange(), kind) {}
- Ownership get() const { return ownership; }
+ ReferenceOwnership get() const { return ownership; }
/// Returns a copy of this attribute without any source information.
- OwnershipAttr *clone(ASTContext &context) const {
- return new (context) OwnershipAttr(get());
+ ReferenceOwnershipAttr *clone(ASTContext &context) const {
+ return new (context) ReferenceOwnershipAttr(get());
}
static bool classof(const DeclAttribute *DA) {
- return DA->getKind() == DAK_Ownership;
+ return DA->getKind() == DAK_ReferenceOwnership;
}
};
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 2d43a1f..c974d92 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -4606,7 +4606,20 @@
bool isLet() const { return getSpecifier() == Specifier::Let; }
/// Is this an immutable 'shared' property?
bool isShared() const { return getSpecifier() == Specifier::Shared; }
-
+
+ ValueOwnership getValueOwnership() const {
+ switch (getSpecifier()) {
+ case Specifier::Let:
+ return ValueOwnership::Default;
+ case Specifier::Var:
+ return ValueOwnership::Default;
+ case Specifier::InOut:
+ return ValueOwnership::InOut;
+ case Specifier::Shared:
+ return ValueOwnership::Shared;
+ }
+ }
+
/// Is this an element in a capture list?
bool isCaptureList() const { return Bits.VarDecl.IsCaptureList; }
diff --git a/include/swift/AST/DiagnosticConsumer.h b/include/swift/AST/DiagnosticConsumer.h
index 9f1edf3..578e432 100644
--- a/include/swift/AST/DiagnosticConsumer.h
+++ b/include/swift/AST/DiagnosticConsumer.h
@@ -19,6 +19,7 @@
#ifndef SWIFT_BASIC_DIAGNOSTICCONSUMER_H
#define SWIFT_BASIC_DIAGNOSTICCONSUMER_H
+#include "swift/Basic/LLVM.h"
#include "swift/Basic/SourceLoc.h"
#include "llvm/Support/SourceMgr.h"
@@ -111,6 +112,75 @@
ArrayRef<DiagnosticArgument> FormatArgs,
const DiagnosticInfo &Info) override;
};
+
+/// \brief DiagnosticConsumer that funnels diagnostics in certain files to
+/// particular sub-consumers.
+///
+/// The intended use case for such a consumer is "batch mode" compilations,
+/// where we want to record diagnostics for each file as if they were compiled
+/// separately. This is important for incremental builds, so that if a file has
+/// warnings but doesn't get recompiled in the next build, the warnings persist.
+///
+/// Diagnostics that are not in one of the special files are emitted into every
+/// sub-consumer. This is necessary to deal with, for example, diagnostics in a
+/// bridging header imported from Objective-C, which isn't really about the
+/// current file.
+class FileSpecificDiagnosticConsumer : public DiagnosticConsumer {
+public:
+ /// A diagnostic consumer, along with the name of the buffer that it should
+ /// be associated with. An empty string means that a consumer is not
+ /// associated with any particular buffer, and should only receive diagnostics
+ /// that are not in any of the other consumers' files.
+ using ConsumerPair =
+ std::pair<std::string, std::unique_ptr<DiagnosticConsumer>>;
+
+private:
+ /// All consumers owned by this FileSpecificDiagnosticConsumer.
+ const SmallVector<ConsumerPair, 4> SubConsumers;
+
+ using ConsumersOrderedByRangeEntry =
+ std::pair<CharSourceRange, DiagnosticConsumer *>;
+
+ /// The consumers owned by this FileSpecificDiagnosticConsumer, sorted by
+ /// the end locations of each file so that a lookup by position can be done
+ /// using binary search.
+ ///
+ /// Generated and cached when the first diagnostic with a location is emitted.
+ /// This allows diagnostics to be emitted before files are actually opened,
+ /// as long as they don't have source locations.
+ ///
+ /// \see #consumerForLocation
+ SmallVector<ConsumersOrderedByRangeEntry, 4> ConsumersOrderedByRange;
+
+ /// Indicates which consumer to send Note diagnostics too.
+ ///
+ /// Notes are always considered attached to the error, warning, or remark
+ /// that was most recently emitted.
+ ///
+ /// If null, Note diagnostics are sent to every consumer.
+ DiagnosticConsumer *ConsumerForSubsequentNotes = nullptr;
+
+public:
+ /// Takes ownership of the DiagnosticConsumers specified in \p consumers.
+ ///
+ /// There must not be two consumers for the same file (i.e., having the same
+ /// buffer name).
+ explicit FileSpecificDiagnosticConsumer(
+ SmallVectorImpl<ConsumerPair> &consumers);
+
+ void handleDiagnostic(SourceManager &SM, SourceLoc Loc,
+ DiagnosticKind Kind,
+ StringRef FormatString,
+ ArrayRef<DiagnosticArgument> FormatArgs,
+ const DiagnosticInfo &Info) override;
+
+ bool finishProcessing() override;
+
+private:
+ void computeConsumersOrderedByRange(SourceManager &SM);
+ DiagnosticConsumer *consumerForLocation(SourceManager &SM,
+ SourceLoc loc) const;
+};
} // end namespace swift
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index 70531ab..b2b5d35 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -1915,7 +1915,7 @@
ERROR(override_ownership_mismatch,none,
"cannot override %select{strong|weak|unowned|unowned(unsafe)}0 property "
"with %select{strong|weak|unowned|unowned(unsafe)}1 property",
- (/*Ownership*/unsigned, /*Ownership*/unsigned))
+ (/*ReferenceOwnership*/unsigned, /*ReferenceOwnership*/unsigned))
ERROR(override_dynamic_self_mismatch,none,
"cannot override a Self return type with a non-Self return type",
())
@@ -3152,22 +3152,22 @@
ERROR(invalid_ownership_type,none,
"'%select{strong|weak|unowned|unowned}0' may only be applied to "
"class and class-bound protocol types, not %1",
- (/*Ownership*/unsigned, Type))
+ (/*ReferenceOwnership*/unsigned, Type))
ERROR(invalid_ownership_protocol_type,none,
"'%select{strong|weak|unowned|unowned}0' must not be applied to "
"non-class-bound %1; consider adding a protocol conformance that has a class bound",
- (/*Ownership*/unsigned, Type))
+ (/*ReferenceOwnership*/unsigned, Type))
ERROR(invalid_weak_ownership_not_optional,none,
"'weak' variable should have optional type %0", (Type))
ERROR(invalid_weak_let,none,
"'weak' must be a mutable variable, because it may change at runtime", ())
ERROR(ownership_invalid_in_protocols,none,
"'%select{strong|weak|unowned|unowned}0' cannot be applied to a property declaration in a protocol",
- (/*Ownership*/unsigned))
+ (/*ReferenceOwnership*/unsigned))
WARNING(ownership_invalid_in_protocols_compat_warning,none,
"'%select{strong|weak|unowned|unowned}0' should not be applied to a property declaration "
"in a protocol and will be disallowed in future versions",
- (/*Ownership*/unsigned))
+ (/*ReferenceOwnership*/unsigned))
// required
ERROR(required_initializer_nonclass,none,
diff --git a/include/swift/AST/Ownership.h b/include/swift/AST/Ownership.h
index c7f1464..2d8f3de 100644
--- a/include/swift/AST/Ownership.h
+++ b/include/swift/AST/Ownership.h
@@ -1,4 +1,4 @@
-//===--- Ownership.h - Swift ASTs for Reference Ownership -------*- C++ -*-===//
+//===--- Ownership.h - Swift ASTs for Ownership ---------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
@@ -10,9 +10,9 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines common structures for working with the different
-// kinds of reference ownership supported by Swift, such as 'weak' and
-// 'unowned'.
+// This file defines common structures for working with the different kinds of
+// reference ownership supported by Swift, such as 'weak' and 'unowned', as well
+// as the different kinds of value ownership, such as 'inout' and '__shared'.
//
//===----------------------------------------------------------------------===//
@@ -26,7 +26,7 @@
/// Different kinds of reference ownership supported by Swift.
// This enum is used in diagnostics. If you add a case here, the diagnostics
// must be updated as well.
-enum class Ownership : uint8_t {
+enum class ReferenceOwnership : uint8_t {
/// \brief a strong reference (the default semantics)
Strong,
@@ -39,7 +39,17 @@
/// \brief an 'unowned(unsafe)' reference
Unmanaged,
};
-
+
+/// Different kinds of value ownership supported by Swift.
+enum class ValueOwnership : uint8_t {
+ /// \brief the default ownership (owned)
+ Default,
+ /// \brief an 'inout' mutating pointer-like value
+ InOut,
+ /// \brief a '__shared' non-mutating pointer-like value
+ Shared
+};
+
} // end namespace swift
#endif
diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h
index b613ae7..4b5324b 100644
--- a/include/swift/AST/Types.h
+++ b/include/swift/AST/Types.h
@@ -1594,17 +1594,16 @@
return ParameterTypeFlags(OptionSet<ParameterFlags>(raw));
}
- ParameterTypeFlags(bool variadic, bool autoclosure, bool escaping, bool inOut, bool shared)
- : value((variadic ? Variadic : 0) |
- (autoclosure ? AutoClosure : 0) |
+ ParameterTypeFlags(bool variadic, bool autoclosure, bool escaping,
+ ValueOwnership ownership)
+ : value((variadic ? Variadic : 0) | (autoclosure ? AutoClosure : 0) |
(escaping ? Escaping : 0) |
- (inOut ? InOut : 0) |
- (shared ? Shared : 0)) {}
+ (ownership == ValueOwnership::InOut ? InOut : 0) |
+ (ownership == ValueOwnership::Shared ? Shared : 0)) {}
/// Create one from what's present in the parameter type
- inline static ParameterTypeFlags fromParameterType(Type paramTy,
- bool isVariadic,
- bool isShared);
+ inline static ParameterTypeFlags
+ fromParameterType(Type paramTy, bool isVariadic, ValueOwnership ownership);
bool isNone() const { return !value; }
bool isVariadic() const { return value.contains(Variadic); }
@@ -1613,6 +1612,15 @@
bool isInOut() const { return value.contains(InOut); }
bool isShared() const { return value.contains(Shared); }
+ ValueOwnership getValueOwnership() const {
+ if (isInOut())
+ return ValueOwnership::InOut;
+ else if (isShared())
+ return ValueOwnership::Shared;
+
+ return ValueOwnership::Default;
+ }
+
ParameterTypeFlags withVariadic(bool variadic) const {
return ParameterTypeFlags(variadic ? value | ParameterTypeFlags::Variadic
: value - ParameterTypeFlags::Variadic);
@@ -4752,15 +4760,18 @@
private:
Type Referent;
public:
- static ReferenceStorageType *get(Type referent, Ownership ownership,
+ static ReferenceStorageType *get(Type referent, ReferenceOwnership ownership,
const ASTContext &C);
Type getReferentType() const { return Referent; }
- Ownership getOwnership() const {
+ ReferenceOwnership getOwnership() const {
switch (getKind()) {
- case TypeKind::WeakStorage: return Ownership::Weak;
- case TypeKind::UnownedStorage: return Ownership::Unowned;
- case TypeKind::UnmanagedStorage: return Ownership::Unmanaged;
+ case TypeKind::WeakStorage:
+ return ReferenceOwnership::Weak;
+ case TypeKind::UnownedStorage:
+ return ReferenceOwnership::Unowned;
+ case TypeKind::UnmanagedStorage:
+ return ReferenceOwnership::Unmanaged;
default: llvm_unreachable("Unhandled reference storage type");
}
}
@@ -4772,10 +4783,10 @@
}
};
BEGIN_CAN_TYPE_WRAPPER(ReferenceStorageType, Type)
- static CanReferenceStorageType get(CanType referent, Ownership ownership) {
- return CanReferenceStorageType(ReferenceStorageType::get(referent,
- ownership,
- referent->getASTContext()));
+static CanReferenceStorageType get(CanType referent,
+ ReferenceOwnership ownership) {
+ return CanReferenceStorageType(ReferenceStorageType::get(
+ referent, ownership, referent->getASTContext()));
}
PROXY_CAN_TYPE_SIMPLE_GETTER(getReferentType)
END_CAN_TYPE_WRAPPER(ReferenceStorageType, Type)
@@ -4789,8 +4800,8 @@
public:
static UnownedStorageType *get(Type referent, const ASTContext &C) {
- return static_cast<UnownedStorageType*>(
- ReferenceStorageType::get(referent, Ownership::Unowned, C));
+ return static_cast<UnownedStorageType *>(
+ ReferenceStorageType::get(referent, ReferenceOwnership::Unowned, C));
}
/// Is this unowned storage type known to be loadable within the given
@@ -4820,8 +4831,8 @@
public:
static UnmanagedStorageType *get(Type referent, const ASTContext &C) {
- return static_cast<UnmanagedStorageType*>(
- ReferenceStorageType::get(referent, Ownership::Unmanaged, C));
+ return static_cast<UnmanagedStorageType *>(
+ ReferenceStorageType::get(referent, ReferenceOwnership::Unmanaged, C));
}
// Implement isa/cast/dyncast/etc.
@@ -4845,8 +4856,8 @@
public:
static WeakStorageType *get(Type referent, const ASTContext &C) {
- return static_cast<WeakStorageType*>(
- ReferenceStorageType::get(referent, Ownership::Weak, C));
+ return static_cast<WeakStorageType *>(
+ ReferenceStorageType::get(referent, ReferenceOwnership::Weak, C));
}
// Implement isa/cast/dyncast/etc.
@@ -5165,7 +5176,8 @@
/// Create one from what's present in the parameter decl and type
inline ParameterTypeFlags
-ParameterTypeFlags::fromParameterType(Type paramTy, bool isVariadic, bool isShared) {
+ParameterTypeFlags::fromParameterType(Type paramTy, bool isVariadic,
+ ValueOwnership ownership) {
bool autoclosure = paramTy->is<AnyFunctionType>() &&
paramTy->castTo<AnyFunctionType>()->isAutoClosure();
bool escaping = paramTy->is<AnyFunctionType>() &&
@@ -5174,8 +5186,12 @@
// decomposition. Start by enabling the assertion there and fixing up those
// callers, then remove this, then remove
// ParameterTypeFlags::fromParameterType entirely.
- bool inOut = paramTy->is<InOutType>();
- return {isVariadic, autoclosure, escaping, inOut, isShared};
+ if (paramTy->is<InOutType>()) {
+ assert(ownership == ValueOwnership::Default ||
+ ownership == ValueOwnership::InOut);
+ ownership = ValueOwnership::InOut;
+ }
+ return {isVariadic, autoclosure, escaping, ownership};
}
inline const Type *BoundGenericType::getTrailingObjectsPointer() const {
diff --git a/include/swift/Basic/FlagSet.h b/include/swift/Basic/FlagSet.h
index e58bf08..8567163 100644
--- a/include/swift/Basic/FlagSet.h
+++ b/include/swift/Basic/FlagSet.h
@@ -60,7 +60,7 @@
if (value) {
Bits |= maskFor<Bit>();
} else {
- Bits |= ~maskFor<Bit>();
+ Bits &= ~maskFor<Bit>();
}
}
diff --git a/include/swift/Driver/ToolChain.h b/include/swift/Driver/ToolChain.h
index 7ec9333..c7b62c7 100644
--- a/include/swift/Driver/ToolChain.h
+++ b/include/swift/Driver/ToolChain.h
@@ -199,8 +199,10 @@
///
/// \param args Invocation arguments.
/// \param sanitizer Sanitizer name.
+ /// \param shared Whether the library is shared
virtual bool sanitizerRuntimeLibExists(const llvm::opt::ArgList &args,
- StringRef sanitizer) const;
+ StringRef sanitizer,
+ bool shared=true) const;
};
} // end namespace driver
diff --git a/include/swift/Frontend/InputFile.h b/include/swift/Frontend/InputFile.h
index 484a08c..caed06f 100644
--- a/include/swift/Frontend/InputFile.h
+++ b/include/swift/Frontend/InputFile.h
@@ -91,6 +91,10 @@
std::string loadedModuleTracePath() const {
return getPrimarySpecificPaths().SupplementaryOutputs.LoadedModuleTracePath;
}
+ std::string serializedDiagnosticsPath() const {
+ return getPrimarySpecificPaths().SupplementaryOutputs
+ .SerializedDiagnosticsPath;
+ }
};
} // namespace swift
diff --git a/include/swift/Frontend/SerializedDiagnosticConsumer.h b/include/swift/Frontend/SerializedDiagnosticConsumer.h
index 55115b9..ac55515 100644
--- a/include/swift/Frontend/SerializedDiagnosticConsumer.h
+++ b/include/swift/Frontend/SerializedDiagnosticConsumer.h
@@ -29,13 +29,14 @@
class DiagnosticConsumer;
namespace serialized_diagnostics {
- /// \brief Create a DiagnosticConsumer that serializes diagnostics to a
- /// file.
+ /// Create a DiagnosticConsumer that serializes diagnostics to a file, using
+ /// Clang's serialized diagnostics format.
///
- /// \param serializedDiagnosticsPath the file path to write the diagnostics.
+ /// \param outputPath the file path to write the diagnostics to.
///
/// \returns A new diagnostic consumer that serializes diagnostics.
- DiagnosticConsumer *createConsumer(llvm::StringRef serializedDiagnosticsPath);
+ std::unique_ptr<DiagnosticConsumer>
+ createConsumer(llvm::StringRef outputPath);
}
}
diff --git a/include/swift/IDE/DigesterEnums.def b/include/swift/IDE/DigesterEnums.def
index c4ec76d..e295f3b 100644
--- a/include/swift/IDE/DigesterEnums.def
+++ b/include/swift/IDE/DigesterEnums.def
@@ -92,6 +92,7 @@
KEY(parentExtensionReqs)
KEY(hasDefaultArg)
KEY(conformingProtocols)
+KEY(enumRawTypeName)
KNOWN_TYPE(Optional)
KNOWN_TYPE(ImplicitlyUnwrappedOptional)
diff --git a/include/swift/Option/SanitizerOptions.h b/include/swift/Option/SanitizerOptions.h
index aef2f02..8454584 100644
--- a/include/swift/Option/SanitizerOptions.h
+++ b/include/swift/Option/SanitizerOptions.h
@@ -32,11 +32,9 @@
// sanitizer dylib with a given name.
/// \return Returns a SanitizerKind.
OptionSet<SanitizerKind> parseSanitizerArgValues(
- const llvm::opt::ArgList &Args,
- const llvm::opt::Arg *A,
- const llvm::Triple &Triple,
- DiagnosticEngine &Diag,
- llvm::function_ref<bool(llvm::StringRef)> sanitizerRuntimeLibExists);
+ const llvm::opt::ArgList &Args, const llvm::opt::Arg *A,
+ const llvm::Triple &Triple, DiagnosticEngine &Diag,
+ llvm::function_ref<bool(llvm::StringRef, bool)> sanitizerRuntimeLibExists);
/// \brief Parses a -sanitize-coverage= argument's value.
llvm::SanitizerCoverageOptions parseSanitizerCoverageArgValue(
diff --git a/include/swift/Parse/Lexer.h b/include/swift/Parse/Lexer.h
index 1cfbe09..71a45e7 100644
--- a/include/swift/Parse/Lexer.h
+++ b/include/swift/Parse/Lexer.h
@@ -461,6 +461,16 @@
};
private:
+ /// Nul character meaning kind.
+ enum class NulCharacterKind {
+ /// String buffer terminator.
+ BufferEnd,
+ /// Embedded nul character.
+ Embedded,
+ /// Code completion marker.
+ CodeCompletion
+ };
+
/// For a source location in the current buffer, returns the corresponding
/// pointer.
const char *getBufferPtrForSourceLoc(SourceLoc Loc) const {
@@ -520,6 +530,8 @@
/// Try to lex conflict markers by checking for the presence of the start and
/// end of the marker in diff3 or Perforce style respectively.
bool tryLexConflictMarker(bool EatNewline);
+
+ NulCharacterKind getNulCharacterKind(const char *Ptr) const;
};
/// Given an ordered token \param Array , get the iterator pointing to the first
diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h
index 6e67e55..599aec4 100644
--- a/include/swift/Parse/Parser.h
+++ b/include/swift/Parse/Parser.h
@@ -1444,7 +1444,8 @@
const SourceManager &SM,
unsigned BufferID,
unsigned Offset = 0,
- unsigned EndOffset = 0);
+ unsigned EndOffset = 0,
+ DiagnosticEngine *Diags = nullptr);
} // end namespace swift
#endif
diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h
index 9e365cf..a331b43 100644
--- a/include/swift/Remote/MetadataReader.h
+++ b/include/swift/Remote/MetadataReader.h
@@ -233,7 +233,7 @@
return StoredPointer();
auto classMeta = cast<TargetClassMetadata<Runtime>>(meta);
- return classMeta->SuperClass;
+ return classMeta->Superclass;
}
/// Given a remote pointer to class metadata, attempt to discover its class
@@ -537,32 +537,24 @@
///
/// The offset is in units of words, from the start of the class's
/// metadata.
- llvm::Optional<uint32_t>
+ llvm::Optional<int32_t>
readGenericArgsOffset(MetadataRef metadata,
ContextDescriptorRef descriptor) {
switch (descriptor->getKind()) {
case ContextDescriptorKind::Class: {
auto type = cast<TargetClassDescriptor<Runtime>>(descriptor);
- auto *classMetadata = dyn_cast<TargetClassMetadata<Runtime>>(metadata);
- if (!classMetadata)
+ if (!type->hasResilientSuperclass())
+ return type->getNonResilientGenericArgumentOffset();
+
+ auto bounds = readMetadataBoundsOfSuperclass(descriptor);
+ if (!bounds)
return llvm::None;
- if (!classMetadata->SuperClass)
- return type->getGenericArgumentOffset(nullptr, nullptr);
+ bounds->adjustForSubclass(type->areImmediateMembersNegative(),
+ type->NumImmediateMembers);
- auto superMetadata = readMetadata(classMetadata->SuperClass);
- if (!superMetadata)
- return llvm::None;
-
- auto superClassMetadata =
- dyn_cast<TargetClassMetadata<Runtime>>(superMetadata);
- if (!superClassMetadata)
- return llvm::None;
-
- auto result =
- type->getGenericArgumentOffset(classMetadata, superClassMetadata);
- return result;
+ return bounds->ImmediateMembersOffset / sizeof(StoredPointer);
}
case ContextDescriptorKind::Enum: {
@@ -580,6 +572,76 @@
}
}
+ using ClassMetadataBounds = TargetClassMetadataBounds<Runtime>;
+
+ // This follows computeMetadataBoundsForSuperclass.
+ llvm::Optional<ClassMetadataBounds>
+ readMetadataBoundsOfSuperclass(ContextDescriptorRef subclassRef) {
+ auto subclass = cast<TargetClassDescriptor<Runtime>>(subclassRef);
+
+ auto rawSuperclass =
+ resolveNullableRelativeField(subclassRef, subclass->Superclass);
+ if (!rawSuperclass) {
+ return ClassMetadataBounds::forSwiftRootClass();
+ }
+
+ return forTypeReference<ClassMetadataBounds>(
+ subclass->getSuperclassReferenceKind(), *rawSuperclass,
+ [&](ContextDescriptorRef superclass)
+ -> llvm::Optional<ClassMetadataBounds> {
+ if (!isa<TargetClassDescriptor<Runtime>>(superclass))
+ return llvm::None;
+ return readMetadataBoundsOfSuperclass(superclass);
+ },
+ [&](MetadataRef metadata) -> llvm::Optional<ClassMetadataBounds> {
+ auto cls = dyn_cast<TargetClassMetadata<Runtime>>(metadata);
+ if (!cls)
+ return llvm::None;
+
+ return cls->getClassBoundsAsSwiftSuperclass();
+ });
+ }
+
+ template <class Result, class DescriptorFn, class MetadataFn>
+ llvm::Optional<Result>
+ forTypeReference(TypeMetadataRecordKind refKind, StoredPointer ref,
+ const DescriptorFn &descriptorFn,
+ const MetadataFn &metadataFn) {
+ switch (refKind) {
+ case TypeMetadataRecordKind::IndirectNominalTypeDescriptor: {
+ StoredPointer descriptorAddress = 0;
+ if (!Reader->readInteger(RemoteAddress(ref), &descriptorAddress))
+ return llvm::None;
+
+ ref = descriptorAddress;
+ LLVM_FALLTHROUGH;
+ }
+
+ case TypeMetadataRecordKind::DirectNominalTypeDescriptor: {
+ auto descriptor = readContextDescriptor(ref);
+ if (!descriptor)
+ return llvm::None;
+
+ return descriptorFn(descriptor);
+ }
+
+ case TypeMetadataRecordKind::IndirectObjCClass: {
+ StoredPointer classRef = 0;
+ if (!Reader->readInteger(RemoteAddress(ref), &classRef))
+ return llvm::None;
+
+ auto metadata = readMetadata(classRef);
+ if (!metadata)
+ return llvm::None;
+
+ return metadataFn(metadata);
+ }
+
+ default:
+ return llvm::None;
+ }
+ }
+
/// Read a single generic type argument from a bound generic type
/// metadata.
llvm::Optional<StoredPointer>
@@ -921,7 +983,7 @@
if (descriptorAddress || !skipArtificialSubclasses)
return static_cast<StoredPointer>(descriptorAddress);
- auto superclassMetadataAddress = classMeta->SuperClass;
+ auto superclassMetadataAddress = classMeta->Superclass;
if (!superclassMetadataAddress)
return 0;
diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h
index cb5b1eb..df39028 100644
--- a/include/swift/Runtime/Metadata.h
+++ b/include/swift/Runtime/Metadata.h
@@ -86,6 +86,7 @@
struct RuntimeTarget<4> {
using StoredPointer = uint32_t;
using StoredSize = uint32_t;
+ using StoredPointerDifference = int32_t;
static constexpr size_t PointerSize = 4;
};
@@ -93,6 +94,7 @@
struct RuntimeTarget<8> {
using StoredPointer = uint64_t;
using StoredSize = uint64_t;
+ using StoredPointerDifference = int64_t;
static constexpr size_t PointerSize = 8;
};
@@ -104,6 +106,10 @@
static constexpr size_t PointerSize = sizeof(uintptr_t);
using StoredPointer = uintptr_t;
using StoredSize = size_t;
+ using StoredPointerDifference = ptrdiff_t;
+
+ static_assert(sizeof(StoredSize) == sizeof(StoredPointerDifference),
+ "target uses differently-sized size_t and ptrdiff_t");
template <typename T>
using Pointer = T*;
@@ -134,6 +140,7 @@
struct External {
using StoredPointer = typename Runtime::StoredPointer;
using StoredSize = typename Runtime::StoredSize;
+ using StoredPointerDifference = typename Runtime::StoredPointerDifference;
static constexpr size_t PointerSize = Runtime::PointerSize;
const StoredPointer PointerValue;
@@ -740,6 +747,7 @@
}
template <typename Runtime> struct TargetGenericMetadataInstantiationCache;
+template <typename Runtime> struct TargetAnyClassMetadata;
template <typename Runtime> struct TargetClassMetadata;
template <typename Runtime> struct TargetStructMetadata;
template <typename Runtime> struct TargetOpaqueMetadata;
@@ -755,18 +763,50 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winvalid-offsetof"
+/// Bounds for metadata objects.
+template <typename Runtime>
+struct TargetMetadataBounds {
+ using StoredSize = typename Runtime::StoredSize;
+
+ /// The negative extent of the metadata, in words.
+ uint32_t NegativeSizeInWords;
+
+ /// The positive extent of the metadata, in words.
+ uint32_t PositiveSizeInWords;
+
+ /// Return the total size of the metadata in bytes, including both
+ /// negatively- and positively-offset members.
+ StoredSize getTotalSizeInBytes() const {
+ return (StoredSize(NegativeSizeInWords) + StoredSize(PositiveSizeInWords))
+ * sizeof(void*);
+ }
+
+ /// Return the offset of the address point of the metadata from its
+ /// start, in bytes.
+ StoredSize getAddressPointInBytes() const {
+ return StoredSize(NegativeSizeInWords) * sizeof(void*);
+ }
+};
+using MetadataBounds = TargetMetadataBounds<InProcess>;
+
/// The common structure of all type metadata.
template <typename Runtime>
struct TargetMetadata {
using StoredPointer = typename Runtime::StoredPointer;
+ /// The basic header type.
+ typedef TargetTypeMetadataHeader<Runtime> HeaderType;
+
constexpr TargetMetadata()
: Kind(static_cast<StoredPointer>(MetadataKind::Class)) {}
constexpr TargetMetadata(MetadataKind Kind)
: Kind(static_cast<StoredPointer>(Kind)) {}
-
- /// The basic header type.
- typedef TargetTypeMetadataHeader<Runtime> HeaderType;
+
+#if SWIFT_OBJC_INTEROP
+protected:
+ constexpr TargetMetadata(TargetAnyClassMetadata<Runtime> *isa)
+ : Kind(reinterpret_cast<StoredPointer>(isa)) {}
+#endif
private:
/// The kind. Only valid for non-class metadata; getKind() must be used to get
@@ -783,6 +823,17 @@
Kind = static_cast<StoredPointer>(kind);
}
+#if SWIFT_OBJC_INTEROP
+protected:
+ const TargetAnyClassMetadata<Runtime> *getClassISA() const {
+ return reinterpret_cast<const TargetAnyClassMetadata<Runtime> *>(Kind);
+ }
+ void setClassISA(const TargetAnyClassMetadata<Runtime> *isa) {
+ Kind = reinterpret_cast<StoredPointer>(isa);
+ }
+#endif
+
+public:
/// Is this a class object--the metadata record for a Swift class (which also
/// serves as the class object), or the class object for an ObjC class (which
/// is not metadata)?
@@ -956,7 +1007,7 @@
auto asWords = reinterpret_cast<
ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> const *>(this);
- return asWords + description->getGenericArgumentOffset(this);
+ return asWords + description->getGenericArgumentOffset();
}
bool satisfiesClassConstraint() const;
@@ -1008,19 +1059,32 @@
const FullOpaqueMetadata METADATA_SYM(Symbol);
#include "swift/Runtime/BuiltinTypes.def"
+using HeapObjectDestroyer =
+ SWIFT_CC(swift) void(SWIFT_CONTEXT HeapObject *);
+
/// The prefix on a heap metadata.
-struct HeapMetadataHeaderPrefix {
+template <typename Runtime>
+struct TargetHeapMetadataHeaderPrefix {
/// Destroy the object, returning the allocated size of the object
/// or 0 if the object shouldn't be deallocated.
- SWIFT_CC(swift) void (*destroy)(SWIFT_CONTEXT HeapObject *);
+ TargetPointer<Runtime, HeapObjectDestroyer> destroy;
};
+using HeapMetadataHeaderPrefix =
+ TargetHeapMetadataHeaderPrefix<InProcess>;
/// The header present on all heap metadata.
-struct HeapMetadataHeader : HeapMetadataHeaderPrefix, TypeMetadataHeader {
- constexpr HeapMetadataHeader(const HeapMetadataHeaderPrefix &heapPrefix,
- const TypeMetadataHeader &typePrefix)
- : HeapMetadataHeaderPrefix(heapPrefix), TypeMetadataHeader(typePrefix) {}
+template <typename Runtime>
+struct TargetHeapMetadataHeader
+ : TargetHeapMetadataHeaderPrefix<Runtime>,
+ TargetTypeMetadataHeader<Runtime> {
+ constexpr TargetHeapMetadataHeader(
+ const TargetHeapMetadataHeaderPrefix<Runtime> &heapPrefix,
+ const TargetTypeMetadataHeader<Runtime> &typePrefix)
+ : TargetHeapMetadataHeaderPrefix<Runtime>(heapPrefix),
+ TargetTypeMetadataHeader<Runtime>(typePrefix) {}
};
+using HeapMetadataHeader =
+ TargetHeapMetadataHeader<InProcess>;
/// The common structure of all metadata for heap-allocated types. A
/// pointer to one of these can be retrieved by loading the 'isa'
@@ -1030,11 +1094,15 @@
/// not be the Swift type metadata for the object's dynamic type.
template <typename Runtime>
struct TargetHeapMetadata : TargetMetadata<Runtime> {
- typedef HeapMetadataHeader HeaderType;
+ using HeaderType = TargetHeapMetadataHeader<Runtime>;
TargetHeapMetadata() = default;
- constexpr TargetHeapMetadata(const TargetMetadata<Runtime> &base)
- : TargetMetadata<Runtime>(base) {}
+ constexpr TargetHeapMetadata(MetadataKind kind)
+ : TargetMetadata<Runtime>(kind) {}
+#if SWIFT_OBJC_INTEROP
+ constexpr TargetHeapMetadata(TargetAnyClassMetadata<Runtime> *isa)
+ : TargetMetadata<Runtime>(isa) {}
+#endif
};
using HeapMetadata = TargetHeapMetadata<InProcess>;
@@ -1075,12 +1143,141 @@
uint32_t getVTableOffset(const TargetClassMetadata<Runtime> *metadata) const {
const auto *description = metadata->getDescription();
if (description->hasResilientSuperclass())
- return metadata->SuperClass->getSizeInWords() + VTableOffset;
+ return metadata->Superclass->getSizeInWords() + VTableOffset;
return VTableOffset;
}
};
-typedef SWIFT_CC(swift) void (*ClassIVarDestroyer)(SWIFT_CONTEXT HeapObject *);
+/// The bounds of a class metadata object.
+///
+/// This type is a currency type and is not part of the ABI.
+/// See TargetStoredClassMetadataBounds for the type of the class
+/// metadata bounds variable.
+template <typename Runtime>
+struct TargetClassMetadataBounds : TargetMetadataBounds<Runtime> {
+ using StoredPointer = typename Runtime::StoredPointer;
+ using StoredSize = typename Runtime::StoredSize;
+ using StoredPointerDifference = typename Runtime::StoredPointerDifference;
+
+ using TargetMetadataBounds<Runtime>::NegativeSizeInWords;
+ using TargetMetadataBounds<Runtime>::PositiveSizeInWords;
+
+ /// The offset from the address point of the metadata to the immediate
+ /// members.
+ StoredPointerDifference ImmediateMembersOffset;
+
+ constexpr TargetClassMetadataBounds() = default;
+ constexpr TargetClassMetadataBounds(
+ StoredPointerDifference immediateMembersOffset,
+ uint32_t negativeSizeInWords, uint32_t positiveSizeInWords)
+ : TargetMetadataBounds<Runtime>{negativeSizeInWords, positiveSizeInWords},
+ ImmediateMembersOffset(immediateMembersOffset) {}
+
+ /// Return the basic bounds of all Swift class metadata.
+ /// The immediate members offset will not be meaningful.
+ static constexpr TargetClassMetadataBounds<Runtime> forSwiftRootClass() {
+ using Metadata = FullMetadata<TargetClassMetadata<Runtime>>;
+ return forAddressPointAndSize(sizeof(typename Metadata::HeaderType),
+ sizeof(Metadata));
+ }
+
+ /// Return the bounds of a Swift class metadata with the given address
+ /// point and size (both in bytes).
+ /// The immediate members offset will not be meaningful.
+ static constexpr TargetClassMetadataBounds<Runtime>
+ forAddressPointAndSize(StoredSize addressPoint, StoredSize totalSize) {
+ return {
+ // Immediate offset in bytes.
+ StoredPointerDifference(totalSize - addressPoint),
+ // Negative size in words.
+ uint32_t(addressPoint / sizeof(StoredPointer)),
+ // Positive size in words.
+ uint32_t((totalSize - addressPoint) / sizeof(StoredPointer))
+ };
+ }
+
+ /// Adjust these bounds for a subclass with the given immediate-members
+ /// section.
+ void adjustForSubclass(bool areImmediateMembersNegative,
+ uint32_t numImmediateMembers) {
+ if (areImmediateMembersNegative) {
+ NegativeSizeInWords += numImmediateMembers;
+ ImmediateMembersOffset =
+ -StoredPointerDifference(NegativeSizeInWords) * sizeof(StoredPointer);
+ } else {
+ ImmediateMembersOffset = PositiveSizeInWords * sizeof(StoredPointer);
+ PositiveSizeInWords += numImmediateMembers;
+ }
+ }
+};
+using ClassMetadataBounds =
+ TargetClassMetadataBounds<InProcess>;
+
+/// The portion of a class metadata object that is compatible with
+/// all classes, even non-Swift ones.
+template <typename Runtime>
+struct TargetAnyClassMetadata : public TargetHeapMetadata<Runtime> {
+ using StoredPointer = typename Runtime::StoredPointer;
+ using StoredSize = typename Runtime::StoredSize;
+
+#if SWIFT_OBJC_INTEROP
+ constexpr TargetAnyClassMetadata(TargetAnyClassMetadata<Runtime> *isa,
+ TargetClassMetadata<Runtime> *superclass)
+ : TargetHeapMetadata<Runtime>(isa),
+ Superclass(superclass),
+ CacheData{nullptr, nullptr},
+ Data(SWIFT_CLASS_IS_SWIFT_MASK) {}
+#endif
+
+ constexpr TargetAnyClassMetadata(TargetClassMetadata<Runtime> *superclass)
+ : TargetHeapMetadata<Runtime>(MetadataKind::Class),
+ Superclass(superclass),
+ CacheData{nullptr, nullptr},
+ Data(SWIFT_CLASS_IS_SWIFT_MASK) {}
+
+#if SWIFT_OBJC_INTEROP
+ // Allow setting the metadata kind to a class ISA on class metadata.
+ using TargetMetadata<Runtime>::getClassISA;
+ using TargetMetadata<Runtime>::setClassISA;
+#endif
+
+ // Note that ObjC classes does not have a metadata header.
+
+ /// The metadata for the superclass. This is null for the root class.
+ ConstTargetMetadataPointer<Runtime, swift::TargetClassMetadata> Superclass;
+
+ // TODO: remove the CacheData and Data fields in non-ObjC-interop builds.
+
+ /// The cache data is used for certain dynamic lookups; it is owned
+ /// by the runtime and generally needs to interoperate with
+ /// Objective-C's use.
+ TargetPointer<Runtime, void> CacheData[2];
+
+ /// The data pointer is used for out-of-line metadata and is
+ /// generally opaque, except that the compiler sets the low bit in
+ /// order to indicate that this is a Swift metatype and therefore
+ /// that the type metadata header is present.
+ StoredSize Data;
+
+ static constexpr StoredPointer offsetToData() {
+ return offsetof(TargetAnyClassMetadata, Data);
+ }
+
+ /// Is this object a valid swift type metadata? That is, can it be
+ /// safely downcast to ClassMetadata?
+ bool isTypeMetadata() const {
+ return (Data & SWIFT_CLASS_IS_SWIFT_MASK);
+ }
+ /// A different perspective on the same bit
+ bool isPureObjC() const {
+ return !isTypeMetadata();
+ }
+};
+using AnyClassMetadata =
+ TargetAnyClassMetadata<InProcess>;
+
+using ClassIVarDestroyer =
+ SWIFT_CC(swift) void(SWIFT_CONTEXT HeapObject *);
/// The structure of all class metadata. This structure is embedded
/// directly within the class's heap metadata structure and therefore
@@ -1089,69 +1286,28 @@
/// Note that the layout of this type is compatible with the layout of
/// an Objective-C class.
template <typename Runtime>
-struct TargetClassMetadata : public TargetHeapMetadata<Runtime> {
+struct TargetClassMetadata : public TargetAnyClassMetadata<Runtime> {
using StoredPointer = typename Runtime::StoredPointer;
using StoredSize = typename Runtime::StoredSize;
+
friend class ReflectionContext;
+
TargetClassMetadata() = default;
- constexpr TargetClassMetadata(const TargetHeapMetadata<Runtime> &base,
- ConstTargetMetadataPointer<Runtime, swift::TargetClassMetadata> superClass,
- StoredPointer data,
+ constexpr TargetClassMetadata(const TargetAnyClassMetadata<Runtime> &base,
ClassFlags flags,
- StoredPointer ivarDestroyer,
+ ClassIVarDestroyer *ivarDestroyer,
StoredPointer size, StoredPointer addressPoint,
StoredPointer alignMask,
StoredPointer classSize, StoredPointer classAddressPoint)
- : TargetHeapMetadata<Runtime>(base), SuperClass(superClass),
- CacheData {0, 0}, Data(data),
+ : TargetAnyClassMetadata<Runtime>(base),
Flags(flags), InstanceAddressPoint(addressPoint),
InstanceSize(size), InstanceAlignMask(alignMask),
Reserved(0), ClassSize(classSize), ClassAddressPoint(classAddressPoint),
Description(nullptr), IVarDestroyer(ivarDestroyer) {}
- // Description's copy ctor is deleted so we have to do this the hard way.
- TargetClassMetadata(const TargetClassMetadata &other)
- : TargetHeapMetadata<Runtime>(other),
- SuperClass(other.SuperClass),
- CacheData{other.CacheData[0], other.CacheData[1]},
- Data(other.Data), Flags(other.Flags),
- InstanceAddressPoint(other.InstanceAddressPoint),
- InstanceSize(other.InstanceSize),
- InstanceAlignMask(other.InstanceAlignMask), Reserved(other.Reserved),
- ClassSize(other.ClassSize), ClassAddressPoint(other.ClassAddressPoint),
- Description(other.Description), IVarDestroyer(other.IVarDestroyer) {}
-
- /// The metadata for the superclass. This is null for the root class.
- ConstTargetMetadataPointer<Runtime, swift::TargetClassMetadata> SuperClass;
-
- /// The cache data is used for certain dynamic lookups; it is owned
- /// by the runtime and generally needs to interoperate with
- /// Objective-C's use.
- StoredPointer CacheData[2];
-
- /// The data pointer is used for out-of-line metadata and is
- /// generally opaque, except that the compiler sets the low bit in
- /// order to indicate that this is a Swift metatype and therefore
- /// that the type metadata header is present.
- StoredPointer Data;
-
- static constexpr StoredPointer offsetToData() {
- return offsetof(TargetClassMetadata, Data);
- }
-
- /// Is this object a valid swift type metadata?
- bool isTypeMetadata() const {
- return (Data & SWIFT_CLASS_IS_SWIFT_MASK);
- }
- /// A different perspective on the same bit
- bool isPureObjC() const {
- return !isTypeMetadata();
- }
-
-private:
// The remaining fields are valid only when isTypeMetadata().
// The Objective-C runtime knows the offsets to some of these fields.
- // Be careful when changing them.
+ // Be careful when accessing them.
/// Swift-specific class flags.
ClassFlags Flags;
@@ -1177,15 +1333,19 @@
/// The offset of the address point within the class object.
uint32_t ClassAddressPoint;
+ // Description is by far the most likely field for a client to try
+ // to access directly, so we force access to go through accessors.
+private:
/// An out-of-line Swift-specific description of the type, or null
/// if this is an artificial subclass. We currently provide no
/// supported mechanism for making a non-artificial subclass
/// dynamically.
ConstTargetMetadataPointer<Runtime, TargetClassDescriptor> Description;
+public:
/// A function for destroying instance variables, used to clean up
/// after an early return from a constructor.
- StoredPointer IVarDestroyer;
+ TargetPointer<Runtime, ClassIVarDestroyer> IVarDestroyer;
// After this come the class members, laid out as follows:
// - class members for the superclass (recursively)
@@ -1194,7 +1354,8 @@
// - class variables (if we choose to support these)
// - "tabulated" virtual methods
-public:
+ using TargetAnyClassMetadata<Runtime>::isTypeMetadata;
+
ConstTargetMetadataPointer<Runtime, TargetClassDescriptor>
getDescription() const {
assert(isTypeMetadata());
@@ -1205,12 +1366,6 @@
Description = description;
}
- /// Only valid if the target is in-process.
- ClassIVarDestroyer getIVarDestroyer() const {
- assert(isTypeMetadata());
- return reinterpret_cast<ClassIVarDestroyer>(IVarDestroyer);
- }
-
/// Is this class an artificial subclass, such as one dynamically
/// created for various dynamic purposes like KVO?
bool isArtificialSubclass() const {
@@ -1302,6 +1457,33 @@
return size / sizeof(StoredPointer);
}
+ /// Given that this class is serving as the superclass of a Swift class,
+ /// return its bounds as metadata.
+ ///
+ /// Note that the ImmediateMembersOffset member will not be meaningful.
+ TargetClassMetadataBounds<Runtime>
+ getClassBoundsAsSwiftSuperclass() const {
+ using Bounds = TargetClassMetadataBounds<Runtime>;
+
+ auto rootBounds = Bounds::forSwiftRootClass();
+
+ // If the class is not type metadata, just use the root-class bounds.
+ if (!isTypeMetadata())
+ return rootBounds;
+
+ // Otherwise, pull out the bounds from the metadata.
+ auto bounds = Bounds::forAddressPointAndSize(getClassAddressPoint(),
+ getClassSize());
+
+ // Round the bounds up to the required dimensions.
+ if (bounds.NegativeSizeInWords < rootBounds.NegativeSizeInWords)
+ bounds.NegativeSizeInWords = rootBounds.NegativeSizeInWords;
+ if (bounds.PositiveSizeInWords < rootBounds.PositiveSizeInWords)
+ bounds.PositiveSizeInWords = rootBounds.PositiveSizeInWords;
+
+ return bounds;
+ }
+
static bool classof(const TargetMetadata<Runtime> *metadata) {
return metadata->getKind() == MetadataKind::Class;
}
@@ -1437,7 +1619,7 @@
mutable std::atomic<CacheValue> Cache;
};
- struct HeaderType : HeaderPrefix, TypeMetadataHeader {};
+ struct HeaderType : HeaderPrefix, TargetTypeMetadataHeader<Runtime> {};
TargetPointer<Runtime, const char> getName() const {
return reinterpret_cast<TargetPointer<Runtime, const char>>(
@@ -1514,7 +1696,7 @@
/// The superclass of the foreign class, if any.
ConstTargetMetadataPointer<Runtime, swift::TargetForeignClassMetadata>
- SuperClass;
+ Superclass;
/// Reserved space. For now, these should be zero-initialized.
StoredPointer Reserved[3];
@@ -1555,11 +1737,14 @@
struct TargetStructMetadata : public TargetValueMetadata<Runtime> {
using StoredPointer = typename Runtime::StoredPointer;
using TargetValueMetadata<Runtime>::TargetValueMetadata;
-
+
const TargetStructDescriptor<Runtime> *getDescription() const {
return llvm::cast<TargetStructDescriptor<Runtime>>(this->Description);
}
+ // The first trailing field of struct metadata is always the generic
+ // argument array.
+
/// Get a pointer to the field offset vector, if present, or null.
const StoredPointer *getFieldOffsets() const {
auto offset = getDescription()->FieldOffsetVectorOffset;
@@ -1569,6 +1754,10 @@
return reinterpret_cast<const StoredPointer *>(asWords + offset);
}
+ static constexpr int32_t getGenericArgumentOffset() {
+ return sizeof(TargetStructMetadata<Runtime>) / sizeof(void*);
+ }
+
static bool classof(const TargetMetadata<Runtime> *metadata) {
return metadata->getKind() == MetadataKind::Struct;
}
@@ -1586,6 +1775,9 @@
return llvm::cast<TargetEnumDescriptor<Runtime>>(this->Description);
}
+ // The first trailing field of enum metadata is always the generic
+ // argument array.
+
/// True if the metadata records the size of the payload area.
bool hasPayloadSize() const {
return getDescription()->hasPayloadSizeOffset();
@@ -1610,6 +1802,10 @@
return *asWords;
}
+ static constexpr int32_t getGenericArgumentOffset() {
+ return sizeof(TargetEnumMetadata<Runtime>) / sizeof(void*);
+ }
+
static bool classof(const TargetMetadata<Runtime> *metadata) {
return metadata->getKind() == MetadataKind::Enum
|| metadata->getKind() == MetadataKind::Optional;
@@ -2056,6 +2252,62 @@
using GenericMetadataInstantiationCache =
TargetGenericMetadataInstantiationCache<InProcess>;
+/// The pattern for class metadata.
+template <typename Runtime>
+struct TargetGenericClassMetadataPattern {
+ using StoredPointer = typename Runtime::StoredPointer;
+
+ /// The heap-destructor function.
+ TargetPointer<Runtime, HeapObjectDestroyer> Destroy;
+
+ /// The ivar-destructor function.
+ TargetPointer<Runtime, ClassIVarDestroyer> IVarDestroyer;
+
+ /// The class flags.
+ ClassFlags Flags;
+
+ /// The size of the immedate-members pattern, in words.
+ ///
+ /// This pattern will be copied into the immediate-members section of
+ /// the allocated class metadata. The pattern data is at the start of
+ /// the pattern buffer.
+ ///
+ /// The rest of the immediate-members section will be zeroed.
+ uint16_t ImmediateMembersPattern_Size;
+
+ /// The offset into the immediate-members section of the metadata, in
+ /// words, into which to copy the immediate-members pattern.
+ uint16_t ImmediateMembersPattern_TargetOffset;
+
+ /// The total amount of extra space to allocate in the metadata, in words.
+ /// This space will always be allocated after the metadata.
+ uint16_t NumExtraDataWords;
+
+ // TODO: only in ObjC interop
+
+ /// The offset of the class RO-data within the extra data pattern,
+ /// in words.
+ uint16_t ClassRODataOffset;
+
+ /// The offset of the metaclass object within the extra data pattern,
+ /// in words.
+ uint16_t MetaclassObjectOffset;
+
+ /// The offset of the metaclass RO-data within the extra data pattern,
+ /// in words.
+ uint16_t MetaclassRODataOffset;
+
+ const StoredPointer *getImmediateMembersPattern() const {
+ return reinterpret_cast<const StoredPointer *>(this + 1);
+ }
+
+ const StoredPointer *getExtraDataPattern() const {
+ return getImmediateMembersPattern() + ImmediateMembersPattern_Size;
+ }
+};
+using GenericClassMetadataPattern =
+ TargetGenericClassMetadataPattern<InProcess>;
+
/// Heap metadata for a box, which may have been generated statically by the
/// compiler or by the runtime.
template <typename Runtime>
@@ -2468,17 +2720,20 @@
using ModuleContextDescriptor = TargetModuleContextDescriptor<InProcess>;
-struct GenericContextDescriptorHeader {
- unsigned NumParams, NumRequirements, NumKeyArguments, NumExtraArguments;
+template<typename Runtime>
+struct TargetGenericContextDescriptorHeader {
+ uint32_t NumParams, NumRequirements, NumKeyArguments, NumExtraArguments;
- unsigned getNumArguments() const {
+ uint32_t getNumArguments() const {
return NumKeyArguments + NumExtraArguments;
}
-
+
bool hasArguments() const {
return getNumArguments() > 0;
}
};
+using GenericContextDescriptorHeader =
+ TargetGenericContextDescriptorHeader<InProcess>;
/// A reference to a generic parameter that is the subject of a requirement.
/// This can refer either directly to a generic parameter or to a path to an
@@ -2699,32 +2954,36 @@
/// CRTP class for a context descriptor that includes trailing generic
/// context description.
-template<typename Self,
- typename HeaderType = GenericContextDescriptorHeader,
- typename...FollowingTrailingObjects>
+template<class Self,
+ template <typename> class TargetGenericContextHeaderType =
+ TargetGenericContextDescriptorHeader,
+ typename... FollowingTrailingObjects>
class TrailingGenericContextObjects;
-template<template<typename> class TargetSelf,
- typename Runtime,
- typename HeaderType,
- typename...FollowingTrailingObjects>
-class TrailingGenericContextObjects<
- TargetSelf<Runtime>,
- HeaderType,
- FollowingTrailingObjects...
-> : protected swift::ABI::TrailingObjects<TargetSelf<Runtime>,
- HeaderType,
+// This oddity with partial specialization is necessary to get
+// reasonable-looking code while also working around various kinds of
+// compiler bad behavior with injected class names.
+template<class Runtime,
+ template <typename> class TargetSelf,
+ template <typename> class TargetGenericContextHeaderType,
+ typename... FollowingTrailingObjects>
+class TrailingGenericContextObjects<TargetSelf<Runtime>,
+ TargetGenericContextHeaderType,
+ FollowingTrailingObjects...> :
+ protected swift::ABI::TrailingObjects<TargetSelf<Runtime>,
+ TargetGenericContextHeaderType<Runtime>,
GenericParamDescriptor,
TargetGenericRequirementDescriptor<Runtime>,
FollowingTrailingObjects...>
{
protected:
using Self = TargetSelf<Runtime>;
+ using GenericContextHeaderType = TargetGenericContextHeaderType<Runtime>;
using GenericRequirementDescriptor =
TargetGenericRequirementDescriptor<Runtime>;
using TrailingObjects = swift::ABI::TrailingObjects<Self,
- HeaderType,
+ GenericContextHeaderType,
GenericParamDescriptor,
GenericRequirementDescriptor,
FollowingTrailingObjects...>;
@@ -2737,12 +2996,16 @@
return static_cast<const Self *>(this);
}
public:
- const HeaderType &getFullGenericContextHeader() const {
+ using StoredSize = typename Runtime::StoredSize;
+ using StoredPointer = typename Runtime::StoredPointer;
+
+ const GenericContextHeaderType &getFullGenericContextHeader() const {
assert(asSelf()->isGeneric());
- return *this->template getTrailingObjects<HeaderType>();
+ return *this->template getTrailingObjects<GenericContextHeaderType>();
}
- const GenericContextDescriptorHeader &getGenericContextHeader() const {
+ const TargetGenericContextDescriptorHeader<Runtime> &
+ getGenericContextHeader() const {
/// HeaderType ought to be convertible to GenericContextDescriptorHeader.
return getFullGenericContextHeader();
}
@@ -2772,8 +3035,15 @@
getGenericContextHeader().NumRequirements};
}
+ /// Return the amount of space that the generic arguments take up in
+ /// metadata of this type.
+ StoredSize getGenericArgumentsStorageSize() const {
+ return StoredSize(getGenericContextHeader().getNumArguments())
+ * sizeof(StoredPointer);
+ }
+
protected:
- size_t numTrailingObjects(OverloadToken<HeaderType>) const {
+ size_t numTrailingObjects(OverloadToken<GenericContextHeaderType>) const {
return asSelf()->isGeneric() ? 1 : 0;
}
@@ -2789,7 +3059,8 @@
/// Reference to a generic context.
template<typename Runtime>
struct TargetGenericContext final
- : TrailingGenericContextObjects<TargetGenericContext<Runtime>>
+ : TrailingGenericContextObjects<TargetGenericContext<Runtime>,
+ TargetGenericContextDescriptorHeader>
{
// This struct is supposed to be empty, but TrailingObjects respects the
// unique-address-per-object C++ rule, so even if this type is empty, the
@@ -2808,7 +3079,7 @@
{
private:
using TrailingGenericContextObjects
- = TrailingGenericContextObjects<TargetExtensionContextDescriptor>;
+ = TrailingGenericContextObjects<TargetExtensionContextDescriptor<Runtime>>;
/// A mangling of the `Self` type context that the extension extends.
/// The mangled name represents the type in the generic context encoded by
@@ -2853,13 +3124,6 @@
template <typename Runtime>
struct TargetTypeGenericContextDescriptorHeader {
- /// Indicates the offset of the instantiation arguments for a type's generic
- /// contexts in instances of its type metadata. For a value type or class
- /// without resilient superclasses, this the the offset from the address
- /// point of the metadata. For a class with a resilient superclass, this
- /// offset is relative to the end of the superclass metadata.
- uint32_t ArgumentOffset;
-
using InstantiationFunction_t =
TargetMetadata<Runtime> *(const TargetTypeContextDescriptor<Runtime> *type,
const void *arguments);
@@ -2878,9 +3142,9 @@
}
/// The base header. Must always be the final member.
- GenericContextDescriptorHeader Base;
+ TargetGenericContextDescriptorHeader<Runtime> Base;
- operator const GenericContextDescriptorHeader &() const {
+ operator const TargetGenericContextDescriptorHeader<Runtime> &() const {
return Base;
}
};
@@ -3011,20 +3275,20 @@
const TargetTypeGenericContextDescriptorHeader<Runtime> &
getFullGenericContextHeader() const;
- const GenericContextDescriptorHeader &getGenericContextHeader() const {
+ const TargetGenericContextDescriptorHeader<Runtime> &
+ getGenericContextHeader() const {
return getFullGenericContextHeader();
}
/// Return the offset of the start of generic arguments in the nominal
/// type's metadata. The returned value is measured in sizeof(void*).
- uint32_t getGenericArgumentOffset(
- const TargetMetadata<Runtime> *metadata) const;
+ int32_t getGenericArgumentOffset() const;
/// Return the start of the generic arguments array in the nominal
/// type's metadata. The returned value is measured in sizeof(void*).
const TargetMetadata<Runtime> * const *getGenericArguments(
const TargetMetadata<Runtime> *metadata) const {
- auto offset = getGenericArgumentOffset(metadata);
+ auto offset = getGenericArgumentOffset();
auto words =
reinterpret_cast<const TargetMetadata<Runtime> * const *>(metadata);
return words + offset;
@@ -3038,18 +3302,103 @@
using TypeContextDescriptor = TargetTypeContextDescriptor<InProcess>;
+/// Storage for class metadata bounds. This is the variable returned
+/// by getAddrOfClassMetadataBounds in the compiler.
+///
+/// This storage is initialized before the allocation of any metadata
+/// for the class to which it belongs. In classes without resilient
+/// superclasses, it is initialized statically with values derived
+/// during compilation. In classes with resilient superclasses, it
+/// is initialized dynamically, generally during the allocation of
+/// the first metadata of this class's type. If metadata for this
+/// class is available to you to use, you must have somehow synchronized
+/// with the thread which allocated the metadata, and therefore the
+/// complete initialization of this variable is also ordered before
+/// your access. That is why you can safely access this variable,
+/// and moreover access it without further atomic accesses. However,
+/// since this variable may be accessed in a way that is not dependency-
+/// ordered on the metadata pointer, it is important that you do a full
+/// synchronization and not just a dependency-ordered (consume)
+/// synchronization when sharing class metadata pointers between
+/// threads. (There are other reasons why this is true; for example,
+/// field offset variables are also accessed without dependency-ordering.)
+///
+/// If you are accessing this storage without such a guarantee, you
+/// should be aware that it may be lazily initialized, and moreover
+/// it may be getting lazily initialized from another thread. To ensure
+/// correctness, the fields must be read in the correct order: the
+/// immediate-members offset is initialized last with a store-release,
+/// so it must be read first with a load-acquire, and if the result
+/// is non-zero then the rest of the variable is known to be valid.
+/// (No locking is required because racing initializations should always
+/// assign the same values to the storage.)
+template <typename Runtime>
+struct TargetStoredClassMetadataBounds {
+ using StoredPointerDifference =
+ typename Runtime::StoredPointerDifference;
+
+ /// The offset to the immediate members. This value is in bytes so that
+ /// clients don't have to sign-extend it.
+
+
+ /// It is not necessary to use atomic-ordered loads when accessing this
+ /// variable just to read the immediate-members offset when drilling to
+ /// the immediate members of an already-allocated metadata object.
+ /// The proper initialization of this variable is always ordered before
+ /// any allocation of metadata for this class.
+ std::atomic<StoredPointerDifference> ImmediateMembersOffset;
+
+ /// The positive and negative bounds of the class metadata.
+ TargetMetadataBounds<Runtime> Bounds;
+
+ /// Attempt to read the cached immediate-members offset.
+ ///
+ /// \return true if the read was successful, or false if the cache hasn't
+ /// been filled yet
+ bool tryGetImmediateMembersOffset(StoredPointerDifference &output) {
+ output = ImmediateMembersOffset.load(std::memory_order_relaxed);
+ return output != 0;
+ }
+
+ /// Attempt to read the full cached bounds.
+ ///
+ /// \return true if the read was successful, or false if the cache hasn't
+ /// been filled yet
+ bool tryGet(TargetClassMetadataBounds<Runtime> &output) {
+ auto offset = ImmediateMembersOffset.load(std::memory_order_acquire);
+ if (offset == 0) return false;
+
+ output.ImmediateMembersOffset = offset;
+ output.NegativeSizeInWords = Bounds.NegativeSizeInWords;
+ output.PositiveSizeInWords = Bounds.PositiveSizeInWords;
+ return true;
+ }
+
+ void initialize(TargetClassMetadataBounds<Runtime> value) {
+ assert(value.ImmediateMembersOffset != 0 &&
+ "attempting to initialize metadata bounds cache to a zero state!");
+
+ Bounds.NegativeSizeInWords = value.NegativeSizeInWords;
+ Bounds.PositiveSizeInWords = value.PositiveSizeInWords;
+ ImmediateMembersOffset.store(value.ImmediateMembersOffset,
+ std::memory_order_release);
+ }
+};
+using StoredClassMetadataBounds =
+ TargetStoredClassMetadataBounds<InProcess>;
+
template <typename Runtime>
class TargetClassDescriptor final
: public TargetTypeContextDescriptor<Runtime>,
public TrailingGenericContextObjects<TargetClassDescriptor<Runtime>,
- TargetTypeGenericContextDescriptorHeader<Runtime>,
+ TargetTypeGenericContextDescriptorHeader,
/*additional trailing objects:*/
TargetVTableDescriptorHeader<Runtime>,
TargetMethodDescriptor<Runtime>> {
private:
using TrailingGenericContextObjects =
TrailingGenericContextObjects<TargetClassDescriptor<Runtime>,
- TargetTypeGenericContextDescriptorHeader<Runtime>,
+ TargetTypeGenericContextDescriptorHeader,
TargetVTableDescriptorHeader<Runtime>,
TargetMethodDescriptor<Runtime>>;
@@ -3061,9 +3410,14 @@
using MethodDescriptor = TargetMethodDescriptor<Runtime>;
using VTableDescriptorHeader = TargetVTableDescriptorHeader<Runtime>;
+ using StoredPointer = typename Runtime::StoredPointer;
+ using StoredPointerDifference = typename Runtime::StoredPointerDifference;
+ using StoredSize = typename Runtime::StoredSize;
+
using TrailingGenericContextObjects::getGenericContext;
using TrailingGenericContextObjects::getGenericContextHeader;
using TrailingGenericContextObjects::getFullGenericContextHeader;
+ using TargetTypeContextDescriptor<Runtime>::getTypeContextDescriptorFlags;
/// The superclass of this class. This pointer can be interpreted
/// using the superclass reference kind stored in the type context
@@ -3071,7 +3425,55 @@
///
/// Note that SwiftObject, the implicit superclass of all Swift root
/// classes when building with ObjC compatibility, does not appear here.
- TargetRelativeDirectPointer<Runtime, const void, /*nullable*/true> SuperClass;
+ TargetRelativeDirectPointer<Runtime, const void, /*nullable*/true> Superclass;
+
+ /// Does this class have a formal superclass?
+ bool hasSuperclass() const {
+ return !Superclass.isNull();
+ }
+
+ TypeMetadataRecordKind getSuperclassReferenceKind() const {
+ return getTypeContextDescriptorFlags().class_getSuperclassReferenceKind();
+ }
+
+ union {
+ /// If this descriptor does not have a resilient superclass, this is the
+ /// negative size of metadata objects of this class (in words).
+ uint32_t MetadataNegativeSizeInWords;
+
+ /// If this descriptor has a resilient superclass, this is a reference
+ /// to a cache holding the metadata's extents.
+ TargetRelativeDirectPointer<Runtime,
+ TargetStoredClassMetadataBounds<Runtime>>
+ ResilientMetadataBounds;
+ };
+
+ union {
+ /// If this descriptor does not have a resilient superclass, this is the
+ /// positive size of metadata objects of this class (in words).
+ uint32_t MetadataPositiveSizeInWords;
+
+ // Maybe add something here that's useful only for resilient types?
+ };
+
+ /// The number of additional members added by this class to the class
+ /// metadata. This data is opaque by default to the runtime, other than
+ /// as exposed in other members; it's really just
+ /// NumImmediateMembers * sizeof(void*) bytes of data.
+ ///
+ /// Whether those bytes are added before or after the address point
+ /// depends on areImmediateMembersNegative().
+ uint32_t NumImmediateMembers; // ABI: could be uint16_t?
+
+ StoredSize getImmediateMembersSize() const {
+ return StoredSize(NumImmediateMembers) * sizeof(StoredPointer);
+ }
+
+ /// Are the immediate members of the class metadata allocated at negative
+ /// offsets instead of positive?
+ bool areImmediateMembersNegative() const {
+ return getTypeContextDescriptorFlags().class_areImmediateMembersNegative();
+ }
/// The number of stored properties in the class, not including its
/// superclasses. If there is a field offset vector, this is its length.
@@ -3113,7 +3515,7 @@
const auto *description = metadata->getDescription();
if (description->hasResilientSuperclass())
- return metadata->SuperClass->getSizeInWords() + FieldOffsetVectorOffset;
+ return metadata->Superclass->getSizeInWords() + FieldOffsetVectorOffset;
return FieldOffsetVectorOffset;
}
@@ -3139,29 +3541,49 @@
numTrailingObjects(OverloadToken<MethodDescriptor>{})};
}
- /// This is factored in a silly way because remote mirrors cannot directly
- /// dereference the SuperClass field of class metadata.
- uint32_t getGenericArgumentOffset(
- const TargetClassMetadata<Runtime> *classMetadata,
- const TargetClassMetadata<Runtime> *superMetadata) const {
- auto Offset = getFullGenericContextHeader().ArgumentOffset;
- if (hasResilientSuperclass())
- return superMetadata->getSizeInWords() + Offset;
+ /// Return the bounds of this class's metadata.
+ TargetClassMetadataBounds<Runtime> getMetadataBounds() const {
+ if (!hasResilientSuperclass())
+ return getNonResilientMetadataBounds();
- return Offset;
+ // This lookup works by ADL and will intentionally fail for
+ // non-InProcess instantiations.
+ return getResilientMetadataBounds(this);
+ }
+
+ /// Given that this class is known to not have a resilient superclass
+ /// return its metadata bounds.
+ TargetClassMetadataBounds<Runtime> getNonResilientMetadataBounds() const {
+ return { getNonResilientImmediateMembersOffset()
+ * StoredPointerDifference(sizeof(void*)),
+ MetadataNegativeSizeInWords,
+ MetadataPositiveSizeInWords };
}
/// Return the offset of the start of generic arguments in the nominal
- /// type's metadata. The returned value is measured in sizeof(void*).
- uint32_t
- getGenericArgumentOffset(const TargetMetadata<Runtime> *metadata) const {
- if (hasResilientSuperclass()) {
- auto *classMetadata = llvm::cast<ClassMetadata>(metadata);
- auto *superMetadata = llvm::cast<ClassMetadata>(classMetadata->SuperClass);
- return getGenericArgumentOffset(classMetadata, superMetadata);
- }
+ /// type's metadata. The returned value is measured in words.
+ int32_t getGenericArgumentOffset() const {
+ if (!hasResilientSuperclass())
+ return getNonResilientGenericArgumentOffset();
- return getFullGenericContextHeader().ArgumentOffset;
+ // This lookup works by ADL and will intentionally fail for
+ // non-InProcess instantiations.
+ return getResilientImmediateMembersOffset(this);
+ }
+
+ /// Given that this class is known to not have a resilient superclass,
+ /// return the offset of its generic arguments in words.
+ int32_t getNonResilientGenericArgumentOffset() const {
+ return getNonResilientImmediateMembersOffset();
+ }
+
+ /// Given that this class is known to not have a resilient superclass,
+ /// return the offset of its immediate members in words.
+ int32_t getNonResilientImmediateMembersOffset() const {
+ assert(!hasResilientSuperclass());
+ return areImmediateMembersNegative()
+ ? -int32_t(MetadataNegativeSizeInWords)
+ : int32_t(MetadataPositiveSizeInWords - NumImmediateMembers);
}
void *getMethod(unsigned i) const {
@@ -3177,6 +3599,11 @@
using ClassDescriptor = TargetClassDescriptor<InProcess>;
+/// Compute the bounds of class metadata with a resilient superclass.
+ClassMetadataBounds getResilientMetadataBounds(
+ const ClassDescriptor *descriptor);
+int32_t getResilientImmediateMembersOffset(const ClassDescriptor *descriptor);
+
template <typename Runtime>
class TargetValueTypeDescriptor
: public TargetTypeContextDescriptor<Runtime> {
@@ -3192,11 +3619,11 @@
class TargetStructDescriptor final
: public TargetValueTypeDescriptor<Runtime>,
public TrailingGenericContextObjects<TargetStructDescriptor<Runtime>,
- TargetTypeGenericContextDescriptorHeader<Runtime>> {
+ TargetTypeGenericContextDescriptorHeader> {
private:
using TrailingGenericContextObjects =
TrailingGenericContextObjects<TargetStructDescriptor<Runtime>,
- TargetTypeGenericContextDescriptorHeader<Runtime>>;
+ TargetTypeGenericContextDescriptorHeader>;
using TrailingObjects =
typename TrailingGenericContextObjects::TrailingObjects;
@@ -3219,8 +3646,8 @@
/// its stored properties.
bool hasFieldOffsetVector() const { return FieldOffsetVectorOffset != 0; }
- uint32_t getGenericArgumentOffset() const {
- return getFullGenericContextHeader().ArgumentOffset;
+ static constexpr int32_t getGenericArgumentOffset() {
+ return TargetStructMetadata<Runtime>::getGenericArgumentOffset();
}
static bool classof(const TargetContextDescriptor<Runtime> *cd) {
@@ -3234,11 +3661,11 @@
class TargetEnumDescriptor final
: public TargetValueTypeDescriptor<Runtime>,
public TrailingGenericContextObjects<TargetEnumDescriptor<Runtime>,
- TargetTypeGenericContextDescriptorHeader<Runtime>> {
+ TargetTypeGenericContextDescriptorHeader> {
private:
using TrailingGenericContextObjects =
TrailingGenericContextObjects<TargetEnumDescriptor<Runtime>,
- TargetTypeGenericContextDescriptorHeader<Runtime>>;
+ TargetTypeGenericContextDescriptorHeader>;
using TrailingObjects =
typename TrailingGenericContextObjects::TrailingObjects;
@@ -3275,8 +3702,8 @@
return getPayloadSizeOffset() != 0;
}
- uint32_t getGenericArgumentOffset() const {
- return getFullGenericContextHeader().ArgumentOffset;
+ static constexpr int32_t getGenericArgumentOffset() {
+ return TargetEnumMetadata<Runtime>::getGenericArgumentOffset();
}
static bool classof(const TargetContextDescriptor<Runtime> *cd) {
@@ -3318,12 +3745,11 @@
}
template <typename Runtime>
-uint32_t TargetTypeContextDescriptor<Runtime>::getGenericArgumentOffset(
- const TargetMetadata<Runtime> *metadata) const {
+int32_t TargetTypeContextDescriptor<Runtime>::getGenericArgumentOffset() const {
switch (this->getKind()) {
case ContextDescriptorKind::Class:
return llvm::cast<TargetClassDescriptor<Runtime>>(this)
- ->getGenericArgumentOffset(metadata);
+ ->getGenericArgumentOffset();
case ContextDescriptorKind::Enum:
return llvm::cast<TargetEnumDescriptor<Runtime>>(this)
->getGenericArgumentOffset();
@@ -3376,16 +3802,32 @@
swift_getGenericMetadata(const TypeContextDescriptor *description,
const void *arguments);
-// Callback to allocate a generic class metadata object.
+/// Allocate a generic class metadata object. This is intended to be
+/// called by the metadata instantiation function of a generic class.
+///
+/// This function:
+/// - computes the required size of the metadata object based on the
+/// class hierarchy;
+/// - allocates memory for the metadata object based on the computed
+/// size and the additional requirements imposed by the pattern;
+/// - copies information from the pattern into the allocated metadata; and
+/// - fully initializes the ClassMetadata header, except that the
+/// superclass pointer will be null (or SwiftObject under ObjC interop
+/// if there is no formal superclass).
+///
+/// The instantiation function is responsible for completing the
+/// initialization, including:
+/// - setting the superclass pointer;
+/// - copying class data from the superclass;
+/// - installing the generic arguments;
+/// - installing new v-table entries and overrides; and
+/// - registering the class with the runtime under ObjC interop.
+/// Most of this work can be achieved by calling swift_initClassMetadata.
SWIFT_RUNTIME_EXPORT
ClassMetadata *
swift_allocateGenericClassMetadata(const ClassDescriptor *description,
- const void *metadataTemplate,
- size_t metadataTemplateSize,
- size_t metadataTemplateAddressPoint,
const void *arguments,
- ClassMetadata *superclass,
- size_t numImmediateMembers);
+ const GenericClassMetadataPattern *pattern);
// Callback to allocate a generic struct/enum metadata object.
SWIFT_RUNTIME_EXPORT
diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def
index b4f8b509..ad3b74f 100644
--- a/include/swift/Runtime/RuntimeFunctions.def
+++ b/include/swift/Runtime/RuntimeFunctions.def
@@ -799,16 +799,11 @@
ATTRS(NoUnwind, ReadOnly))
// Metadata *swift_allocateGenericClassMetadata(ClassDescriptor *type,
-// const void *template,
-// size_t templateSize,
-// size_t templateAddressPoint,
// const void * const *arguments,
-// objc_class *superclass,
-// size_t numImmediateMembers);
+// const void *template);
FUNCTION(AllocateGenericClassMetadata, swift_allocateGenericClassMetadata,
C_CC, RETURNS(TypeMetadataPtrTy),
- ARGS(TypeContextDescriptorPtrTy, Int8PtrPtrTy, SizeTy, SizeTy,
- Int8PtrPtrTy, ObjCClassPtrTy, SizeTy),
+ ARGS(TypeContextDescriptorPtrTy, Int8PtrPtrTy, Int8PtrPtrTy),
ATTRS(NoUnwind))
// Metadata *swift_allocateGenericValueMetadata(ValueTypeDescriptor *type,
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index f4a8021..63c1b41 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -55,7 +55,7 @@
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
/// Don't worry about adhering to the 80-column limit for this line.
-const uint16_t VERSION_MINOR = 400; // Last change: sil_property
+const uint16_t VERSION_MINOR = 401; // Last change: ValueOwnership
using DeclIDField = BCFixed<31>;
@@ -311,13 +311,22 @@
// These IDs must \em not be renumbered or reordered without incrementing
// VERSION_MAJOR.
-enum Ownership : uint8_t {
+enum ReferenceOwnership : uint8_t {
Strong = 0,
Weak,
Unowned,
Unmanaged,
};
-using OwnershipField = BCFixed<2>;
+using ReferenceOwnershipField = BCFixed<2>;
+
+// These IDs must \em not be renumbered or reordered without incrementing
+// VERSION_MAJOR.
+enum ValueOwnership : uint8_t {
+ Default = 0,
+ InOut,
+ Shared,
+};
+using ValueOwnershipField = BCFixed<2>;
// These IDs must \em not be renumbered or reordered without incrementing
// VERSION_MAJOR.
@@ -656,8 +665,7 @@
BCFixed<1>, // vararg?
BCFixed<1>, // autoclosure?
BCFixed<1>, // escaping?
- BCFixed<1>, // inout?
- BCFixed<1> // shared?
+ ValueOwnershipField // inout, shared or owned?
>;
using TupleTypeLayout = BCRecordLayout<
@@ -671,8 +679,7 @@
BCFixed<1>, // vararg?
BCFixed<1>, // autoclosure?
BCFixed<1>, // escaping?
- BCFixed<1>, // inout?
- BCFixed<1> // shared?
+ ValueOwnershipField // inout, shared or owned?
>;
using FunctionTypeLayout = BCRecordLayout<
@@ -800,8 +807,8 @@
using ReferenceStorageTypeLayout = BCRecordLayout<
REFERENCE_STORAGE_TYPE,
- OwnershipField, // ownership
- TypeIDField // implementation type
+ ReferenceOwnershipField, // ownership
+ TypeIDField // implementation type
>;
using UnboundGenericTypeLayout = BCRecordLayout<
@@ -1410,7 +1417,8 @@
>;
// Stub layouts, unused.
- using OwnershipDeclAttrLayout = BCRecordLayout<Ownership_DECL_ATTR>;
+ using ReferenceOwnershipDeclAttrLayout
+ = BCRecordLayout<ReferenceOwnership_DECL_ATTR>;
using RawDocCommentDeclAttrLayout = BCRecordLayout<RawDocComment_DECL_ATTR>;
using AccessControlDeclAttrLayout = BCRecordLayout<AccessControl_DECL_ATTR>;
using SetterAccessDeclAttrLayout = BCRecordLayout<SetterAccess_DECL_ATTR>;
diff --git a/include/swift/Subsystems.h b/include/swift/Subsystems.h
index 36ade9a..caf4ca8 100644
--- a/include/swift/Subsystems.h
+++ b/include/swift/Subsystems.h
@@ -128,6 +128,7 @@
std::vector<Token> tokenize(const LangOptions &LangOpts,
const SourceManager &SM, unsigned BufferID,
unsigned Offset = 0, unsigned EndOffset = 0,
+ DiagnosticEngine *Diags = nullptr,
bool KeepComments = true,
bool TokenizeInterpolatedString = true,
ArrayRef<Token> SplitTokens = ArrayRef<Token>());
diff --git a/include/swift/SwiftDemangle/Platform.h b/include/swift/SwiftDemangle/Platform.h
index 286018a..c44121d 100644
--- a/include/swift/SwiftDemangle/Platform.h
+++ b/include/swift/SwiftDemangle/Platform.h
@@ -17,7 +17,7 @@
extern "C" {
#endif
-#if defined(SwiftDemangle_EXPORTS)
+#if defined(swiftDemangle_EXPORTS)
# if defined(__ELF__)
# define SWIFT_DEMANGLE_LINKAGE __attribute__((__visibility__("protected")))
# elif defined(__MACH__)
diff --git a/include/swift/SwiftRemoteMirror/CMakeLists.txt b/include/swift/SwiftRemoteMirror/CMakeLists.txt
index bbaba07..69d8450 100644
--- a/include/swift/SwiftRemoteMirror/CMakeLists.txt
+++ b/include/swift/SwiftRemoteMirror/CMakeLists.txt
@@ -1,9 +1,12 @@
set(swift_remote_mirror_headers)
list(APPEND swift_remote_mirror_headers
- "MemoryReaderInterface.h"
- "SwiftRemoteMirror.h"
- "SwiftRemoteMirrorTypes.h")
+ MemoryReaderInterface.h
+ Platform.h
+ SwiftRemoteMirror.h
+ SwiftRemoteMirrorTypes.h)
swift_install_in_component("swift-remote-mirror-headers"
- FILES ${swift_remote_mirror_headers}
- DESTINATION "include/swift/SwiftRemoteMirror")
+ FILES
+ ${swift_remote_mirror_headers}
+ DESTINATION
+ "include/swift/SwiftRemoteMirror")
diff --git a/include/swift/SwiftRemoteMirror/Platform.h b/include/swift/SwiftRemoteMirror/Platform.h
new file mode 100644
index 0000000..5353344
--- /dev/null
+++ b/include/swift/SwiftRemoteMirror/Platform.h
@@ -0,0 +1,45 @@
+//===-- SwiftRemoteMirror/Platform.h - Remote Mirror Platform --*-- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_REMOTE_MIRROR_PLATFORM_H
+#define SWIFT_REMOTE_MIRROR_PLATFORM_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(swiftRemoteMirror_EXPORTS)
+# if defined(__ELF__)
+# define SWIFT_REMOTE_MIRROR_LINKAGE __attribute__((__visibility__("protected")))
+# elif defined(__MACH__)
+# define SWIFT_REMOTE_MIRROR_LINKAGE __attribute__((__visibility__("default")))
+# else
+# define SWIFT_REMOTE_MIRROR_LINKAGE __declspec(dllexport)
+# endif
+#else
+# if defined(__ELF__)
+# define SWIFT_REMOTE_MIRROR_LINKAGE __attribute__((__visibility__("default")))
+# elif defined(__MACH__)
+# define SWIFT_REMOTE_MIRROR_LINKAGE __attribute__((__visibility__("default")))
+# else
+# define SWIFT_REMOTE_MIRROR_LINKAGE __declspec(dllimport)
+# endif
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
+
+
diff --git a/include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h b/include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h
index b2e4667..3459362 100644
--- a/include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h
+++ b/include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h
@@ -20,6 +20,7 @@
#ifndef SWIFT_REMOTE_MIRROR_H
#define SWIFT_REMOTE_MIRROR_H
+#include "Platform.h"
#include "MemoryReaderInterface.h"
#include "SwiftRemoteMirrorTypes.h"
@@ -37,24 +38,26 @@
#endif
/// Get the metadata version supported by the Remote Mirror library.
-uint16_t
-swift_reflection_getSupportedMetadataVersion();
+SWIFT_REMOTE_MIRROR_LINKAGE
+uint16_t swift_reflection_getSupportedMetadataVersion();
/// \returns An opaque reflection context.
+SWIFT_REMOTE_MIRROR_LINKAGE
SwiftReflectionContextRef
-swift_reflection_createReflectionContext(
- void *ReaderContext,
- uint8_t PointerSize,
- FreeBytesFunction Free,
- ReadBytesFunction ReadBytes,
- GetStringLengthFunction GetStringLength,
- GetSymbolAddressFunction GetSymbolAddress);
+swift_reflection_createReflectionContext(void *ReaderContext,
+ uint8_t PointerSize,
+ FreeBytesFunction Free,
+ ReadBytesFunction ReadBytes,
+ GetStringLengthFunction GetStringLength,
+ GetSymbolAddressFunction GetSymbolAddress);
/// Destroys an opaque reflection context.
+SWIFT_REMOTE_MIRROR_LINKAGE
void
swift_reflection_destroyReflectionContext(SwiftReflectionContextRef Context);
/// Add reflection sections for a loaded Swift image.
+SWIFT_REMOTE_MIRROR_LINKAGE
void
swift_reflection_addReflectionInfo(SwiftReflectionContextRef ContextRef,
swift_reflection_info_t Info);
@@ -62,6 +65,7 @@
#if defined(__APPLE__) && defined(__MACH__)
/// Add reflection information from a loaded Swift image.
/// Returns true on success, false if the image's memory couldn't be read.
+SWIFT_REMOTE_MIRROR_LINKAGE
int
swift_reflection_addImage(SwiftReflectionContextRef ContextRef,
swift_addr_t imageStart);
@@ -69,9 +73,9 @@
/// Returns a boolean indicating if the isa mask was successfully
/// read, in which case it is stored in the isaMask out parameter.
-int
-swift_reflection_readIsaMask(SwiftReflectionContextRef ContextRef,
- uintptr_t *outIsaMask);
+SWIFT_REMOTE_MIRROR_LINKAGE
+int swift_reflection_readIsaMask(SwiftReflectionContextRef ContextRef,
+ uintptr_t *outIsaMask);
/// Returns an opaque type reference for a metadata pointer, or
/// NULL if one can't be constructed.
@@ -79,6 +83,7 @@
/// This function loses information; in particular, passing the
/// result to swift_reflection_infoForTypeRef() will not give
/// the same result as calling swift_reflection_infoForMetadata().
+SWIFT_REMOTE_MIRROR_LINKAGE
swift_typeref_t
swift_reflection_typeRefForMetadata(SwiftReflectionContextRef ContextRef,
uintptr_t Metadata);
@@ -91,10 +96,12 @@
/// positive if the address in question is not really a Swift or
/// Objective-C object. If addReflectionInfo is used, the return value
/// will always be false.
+SWIFT_REMOTE_MIRROR_LINKAGE
int
swift_reflection_ownsObject(SwiftReflectionContextRef ContextRef, uintptr_t Object);
/// Returns the metadata pointer for a given object.
+SWIFT_REMOTE_MIRROR_LINKAGE
uintptr_t
swift_reflection_metadataForObject(SwiftReflectionContextRef ContextRef,
uintptr_t Object);
@@ -105,11 +112,13 @@
/// This function loses information; in particular, passing the
/// result to swift_reflection_infoForTypeRef() will not give
/// the same result as calling swift_reflection_infoForInstance().
+SWIFT_REMOTE_MIRROR_LINKAGE
swift_typeref_t
swift_reflection_typeRefForInstance(SwiftReflectionContextRef ContextRef,
uintptr_t Object);
/// Returns a typeref from a mangled type name string.
+SWIFT_REMOTE_MIRROR_LINKAGE
swift_typeref_t
swift_reflection_typeRefForMangledTypeName(SwiftReflectionContextRef ContextRef,
const char *MangledName,
@@ -117,47 +126,52 @@
/// Returns a structure describing the layout of a value of a typeref.
/// For classes, this returns the reference value itself.
+SWIFT_REMOTE_MIRROR_LINKAGE
swift_typeinfo_t
swift_reflection_infoForTypeRef(SwiftReflectionContextRef ContextRef,
swift_typeref_t OpaqueTypeRef);
/// Returns the information about a child field of a value by index.
+SWIFT_REMOTE_MIRROR_LINKAGE
swift_childinfo_t
swift_reflection_childOfTypeRef(SwiftReflectionContextRef ContextRef,
- swift_typeref_t OpaqueTypeRef,
- unsigned Index);
+ swift_typeref_t OpaqueTypeRef, unsigned Index);
/// Returns a structure describing the layout of a class instance
/// from the isa pointer of a class.
+SWIFT_REMOTE_MIRROR_LINKAGE
swift_typeinfo_t
swift_reflection_infoForMetadata(SwiftReflectionContextRef ContextRef,
uintptr_t Metadata);
/// Returns the information about a child field of a class instance
/// by index.
+SWIFT_REMOTE_MIRROR_LINKAGE
swift_childinfo_t
swift_reflection_childOfMetadata(SwiftReflectionContextRef ContextRef,
- uintptr_t Metadata,
- unsigned Index);
+ uintptr_t Metadata, unsigned Index);
/// Returns a structure describing the layout of a class or closure
/// context instance, from a pointer to the object itself.
+SWIFT_REMOTE_MIRROR_LINKAGE
swift_typeinfo_t
swift_reflection_infoForInstance(SwiftReflectionContextRef ContextRef,
uintptr_t Object);
/// Returns the information about a child field of a class or closure
/// context instance.
+SWIFT_REMOTE_MIRROR_LINKAGE
swift_childinfo_t
swift_reflection_childOfInstance(SwiftReflectionContextRef ContextRef,
- uintptr_t Object,
- unsigned Index);
+ uintptr_t Object, unsigned Index);
/// Returns the number of generic arguments of a typeref.
+SWIFT_REMOTE_MIRROR_LINKAGE
unsigned
swift_reflection_genericArgumentCountOfTypeRef(swift_typeref_t OpaqueTypeRef);
/// Returns a fully instantiated typeref for a generic argument by index.
+SWIFT_REMOTE_MIRROR_LINKAGE
swift_typeref_t
swift_reflection_genericArgumentOfTypeRef(swift_typeref_t OpaqueTypeRef,
unsigned Index);
@@ -181,6 +195,7 @@
///
/// Returns true if InstanceTypeRef and StartOfInstanceData contain valid
/// valid values.
+SWIFT_REMOTE_MIRROR_LINKAGE
int swift_reflection_projectExistential(SwiftReflectionContextRef ContextRef,
swift_addr_t ExistentialAddress,
swift_typeref_t ExistentialTypeRef,
@@ -188,17 +203,21 @@
swift_addr_t *OutStartOfInstanceData);
/// Dump a brief description of the typeref as a tree to stderr.
+SWIFT_REMOTE_MIRROR_LINKAGE
void swift_reflection_dumpTypeRef(swift_typeref_t OpaqueTypeRef);
/// Dump information about the layout for a typeref.
+SWIFT_REMOTE_MIRROR_LINKAGE
void swift_reflection_dumpInfoForTypeRef(SwiftReflectionContextRef ContextRef,
swift_typeref_t OpaqueTypeRef);
/// Dump information about the layout of a class instance from its isa pointer.
+SWIFT_REMOTE_MIRROR_LINKAGE
void swift_reflection_dumpInfoForMetadata(SwiftReflectionContextRef ContextRef,
uintptr_t Metadata);
/// Dump information about the layout of a class or closure context instance.
+SWIFT_REMOTE_MIRROR_LINKAGE
void swift_reflection_dumpInfoForInstance(SwiftReflectionContextRef ContextRef,
uintptr_t Object);
@@ -209,10 +228,9 @@
///
/// Returns the length of the demangled string this function tried to copy
/// into `OutDemangledName`.
-size_t swift_reflection_demangle(const char *MangledName,
- size_t Length,
- char *OutDemangledName,
- size_t MaxLength);
+SWIFT_REMOTE_MIRROR_LINKAGE
+size_t swift_reflection_demangle(const char *MangledName, size_t Length,
+ char *OutDemangledName, size_t MaxLength);
#ifdef __cplusplus
} // extern "C"
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 659a6ec..6336d03 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -3376,9 +3376,10 @@
return compTy;
}
-ReferenceStorageType *ReferenceStorageType::get(Type T, Ownership ownership,
+ReferenceStorageType *ReferenceStorageType::get(Type T,
+ ReferenceOwnership ownership,
const ASTContext &C) {
- assert(ownership != Ownership::Strong &&
+ assert(ownership != ReferenceOwnership::Strong &&
"ReferenceStorageType is unnecessary for strong ownership");
assert(!T->hasTypeVariable()); // not meaningful in type-checker
auto properties = T->getRecursiveProperties();
@@ -3390,16 +3391,17 @@
switch (ownership) {
- case Ownership::Strong: llvm_unreachable("not possible");
- case Ownership::Unowned:
+ case ReferenceOwnership::Strong:
+ llvm_unreachable("not possible");
+ case ReferenceOwnership::Unowned:
return entry = new (C, arena) UnownedStorageType(
T, T->isCanonical() ? &C : nullptr, properties);
- case Ownership::Weak:
+ case ReferenceOwnership::Weak:
assert(T->getOptionalObjectType() &&
"object of weak storage type is not optional");
return entry = new (C, arena)
WeakStorageType(T, T->isCanonical() ? &C : nullptr, properties);
- case Ownership::Unmanaged:
+ case ReferenceOwnership::Unmanaged:
return entry = new (C, arena) UnmanagedStorageType(
T, T->isCanonical() ? &C : nullptr, properties);
}
@@ -3564,9 +3566,10 @@
default:
// assert(type->is<InOutType>() && "Found naked inout type");
- result.push_back(AnyFunctionType::Param(type->getInOutObjectType(),
- Identifier(),
- ParameterTypeFlags::fromParameterType(type, false, false)));
+ result.push_back(
+ AnyFunctionType::Param(type->getInOutObjectType(), Identifier(),
+ ParameterTypeFlags::fromParameterType(
+ type, false, ValueOwnership::Default)));
return;
}
}
diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp
index 374689c..cd0c9a1 100644
--- a/lib/AST/ASTVerifier.cpp
+++ b/lib/AST/ASTVerifier.cpp
@@ -2249,9 +2249,9 @@
// The fact that this is *directly* be a reference storage type
// cuts the code down quite a bit in getTypeOfReference.
- if (var->getAttrs().hasAttribute<OwnershipAttr>() !=
+ if (var->getAttrs().hasAttribute<ReferenceOwnershipAttr>() !=
isa<ReferenceStorageType>(var->getInterfaceType().getPointer())) {
- if (var->getAttrs().hasAttribute<OwnershipAttr>()) {
+ if (var->getAttrs().hasAttribute<ReferenceOwnershipAttr>()) {
Out << "VarDecl has an ownership attribute, but its type"
" is not a ReferenceStorageType: ";
} else {
diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp
index 366ea07..42d480b 100644
--- a/lib/AST/Attr.cpp
+++ b/lib/AST/Attr.cpp
@@ -338,7 +338,7 @@
#include "swift/AST/Attr.def"
case DAK_Inline:
case DAK_AccessControl:
- case DAK_Ownership:
+ case DAK_ReferenceOwnership:
case DAK_Effects:
case DAK_Optimize:
if (DeclAttribute::isDeclModifier(getKind())) {
@@ -622,12 +622,16 @@
}
llvm_unreachable("bad access level");
- case DAK_Ownership:
- switch (cast<OwnershipAttr>(this)->get()) {
- case Ownership::Strong: llvm_unreachable("Never present in the attribute");
- case Ownership::Weak: return "weak";
- case Ownership::Unowned: return "unowned";
- case Ownership::Unmanaged: return "unowned(unsafe)";
+ case DAK_ReferenceOwnership:
+ switch (cast<ReferenceOwnershipAttr>(this)->get()) {
+ case ReferenceOwnership::Strong:
+ llvm_unreachable("Never present in the attribute");
+ case ReferenceOwnership::Weak:
+ return "weak";
+ case ReferenceOwnership::Unowned:
+ return "unowned";
+ case ReferenceOwnership::Unmanaged:
+ return "unowned(unsafe)";
}
llvm_unreachable("bad ownership kind");
case DAK_RawDocComment:
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 44c79c1..d8b0f72 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -1177,7 +1177,7 @@
// Look through most attributes.
if (const auto attributed = dyn_cast<AttributedTypeRepr>(typeRepr)) {
// Weak ownership implies optionality.
- if (attributed->getAttrs().getOwnership() == Ownership::Weak)
+ if (attributed->getAttrs().getOwnership() == ReferenceOwnership::Weak)
return true;
return isDefaultInitializable(attributed->getTypeRepr());
@@ -4416,8 +4416,8 @@
}
ParameterTypeFlags ParamDecl::getParameterFlags() const {
- return ParameterTypeFlags::fromParameterType(getType(), isVariadic(), isShared())
- .withInOut(isInOut());
+ return ParameterTypeFlags::fromParameterType(getType(), isVariadic(),
+ getValueOwnership());
}
/// Return the full source range of this parameter.
diff --git a/lib/AST/DiagnosticConsumer.cpp b/lib/AST/DiagnosticConsumer.cpp
index 0681432..230dc55 100644
--- a/lib/AST/DiagnosticConsumer.cpp
+++ b/lib/AST/DiagnosticConsumer.cpp
@@ -14,15 +14,172 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "swift-basic"
+#define DEBUG_TYPE "swift-ast"
#include "swift/AST/DiagnosticConsumer.h"
#include "swift/AST/DiagnosticEngine.h"
+#include "swift/Basic/Defer.h"
+#include "swift/Basic/SourceManager.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace swift;
-DiagnosticConsumer::~DiagnosticConsumer() { }
+DiagnosticConsumer::~DiagnosticConsumer() = default;
+
+llvm::SMLoc DiagnosticConsumer::getRawLoc(SourceLoc loc) {
+ return loc.Value;
+}
+
+LLVM_ATTRIBUTE_UNUSED
+static bool hasDuplicateFileNames(
+ ArrayRef<FileSpecificDiagnosticConsumer::ConsumerPair> consumers) {
+ llvm::StringSet<> seenFiles;
+ for (const auto &consumerPair : consumers) {
+ if (consumerPair.first.empty()) {
+ // We can handle multiple consumers that aren't associated with any file,
+ // because they only collect diagnostics that aren't in any of the special
+ // files. This isn't an important use case to support, but also SmallSet
+ // doesn't handle empty strings anyway!
+ continue;
+ }
+
+ bool isUnique = seenFiles.insert(consumerPair.first).second;
+ if (!isUnique)
+ return true;
+ }
+ return false;
+}
+
+FileSpecificDiagnosticConsumer::FileSpecificDiagnosticConsumer(
+ SmallVectorImpl<ConsumerPair> &consumers)
+ : SubConsumers(std::move(consumers)) {
+ assert(!SubConsumers.empty() &&
+ "don't waste time handling diagnostics that will never get emitted");
+ assert(!hasDuplicateFileNames(SubConsumers) &&
+ "having multiple consumers for the same file is not implemented");
+}
+
+void FileSpecificDiagnosticConsumer::computeConsumersOrderedByRange(
+ SourceManager &SM) {
+ // Look up each file's source range and add it to the "map" (to be sorted).
+ for (const ConsumerPair &pair : SubConsumers) {
+ if (pair.first.empty())
+ continue;
+
+ Optional<unsigned> bufferID = SM.getIDForBufferIdentifier(pair.first);
+ assert(bufferID.hasValue() && "consumer registered for unknown file");
+ CharSourceRange range = SM.getRangeForBuffer(bufferID.getValue());
+ ConsumersOrderedByRange.emplace_back(range, pair.second.get());
+ }
+
+ // Sort the "map" by buffer /end/ location, for use with std::lower_bound
+ // later. (Sorting by start location would produce the same sort, since the
+ // ranges must not be overlapping, but since we need to check end locations
+ // later it's consistent to sort by that here.)
+ std::sort(ConsumersOrderedByRange.begin(), ConsumersOrderedByRange.end(),
+ [](const ConsumersOrderedByRangeEntry &left,
+ const ConsumersOrderedByRangeEntry &right) -> bool {
+ auto compare = std::less<const char *>();
+ return compare(getRawLoc(left.first.getEnd()).getPointer(),
+ getRawLoc(right.first.getEnd()).getPointer());
+ });
+
+ // Check that the ranges are non-overlapping. If the files really are all
+ // distinct, this should be trivially true, but if it's ever not we might end
+ // up mis-filing diagnostics.
+ assert(ConsumersOrderedByRange.end() ==
+ std::adjacent_find(ConsumersOrderedByRange.begin(),
+ ConsumersOrderedByRange.end(),
+ [](const ConsumersOrderedByRangeEntry &left,
+ const ConsumersOrderedByRangeEntry &right) {
+ return left.first.overlaps(right.first);
+ }) &&
+ "overlapping ranges despite having distinct files");
+}
+
+DiagnosticConsumer *
+FileSpecificDiagnosticConsumer::consumerForLocation(SourceManager &SM,
+ SourceLoc loc) const {
+ // If there's only one consumer, we'll use it no matter what, because...
+ // - ...all diagnostics within the file will go to that consumer.
+ // - ...all diagnostics not within the file will not be claimed by any
+ // consumer, and so will go to all (one) consumers.
+ if (SubConsumers.size() == 1)
+ return SubConsumers.front().second.get();
+
+ // Diagnostics with invalid locations always go to every consumer.
+ if (loc.isInvalid())
+ return nullptr;
+
+ // This map is generated on first use and cached, to allow the
+ // FileSpecificDiagnosticConsumer to be set up before the source files are
+ // actually loaded.
+ if (ConsumersOrderedByRange.empty()) {
+ auto *mutableThis = const_cast<FileSpecificDiagnosticConsumer*>(this);
+ mutableThis->computeConsumersOrderedByRange(SM);
+ }
+
+ // This std::lower_bound call is doing a binary search for the first range
+ // that /might/ contain 'loc'. Specifically, since the ranges are sorted
+ // by end location, it's looking for the first range where the end location
+ // is greater than or equal to 'loc'.
+ auto possiblyContainingRangeIter =
+ std::lower_bound(ConsumersOrderedByRange.begin(),
+ ConsumersOrderedByRange.end(),
+ loc,
+ [](const ConsumersOrderedByRangeEntry &entry,
+ SourceLoc loc) -> bool {
+ auto compare = std::less<const char *>();
+ return compare(getRawLoc(entry.first.getEnd()).getPointer(),
+ getRawLoc(loc).getPointer());
+ });
+
+ if (possiblyContainingRangeIter != ConsumersOrderedByRange.end() &&
+ possiblyContainingRangeIter->first.contains(loc)) {
+ return possiblyContainingRangeIter->second;
+ }
+
+ return nullptr;
+}
+
+void FileSpecificDiagnosticConsumer::handleDiagnostic(
+ SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
+ StringRef FormatString, ArrayRef<DiagnosticArgument> FormatArgs,
+ const DiagnosticInfo &Info) {
+
+ DiagnosticConsumer *specificConsumer;
+ switch (Kind) {
+ case DiagnosticKind::Error:
+ case DiagnosticKind::Warning:
+ case DiagnosticKind::Remark:
+ specificConsumer = consumerForLocation(SM, Loc);
+ ConsumerForSubsequentNotes = specificConsumer;
+ break;
+ case DiagnosticKind::Note:
+ specificConsumer = ConsumerForSubsequentNotes;
+ break;
+ }
+
+ if (specificConsumer) {
+ specificConsumer->handleDiagnostic(SM, Loc, Kind, FormatString, FormatArgs,
+ Info);
+ } else {
+ for (auto &subConsumer : SubConsumers) {
+ subConsumer.second->handleDiagnostic(SM, Loc, Kind, FormatString,
+ FormatArgs, Info);
+ }
+ }
+}
+
+bool FileSpecificDiagnosticConsumer::finishProcessing() {
+ // Deliberately don't use std::any_of here because we don't want early-exit
+ // behavior.
+ bool hadError = false;
+ for (auto &subConsumer : SubConsumers)
+ hadError |= subConsumer.second->finishProcessing();
+ return hadError;
+}
void NullDiagnosticConsumer::handleDiagnostic(
SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
diff --git a/lib/AST/Parameter.cpp b/lib/AST/Parameter.cpp
index 98c56de..2adab4f 100644
--- a/lib/AST/Parameter.cpp
+++ b/lib/AST/Parameter.cpp
@@ -127,10 +127,10 @@
for (auto P : *this) {
auto type = getType(P);
- argumentInfo.emplace_back(type->getInOutObjectType(), P->getArgumentName(),
- ParameterTypeFlags::fromParameterType(
- type, P->isVariadic(), P->isShared())
- .withInOut(P->isInOut()));
+ argumentInfo.emplace_back(
+ type->getInOutObjectType(), P->getArgumentName(),
+ ParameterTypeFlags::fromParameterType(type, P->isVariadic(),
+ P->getValueOwnership()));
}
return TupleType::get(argumentInfo, C);
diff --git a/lib/Basic/Version.cpp b/lib/Basic/Version.cpp
index e363a30..7efc861 100644
--- a/lib/Basic/Version.cpp
+++ b/lib/Basic/Version.cpp
@@ -319,9 +319,9 @@
switch (Components[0]) {
case 3:
#ifdef SWIFT_VERSION_PATCHLEVEL
- return Version{3, 3, SWIFT_VERSION_PATCHLEVEL};
+ return Version{3, 4, SWIFT_VERSION_PATCHLEVEL};
#else
- return Version{3, 3};
+ return Version{3, 4};
#endif
case 4:
static_assert(SWIFT_VERSION_MAJOR == 4,
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 3089929..1cbda0c 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -2054,7 +2054,8 @@
return;
}
if (attrs & clang::ObjCPropertyDecl::OBJC_PR_weak) {
- prop->getAttrs().add(new (ctx) OwnershipAttr(Ownership::Weak));
+ prop->getAttrs().add(new (ctx)
+ ReferenceOwnershipAttr(ReferenceOwnership::Weak));
prop->setType(WeakStorageType::get(prop->getType(), ctx));
prop->setInterfaceType(WeakStorageType::get(
prop->getInterfaceType(), ctx));
@@ -2062,7 +2063,8 @@
}
if ((attrs & clang::ObjCPropertyDecl::OBJC_PR_assign) ||
(attrs & clang::ObjCPropertyDecl::OBJC_PR_unsafe_unretained)) {
- prop->getAttrs().add(new (ctx) OwnershipAttr(Ownership::Unmanaged));
+ prop->getAttrs().add(
+ new (ctx) ReferenceOwnershipAttr(ReferenceOwnership::Unmanaged));
prop->setType(UnmanagedStorageType::get(prop->getType(), ctx));
prop->setInterfaceType(UnmanagedStorageType::get(
prop->getInterfaceType(), ctx));
@@ -4735,7 +4737,7 @@
!isa<clang::ObjCProtocolDecl>(redecl->getDeclContext()))
original->setImplicit(false);
- if (!original->getAttrs().hasAttribute<OwnershipAttr>() &&
+ if (!original->getAttrs().hasAttribute<ReferenceOwnershipAttr>() &&
!original->getAttrs().hasAttribute<NSCopyingAttr>()) {
applyPropertyOwnership(original,
redecl->getPropertyAttributesAsWritten());
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index f43a17a..1b9e677 100644
--- a/lib/Driver/Compilation.cpp
+++ b/lib/Driver/Compilation.cpp
@@ -419,7 +419,7 @@
/// TaskFinishedResponse::ContinueExecution from any of the constituent
/// calls.
TaskFinishedResponse
- unpackAndFinishBatch(ProcessId Pid, int ReturnCode, StringRef Output,
+ unpackAndFinishBatch(int ReturnCode, StringRef Output,
StringRef Errors, const BatchJob *B) {
if (Comp.ShowJobLifecycle)
llvm::outs() << "Batch job finished: " << LogJob(B) << "\n";
@@ -428,7 +428,8 @@
if (Comp.ShowJobLifecycle)
llvm::outs() << " ==> Unpacked batch constituent finished: "
<< LogJob(J) << "\n";
- auto r = taskFinished(Pid, ReturnCode, Output, Errors, (void *)J);
+ auto r = taskFinished(llvm::sys::ProcessInfo::InvalidPid, ReturnCode, Output,
+ Errors, (void *)J);
if (r != TaskFinishedResponse::ContinueExecution)
res = r;
}
@@ -443,26 +444,29 @@
StringRef Errors, void *Context) {
const Job *FinishedCmd = (const Job *)Context;
- if (Comp.ShowDriverTimeCompilation) {
- DriverTimers[FinishedCmd]->stopTimer();
+ if (Pid != llvm::sys::ProcessInfo::InvalidPid) {
+
+ if (Comp.ShowDriverTimeCompilation) {
+ DriverTimers[FinishedCmd]->stopTimer();
+ }
+
+ if (Comp.Level == OutputLevel::Parseable) {
+ // Parseable output was requested.
+ parseable_output::emitFinishedMessage(llvm::errs(), *FinishedCmd, Pid,
+ ReturnCode, Output);
+ } else {
+ // Otherwise, send the buffered output to stderr, though only if we
+ // support getting buffered output.
+ if (TaskQueue::supportsBufferingOutput())
+ llvm::errs() << Output;
+ }
}
if (BatchJobs.count(FinishedCmd) != 0) {
- return unpackAndFinishBatch(Pid, ReturnCode, Output, Errors,
+ return unpackAndFinishBatch(ReturnCode, Output, Errors,
static_cast<const BatchJob *>(FinishedCmd));
}
- if (Comp.Level == OutputLevel::Parseable) {
- // Parseable output was requested.
- parseable_output::emitFinishedMessage(llvm::errs(), *FinishedCmd, Pid,
- ReturnCode, Output);
- } else {
- // Otherwise, send the buffered output to stderr, though only if we
- // support getting buffered output.
- if (TaskQueue::supportsBufferingOutput())
- llvm::errs() << Output;
- }
-
// In order to handle both old dependencies that have disappeared and new
// dependencies that have arisen, we need to reload the dependency file.
// Do this whether or not the build succeeded.
@@ -505,30 +509,6 @@
return TaskFinishedResponse::ContinueExecution;
}
- /// Unpack a \c BatchJob that has finished into its constituent \c Job
- /// members, and call \c taskSignalled on each, propagating any \c
- /// TaskFinishedResponse other than \c
- /// TaskFinishedResponse::ContinueExecution from any of the constituent
- /// calls.
- TaskFinishedResponse
- unpackAndSignalBatch(ProcessId Pid, StringRef ErrorMsg, StringRef Output,
- StringRef Errors, const BatchJob *B,
- Optional<int> Signal) {
- if (Comp.ShowJobLifecycle)
- llvm::outs() << "Batch job signalled: " << LogJob(B) << "\n";
- auto res = TaskFinishedResponse::ContinueExecution;
- for (const Job *J : B->getCombinedJobs()) {
- if (Comp.ShowJobLifecycle)
- llvm::outs() << " ==> Unpacked batch constituent signalled: "
- << LogJob(J) << "\n";
- auto r = taskSignalled(Pid, ErrorMsg, Output, Errors,
- (void *)J, Signal);
- if (r != TaskFinishedResponse::ContinueExecution)
- res = r;
- }
- return res;
- }
-
TaskFinishedResponse
taskSignalled(ProcessId Pid, StringRef ErrorMsg, StringRef Output,
StringRef Errors, void *Context, Optional<int> Signal) {
@@ -538,12 +518,6 @@
DriverTimers[SignalledCmd]->stopTimer();
}
- if (BatchJobs.count(SignalledCmd) != 0) {
- return unpackAndSignalBatch(Pid, ErrorMsg, Output, Errors,
- static_cast<const BatchJob *>(SignalledCmd),
- Signal);
- }
-
if (Comp.Level == OutputLevel::Parseable) {
// Parseable output was requested.
parseable_output::emitSignalledMessage(llvm::errs(), *SignalledCmd,
@@ -554,7 +528,6 @@
if (TaskQueue::supportsBufferingOutput())
llvm::errs() << Output;
}
-
if (!ErrorMsg.empty())
Comp.Diags.diagnose(SourceLoc(), diag::error_unable_to_execute_command,
ErrorMsg);
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 9abdd59..c4186b8 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -1356,8 +1356,8 @@
if (const Arg *A = Args.getLastArg(options::OPT_sanitize_EQ))
OI.SelectedSanitizers = parseSanitizerArgValues(
Args, A, TC.getTriple(), Diags,
- [&](StringRef sanitizerName) {
- return TC.sanitizerRuntimeLibExists(Args, sanitizerName);
+ [&](StringRef sanitizerName, bool shared) {
+ return TC.sanitizerRuntimeLibExists(Args, sanitizerName, shared);
});
if (const Arg *A = Args.getLastArg(options::OPT_sanitize_coverage_EQ)) {
diff --git a/lib/Driver/ParseableOutput.cpp b/lib/Driver/ParseableOutput.cpp
index 73e59cd..5fed352 100644
--- a/lib/Driver/ParseableOutput.cpp
+++ b/lib/Driver/ParseableOutput.cpp
@@ -133,9 +133,9 @@
}
}
types::forAllTypes([&](types::ID Ty) {
- auto Output = Cmd.getOutput().getAdditionalOutputForType(Ty);
- if (!Output.empty())
- Outputs.push_back(OutputPair(Ty, Output));
+ for (auto Output : Cmd.getOutput().getAdditionalOutputsForType(Ty)) {
+ Outputs.push_back(OutputPair(Ty, Output));
+ }
});
}
diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp
index e5c3532..59be9d8 100644
--- a/lib/Driver/ToolChain.cpp
+++ b/lib/Driver/ToolChain.cpp
@@ -317,7 +317,8 @@
bool
ToolChain::sanitizerRuntimeLibExists(const ArgList &args,
- StringRef sanitizerName) const {
+ StringRef sanitizerName,
+ bool shared) const {
// Assume no sanitizers are supported by default.
// This method should be overriden by a platform-specific subclass.
return false;
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index 37d50c7..d8e7610 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -1132,18 +1132,21 @@
}
bool toolchains::Darwin::sanitizerRuntimeLibExists(
- const ArgList &args, StringRef sanitizer) const {
+ const ArgList &args, StringRef sanitizer, bool shared) const {
SmallString<128> sanitizerLibPath;
getClangLibraryPath(*this, args, sanitizerLibPath);
llvm::sys::path::append(sanitizerLibPath,
- getSanitizerRuntimeLibNameForDarwin(sanitizer, this->getTriple()));
+ getSanitizerRuntimeLibNameForDarwin(
+ sanitizer, this->getTriple(), shared));
return llvm::sys::fs::exists(sanitizerLibPath.str());
}
bool toolchains::GenericUnix::sanitizerRuntimeLibExists(
- const ArgList &args, StringRef sanitizer) const {
+ const ArgList &args, StringRef sanitizer, bool shared) const {
SmallString<128> sanitizerLibPath;
getClangLibraryPath(*this, args, sanitizerLibPath);
+
+ // All libraries are static for linux.
llvm::sys::path::append(sanitizerLibPath,
getSanitizerRuntimeLibNameForLinux(sanitizer, this->getTriple()));
return llvm::sys::fs::exists(sanitizerLibPath.str());
@@ -1784,4 +1787,3 @@
std::string toolchains::Cygwin::getTargetForLinker() const {
return "";
}
-
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index 6a30cb7..64f7038 100644
--- a/lib/Driver/ToolChains.h
+++ b/lib/Driver/ToolChains.h
@@ -34,7 +34,8 @@
Darwin(const Driver &D, const llvm::Triple &Triple) : ToolChain(D, Triple) {}
~Darwin() = default;
bool sanitizerRuntimeLibExists(const llvm::opt::ArgList &args,
- StringRef sanitizerLibName)
+ StringRef sanitizerLibName,
+ bool shared)
const override;
};
@@ -73,7 +74,8 @@
GenericUnix(const Driver &D, const llvm::Triple &Triple) : ToolChain(D, Triple) {}
~GenericUnix() = default;
bool sanitizerRuntimeLibExists(const llvm::opt::ArgList &args,
- StringRef sanitizerLibName)
+ StringRef sanitizerLibName,
+ bool shared)
const override;
};
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index f00ba48..6eb05c3 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -686,7 +686,7 @@
if (const Arg *A = Args.getLastArg(options::OPT_sanitize_EQ)) {
Opts.Sanitizers = parseSanitizerArgValues(
Args, A, Triple, Diags,
- /* sanitizerRuntimeLibExists= */[](StringRef libName) {
+ /* sanitizerRuntimeLibExists= */[](StringRef libName, bool shared) {
// The driver has checked the existence of the library
// already.
diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp
index e801410..f3634f3 100644
--- a/lib/Frontend/FrontendOptions.cpp
+++ b/lib/Frontend/FrontendOptions.cpp
@@ -116,19 +116,15 @@
else
fn(input.outputFilename());
}
- (void)InputsAndOutputs.forEachInputProducingSupplementaryOutput(
- [&](const InputFile &inp) -> bool {
- const SupplementaryOutputPaths &outs =
- inp.getPrimarySpecificPaths().SupplementaryOutputs;
- const std::string *outputs[] = {&outs.ModuleOutputPath,
- &outs.ModuleDocOutputPath,
- &outs.ObjCHeaderOutputPath};
- for (const std::string *next : outputs) {
- if (!next->empty())
- fn(*next);
- }
- return false;
- });
+ const SupplementaryOutputPaths &outs =
+ input.getPrimarySpecificPaths().SupplementaryOutputs;
+ const std::string *outputs[] = {&outs.ModuleOutputPath,
+ &outs.ModuleDocOutputPath,
+ &outs.ObjCHeaderOutputPath};
+ for (const std::string *next : outputs) {
+ if (!next->empty())
+ fn(*next);
+ }
}
const char *
diff --git a/lib/Frontend/PrintingDiagnosticConsumer.cpp b/lib/Frontend/PrintingDiagnosticConsumer.cpp
index 11c1eab..69a8933 100644
--- a/lib/Frontend/PrintingDiagnosticConsumer.cpp
+++ b/lib/Frontend/PrintingDiagnosticConsumer.cpp
@@ -63,10 +63,6 @@
};
} // end anonymous namespace
-llvm::SMLoc DiagnosticConsumer::getRawLoc(SourceLoc loc) {
- return loc.Value;
-}
-
void PrintingDiagnosticConsumer::handleDiagnostic(
SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
StringRef FormatString, ArrayRef<DiagnosticArgument> FormatArgs,
diff --git a/lib/Frontend/SerializedDiagnosticConsumer.cpp b/lib/Frontend/SerializedDiagnosticConsumer.cpp
index bf61701..bd4dec1 100644
--- a/lib/Frontend/SerializedDiagnosticConsumer.cpp
+++ b/lib/Frontend/SerializedDiagnosticConsumer.cpp
@@ -222,9 +222,10 @@
};
} // end anonymous namespace
-namespace swift { namespace serialized_diagnostics {
- DiagnosticConsumer *createConsumer(StringRef serializedDiagnosticsPath) {
- return new SerializedDiagnosticConsumer(serializedDiagnosticsPath);
+namespace swift {
+namespace serialized_diagnostics {
+ std::unique_ptr<DiagnosticConsumer> createConsumer(StringRef outputPath) {
+ return llvm::make_unique<SerializedDiagnosticConsumer>(outputPath);
}
} // namespace serialized_diagnostics
} // namespace swift
diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp
index 3bce5e8..b83b771 100644
--- a/lib/FrontendTool/FrontendTool.cpp
+++ b/lib/FrontendTool/FrontendTool.cpp
@@ -1335,7 +1335,7 @@
// Just because we had an AST error it doesn't mean we can't performLLVM.
bool HadError = Instance.getASTContext().hadError();
-
+
// If the AST Context has no errors but no IRModule is available,
// parallelIRGen happened correctly, since parallel IRGen produces multiple
// modules.
@@ -1509,6 +1509,50 @@
ProfileEvents, ProfileEntities);
}
+/// Creates a diagnostic consumer that handles serializing diagnostics, based on
+/// the supplementary output paths specified by \p inputsAndOutputs.
+///
+/// The returned consumer will handle producing multiple serialized diagnostics
+/// files if necessary, by using sub-consumers for each file and dispatching to
+/// the right one.
+///
+/// If no serialized diagnostics are being produced, returns null.
+static std::unique_ptr<DiagnosticConsumer>
+createSerializedDiagnosticConsumerIfNeeded(
+ const FrontendInputsAndOutputs &inputsAndOutputs) {
+
+ // The "4" here is somewhat arbitrary. In practice we're going to have one
+ // sub-consumer for each .dia file we're trying to output, which (again in
+ // practice) is going to be 1 in WMO mode and equal to the number of primary
+ // inputs in batch mode. That in turn is going to be "the number of files we
+ // need to recompile in this build, divided by the number of jobs". So a
+ // value of "4" here means that there would be no heap allocation on a clean
+ // build of a module with up to 32 files on an 8-core machine, if the user
+ // doesn't customize anything.
+ SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 4>
+ serializedConsumers;
+
+ inputsAndOutputs.forEachInputProducingSupplementaryOutput(
+ [&](const InputFile &Input) -> bool {
+ std::string serializedDiagnosticsPath = Input.serializedDiagnosticsPath();
+ if (serializedDiagnosticsPath.empty())
+ return false;
+
+ serializedConsumers.emplace_back(
+ Input.file(),
+ serialized_diagnostics::createConsumer(serializedDiagnosticsPath));
+
+ // Continue for other inputs.
+ return false;
+ });
+
+ if (serializedConsumers.empty())
+ return nullptr;
+ if (serializedConsumers.size() == 1)
+ return std::move(serializedConsumers.front()).second;
+ return llvm::make_unique<FileSpecificDiagnosticConsumer>(serializedConsumers);
+}
+
int swift::performFrontend(ArrayRef<const char *> Args,
const char *Argv0, void *MainAddr,
FrontendObserver *observer) {
@@ -1621,20 +1665,13 @@
// arguments are generated by the driver, not directly by a user. The driver
// is responsible for emitting diagnostics for its own errors. See SR-2683
// for details.
- //
- // FIXME: Do we need one SerializedConsumer per primary? Owned by the
- // SourceFile?
- std::unique_ptr<DiagnosticConsumer> SerializedConsumer;
- {
- const std::string &SerializedDiagnosticsPath =
- Invocation.getSerializedDiagnosticsPathForAtMostOnePrimary();
- if (!SerializedDiagnosticsPath.empty()) {
- SerializedConsumer.reset(
- serialized_diagnostics::createConsumer(SerializedDiagnosticsPath));
- Instance->addDiagnosticConsumer(SerializedConsumer.get());
- }
- }
+ std::unique_ptr<DiagnosticConsumer> SerializedConsumerDispatcher =
+ createSerializedDiagnosticConsumerIfNeeded(
+ Invocation.getFrontendOptions().InputsAndOutputs);
+ if (SerializedConsumerDispatcher)
+ Instance->addDiagnosticConsumer(SerializedConsumerDispatcher.get());
+ // FIXME: The fix-its need to be multiplexed like the serialized diagnostics.
std::unique_ptr<DiagnosticConsumer> FixitsConsumer;
{
const std::string &FixitsOutputPath =
diff --git a/lib/IRGen/ClassMetadataVisitor.h b/lib/IRGen/ClassMetadataVisitor.h
index 1dbfd60..566e4ac 100644
--- a/lib/IRGen/ClassMetadataVisitor.h
+++ b/lib/IRGen/ClassMetadataVisitor.h
@@ -113,8 +113,7 @@
asImpl().noteStartOfImmediateMembers(theClass);
// Add space for the generic parameters, if applicable.
- // Note that we only add references for the immediate parameters;
- // parameters for the parent context are handled by the parent.
+ // This must always be the first item in the immediate members.
asImpl().addGenericFields(theClass, type, theClass);
// Add vtable entries.
diff --git a/lib/IRGen/EnumMetadataVisitor.h b/lib/IRGen/EnumMetadataVisitor.h
index bc8334a..402bf06 100644
--- a/lib/IRGen/EnumMetadataVisitor.h
+++ b/lib/IRGen/EnumMetadataVisitor.h
@@ -50,12 +50,10 @@
// EnumMetadata header.
asImpl().addNominalTypeDescriptor();
- // If changing this layout, you must update the magic number in
- // emitParentMetadataRef.
-
// Instantiation-specific.
- // Add fields for generic cases.
+ // Generic arguments.
+ // This must always be the first piece of trailing data.
asImpl().addGenericFields(Target, Target->getDeclaredTypeInContext());
// Reserve a word to cache the payload size if the type has dynamic layout.
diff --git a/lib/IRGen/GenClass.cpp b/lib/IRGen/GenClass.cpp
index d48f8d5..baeee73 100644
--- a/lib/IRGen/GenClass.cpp
+++ b/lib/IRGen/GenClass.cpp
@@ -1947,7 +1947,7 @@
if (!prop->isSettable(prop->getDeclContext()))
outs << ",R";
// Weak and Unowned properties are (weak).
- else if (prop->getAttrs().hasAttribute<OwnershipAttr>())
+ else if (prop->getAttrs().hasAttribute<ReferenceOwnershipAttr>())
outs << ",W";
// If the property is @NSCopying, or is bridged to a value class, the
// property is (copy).
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index f98e69c..ec0f4c2 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -3342,11 +3342,18 @@
/// Returns the address of a class metadata base offset.
llvm::Constant *
-IRGenModule::getAddrOfClassMetadataBaseOffset(ClassDecl *D,
- ForDefinition_t forDefinition) {
+IRGenModule::getAddrOfClassMetadataBounds(ClassDecl *D,
+ ForDefinition_t forDefinition) {
+ // StoredClassMetadataBounds
+ auto layoutTy = llvm::StructType::get(getLLVMContext(), {
+ SizeTy, // Immediate members offset
+ Int32Ty, // Negative size in words
+ Int32Ty // Positive size in words
+ });
+
LinkEntity entity = LinkEntity::forClassMetadataBaseOffset(D);
return getAddrOfLLVMVariable(entity, getPointerAlignment(), forDefinition,
- SizeTy, DebugTypeInfo());
+ layoutTy, DebugTypeInfo());
}
/// Return the address of a generic type's metadata instantiation cache.
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index 92a6b49..7f81ae9 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -1113,8 +1113,7 @@
unsigned index = 1;
Address addr(metadata, IGF.IGM.getPointerAlignment());
- addr = IGF.Builder.CreateBitCast(addr,
- IGF.IGM.TypeMetadataPtrTy->getPointerTo());
+ addr = IGF.Builder.CreateElementBitCast(addr, IGF.IGM.TypeMetadataPtrTy);
return IGF.Builder.CreateConstArrayGEP(addr, index, IGF.IGM.getPointerSize());
}
@@ -2107,13 +2106,13 @@
auto &C = IGF.IGM.Context;
CanType referent;
switch (type->getOwnership()) {
- case Ownership::Strong:
+ case ReferenceOwnership::Strong:
llvm_unreachable("shouldn't be a ReferenceStorageType");
- case Ownership::Weak:
+ case ReferenceOwnership::Weak:
referent = type.getReferentType().getOptionalObjectType();
break;
- case Ownership::Unmanaged:
- case Ownership::Unowned:
+ case ReferenceOwnership::Unmanaged:
+ case ReferenceOwnership::Unowned:
referent = type.getReferentType();
break;
}
@@ -2134,7 +2133,7 @@
//
// FIXME: This sounds wrong, an Objective-C tagged pointer could be
// stored in an unmanaged reference for instance.
- if (type->getOwnership() == Ownership::Unmanaged) {
+ if (type->getOwnership() == ReferenceOwnership::Unmanaged) {
auto metatype = CanMetatypeType::get(C.TheNativeObjectType);
return emitFromValueWitnessTable(metatype);
}
@@ -2161,7 +2160,7 @@
// Get the reference storage type of the builtin object whose value
// witness we can borrow.
- if (type->getOwnership() == Ownership::Weak)
+ if (type->getOwnership() == ReferenceOwnership::Weak)
valueWitnessReferent = OptionalType::get(valueWitnessReferent)
->getCanonicalType();
@@ -2644,19 +2643,12 @@
/// Fill in the fields of a TypeGenericContextDescriptorHeader.
void addGenericParametersHeader() {
- asImpl().addGenericParamsOffset();
asImpl().addMetadataInstantiationFunction();
asImpl().addMetadataInstantiationCache();
super::addGenericParametersHeader();
}
- void addGenericParamsOffset() {
- // Include the offset to the generic argument vector inside a metadata
- // record for this type.
- B.addInt32(asImpl().getGenericParamsOffset() / IGM.getPointerSize());
- }
-
void addMetadataInstantiationFunction() {
if (!HasMetadata) {
B.addInt32(0);
@@ -2716,7 +2708,6 @@
}
// Subclasses should provide:
- // Size getGenericParamsOffset();
// ContextDescriptorKind getContextKind();
// void addLayoutInfo(); // ABI TODO: should be superseded
};
@@ -2797,7 +2788,7 @@
return cast<StructDecl>(Type);
}
- Size FieldVectorOffset, GenericParamsOffset;
+ Size FieldVectorOffset;
public:
StructContextDescriptorBuilder(IRGenModule &IGM, StructDecl *Type,
@@ -2805,14 +2796,9 @@
: super(IGM, Type, requireMetadata)
{
auto &layout = IGM.getMetadataLayout(getType());
- GenericParamsOffset = layout.getStaticGenericRequirementsOffset();
FieldVectorOffset = layout.getFieldOffsetVectorOffset().getStatic();
}
- Size getGenericParamsOffset() {
- return GenericParamsOffset;
- }
-
ContextDescriptorKind getContextKind() {
return ContextDescriptorKind::Struct;
}
@@ -2848,7 +2834,6 @@
return cast<EnumDecl>(Type);
}
- Size GenericParamsOffset;
Size PayloadSizeOffset;
const EnumImplStrategy &Strategy;
@@ -2860,15 +2845,10 @@
getType()->getDeclaredTypeInContext()->getCanonicalType()))
{
auto &layout = IGM.getMetadataLayout(getType());
- GenericParamsOffset = layout.getStaticGenericRequirementsOffset();
if (layout.hasPayloadSizeOffset())
PayloadSizeOffset = layout.getPayloadSizeOffset().getStatic();
}
- Size getGenericParamsOffset() {
- return GenericParamsOffset;
- }
-
ContextDescriptorKind getContextKind() {
return ContextDescriptorKind::Enum;
}
@@ -2913,44 +2893,30 @@
return cast<ClassDecl>(Type);
}
+ // Non-null unless the type is foreign.
+ ClassMetadataLayout *MetadataLayout = nullptr;
+
Optional<TypeEntityReference> SuperClassRef;
- // Offsets of key fields in the metadata records.
- Size FieldVectorOffset, GenericParamsOffset;
-
- SILVTable *VTable;
-
- Size VTableOffset;
- unsigned VTableSize;
+ SILVTable *VTable = nullptr;
+ unsigned VTableSize = 0;
public:
ClassContextDescriptorBuilder(IRGenModule &IGM, ClassDecl *Type,
RequireMetadata_t requireMetadata)
: super(IGM, Type, requireMetadata)
{
- if (getType()->isForeign()) {
- VTable = nullptr;
- VTableSize = 0;
- return;
- }
+ if (getType()->isForeign()) return;
+
+ MetadataLayout = &IGM.getClassMetadataLayout(Type);
if (auto superclassDecl = getType()->getSuperclassDecl()) {
SuperClassRef = IGM.getTypeEntityReference(superclassDecl);
}
- auto &layout = IGM.getClassMetadataLayout(getType());
-
- VTable = IGM.getSILModule().lookUpVTable(getType());
- VTableSize = layout.getVTableSize();
-
- if (layout.hasResilientSuperclass()) {
- FieldVectorOffset = layout.getRelativeFieldOffsetVectorOffset();
- GenericParamsOffset = layout.getRelativeGenericRequirementsOffset();
- VTableOffset = layout.getRelativeVTableOffset();
- } else {
- FieldVectorOffset = layout.getStaticFieldOffsetVectorOffset();
- GenericParamsOffset = layout.getStaticGenericRequirementsOffset();
- VTableOffset = layout.getStaticVTableOffset();
+ VTableSize = MetadataLayout->getVTableSize();
+ if (VTableSize) {
+ VTable = IGM.getSILModule().lookUpVTable(getType());
}
}
@@ -2966,14 +2932,17 @@
uint16_t getKindSpecificFlags() {
TypeContextDescriptorFlags flags;
- flags.setIsReflectable(true); // class is always reflectable
+ // Classes are always reflectable.
+ flags.setIsReflectable(true);
if (!getType()->isForeign()) {
+ if (MetadataLayout->areImmediateMembersNegative())
+ flags.class_setAreImmediateMembersNegative(true);
+
if (VTableSize != 0)
flags.class_setHasVTable(true);
- auto &layout = IGM.getClassMetadataLayout(getType());
- if (layout.hasResilientSuperclass())
+ if (MetadataLayout->hasResilientSuperclass())
flags.class_setHasResilientSuperclass(true);
}
@@ -2986,15 +2955,21 @@
return flags.getOpaqueValue();
}
- Size getGenericParamsOffset() {
- return GenericParamsOffset;
+ Size getFieldVectorOffset() {
+ if (!MetadataLayout) return Size(0);
+ return (MetadataLayout->hasResilientSuperclass()
+ ? MetadataLayout->getRelativeFieldOffsetVectorOffset()
+ : MetadataLayout->getStaticFieldOffsetVectorOffset());
}
void addVTable() {
if (VTableSize == 0)
return;
-
- B.addInt32(VTableOffset / IGM.getPointerSize());
+
+ auto offset = MetadataLayout->hasResilientSuperclass()
+ ? MetadataLayout->getRelativeVTableOffset()
+ : MetadataLayout->getStaticVTableOffset();
+ B.addInt32(offset / IGM.getPointerSize());
B.addInt32(VTableSize);
addVTableEntries(getType());
@@ -3052,11 +3027,45 @@
B.addInt32(0);
}
+ // union {
+ // uint32_t MetadataNegativeSizeInWords;
+ // RelativeDirectPointer<StoredClassMetadataBounds>
+ // ResilientMetadataBounds;
+ // };
+ if (!MetadataLayout) {
+ // FIXME: do something meaningful for foreign classes?
+ B.addInt32(0);
+ } else if (!MetadataLayout->hasResilientSuperclass()) {
+ B.addInt32(MetadataLayout->getSize().AddressPoint
+ / IGM.getPointerSize());
+ } else {
+ B.addRelativeAddress(
+ IGM.getAddrOfClassMetadataBounds(getType(), NotForDefinition));
+ }
+
+ // union {
+ // uint32_t MetadataPositiveSizeInWords;
+ // };
+ if (!MetadataLayout) {
+ // FIXME: do something meaningful for foreign classes?
+ B.addInt32(0);
+ } else if (!MetadataLayout->hasResilientSuperclass()) {
+ B.addInt32(MetadataLayout->getSize().getOffsetToEnd()
+ / IGM.getPointerSize());
+ } else {
+ B.addInt32(0); // currently unused
+ }
+
+ // uint32_t NumImmediateMembers;
+ auto numImmediateMembers =
+ (MetadataLayout ? MetadataLayout->getNumImmediateMembers() : 0);
+ B.addInt32(numImmediateMembers);
+
// uint32_t NumFields;
B.addInt32(std::distance(properties.begin(), properties.end()));
// uint32_t FieldOffsetVectorOffset;
- B.addInt32(FieldVectorOffset / IGM.getPointerSize());
+ B.addInt32(getFieldVectorOffset() / IGM.getPointerSize());
addFieldTypes(IGM, getType(), properties);
}
@@ -3193,7 +3202,11 @@
namespace {
/// An adapter class which turns a metadata layout class into a
/// generic metadata layout class.
- template <class Impl, class Base>
+ ///
+ /// If AddGenericArguments is false, fill ops will be added for the
+ /// arguments, but space for them won't actually be built into the
+ /// pattern.
+ template <class Impl, class Base, bool AddGenericArguments = true>
class GenericMetadataBuilderBase : public Base {
typedef Base super;
@@ -3210,7 +3223,7 @@
/// The total size of the template (following any header).
Size TemplateSize = Size::invalid();
-
+
IRGenModule &IGM = super::IGM;
using super::asImpl;
using super::Target;
@@ -3319,6 +3332,10 @@
TemplateSize = getNextOffsetFromTemplateHeader();
+ asImpl().emitInstantiationDefinitions();
+ }
+
+ void emitInstantiationDefinitions() {
asImpl().emitCreateFunction();
asImpl().emitInstantiationCache();
}
@@ -3337,14 +3354,16 @@
template <class... T>
void addGenericArgument(CanType type, T &&...args) {
FillOps.push_back({type, None});
- super::addGenericArgument(type, std::forward<T>(args)...);
+ if (AddGenericArguments)
+ super::addGenericArgument(type, std::forward<T>(args)...);
}
template <class... T>
void addGenericWitnessTable(CanType type, ProtocolConformanceRef conf,
T &&...args) {
FillOps.push_back({type, conf});
- super::addGenericWitnessTable(type, conf, std::forward<T>(args)...);
+ if (AddGenericArguments)
+ super::addGenericWitnessTable(type, conf, std::forward<T>(args)...);
}
// Can be overridden by subclassers to emit other dependent metadata.
@@ -3544,11 +3563,10 @@
using super::Target;
using super::asImpl;
- bool HasResilientSuperclass = false;
-
ConstantStructBuilder &B;
const StructLayout &Layout;
const ClassLayout &FieldLayout;
+ ClassMetadataLayout &MetadataLayout;
MemberBuilder Members;
@@ -3558,47 +3576,59 @@
const ClassLayout &fieldLayout)
: super(IGM, theClass), B(builder),
Layout(layout), FieldLayout(fieldLayout),
+ MetadataLayout(IGM.getClassMetadataLayout(theClass)),
Members(IGM, theClass, builder, layout, fieldLayout) {}
public:
- void noteResilientSuperclass() {
- HasResilientSuperclass = true;
- }
+ void noteResilientSuperclass() {}
void noteStartOfImmediateMembers(ClassDecl *theClass) {
+ if (theClass == Target) {
+ emitClassMetadataBaseOffset();
+ }
+ }
+
+ /// Emit the base-offset variable for the class.
+ void emitClassMetadataBaseOffset() {
// Only classes defined in resilient modules, or those that have
// a resilient superclass need this.
- if (!HasResilientSuperclass &&
- !IGM.isResilient(theClass, ResilienceExpansion::Minimal)) {
+ if (!MetadataLayout.hasResilientSuperclass() &&
+ !IGM.isResilient(Target, ResilienceExpansion::Minimal)) {
return;
}
- if (theClass == Target) {
- auto *offsetAddr =
- IGM.getAddrOfClassMetadataBaseOffset(theClass,
- ForDefinition);
- auto *offsetVar = cast<llvm::GlobalVariable>(offsetAddr);
+ auto *offsetAddr =
+ IGM.getAddrOfClassMetadataBounds(Target, ForDefinition);
+ auto *offsetVar = cast<llvm::GlobalVariable>(offsetAddr);
- if (HasResilientSuperclass) {
- // If the superclass is resilient to us, we have to compute and
- // initialize the global when we initialize the metadata.
- auto *init = llvm::ConstantInt::get(IGM.SizeTy, 0);
-
- offsetVar->setInitializer(init);
- offsetVar->setConstant(false);
- return;
- }
-
- // Otherwise, we know the offset at compile time, even if our
- // clients do not, so just emit a constant.
- auto &layout = IGM.getClassMetadataLayout(theClass);
-
- auto value = layout.getStartOfImmediateMembers();
- auto *init = llvm::ConstantInt::get(IGM.SizeTy, value.getValue());
+ if (MetadataLayout.hasResilientSuperclass()) {
+ // If the superclass is resilient to us, we have to compute and
+ // initialize the global when we initialize the metadata.
+ auto init = llvm::ConstantAggregateZero::get(offsetVar->getValueType());
offsetVar->setInitializer(init);
- offsetVar->setConstant(true);
+ offsetVar->setConstant(false);
+ return;
}
+
+ // Otherwise, we know the offset at compile time, even if our
+ // clients do not, so just emit a constant.
+ auto &layout = IGM.getClassMetadataLayout(Target);
+
+ auto immediateMembersOffset = layout.getStartOfImmediateMembers();
+ auto size = layout.getSize();
+ auto negativeSizeInWords = size.AddressPoint / IGM.getPointerSize();
+ auto positiveSizeInWords = size.getOffsetToEnd() / IGM.getPointerSize();
+
+ auto initTy = cast<llvm::StructType>(offsetVar->getValueType());
+ auto *init = llvm::ConstantStruct::get(initTy, {
+ llvm::ConstantInt::get(IGM.SizeTy, immediateMembersOffset.getValue()),
+ llvm::ConstantInt::get(IGM.Int32Ty, negativeSizeInWords),
+ llvm::ConstantInt::get(IGM.Int32Ty, positiveSizeInWords)
+ });
+
+ offsetVar->setInitializer(init);
+ offsetVar->setConstant(true);
}
/// The 'metadata flags' field in a class is actually a pointer to
@@ -3744,16 +3774,16 @@
}
void addClassSize() {
- auto size = IGM.getMetadataLayout(Target).getSize();
+ auto size = MetadataLayout.getSize();
B.addInt32(size.FullSize.getValue());
}
void addClassAddressPoint() {
// FIXME: Wrong
- auto size = IGM.getMetadataLayout(Target).getSize();
+ auto size = MetadataLayout.getSize();
B.addInt32(size.AddressPoint.getValue());
}
-
+
void addClassCacheData() {
// We initially fill in these fields with addresses taken from
// the ObjC runtime.
@@ -3857,52 +3887,20 @@
return metadata;
}
- // Store the runtime-computed metadata size of our superclass into the
- // target class's metadata base offset global variable.
- //
- // Note that this code will run for each generic instantiation of the
- // class, if the class is generic. This should be OK because the
- // metadata size does not change between generic instantiations, so
- // all stores after the first should be idempotent.
- void emitInitializeClassMetadataBaseOffset(IRGenFunction &IGF,
- llvm::Value *superMetadata) {
- if (!HasResilientSuperclass)
- return;
+ /// Materialize type metadata for the given type and store it into the
+ /// superclass field of the given metadata.
+ void emitStoreOfSuperclass(IRGenFunction &IGF, CanType superclassType,
+ llvm::Value *metadata) {
+ llvm::Value *superMetadata =
+ emitClassHeapMetadataRef(IGF, superclassType,
+ MetadataValueType::TypeMetadata,
+ /*allowUninit*/ false);
- auto &layout = IGM.getClassMetadataLayout(Target);
-
- // Load the size of the superclass metadata.
- Address metadataAsBytes(
- IGF.Builder.CreateBitCast(superMetadata, IGF.IGM.Int8PtrTy),
- IGM.getPointerAlignment());
-
- Address sizeSlot = IGF.Builder.CreateConstByteArrayGEP(
- metadataAsBytes,
- layout.getMetadataSizeOffset());
- sizeSlot = IGF.Builder.CreateBitCast(sizeSlot,
- IGM.Int32Ty->getPointerTo());
- llvm::Value *size = IGF.Builder.CreateLoad(sizeSlot);
-
- Address addressPointSlot = IGF.Builder.CreateConstByteArrayGEP(
- metadataAsBytes,
- layout.getMetadataAddressPointOffset());
- addressPointSlot = IGF.Builder.CreateBitCast(addressPointSlot,
- IGM.Int32Ty->getPointerTo());
- llvm::Value *addressPoint = IGF.Builder.CreateLoad(addressPointSlot);
-
- size = IGF.Builder.CreateSub(size, addressPoint);
-
- if (IGM.SizeTy != IGM.Int32Ty)
- size = IGF.Builder.CreateZExt(size, IGM.SizeTy);
-
- Address offsetAddr(
- IGM.getAddrOfClassMetadataBaseOffset(Target,
- NotForDefinition),
- IGM.getPointerAlignment());
-
- // FIXME: Do we need to worry about memory barriers here, and when we
- // load from the global?
- IGF.Builder.CreateStore(size, offsetAddr);
+ Address superField =
+ emitAddressOfSuperclassRefInClassMetadata(IGF, metadata);
+ superField = IGF.Builder.CreateElementBitCast(superField,
+ IGM.TypeMetadataPtrTy);
+ IGF.Builder.CreateStore(superMetadata, superField);
}
// Update vtable entries for method overrides. The runtime copies in
@@ -3989,7 +3987,6 @@
using super::Target;
using super::B;
using super::addReferenceToHeapMetadata;
- using super::emitInitializeClassMetadataBaseOffset;
using super::emitFinishInitializationOfClassMetadata;
using super::emitFinishIdempotentInitialization;
using super::emitFieldOffsetGlobals;
@@ -4080,18 +4077,7 @@
// Initialize the superclass if we didn't do so as a constant.
if (HasUnfilledSuperclass) {
auto superclass = type->getSuperclass()->getCanonicalType();
- llvm::Value *superMetadata =
- emitClassHeapMetadataRef(IGF, superclass,
- MetadataValueType::TypeMetadata,
- /*allowUninit*/ false);
-
- emitInitializeClassMetadataBaseOffset(IGF, superMetadata);
-
- Address superField =
- emitAddressOfSuperclassRefInClassMetadata(IGF, metadata);
- superField = IGF.Builder.CreateElementBitCast(superField,
- IGM.TypeMetadataPtrTy);
- IGF.Builder.CreateStore(superMetadata, superField);
+ this->emitStoreOfSuperclass(IGF, superclass, metadata);
}
// Relocate the metadata if it has a superclass that is resilient
@@ -4139,20 +4125,18 @@
: super(IGM, theClass, builder, layout, fieldLayout) {}
};
- /// A builder for generic class metadata.
+ /// A builder for GenericClassMetadataPattern objects.
class GenericClassMetadataBuilder :
public GenericMetadataBuilderBase<GenericClassMetadataBuilder,
ClassMetadataBuilderBase<GenericClassMetadataBuilder,
- ResilientClassMemberBuilder>>
+ ResilientClassMemberBuilder>,
+ /*add generic arguments*/ false>
{
typedef GenericMetadataBuilderBase super;
- Size MetaclassPtrOffset = Size::invalid();
- Size ClassRODataPtrOffset = Size::invalid();
- Size MetaclassRODataPtrOffset = Size::invalid();
- Size DependentMetaclassPoint = Size::invalid();
- Size DependentClassRODataPoint = Size::invalid();
- Size DependentMetaclassRODataPoint = Size::invalid();
+ Optional<ConstantAggregateBuilderBase::PlaceholderPosition>
+ NumExtraDataWords, ClassRODataOffset, MetaclassObjectOffset,
+ MetaclassRODataOffset;
public:
GenericClassMetadataBuilder(IRGenModule &IGM, ClassDecl *theClass,
ConstantStructBuilder &B,
@@ -4165,70 +4149,107 @@
HasDependentMetadata = true;
}
- void addSuperClass() {
- // Filled in by the runtime.
- B.addNullPointer(IGM.TypeMetadataPtrTy);
+ void layout() {
+ // HeapObjectDestroyer *Destroy;
+ addDestructorFunction();
+
+ // ClassIVarDestroyer *IVarDestroyer;
+ addIVarDestroyer();
+
+ // ClassFlags Flags;
+ addClassFlags();
+
+ // TODO: consider using this to initialize the field offsets (and then
+ // suppress dynamic layout for them).
+ // uint16_t ImmediateMembersPattern_Size;
+ // uint16_t ImmediateMembersPattern_TargetOffset;
+ B.addInt16(0);
+ B.addInt16(0);
+
+ // uint16_t NumExtraDataWords;
+ NumExtraDataWords = B.addPlaceholderWithSize(IGM.Int16Ty);
+
+ // uint16_t ClassRODataOffset;
+ ClassRODataOffset = B.addPlaceholderWithSize(IGM.Int16Ty);
+
+ // uint16_t MetaclassObjectOffset;
+ MetaclassObjectOffset = B.addPlaceholderWithSize(IGM.Int16Ty);
+
+ // uint16_t MetadataRODataOffset;
+ MetaclassRODataOffset = B.addPlaceholderWithSize(IGM.Int16Ty);
+
+ // Immediate members pattern:
+ // (currently we don't take advantage of this)
+
+ // Extra data pattern:
+ addExtraDataPattern();
+
+ // We're done with the pattern now.
+#ifndef NDEBUG
+ auto finalOffset = getNextOffsetFromTemplateHeader();
+#endif
+
+ // Emit the base-offset variable.
+ emitClassMetadataBaseOffset();
+
+ // Emit the nominal type descriptor.
+ (void) ClassContextDescriptorBuilder(IGM, Target, RequireMetadata).emit();
+
+ // Register fill ops for all the immediate type arguments.
+ addGenericFields(Target, Target->getDeclaredTypeInContext(), Target);
+
+ // Emit instantiation information.
+ emitInstantiationDefinitions();
+
+ assert(finalOffset == getNextOffsetFromTemplateHeader() &&
+ "shouldn't have added anything to the pattern");
}
- llvm::Value *emitAllocateMetadata(IRGenFunction &IGF,
- llvm::Value *descriptor,
- llvm::Value *arguments) {
- llvm::Value *superMetadata;
- if (Target->hasSuperclass()) {
- Type superclass = Target->getSuperclass();
- superclass = Target->mapTypeIntoContext(superclass);
- superMetadata =
- emitClassHeapMetadataRef(IGF, superclass->getCanonicalType(),
- MetadataValueType::ObjCClass);
+ uint16_t getOffsetInWords(Size begin, Size offset) {
+ // Subtract the offset from the initial offset and divide by the
+ // pointer size, rounding up.
+ auto result =
+ (offset - begin + IGM.getPointerSize() - Size(1))
+ / IGM.getPointerSize();
+ assert(result < (1 << 16));
+ return uint16_t(result);
+ };
- emitInitializeClassMetadataBaseOffset(IGF, superMetadata);
- } else if (IGM.ObjCInterop) {
- superMetadata = emitObjCHeapMetadataRef(IGF,
- IGM.getObjCRuntimeBaseForSwiftRootClass(Target));
- } else {
- superMetadata = llvm::ConstantPointerNull::get(IGM.ObjCClassPtrTy);
+ void addExtraDataPattern() {
+ Size extraDataBegin = getNextOffsetFromTemplateHeader();
+
+ uint16_t classRODataOffsetWords = 0;
+ uint16_t metaclassObjectOffsetWords = 0;
+ uint16_t metaclassRODataOffsetWords = 0;
+ if (IGM.ObjCInterop) {
+ // Add the metaclass object.
+ metaclassObjectOffsetWords =
+ getOffsetInWords(extraDataBegin, getNextOffsetFromTemplateHeader());
+ addMetaclassObject();
+
+ // Add the RO-data objects.
+ auto roDataPoints =
+ emitClassPrivateDataFields(IGM, B, Target);
+ classRODataOffsetWords =
+ getOffsetInWords(extraDataBegin, roDataPoints.first);
+ metaclassRODataOffsetWords =
+ getOffsetInWords(extraDataBegin, roDataPoints.second);
}
- auto templatePointer = IGM.getAddrOfTypeMetadataPattern(Target);
- auto templateSize = IGM.getSize(TemplateSize);
- auto templateAddressPoint = IGM.getSize(AddressPoint);
+ auto extraDataEnd = getNextOffsetFromTemplateHeader();
+ auto numExtraDataWords = getOffsetInWords(extraDataBegin, extraDataEnd);
- auto numImmediateMembers =
- IGM.getSize(Size(IGM.getClassMetadataLayout(Target).getNumImmediateMembers()));
+ B.fillPlaceholderWithInt(*NumExtraDataWords, IGM.Int16Ty,
+ numExtraDataWords);
+ B.fillPlaceholderWithInt(*ClassRODataOffset, IGM.Int16Ty,
+ classRODataOffsetWords);
+ B.fillPlaceholderWithInt(*MetaclassObjectOffset, IGM.Int16Ty,
+ metaclassObjectOffsetWords);
+ B.fillPlaceholderWithInt(*MetaclassRODataOffset, IGM.Int16Ty,
+ metaclassRODataOffsetWords);
+ }
- return IGF.Builder.CreateCall(IGM.getAllocateGenericClassMetadataFn(),
- {descriptor, templatePointer, templateSize,
- templateAddressPoint, arguments,
- superMetadata, numImmediateMembers});
- }
-
- void addMetadataFlags() {
- // The metaclass pointer will be instantiated here.
- MetaclassPtrOffset = getNextOffsetFromTemplateHeader();
- B.addInt(IGM.MetadataKindTy, 0);
- }
-
- void addClassDataPointer() {
- // The rodata pointer will be instantiated here.
- // Make sure we at least set the 'is Swift class' bit, though.
- ClassRODataPtrOffset = getNextOffsetFromTemplateHeader();
- if (!IGM.ObjCInterop) {
- // FIXME: Remove null data altogether rdar://problem/18801263
- B.addInt(IGM.MetadataKindTy, 1);
- } else {
- B.addInt(IGM.MetadataKindTy, IGM.UseDarwinPreStableABIBit ? 1 : 2);
- }
- }
-
- void addDependentData() {
- if (!IGM.ObjCInterop) {
- // Every piece of data in the dependent data appears to be related to
- // Objective-C information. If we're not doing Objective-C interop, we
- // can just skip adding it to the class.
- return;
- }
- // Emit space for the dependent metaclass.
- DependentMetaclassPoint = getNextOffsetFromTemplateHeader();
+ void addMetaclassObject() {
// isa
ClassDecl *rootClass = getRootClassForMetaclass(IGM, Target);
auto isa = IGM.getAddrOfMetaclassObject(rootClass, NotForDefinition);
@@ -4240,17 +4261,9 @@
// vtable
B.add(IGM.getObjCEmptyVTablePtr());
// rodata, which is always dependent
- MetaclassRODataPtrOffset = getNextOffsetFromTemplateHeader();
B.addInt(IGM.IntPtrTy, 0);
-
- std::tie(DependentClassRODataPoint, DependentMetaclassRODataPoint)
- = emitClassPrivateDataFields(IGM, B, Target);
}
- void noteStartOfFieldOffsets(ClassDecl *whichClass) {}
-
- void noteEndOfFieldOffsets(ClassDecl *whichClass) {}
-
// Suppress GenericMetadataBuilderBase's default behavior of introducing
// fill ops for generic arguments unless they belong directly to the target
// class and not its ancestors.
@@ -4278,91 +4291,29 @@
}
}
+ llvm::Value *emitAllocateMetadata(IRGenFunction &IGF,
+ llvm::Value *descriptor,
+ llvm::Value *arguments) {
+ auto templatePointer = IGM.getAddrOfTypeMetadataPattern(Target);
+ auto metadata =
+ IGF.Builder.CreateCall(IGM.getAllocateGenericClassMetadataFn(),
+ {descriptor, arguments, templatePointer});
+
+ return metadata;
+ }
+
void emitInitializeMetadata(IRGenFunction &IGF,
llvm::Value *metadata,
bool isVWTMutable) {
assert(!HasDependentVWT && "class should never have dependent VWT");
- // Fill in the metaclass pointer.
- Address metadataPtr(IGF.Builder.CreateBitCast(metadata, IGF.IGM.Int8PtrPtrTy),
- IGF.IGM.getPointerAlignment());
-
- llvm::Value *metaclass;
- if (IGF.IGM.ObjCInterop) {
- assert(!DependentMetaclassPoint.isInvalid());
- assert(!MetaclassPtrOffset.isInvalid());
-
- Address metaclassPtrSlot = createPointerSizedGEP(IGF, metadataPtr,
- MetaclassPtrOffset - AddressPoint);
- metaclassPtrSlot = IGF.Builder.CreateBitCast(metaclassPtrSlot,
- IGF.IGM.ObjCClassPtrTy->getPointerTo());
- Address metaclassRawPtr = createPointerSizedGEP(IGF, metadataPtr,
- DependentMetaclassPoint - AddressPoint);
- metaclass = IGF.Builder.CreateBitCast(metaclassRawPtr,
- IGF.IGM.ObjCClassPtrTy)
- .getAddress();
- IGF.Builder.CreateStore(metaclass, metaclassPtrSlot);
- } else {
- // FIXME: Remove altogether rather than injecting a NULL value.
- // rdar://problem/18801263
- assert(!MetaclassPtrOffset.isInvalid());
- Address metaclassPtrSlot = createPointerSizedGEP(IGF, metadataPtr,
- MetaclassPtrOffset - AddressPoint);
- metaclassPtrSlot = IGF.Builder.CreateBitCast(metaclassPtrSlot,
- IGF.IGM.ObjCClassPtrTy->getPointerTo());
- IGF.Builder.CreateStore(
- llvm::ConstantPointerNull::get(IGF.IGM.ObjCClassPtrTy),
- metaclassPtrSlot);
- }
-
- // Fill in the rodata reference in the class.
- Address classRODataPtr;
- if (IGF.IGM.ObjCInterop) {
- assert(!DependentClassRODataPoint.isInvalid());
- assert(!ClassRODataPtrOffset.isInvalid());
- Address rodataPtrSlot = createPointerSizedGEP(IGF, metadataPtr,
- ClassRODataPtrOffset - AddressPoint);
- rodataPtrSlot = IGF.Builder.CreateBitCast(rodataPtrSlot,
- IGF.IGM.IntPtrTy->getPointerTo());
-
- classRODataPtr = createPointerSizedGEP(IGF, metadataPtr,
- DependentClassRODataPoint - AddressPoint);
- // Set the low bit of the value to indicate "compiled by Swift".
- llvm::Value *rodata = IGF.Builder.CreatePtrToInt(
- classRODataPtr.getAddress(), IGF.IGM.IntPtrTy);
- rodata = IGF.Builder.CreateOr(rodata, 1);
- IGF.Builder.CreateStore(rodata, rodataPtrSlot);
- } else {
- // NOTE: Unlike other bits of the metadata that should later be removed,
- // this one is important because things check this value's flags to
- // determine what kind of object it is. That said, if those checks
- // are determined to be removable, we can remove this as well per
- // rdar://problem/18801263
- assert(!ClassRODataPtrOffset.isInvalid());
- Address rodataPtrSlot = createPointerSizedGEP(IGF, metadataPtr,
- ClassRODataPtrOffset - AddressPoint);
- rodataPtrSlot = IGF.Builder.CreateBitCast(rodataPtrSlot,
- IGF.IGM.IntPtrTy->getPointerTo());
-
- IGF.Builder.CreateStore(llvm::ConstantInt::get(IGF.IGM.IntPtrTy, 1),
- rodataPtrSlot);
- }
-
- // Fill in the rodata reference in the metaclass.
- Address metaclassRODataPtr;
- if (IGF.IGM.ObjCInterop) {
- assert(!DependentMetaclassRODataPoint.isInvalid());
- assert(!MetaclassRODataPtrOffset.isInvalid());
- Address rodataPtrSlot = createPointerSizedGEP(IGF, metadataPtr,
- MetaclassRODataPtrOffset - AddressPoint);
- rodataPtrSlot = IGF.Builder.CreateBitCast(rodataPtrSlot,
- IGF.IGM.IntPtrTy->getPointerTo());
-
- metaclassRODataPtr = createPointerSizedGEP(IGF, metadataPtr,
- DependentMetaclassRODataPoint - AddressPoint);
- llvm::Value *rodata = IGF.Builder.CreatePtrToInt(
- metaclassRODataPtr.getAddress(), IGF.IGM.IntPtrTy);
- IGF.Builder.CreateStore(rodata, rodataPtrSlot);
+ // Install the superclass. The runtime takes care of installing
+ // SwiftObject if we're building with ObjC interop and don't have
+ // a formal superclass.
+ if (Target->hasSuperclass()) {
+ CanType superclass = Target->mapTypeIntoContext(Target->getSuperclass())
+ ->getCanonicalType();
+ emitStoreOfSuperclass(IGF, superclass, metadata);
}
// We can assume that this never relocates the metadata because
diff --git a/lib/IRGen/GenMeta.h b/lib/IRGen/GenMeta.h
index ee85978..3f398c8 100644
--- a/lib/IRGen/GenMeta.h
+++ b/lib/IRGen/GenMeta.h
@@ -151,13 +151,6 @@
ArchetypeType *archetype);
/// Given a reference to nominal type metadata of the given type,
- /// derive a reference to the parent type metadata. There must be a
- /// parent type.
- llvm::Value *emitParentMetadataRef(IRGenFunction &IGF,
- NominalTypeDecl *theDecl,
- llvm::Value *metadata);
-
- /// Given a reference to nominal type metadata of the given type,
/// derive a reference to the type metadata stored in the nth
/// requirement slot. The type must have generic arguments.
llvm::Value *emitArgumentMetadataRef(IRGenFunction &IGF,
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index 5377b02..2fdf1c4 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -1210,7 +1210,8 @@
ConcreteType(SILWT->getConformance()->getDeclContext()
->mapTypeIntoContext(
SILWT->getConformance()->getType()
- ->getCanonicalType())),
+ ->getCanonicalType())
+ ->getCanonicalType()),
Conformance(*SILWT->getConformance()),
SILEntries(SILWT->getEntries()),
SILConditionalConformances(SILWT->getConditionalConformances()),
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index 5b93a9a..6fb2258 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -1150,8 +1150,8 @@
/// Determine whether the given type requires foreign type metadata.
bool requiresForeignTypeMetadata(CanType type);
- llvm::Constant *getAddrOfClassMetadataBaseOffset(ClassDecl *D,
- ForDefinition_t forDefinition);
+ llvm::Constant *getAddrOfClassMetadataBounds(ClassDecl *D,
+ ForDefinition_t forDefinition);
llvm::Constant *getAddrOfTypeContextDescriptor(NominalTypeDecl *D,
RequireMetadata_t requireMetadata,
ConstantInit definition = ConstantInit());
diff --git a/lib/IRGen/MetadataLayout.cpp b/lib/IRGen/MetadataLayout.cpp
index 491539f..852cf2a 100644
--- a/lib/IRGen/MetadataLayout.cpp
+++ b/lib/IRGen/MetadataLayout.cpp
@@ -162,11 +162,13 @@
if (offset.isStatic())
return Offset(offset.getStaticOffset());
- Address offsetBaseAddr(
- IGF.IGM.getAddrOfClassMetadataBaseOffset(cast<ClassDecl>(getDecl()),
- NotForDefinition),
+ Address layoutAddr(
+ IGF.IGM.getAddrOfClassMetadataBounds(cast<ClassDecl>(getDecl()),
+ NotForDefinition),
IGF.IGM.getPointerAlignment());
+ auto offsetBaseAddr = IGF.Builder.CreateStructGEP(layoutAddr, 0, Size(0));
+
// FIXME: Should this be an invariant load?
llvm::Value *offsetVal = IGF.Builder.CreateLoad(offsetBaseAddr, "base");
diff --git a/lib/IRGen/MetadataLayout.h b/lib/IRGen/MetadataLayout.h
index cc0851d..9410c56 100644
--- a/lib/IRGen/MetadataLayout.h
+++ b/lib/IRGen/MetadataLayout.h
@@ -227,6 +227,10 @@
return HasResilientSuperclass;
}
+ constexpr static bool areImmediateMembersNegative() {
+ return false;
+ }
+
Size getMetadataSizeOffset() const;
Size getMetadataAddressPointOffset() const;
diff --git a/lib/IRGen/StructMetadataVisitor.h b/lib/IRGen/StructMetadataVisitor.h
index 15e29fc..ce870fe 100644
--- a/lib/IRGen/StructMetadataVisitor.h
+++ b/lib/IRGen/StructMetadataVisitor.h
@@ -48,10 +48,10 @@
// StructMetadata header.
asImpl().addNominalTypeDescriptor();
- // If changing this layout, you must update the magic number in
- // emitParentMetadataRef.
-
// Instantiation-specific.
+
+ // Generic arguments.
+ // This must always be the first piece of trailing data.
asImpl().addGenericFields(Target, Target->getDeclaredTypeInContext());
// Struct field offsets.
diff --git a/lib/Option/SanitizerOptions.cpp b/lib/Option/SanitizerOptions.cpp
index d168b29..62016b3 100644
--- a/lib/Option/SanitizerOptions.cpp
+++ b/lib/Option/SanitizerOptions.cpp
@@ -41,6 +41,18 @@
llvm_unreachable("Unsupported sanitizer");
}
+static const char* toFileName(const SanitizerKind kind) {
+ switch (kind) {
+ case SanitizerKind::Address:
+ return "asan";
+ case SanitizerKind::Thread:
+ return "tsan";
+ case SanitizerKind::Fuzzer:
+ return "fuzzer";
+ }
+ llvm_unreachable("Unsupported sanitizer");
+}
+
llvm::SanitizerCoverageOptions swift::parseSanitizerCoverageArgValue(
const llvm::opt::Arg *A, const llvm::Triple &Triple,
DiagnosticEngine &Diags, OptionSet<SanitizerKind> sanitizers) {
@@ -108,33 +120,43 @@
return opts;
}
-static bool isTSanSupported(
- const llvm::Triple &Triple,
- llvm::function_ref<bool(llvm::StringRef)> sanitizerRuntimeLibExists) {
-
- return Triple.isArch64Bit() && sanitizerRuntimeLibExists("tsan");
-}
-
OptionSet<SanitizerKind> swift::parseSanitizerArgValues(
const llvm::opt::ArgList &Args,
const llvm::opt::Arg *A,
const llvm::Triple &Triple,
DiagnosticEngine &Diags,
- llvm::function_ref<bool(llvm::StringRef)> sanitizerRuntimeLibExists) {
+ llvm::function_ref<bool(llvm::StringRef, bool)> sanitizerRuntimeLibExists) {
OptionSet<SanitizerKind> sanitizerSet;
// Find the sanitizer kind.
for (int i = 0, n = A->getNumValues(); i != n; ++i) {
- StringRef opt = A->getValue(i);
- if (opt == "address") {
- sanitizerSet |= SanitizerKind::Address;
- } else if (opt == "thread") {
- sanitizerSet |= SanitizerKind::Thread;
- } else if (opt == "fuzzer") {
- sanitizerSet |= SanitizerKind::Fuzzer;
- } else {
+ auto kind = llvm::StringSwitch<Optional<SanitizerKind>>(A->getValue(i))
+ .Case("address", SanitizerKind::Address)
+ .Case("thread", SanitizerKind::Thread)
+ .Case("fuzzer", SanitizerKind::Fuzzer)
+ .Default(None);
+ bool isShared = kind && *kind != SanitizerKind::Fuzzer;
+ if (!kind) {
Diags.diagnose(SourceLoc(), diag::error_unsupported_option_argument,
A->getOption().getPrefixedName(), A->getValue(i));
+ } else {
+ // Support is determined by existance of the sanitizer library.
+ bool sanitizerSupported =
+ sanitizerRuntimeLibExists(toFileName(*kind), isShared);
+
+ // TSan is explicitly not supported for 32 bits.
+ if (*kind == SanitizerKind::Thread && !Triple.isArch64Bit())
+ sanitizerSupported = false;
+
+ if (!sanitizerSupported) {
+ SmallString<128> b;
+ Diags.diagnose(SourceLoc(), diag::error_unsupported_opt_for_target,
+ (A->getOption().getPrefixedName() + toStringRef(*kind))
+ .toStringRef(b),
+ Triple.getTriple());
+ } else {
+ sanitizerSet |= *kind;
+ }
}
}
@@ -159,16 +181,5 @@
+ toStringRef(SanitizerKind::Thread)).toStringRef(b2));
}
- // Thread Sanitizer only works on OS X and the simulators. It's only supported
- // on 64 bit architectures.
- if ((sanitizerSet & SanitizerKind::Thread) &&
- !isTSanSupported(Triple, sanitizerRuntimeLibExists)) {
- SmallString<128> b;
- Diags.diagnose(SourceLoc(), diag::error_unsupported_opt_for_target,
- (A->getOption().getPrefixedName()
- + toStringRef(SanitizerKind::Thread)).toStringRef(b),
- Triple.getTriple());
- }
-
return sanitizerSet;
}
diff --git a/lib/Parse/Lexer.cpp b/lib/Parse/Lexer.cpp
index 79ba4a2..312666e 100644
--- a/lib/Parse/Lexer.cpp
+++ b/lib/Parse/Lexer.cpp
@@ -351,16 +351,19 @@
}
break; // Otherwise, eat other characters.
case 0:
- // If this is a random nul character in the middle of a buffer, skip it as
- // whitespace.
- if (CurPtr-1 != BufferEnd) {
+ switch (getNulCharacterKind(CurPtr - 1)) {
+ case NulCharacterKind::Embedded:
+ // If this is a random nul character in the middle of a buffer, skip it
+ // as whitespace.
diagnoseEmbeddedNul(Diags, CurPtr-1);
- break;
+ LLVM_FALLTHROUGH;
+ case NulCharacterKind::CodeCompletion:
+ continue;
+ case NulCharacterKind::BufferEnd:
+ // Otherwise, the last line of the file does not have a newline.
+ --CurPtr;
+ return;
}
-
- // Otherwise, the last line of the file does not have a newline.
- --CurPtr;
- return;
}
}
}
@@ -422,26 +425,30 @@
break; // Otherwise, eat other characters.
case 0:
- // If this is a random nul character in the middle of a buffer, skip it as
- // whitespace.
- if (CurPtr-1 != BufferEnd) {
- diagnoseEmbeddedNul(Diags, CurPtr-1);
- break;
+ switch (getNulCharacterKind(CurPtr - 1)) {
+ case NulCharacterKind::Embedded:
+ // If this is a random nul character in the middle of a buffer, skip it
+ // as whitespace.
+ diagnoseEmbeddedNul(Diags, CurPtr - 1);
+ LLVM_FALLTHROUGH;
+ case NulCharacterKind::CodeCompletion:
+ continue;
+ case NulCharacterKind::BufferEnd: {
+ // Otherwise, we have an unterminated /* comment.
+ --CurPtr;
+
+ // Count how many levels deep we are.
+ llvm::SmallString<8> Terminator("*/");
+ while (--Depth != 0)
+ Terminator += "*/";
+
+ const char *EOL = (CurPtr[-1] == '\n') ? (CurPtr - 1) : CurPtr;
+ diagnose(EOL, diag::lex_unterminated_block_comment)
+ .fixItInsert(getSourceLoc(EOL), Terminator);
+ diagnose(StartPtr, diag::lex_comment_start);
+ return;
}
-
- // Otherwise, we have an unterminated /* comment.
- --CurPtr;
-
- // Count how many levels deep we are.
- llvm::SmallString<8> Terminator("*/");
- while (--Depth != 0)
- Terminator += "*/";
-
- const char *EOL = (CurPtr[-1] == '\n') ? (CurPtr - 1) : CurPtr;
- diagnose(EOL, diag::lex_unterminated_block_comment)
- .fixItInsert(getSourceLoc(EOL), Terminator);
- diagnose(StartPtr, diag::lex_comment_start);
- return;
+ }
}
}
}
@@ -1857,6 +1864,16 @@
return false;
}
+Lexer::NulCharacterKind Lexer::getNulCharacterKind(const char *Ptr) const {
+ assert(Ptr != nullptr && *Ptr == 0);
+ if (Ptr == CodeCompletionPtr) {
+ return NulCharacterKind::CodeCompletion;
+ }
+ if (Ptr == BufferEnd) {
+ return NulCharacterKind::BufferEnd;
+ }
+ return NulCharacterKind::Embedded;
+}
void Lexer::tryLexEditorPlaceholder() {
assert(CurPtr[-1] == '<' && CurPtr[0] == '#');
@@ -2164,22 +2181,23 @@
return formToken(tok::unknown, TokStart);
case 0:
- if (CurPtr-1 == CodeCompletionPtr)
+ switch (getNulCharacterKind(CurPtr - 1)) {
+ case NulCharacterKind::CodeCompletion:
return formToken(tok::code_complete, TokStart);
- // If this is a random nul character in the middle of a buffer, skip it as
- // whitespace.
- if (CurPtr-1 != BufferEnd) {
+ case NulCharacterKind::Embedded:
+ // If this is a random nul character in the middle of a buffer, skip it as
+ // whitespace.
diagnoseEmbeddedNul(Diags, CurPtr-1);
goto Restart;
+ case NulCharacterKind::BufferEnd:
+ // Otherwise, this is the real end of the buffer. Put CurPtr back into
+ // buffer bounds.
+ --CurPtr;
+ // Return EOF.
+ return formToken(tok::eof, TokStart);
}
- // Otherwise, this is the real end of the buffer. Put CurPtr back into
- // buffer bounds.
- --CurPtr;
- // Return EOF.
- return formToken(tok::eof, TokStart);
-
case '@': return formToken(tok::at_sign, TokStart);
case '{': return formToken(tok::l_brace, TokStart);
case '[': {
@@ -2323,7 +2341,6 @@
Restart:
const char *TriviaStart = CurPtr;
- // TODO: Handle random nul('\0') character in the middle of a buffer.
// TODO: Handle invalid UTF8 sequence which is skipped in lexImpl().
switch (*CurPtr++) {
case '\n':
@@ -2403,6 +2420,19 @@
goto Restart;
}
break;
+ case 0:
+ switch (getNulCharacterKind(CurPtr - 1)) {
+ case NulCharacterKind::Embedded: {
+ diagnoseEmbeddedNul(Diags, CurPtr - 1);
+ size_t Length = CurPtr - TriviaStart;
+ Pieces.push_back(TriviaPiece::garbageText({TriviaStart, Length}));
+ goto Restart;
+ }
+ case NulCharacterKind::CodeCompletion:
+ case NulCharacterKind::BufferEnd:
+ break;
+ }
+ break;
default:
break;
}
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 2e8e92b..b2dcd16 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -680,19 +680,20 @@
break;
}
- case DAK_Ownership: {
+ case DAK_ReferenceOwnership: {
// Handle weak/unowned/unowned(unsafe).
- Ownership Kind = AttrName == "weak" ? Ownership::Weak : Ownership::Unowned;
+ auto Kind = AttrName == "weak" ? ReferenceOwnership::Weak
+ : ReferenceOwnership::Unowned;
SourceLoc EndLoc = Loc;
- if (Kind == Ownership::Unowned && Tok.is(tok::l_paren)) {
+ if (Kind == ReferenceOwnership::Unowned && Tok.is(tok::l_paren)) {
// Parse an optional specifier after unowned.
SourceLoc lp = consumeToken(tok::l_paren);
if (Tok.is(tok::identifier) && Tok.getText() == "safe") {
consumeToken();
} else if (Tok.is(tok::identifier) && Tok.getText() == "unsafe") {
consumeToken();
- Kind = Ownership::Unmanaged;
+ Kind = ReferenceOwnership::Unmanaged;
} else {
diagnose(Tok, diag::attr_unowned_invalid_specifier);
consumeIf(tok::identifier);
@@ -705,8 +706,8 @@
}
if (!DiscardAttribute)
- Attributes.add(new (Context) OwnershipAttr(SourceRange(Loc, EndLoc),
- Kind));
+ Attributes.add(
+ new (Context) ReferenceOwnershipAttr(SourceRange(Loc, EndLoc), Kind));
break;
}
@@ -2350,7 +2351,7 @@
Kind = DAK_AccessControl;
} else if (Tok.isContextualKeyword("weak") ||
Tok.isContextualKeyword("unowned")) {
- Kind = DAK_Ownership;
+ Kind = DAK_ReferenceOwnership;
} else if (Tok.isContextualKeyword("optional")) {
Kind = DAK_Optional;
} else if (Tok.isContextualKeyword("required")) {
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index c7ae952..65dd272 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -2498,20 +2498,21 @@
// Check for the strength specifier: "weak", "unowned", or
// "unowned(safe/unsafe)".
SourceLoc loc;
- Ownership ownershipKind = Ownership::Strong;
+ auto ownershipKind = ReferenceOwnership::Strong;
if (Tok.isContextualKeyword("weak")){
loc = consumeToken(tok::identifier);
- ownershipKind = Ownership::Weak;
+ ownershipKind = ReferenceOwnership::Weak;
} else if (Tok.isContextualKeyword("unowned")) {
loc = consumeToken(tok::identifier);
- ownershipKind = Ownership::Unowned;
+ ownershipKind = ReferenceOwnership::Unowned;
// Skip over "safe" and "unsafe" if present.
if (consumeIf(tok::l_paren)) {
if (Tok.getText() == "safe")
- ownershipKind = Ownership::Unowned; // FIXME: No "safe" variant.
+ ownershipKind =
+ ReferenceOwnership::Unowned; // FIXME: No "safe" variant.
else if (Tok.getText() == "unsafe")
- ownershipKind = Ownership::Unmanaged;
+ ownershipKind = ReferenceOwnership::Unmanaged;
else
diagnose(Tok, diag::attr_unowned_invalid_specifier);
consumeIf(tok::identifier);
@@ -2570,17 +2571,17 @@
// Create the VarDecl and the PatternBindingDecl for the captured
// expression. This uses the parent declcontext (not the closure) since
// the initializer expression is evaluated before the closure is formed.
- auto specifierKind = (ownershipKind != Ownership::Weak)
- ? VarDecl::Specifier::Let
- : VarDecl::Specifier::Var;
+ auto specifierKind = (ownershipKind != ReferenceOwnership::Weak)
+ ? VarDecl::Specifier::Let
+ : VarDecl::Specifier::Var;
auto *VD = new (Context) VarDecl(/*isStatic*/false,
specifierKind,
/*isCaptureList*/true,
nameLoc, name, Type(), CurDeclContext);
// Attributes.
- if (ownershipKind != Ownership::Strong)
- VD->getAttrs().add(new (Context) OwnershipAttr(ownershipKind));
+ if (ownershipKind != ReferenceOwnership::Strong)
+ VD->getAttrs().add(new (Context) ReferenceOwnershipAttr(ownershipKind));
auto pattern = new (Context) NamedPattern(VD, /*implicit*/true);
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 5044e91..f3c7858 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -45,6 +45,7 @@
template <typename DF>
void tokenize(const LangOptions &LangOpts, const SourceManager &SM,
unsigned BufferID, unsigned Offset, unsigned EndOffset,
+ DiagnosticEngine * Diags,
CommentRetentionMode RetainComments,
TriviaRetentionMode TriviaRetention,
bool TokenizeInterpolatedString, ArrayRef<Token> SplitTokens,
@@ -56,7 +57,7 @@
if (Offset == 0 && EndOffset == 0)
EndOffset = SM.getRangeForBuffer(BufferID).getByteLength();
- Lexer L(LangOpts, SM, BufferID, /*Diags=*/nullptr, /*InSILMode=*/false,
+ Lexer L(LangOpts, SM, BufferID, Diags, /*InSILMode=*/false,
RetainComments, TriviaRetention, Offset, EndOffset);
auto TokComp = [&](const Token &A, const Token &B) {
@@ -260,6 +261,7 @@
std::vector<Token> NewTokens = swift::tokenize(LangOpts, SM, BufID,
Offset, EndOffset,
+ /*Diags=*/nullptr,
/*KeepComments=*/true);
Toks.insert(Toks.end(), NewTokens.begin(), NewTokens.end());
@@ -278,12 +280,14 @@
std::vector<Token> swift::tokenize(const LangOptions &LangOpts,
const SourceManager &SM, unsigned BufferID,
unsigned Offset, unsigned EndOffset,
+ DiagnosticEngine *Diags,
bool KeepComments,
bool TokenizeInterpolatedString,
ArrayRef<Token> SplitTokens) {
std::vector<Token> Tokens;
tokenize(LangOpts, SM, BufferID, Offset, EndOffset,
+ Diags,
KeepComments ? CommentRetentionMode::ReturnAsTokens
: CommentRetentionMode::AttachToNextToken,
TriviaRetentionMode::WithoutTrivia, TokenizeInterpolatedString,
@@ -299,13 +303,15 @@
std::vector<std::pair<RC<syntax::RawSyntax>, syntax::AbsolutePosition>>
swift::tokenizeWithTrivia(const LangOptions &LangOpts, const SourceManager &SM,
unsigned BufferID, unsigned Offset,
- unsigned EndOffset) {
+ unsigned EndOffset,
+ DiagnosticEngine *Diags) {
std::vector<std::pair<RC<syntax::RawSyntax>, syntax::AbsolutePosition>>
Tokens;
syntax::AbsolutePosition RunningPos;
tokenize(
LangOpts, SM, BufferID, Offset, EndOffset,
+ Diags,
CommentRetentionMode::AttachToNextToken, TriviaRetentionMode::WithTrivia,
/*TokenizeInterpolatedString=*/false,
/*SplitTokens=*/ArrayRef<Token>(),
diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp
index c6cc8c2..da75cf4 100644
--- a/lib/SIL/SILFunctionType.cpp
+++ b/lib/SIL/SILFunctionType.cpp
@@ -593,36 +593,43 @@
assert(numEltTypes > 0);
- // If we don't have 'self', we don't need to do anything special.
- if (!extInfo.hasSelfParam() && !Foreign.Self.isImportAsMember()) {
- CanType ty = AnyFunctionType::composeInput(M.getASTContext(), params,
- /*canonicalVararg*/true)
- ->getCanonicalType();
+ auto handleParameter = [&](AbstractionPattern pattern,
+ ParameterTypeFlags paramFlags, CanType ty) {
CanTupleType tty = dyn_cast<TupleType>(ty);
// If the abstraction pattern is opaque, and the tuple type is
// materializable -- if it doesn't contain an l-value type -- then it's
// a valid target for substitution and we should not expand it.
- if (!tty || (origType.isTypeParameter() && !tty->hasInOutElement())) {
- auto flags = (params.size() == 1)
- ? params.front().getParameterFlags()
- : ParameterTypeFlags();
- if (flags.isShared()) {
- visitSharedType(origType, ty, extInfo.getSILRepresentation());
+ auto silExtInfo = extInfo.getSILRepresentation();
+ if (!tty || (pattern.isTypeParameter() && !tty->hasInOutElement())) {
+ if (paramFlags.isShared()) {
+ visitSharedType(pattern, ty, silExtInfo);
} else {
- visit(origType, ty);
+ visit(pattern, ty);
}
return;
}
for (auto i : indices(tty.getElementTypes())) {
- if (tty->getElement(i).getParameterFlags().isShared()) {
- visitSharedType(origType.getTupleElementType(i),
- tty.getElementType(i),
- extInfo.getSILRepresentation());
+ auto patternEltTy = pattern.getTupleElementType(i);
+ auto trueEltTy = tty.getElementType(i);
+ auto flags = tty->getElement(i).getParameterFlags();
+ if (flags.isShared()) {
+ visitSharedType(patternEltTy, trueEltTy, silExtInfo);
} else {
- visit(origType.getTupleElementType(i), tty.getElementType(i));
+ visit(patternEltTy, trueEltTy);
}
}
+ };
+
+ // If we don't have 'self', we don't need to do anything special.
+ if (!extInfo.hasSelfParam() && !Foreign.Self.isImportAsMember()) {
+ CanType ty = AnyFunctionType::composeInput(M.getASTContext(), params,
+ /*canonicalVararg*/true)
+ ->getCanonicalType();
+ auto flags = (params.size() == 1) ? params.front().getParameterFlags()
+ : ParameterTypeFlags();
+
+ handleParameter(origType, flags, ty);
return;
}
@@ -630,25 +637,11 @@
// Process all the non-self parameters.
for (unsigned i = 0; i != numNonSelfParams; ++i) {
- CanType ty = params[i].getType();
- CanTupleType tty = dyn_cast<TupleType>(ty);
+ CanType ty = params[i].getType();
AbstractionPattern eltPattern = origType.getTupleElementType(i);
- // If the abstraction pattern is opaque, and the tuple type is
- // materializable -- if it doesn't contain an l-value type -- then it's
- // a valid target for substitution and we should not expand it.
- if (!tty || (eltPattern.isTypeParameter() && !tty->hasInOutElement())) {
- if (params[i].isShared()) {
- visitSharedType(eltPattern, ty, extInfo.getSILRepresentation());
- } else {
- visit(eltPattern, ty);
- }
- continue;
- }
+ auto flags = params[i].getParameterFlags();
- assert(eltPattern.isTuple());
- for (unsigned j = 0; j < eltPattern.getNumTupleElements(); ++j) {
- visit(eltPattern.getTupleElementType(j), tty.getElementType(j));
- }
+ handleParameter(eltPattern, flags, ty);
}
// Process the self parameter. Note that we implicitly drop self
diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp
index ab86919..357f728 100644
--- a/lib/SIL/SILPrinter.cpp
+++ b/lib/SIL/SILPrinter.cpp
@@ -2634,7 +2634,7 @@
}
OS << "\n\nimport Builtin\nimport " << STDLIB_NAME
- << "\nimport SwiftShims" << "\n\n";
+ << "\nimport " << SWIFT_SHIMS_NAME << "\n\n";
// Print the declarations and types from the associated context (origin module or
// current file).
diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp
index 74ac49b..e1aa7e4 100644
--- a/lib/SILGen/SILGenLValue.cpp
+++ b/lib/SILGen/SILGenLValue.cpp
@@ -2926,12 +2926,12 @@
auto swiftStorageType = storageType.castTo<ReferenceStorageType>();
switch (swiftStorageType->getOwnership()) {
- case Ownership::Weak:
+ case ReferenceOwnership::Weak:
// Weak storage types are handled with their underlying type.
llvm_unreachable("weak pointers are always the right optional types");
- case Ownership::Strong:
+ case ReferenceOwnership::Strong:
llvm_unreachable("strong reference storage type should be impossible");
- case Ownership::Unowned: {
+ case ReferenceOwnership::Unowned: {
// For @unowned(safe) types, we need to generate a strong retain and
// strip the unowned box.
auto unownedType = storageType.castTo<UnownedStorageType>();
@@ -2940,7 +2940,7 @@
return B.createCopyUnownedValue(loc, src);
}
- case Ownership::Unmanaged: {
+ case ReferenceOwnership::Unmanaged: {
// For @unowned(unsafe) types, we need to strip the unmanaged box
// and then do an (unsafe) retain.
auto unmanagedType = storageType.castTo<UnmanagedStorageType>();
@@ -2957,16 +2957,16 @@
auto swiftStorageType = src.getType().castTo<ReferenceStorageType>();
switch (swiftStorageType->getOwnership()) {
- case Ownership::Weak:
+ case ReferenceOwnership::Weak:
// Weak storage types are handled with their underlying type.
llvm_unreachable("weak pointers are always the right optional types");
- case Ownership::Strong:
+ case ReferenceOwnership::Strong:
llvm_unreachable("strong reference storage type should be impossible");
- case Ownership::Unowned:
+ case ReferenceOwnership::Unowned:
// For @unowned(safe) types, we need to generate a strong retain and
// strip the unowned box.
return B.createCopyUnownedValue(loc, src);
- case Ownership::Unmanaged:
+ case ReferenceOwnership::Unmanaged:
// For @unowned(unsafe) types, we need to strip the unmanaged box
// and then do an (unsafe) retain.
return B.createUnsafeCopyUnownedValue(loc, src);
@@ -2985,12 +2985,12 @@
auto swiftStorageType = storageType.castTo<ReferenceStorageType>();
switch (swiftStorageType->getOwnership()) {
- case Ownership::Weak: {
+ case ReferenceOwnership::Weak: {
// For @weak types, we need to create an Optional<T>.
// Optional<T> is currently loadable, but it probably won't be forever.
return SGF.B.createLoadWeak(loc, src, isTake);
}
- case Ownership::Unowned: {
+ case ReferenceOwnership::Unowned: {
// For @unowned(safe) types, we need to strip the unowned box.
auto unownedType = storageType.castTo<UnownedStorageType>();
if (!unownedType->isLoadable(ResilienceExpansion::Maximal)) {
@@ -3012,7 +3012,7 @@
SGF.B.createDestroyValue(loc, unownedValue);
return strongValue;
}
- case Ownership::Unmanaged: {
+ case ReferenceOwnership::Unmanaged: {
// For @unowned(unsafe) types, we need to strip the unmanaged box.
auto unmanagedType = storageType.castTo<UnmanagedStorageType>();
auto value = SGF.B.createLoad(loc, src, LoadOwnershipQualifier::Trivial);
@@ -3021,7 +3021,7 @@
// SEMANTIC ARC TODO: Does this need a cleanup?
return SGF.B.createCopyValue(loc, result);
}
- case Ownership::Strong:
+ case ReferenceOwnership::Strong:
llvm_unreachable("strong reference storage type should be impossible");
}
}
@@ -3039,7 +3039,7 @@
auto swiftStorageType = storageType.castTo<ReferenceStorageType>();
switch (swiftStorageType->getOwnership()) {
- case Ownership::Weak: {
+ case ReferenceOwnership::Weak: {
// For @weak types, we need to break down an Optional<T> and then
// emit the storeWeak ourselves.
SGF.B.createStoreWeak(loc, value, dest, isInit);
@@ -3048,7 +3048,7 @@
SGF.B.emitDestroyValueOperation(loc, value);
return;
}
- case Ownership::Unowned: {
+ case ReferenceOwnership::Unowned: {
// For @unowned(safe) types, we need to enter the unowned box by
// turning the strong retain into an unowned retain.
auto unownedType = storageType.castTo<UnownedStorageType>();
@@ -3068,7 +3068,7 @@
SGF.B.emitDestroyValueOperation(loc, value);
return;
}
- case Ownership::Unmanaged: {
+ case ReferenceOwnership::Unmanaged: {
// For @unowned(unsafe) types, we need to enter the unmanaged box and
// release the strong retain.
auto unmanagedValue =
@@ -3077,7 +3077,7 @@
SGF.B.emitDestroyValueOperation(loc, value);
return;
}
- case Ownership::Strong:
+ case ReferenceOwnership::Strong:
llvm_unreachable("strong reference storage type should be impossible");
}
}
@@ -3159,11 +3159,11 @@
auto swiftStorageType = storageType.castTo<ReferenceStorageType>();
switch (swiftStorageType->getOwnership()) {
- case Ownership::Weak:
+ case ReferenceOwnership::Weak:
llvm_unreachable("weak types are never loadable");
- case Ownership::Strong:
+ case ReferenceOwnership::Strong:
llvm_unreachable("strong reference storage type should be impossible");
- case Ownership::Unowned: {
+ case ReferenceOwnership::Unowned: {
// For @unowned types, place into an unowned box.
auto unownedType = storageType.castTo<UnownedStorageType>();
assert(unownedType->isLoadable(ResilienceExpansion::Maximal));
@@ -3174,7 +3174,7 @@
B.emitDestroyValueOperation(loc, semanticValue);
return unowned;
}
- case Ownership::Unmanaged: {
+ case ReferenceOwnership::Unmanaged: {
// For @unmanaged types, place into an unmanaged box.
SILValue unmanaged =
B.createRefToUnmanaged(loc, semanticValue, storageType);
diff --git a/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp b/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp
index 37570d6..6e5c567 100644
--- a/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp
+++ b/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp
@@ -2367,9 +2367,7 @@
DT, nullptr);
DEBUG(getFunction()->viewCFG());
- }
- if (HasChanged) {
// We preserve the dominator tree. Let's invalidate everything
// else.
DA->lockInvalidation();
diff --git a/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp b/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp
index b36d7a9..7264c14 100644
--- a/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp
+++ b/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp
@@ -244,6 +244,20 @@
// capture and, for some reason, the closure is dead.
}
+// Verify that accesses are not nested before mandatory inlining.
+// Closure captures should also not be nested within an access.
+static void checkUsesOfAccess(BeginAccessInst *access) {
+#ifndef NDEBUG
+ // These conditions are only true prior to mandatory inlining.
+ assert(!access->getFunction()->wasDeserializedCanonical());
+ for (auto *use : access->getUses()) {
+ auto user = use->getUser();
+ assert(!isa<BeginAccessInst>(user));
+ assert(!isa<PartialApplyInst>(user));
+ }
+#endif
+}
+
void SelectEnforcement::analyzeProjection(ProjectBoxInst *projection) {
for (auto *use : projection->getUses()) {
auto user = use->getUser();
@@ -253,6 +267,8 @@
if (access->getEnforcement() == SILAccessEnforcement::Unknown)
Accesses.push_back(access);
+ checkUsesOfAccess(access);
+
continue;
}
if (isa<PartialApplyInst>(user))
@@ -564,16 +580,26 @@
void AccessEnforcementSelection::processFunction(SILFunction *F) {
DEBUG(llvm::dbgs() << "Access Enforcement Selection in " << F->getName()
<< "\n");
+
+ // This ModuleTransform needs to analyze closures and their parent scopes in
+ // the same pass, and the parent needs to be analyzed before the closure.
#ifndef NDEBUG
auto *CSA = getAnalysis<ClosureScopeAnalysis>();
if (isNonEscapingClosure(F->getLoweredFunctionType())) {
for (auto *scopeF : CSA->getClosureScopes(F)) {
DEBUG(llvm::dbgs() << " Parent scope: " << scopeF->getName() << "\n");
assert(visited.count(scopeF));
+ // Closures must be defined in the same module as their parent scope.
+ assert(scopeF->wasDeserializedCanonical()
+ == F->wasDeserializedCanonical());
}
}
visited.insert(F);
#endif
+ // Deserialized functions, which have been mandatory inlined, no longer meet
+ // the structural requirements on access markers required by this pass.
+ if (F->wasDeserializedCanonical())
+ return;
for (auto &bb : *F) {
for (auto ii = bb.begin(), ie = bb.end(); ii != ie;) {
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index 4ed18d5..a66963f 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -2014,8 +2014,8 @@
TVO_CanBindToInOut);
// For weak variables, use Optional<T>.
- if (auto *OA = var->getAttrs().getAttribute<OwnershipAttr>())
- if (OA->get() == Ownership::Weak) {
+ if (auto *OA = var->getAttrs().getAttribute<ReferenceOwnershipAttr>())
+ if (OA->get() == ReferenceOwnership::Weak) {
ty = CS.getTypeChecker().getOptionalType(var->getLoc(), ty);
if (!ty) return Type();
}
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index c2e6c92..0410e3e 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -189,8 +189,8 @@
void visitConsumingAttr(ConsumingAttr *attr) { visitMutationAttr(attr); }
void visitDynamicAttr(DynamicAttr *attr);
- void visitOwnershipAttr(OwnershipAttr *attr) {
- TC.checkOwnershipAttr(cast<VarDecl>(D), attr);
+ void visitReferenceOwnershipAttr(ReferenceOwnershipAttr *attr) {
+ TC.checkReferenceOwnershipAttr(cast<VarDecl>(D), attr);
}
void visitFinalAttr(FinalAttr *attr) {
@@ -821,8 +821,8 @@
IGNORED_ATTR(ObjCRuntimeName)
IGNORED_ATTR(Optional)
IGNORED_ATTR(Override)
- IGNORED_ATTR(Ownership)
IGNORED_ATTR(RawDocComment)
+ IGNORED_ATTR(ReferenceOwnership)
IGNORED_ATTR(RequiresStoredPropertyInits)
IGNORED_ATTR(RestatedObjCConformance)
IGNORED_ATTR(Semantics)
@@ -2106,11 +2106,12 @@
if (!var->hasType())
return;
- if (auto *attr = var->getAttrs().getAttribute<OwnershipAttr>())
- checkOwnershipAttr(var, attr);
+ if (auto *attr = var->getAttrs().getAttribute<ReferenceOwnershipAttr>())
+ checkReferenceOwnershipAttr(var, attr);
}
-void TypeChecker::checkOwnershipAttr(VarDecl *var, OwnershipAttr *attr) {
+void TypeChecker::checkReferenceOwnershipAttr(VarDecl *var,
+ ReferenceOwnershipAttr *attr) {
// Don't check ownership attribute if the declaration is already marked invalid.
if (var->isInvalid())
return;
@@ -2127,12 +2128,12 @@
// A weak variable must have type R? or R! for some ownership-capable type R.
Type underlyingType = type;
switch (ownershipKind) {
- case Ownership::Strong:
+ case ReferenceOwnership::Strong:
llvm_unreachable("Cannot specify 'strong' in an ownership attribute");
- case Ownership::Unowned:
- case Ownership::Unmanaged:
+ case ReferenceOwnership::Unowned:
+ case ReferenceOwnership::Unmanaged:
break;
- case Ownership::Weak:
+ case ReferenceOwnership::Weak:
if (var->isLet()) {
diagnose(var->getStartLoc(), diag::invalid_weak_let);
attr->setInvalid();
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 77b6384..d64e9a1 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -6225,13 +6225,15 @@
// If we have an explicit ownership modifier and our parent doesn't,
// complain.
- auto parentAttr = matchDecl->getAttrs().getAttribute<OwnershipAttr>();
- if (auto ownershipAttr = decl->getAttrs().getAttribute<OwnershipAttr>()) {
- Ownership parentOwnership;
+ auto parentAttr =
+ matchDecl->getAttrs().getAttribute<ReferenceOwnershipAttr>();
+ if (auto ownershipAttr =
+ decl->getAttrs().getAttribute<ReferenceOwnershipAttr>()) {
+ ReferenceOwnership parentOwnership;
if (parentAttr)
parentOwnership = parentAttr->get();
else
- parentOwnership = Ownership::Strong;
+ parentOwnership = ReferenceOwnership::Strong;
if (parentOwnership != ownershipAttr->get()) {
TC.diagnose(decl, diag::override_ownership_mismatch,
(unsigned)parentOwnership,
@@ -6505,7 +6507,7 @@
UNINTERESTING_ATTR(Prefix)
UNINTERESTING_ATTR(Postfix)
UNINTERESTING_ATTR(Infix)
- UNINTERESTING_ATTR(Ownership)
+ UNINTERESTING_ATTR(ReferenceOwnership)
UNINTERESTING_ATTR(SynthesizedProtocol)
UNINTERESTING_ATTR(RequiresStoredPropertyInits)
diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp
index 6c69d01..4bfcae2 100644
--- a/lib/Sema/TypeCheckPattern.cpp
+++ b/lib/Sema/TypeCheckPattern.cpp
@@ -1099,7 +1099,7 @@
var->setInterfaceType(type->mapTypeOutOfContext());
checkTypeModifyingDeclAttributes(var);
- if (var->getAttrs().hasAttribute<OwnershipAttr>())
+ if (var->getAttrs().hasAttribute<ReferenceOwnershipAttr>())
type = var->getType()->getReferenceStorageReferent();
else if (!var->isInvalid())
type = var->getType();
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 879d0e0..1eb9085 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -2854,10 +2854,20 @@
ParameterTypeFlags paramFlags;
if (isImmediateFunctionInput) {
- bool isShared = (tyR->getKind() == TypeReprKind::Shared);
- bool isInOut = (tyR->getKind() == TypeReprKind::InOut);
- paramFlags = ParameterTypeFlags::fromParameterType(ty, variadic, isShared)
- .withInOut(isInOut);
+ ValueOwnership ownership;
+ switch (tyR->getKind()) {
+ case TypeReprKind::Shared:
+ ownership = ValueOwnership::Shared;
+ break;
+ case TypeReprKind::InOut:
+ ownership = ValueOwnership::InOut;
+ break;
+ default:
+ ownership = ValueOwnership::Default;
+ break;
+ }
+ paramFlags =
+ ParameterTypeFlags::fromParameterType(ty, variadic, ownership);
}
elements.emplace_back(ty->getInOutObjectType(), name, paramFlags);
}
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index dd6fddf..61bd01b 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -1318,7 +1318,7 @@
void checkDeclAttributes(Decl *D);
void checkTypeModifyingDeclAttributes(VarDecl *var);
- void checkOwnershipAttr(VarDecl *D, OwnershipAttr *attr);
+ void checkReferenceOwnershipAttr(VarDecl *D, ReferenceOwnershipAttr *attr);
void computeAccessLevel(ValueDecl *D);
void computeDefaultAccessLevel(ExtensionDecl *D);
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index ba1d6ba..8d0c1db 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -2078,6 +2078,24 @@
return None;
}
+/// Translate from the serialization VarDeclSpecifier enumerators, which are
+/// guaranteed to be stable, to the AST ones.
+static Optional<swift::VarDecl::Specifier>
+getActualVarDeclSpecifier(serialization::VarDeclSpecifier raw) {
+ switch (raw) {
+#define CASE(ID) \
+ case serialization::VarDeclSpecifier::ID: \
+ return swift::VarDecl::Specifier::ID;
+ CASE(Let)
+ CASE(Var)
+ CASE(InOut)
+ CASE(Shared)
+ }
+#undef CASE
+ return None;
+}
+
+
void ModuleFile::configureStorage(AbstractStorageDecl *decl,
unsigned rawStorageKind,
serialization::DeclID getter,
@@ -2894,7 +2912,7 @@
DeclContextID contextID;
bool isImplicit, isObjC, isStatic, hasNonPatternBindingInit;
bool isGetterMutating, isSetterMutating;
- unsigned specifier;
+ unsigned rawSpecifier;
uint8_t storageKind, rawAccessLevel, rawSetterAccessLevel;
TypeID interfaceTypeID;
DeclID getterID, setterID, materializeForSetID, willSetID, didSetID;
@@ -2902,7 +2920,7 @@
ArrayRef<uint64_t> dependencyIDs;
decls_block::VarLayout::readRecord(scratch, nameID, contextID,
- isImplicit, isObjC, isStatic, specifier,
+ isImplicit, isObjC, isStatic, rawSpecifier,
hasNonPatternBindingInit,
isGetterMutating, isSetterMutating,
storageKind, interfaceTypeID,
@@ -2954,9 +2972,15 @@
if (declOrOffset.isComplete())
return declOrOffset;
- auto var = createDecl<VarDecl>(/*IsStatic*/isStatic,
- (VarDecl::Specifier)specifier,
- /*IsCaptureList*/false, SourceLoc(), name,
+ auto specifier = getActualVarDeclSpecifier(
+ (serialization::VarDeclSpecifier)rawSpecifier);
+ if (!specifier) {
+ error();
+ return nullptr;
+ }
+
+ auto var = createDecl<VarDecl>(/*IsStatic*/ isStatic, *specifier,
+ /*IsCaptureList*/ false, SourceLoc(), name,
Type(), DC);
var->setHasNonPatternBindingInit(hasNonPatternBindingInit);
var->setIsGetterMutating(isGetterMutating);
@@ -2967,7 +2991,8 @@
var->setInterfaceType(interfaceType);
if (auto referenceStorage = interfaceType->getAs<ReferenceStorageType>())
- AddAttribute(new (ctx) OwnershipAttr(referenceStorage->getOwnership()));
+ AddAttribute(
+ new (ctx) ReferenceOwnershipAttr(referenceStorage->getOwnership()));
configureStorage(var, storageKind, getterID, setterID, materializeForSetID,
addressorID, mutableAddressorID, willSetID, didSetID);
@@ -3002,18 +3027,25 @@
case decls_block::PARAM_DECL: {
IdentifierID argNameID, paramNameID;
DeclContextID contextID;
- unsigned specifier;
+ unsigned rawSpecifier;
TypeID interfaceTypeID;
decls_block::ParamLayout::readRecord(scratch, argNameID, paramNameID,
- contextID, specifier, interfaceTypeID);
+ contextID, rawSpecifier,
+ interfaceTypeID);
auto DC = ForcedContext ? *ForcedContext : getDeclContext(contextID);
if (declOrOffset.isComplete())
return declOrOffset;
- auto param = createDecl<ParamDecl>((VarDecl::Specifier)specifier,
- SourceLoc(), SourceLoc(),
+ auto specifier = getActualVarDeclSpecifier(
+ (serialization::VarDeclSpecifier)rawSpecifier);
+ if (!specifier) {
+ error();
+ return nullptr;
+ }
+
+ auto param = createDecl<ParamDecl>(*specifier, SourceLoc(), SourceLoc(),
getIdentifier(argNameID), SourceLoc(),
getIdentifier(paramNameID), Type(), DC);
@@ -3995,15 +4027,35 @@
}
}
-/// Translate from the serialization Ownership enumerators, which are
+/// Translate from the serialization ReferenceOwnership enumerators, which are
/// guaranteed to be stable, to the AST ones.
-static
-Optional<swift::Ownership> getActualOwnership(serialization::Ownership raw) {
+static Optional<swift::ReferenceOwnership>
+getActualReferenceOwnership(serialization::ReferenceOwnership raw) {
switch (raw) {
- case serialization::Ownership::Strong: return swift::Ownership::Strong;
- case serialization::Ownership::Unmanaged:return swift::Ownership::Unmanaged;
- case serialization::Ownership::Unowned: return swift::Ownership::Unowned;
- case serialization::Ownership::Weak: return swift::Ownership::Weak;
+ case serialization::ReferenceOwnership::Strong:
+ return swift::ReferenceOwnership::Strong;
+ case serialization::ReferenceOwnership::Unmanaged:
+ return swift::ReferenceOwnership::Unmanaged;
+ case serialization::ReferenceOwnership::Unowned:
+ return swift::ReferenceOwnership::Unowned;
+ case serialization::ReferenceOwnership::Weak:
+ return swift::ReferenceOwnership::Weak;
+ }
+ return None;
+}
+
+/// Translate from the serialization ValueOwnership enumerators, which are
+/// guaranteed to be stable, to the AST ones.
+static Optional<swift::ValueOwnership>
+getActualValueOwnership(serialization::ValueOwnership raw) {
+ switch (raw) {
+#define CASE(ID) \
+ case serialization::ValueOwnership::ID: \
+ return swift::ValueOwnership::ID;
+ CASE(Default)
+ CASE(InOut)
+ CASE(Shared)
+#undef CASE
}
return None;
}
@@ -4148,19 +4200,25 @@
case decls_block::PAREN_TYPE: {
TypeID underlyingID;
- bool isVariadic, isAutoClosure, isEscaping, isInOut, isShared;
+ bool isVariadic, isAutoClosure, isEscaping;
+ unsigned rawOwnership;
decls_block::ParenTypeLayout::readRecord(scratch, underlyingID, isVariadic,
isAutoClosure, isEscaping,
- isInOut, isShared);
+ rawOwnership);
+ auto ownership =
+ getActualValueOwnership((serialization::ValueOwnership)rawOwnership);
+ if (!ownership) {
+ error();
+ return nullptr;
+ }
auto underlyingTy = getTypeChecked(underlyingID);
if (!underlyingTy)
return underlyingTy.takeError();
-
+
typeOrOffset = ParenType::get(
ctx, underlyingTy.get()->getInOutObjectType(),
- ParameterTypeFlags(isVariadic, isAutoClosure, isEscaping,
- isInOut, isShared));
+ ParameterTypeFlags(isVariadic, isAutoClosure, isEscaping, *ownership));
break;
}
@@ -4180,19 +4238,27 @@
IdentifierID nameID;
TypeID typeID;
- bool isVariadic, isAutoClosure, isEscaping, isInOut, isShared;
- decls_block::TupleTypeEltLayout::readRecord(
- scratch, nameID, typeID, isVariadic, isAutoClosure, isEscaping,
- isInOut, isShared);
+ bool isVariadic, isAutoClosure, isEscaping;
+ unsigned rawOwnership;
+ decls_block::TupleTypeEltLayout::readRecord(scratch, nameID, typeID,
+ isVariadic, isAutoClosure,
+ isEscaping, rawOwnership);
+
+ auto ownership =
+ getActualValueOwnership((serialization::ValueOwnership)rawOwnership);
+ if (!ownership) {
+ error();
+ return nullptr;
+ }
auto elementTy = getTypeChecked(typeID);
if (!elementTy)
return elementTy.takeError();
-
- elements.emplace_back(
- elementTy.get()->getInOutObjectType(), getIdentifier(nameID),
- ParameterTypeFlags(isVariadic, isAutoClosure, isEscaping,
- isInOut, isShared));
+
+ elements.emplace_back(elementTy.get()->getInOutObjectType(),
+ getIdentifier(nameID),
+ ParameterTypeFlags(isVariadic, isAutoClosure,
+ isEscaping, *ownership));
}
typeOrOffset = TupleType::get(elements, ctx);
@@ -4326,8 +4392,8 @@
decls_block::ReferenceStorageTypeLayout::readRecord(scratch, rawOwnership,
objectTypeID);
- auto ownership =
- getActualOwnership((serialization::Ownership) rawOwnership);
+ auto ownership = getActualReferenceOwnership(
+ (serialization::ReferenceOwnership)rawOwnership);
if (!ownership.hasValue()) {
error();
break;
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index e805030..dfeb917 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -2169,7 +2169,7 @@
switch (DA->getKind()) {
case DAK_RawDocComment:
- case DAK_Ownership: // Serialized as part of the type.
+ case DAK_ReferenceOwnership: // Serialized as part of the type.
case DAK_AccessControl:
case DAK_SetterAccess:
case DAK_ObjCBridged:
@@ -3478,12 +3478,23 @@
/// Translate from the AST ownership enum to the Serialization enum
/// values, which are guaranteed to be stable.
-static uint8_t getRawStableOwnership(swift::Ownership ownership) {
+static uint8_t
+getRawStableReferenceOwnership(swift::ReferenceOwnership ownership) {
switch (ownership) {
- SIMPLE_CASE(Ownership, Strong)
- SIMPLE_CASE(Ownership, Weak)
- SIMPLE_CASE(Ownership, Unowned)
- SIMPLE_CASE(Ownership, Unmanaged)
+ SIMPLE_CASE(ReferenceOwnership, Strong)
+ SIMPLE_CASE(ReferenceOwnership, Weak)
+ SIMPLE_CASE(ReferenceOwnership, Unowned)
+ SIMPLE_CASE(ReferenceOwnership, Unmanaged)
+ }
+ llvm_unreachable("bad ownership kind");
+}
+/// Translate from the AST ownership enum to the Serialization enum
+/// values, which are guaranteed to be stable.
+static uint8_t getRawStableValueOwnership(swift::ValueOwnership ownership) {
+ switch (ownership) {
+ SIMPLE_CASE(ValueOwnership, Default)
+ SIMPLE_CASE(ValueOwnership, InOut)
+ SIMPLE_CASE(ValueOwnership, Shared)
}
llvm_unreachable("bad ownership kind");
}
@@ -3589,12 +3600,14 @@
case TypeKind::Paren: {
auto parenTy = cast<ParenType>(ty.getPointer());
auto paramFlags = parenTy->getParameterFlags();
+ auto rawOwnership =
+ getRawStableValueOwnership(paramFlags.getValueOwnership());
unsigned abbrCode = DeclTypeAbbrCodes[ParenTypeLayout::Code];
ParenTypeLayout::emitRecord(
Out, ScratchRecord, abbrCode, addTypeRef(parenTy->getUnderlyingType()),
paramFlags.isVariadic(), paramFlags.isAutoClosure(),
- paramFlags.isEscaping(), paramFlags.isInOut(), paramFlags.isShared());
+ paramFlags.isEscaping(), rawOwnership);
break;
}
@@ -3607,11 +3620,12 @@
abbrCode = DeclTypeAbbrCodes[TupleTypeEltLayout::Code];
for (auto &elt : tupleTy->getElements()) {
auto paramFlags = elt.getParameterFlags();
+ auto rawOwnership =
+ getRawStableValueOwnership(paramFlags.getValueOwnership());
TupleTypeEltLayout::emitRecord(
Out, ScratchRecord, abbrCode, addDeclBaseNameRef(elt.getName()),
addTypeRef(elt.getType()), paramFlags.isVariadic(),
- paramFlags.isAutoClosure(), paramFlags.isEscaping(),
- paramFlags.isInOut(), paramFlags.isShared());
+ paramFlags.isAutoClosure(), paramFlags.isEscaping(), rawOwnership);
}
break;
@@ -3890,7 +3904,8 @@
auto refTy = cast<ReferenceStorageType>(ty.getPointer());
unsigned abbrCode = DeclTypeAbbrCodes[ReferenceStorageTypeLayout::Code];
- auto stableOwnership = getRawStableOwnership(refTy->getOwnership());
+ auto stableOwnership =
+ getRawStableReferenceOwnership(refTy->getOwnership());
ReferenceStorageTypeLayout::emitRecord(Out, ScratchRecord, abbrCode,
stableOwnership,
addTypeRef(refTy->getReferentType()));
diff --git a/stdlib/public/SwiftRemoteMirror/CMakeLists.txt b/stdlib/public/SwiftRemoteMirror/CMakeLists.txt
index bacdf0d..93255e9 100644
--- a/stdlib/public/SwiftRemoteMirror/CMakeLists.txt
+++ b/stdlib/public/SwiftRemoteMirror/CMakeLists.txt
@@ -4,10 +4,15 @@
# 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)
- add_swift_library(swiftRemoteMirror SHARED TARGET_LIBRARY DONT_EMBED_BITCODE NOSWIFTRT
- SwiftRemoteMirror.cpp
- LINK_LIBRARIES swiftReflection
- C_COMPILE_FLAGS ${SWIFT_RUNTIME_CXX_FLAGS}
- LINK_FLAGS ${SWIFT_RUNTIME_LINK_FLAGS}
- INSTALL_IN_COMPONENT swift-remote-mirror)
+ add_swift_library(swiftRemoteMirror
+ SHARED TARGET_LIBRARY DONT_EMBED_BITCODE NOSWIFTRT
+ SwiftRemoteMirror.cpp
+ LINK_LIBRARIES
+ swiftReflection
+ C_COMPILE_FLAGS
+ ${SWIFT_RUNTIME_CXX_FLAGS} -DswiftRemoteMirror_EXPORTS
+ LINK_FLAGS
+ ${SWIFT_RUNTIME_LINK_FLAGS}
+ INSTALL_IN_COMPONENT
+ swift-remote-mirror)
endif()
diff --git a/stdlib/public/core/Integers.swift.gyb b/stdlib/public/core/Integers.swift.gyb
index 4f69a62..76bc9ca 100644
--- a/stdlib/public/core/Integers.swift.gyb
+++ b/stdlib/public/core/Integers.swift.gyb
@@ -884,8 +884,8 @@
# operator:
# + unsafeAdding(_:)
# - unsafeSubtracting(_:)
-# * unsafeMultiplying(_:)
-# / unsafeDividing(by:)
+# * unsafeMultiplied(by:)
+# / unsafeDivided(by:)
def unsafeOperationComment(operator):
comments = {
'+': """\
diff --git a/stdlib/public/core/RangeReplaceableCollection.swift b/stdlib/public/core/RangeReplaceableCollection.swift
index 8e35596..5b42713 100644
--- a/stdlib/public/core/RangeReplaceableCollection.swift
+++ b/stdlib/public/core/RangeReplaceableCollection.swift
@@ -832,6 +832,7 @@
public mutating func removeLast() -> Element {
_precondition(!isEmpty, "Can't remove last element from an empty collection")
// NOTE if you change this implementation, change popLast above as well
+ // AND change the tie-breaker implementations in the next extension
if let result = _customRemoveLast() { return result }
return remove(at: index(before: endIndex))
}
@@ -865,10 +866,27 @@
}
}
-// FIXME: swift-3-indexing-model: file a bug for the compiler?
/// Ambiguity breakers.
extension RangeReplaceableCollection
- where Self : BidirectionalCollection, SubSequence == Self {
+where Self : BidirectionalCollection, SubSequence == Self {
+ /// Removes and returns the last element of the collection.
+ ///
+ /// Calling this method may invalidate all saved indices of this
+ /// collection. Do not rely on a previously stored index value after
+ /// altering a collection with any operation that can change its length.
+ ///
+ /// - Returns: The last element of the collection if the collection is not
+ /// empty; otherwise, `nil`.
+ ///
+ /// - Complexity: O(1)
+ @_inlineable
+ public mutating func popLast() -> Element? {
+ if isEmpty { return nil }
+ // duplicate of removeLast logic below, to avoid redundant precondition
+ if let result = _customRemoveLast() { return result }
+ return remove(at: index(before: endIndex))
+ }
+
/// Removes and returns the last element of the collection.
///
/// The collection must not be empty.
@@ -884,9 +902,8 @@
@discardableResult
public mutating func removeLast() -> Element {
_precondition(!isEmpty, "Can't remove last element from an empty collection")
- if let result = _customRemoveLast() {
- return result
- }
+ // NOTE if you change this implementation, change popLast above as well
+ if let result = _customRemoveLast() { return result }
return remove(at: index(before: endIndex))
}
diff --git a/stdlib/public/runtime/Casting.cpp b/stdlib/public/runtime/Casting.cpp
index c551c89..a023d4a 100644
--- a/stdlib/public/runtime/Casting.cpp
+++ b/stdlib/public/runtime/Casting.cpp
@@ -75,7 +75,7 @@
auto classType = static_cast<const ClassMetadata *>(type);
// Look through artificial subclasses.
while (classType->isTypeMetadata() && classType->isArtificialSubclass())
- classType = classType->SuperClass;
+ classType = classType->Superclass;
// Ask the Objective-C runtime to name ObjC classes.
if (!classType->isTypeMetadata()) {
@@ -262,7 +262,7 @@
if (sourceType == targetType) {
return sourceType;
}
- sourceType = sourceType->SuperClass;
+ sourceType = sourceType->Superclass;
} while (sourceType);
return nullptr;
@@ -3228,7 +3228,7 @@
const Metadata *swift::_swift_class_getSuperclass(const Metadata *theClass) {
if (const ClassMetadata *classType = theClass->getClassObject())
if (classHasSuperclass(classType))
- return getMetadataForClass(classType->SuperClass);
+ return getMetadataForClass(classType->Superclass);
return nullptr;
}
diff --git a/stdlib/public/runtime/Demangle.cpp b/stdlib/public/runtime/Demangle.cpp
index 0cf3b33..af0d7fe 100644
--- a/stdlib/public/runtime/Demangle.cpp
+++ b/stdlib/public/runtime/Demangle.cpp
@@ -263,7 +263,7 @@
#if SWIFT_OBJC_INTEROP
// Peek through artificial subclasses.
while (classType->isTypeMetadata() && classType->isArtificialSubclass())
- classType = classType->SuperClass;
+ classType = classType->Superclass;
#endif
description = classType->getDescription();
break;
diff --git a/stdlib/public/runtime/ErrorObjectNative.cpp b/stdlib/public/runtime/ErrorObjectNative.cpp
index 7d8ef2d..1b1a8ae 100644
--- a/stdlib/public/runtime/ErrorObjectNative.cpp
+++ b/stdlib/public/runtime/ErrorObjectNative.cpp
@@ -61,7 +61,7 @@
/// Heap metadata for Error boxes.
static const FullMetadata<HeapMetadata> ErrorMetadata{
HeapMetadataHeader{{_destroyErrorObject}, {&VALUE_WITNESS_SYM(Bo)}},
- Metadata{MetadataKind::ErrorObject},
+ HeapMetadata(MetadataKind::ErrorObject),
};
BoxPair
diff --git a/stdlib/public/runtime/HeapObject.cpp b/stdlib/public/runtime/HeapObject.cpp
index 6fa1417..c4a78d2 100644
--- a/stdlib/public/runtime/HeapObject.cpp
+++ b/stdlib/public/runtime/HeapObject.cpp
@@ -658,10 +658,10 @@
}
#endif
- if (auto fn = classMetadata->getIVarDestroyer())
- fn(object);
+ if (classMetadata->IVarDestroyer)
+ classMetadata->IVarDestroyer(object);
- classMetadata = classMetadata->SuperClass->getClassObject();
+ classMetadata = classMetadata->Superclass->getClassObject();
assert(classMetadata && "Given metatype not a superclass of object type?");
}
@@ -671,7 +671,7 @@
if (!usesNativeSwiftReferenceCounting(classMetadata)) {
// Find the pure Objective-C superclass.
while (!classMetadata->isPureObjC())
- classMetadata = classMetadata->SuperClass->getClassObject();
+ classMetadata = classMetadata->Superclass->getClassObject();
// Set the class to the pure Objective-C superclass, so that when dealloc
// runs, it starts at that superclass.
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index cb874d8..049e67f 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -74,6 +74,92 @@
static const size_t ValueTypeMetadataAddressPoint = sizeof(TypeMetadataHeader);
+static ClassMetadataBounds
+computeMetadataBoundsForSuperclass(const void *ref,
+ TypeMetadataRecordKind refKind) {
+ switch (refKind) {
+ case TypeMetadataRecordKind::IndirectNominalTypeDescriptor: {
+ auto description = *reinterpret_cast<const ClassDescriptor * const *>(ref);
+ if (!description) {
+ swift::fatalError(0, "instantiating class metadata for class with "
+ "missing weak-linked ancestor");
+ }
+ return description->getMetadataBounds();
+ }
+
+ case TypeMetadataRecordKind::DirectNominalTypeDescriptor: {
+ auto description = reinterpret_cast<const ClassDescriptor *>(ref);
+ return description->getMetadataBounds();
+ }
+
+ case TypeMetadataRecordKind::IndirectObjCClass:
+#if SWIFT_OBJC_INTEROP
+ {
+ auto cls = *reinterpret_cast<const Class *>(ref);
+ cls = swift_getInitializedObjCClass(cls);
+ auto metadata = reinterpret_cast<const ClassMetadata *>(cls);
+ return metadata->getClassBoundsAsSwiftSuperclass();
+ }
+#else
+ // fallthrough
+#endif
+
+ case TypeMetadataRecordKind::Reserved:
+ break;
+ }
+ swift_runtime_unreachable("unsupported superclass reference kind");
+}
+
+static ClassMetadataBounds computeMetadataBoundsFromSuperclass(
+ const ClassDescriptor *description,
+ StoredClassMetadataBounds &storedBounds) {
+ ClassMetadataBounds bounds;
+
+ // Compute the bounds for the superclass, extending it to the minimum
+ // bounds of a Swift class.
+ if (const void *superRef = description->Superclass.get()) {
+ bounds = computeMetadataBoundsForSuperclass(superRef,
+ description->getSuperclassReferenceKind());
+ } else {
+ bounds = ClassMetadataBounds::forSwiftRootClass();
+ }
+
+ // Add the subclass's immediate members.
+ bounds.adjustForSubclass(description->areImmediateMembersNegative(),
+ description->NumImmediateMembers);
+
+ // Cache before returning.
+ storedBounds.initialize(bounds);
+ return bounds;
+}
+
+ClassMetadataBounds
+swift::getResilientMetadataBounds(const ClassDescriptor *description) {
+ assert(description->hasResilientSuperclass());
+ auto &storedBounds = *description->ResilientMetadataBounds.get();
+
+ ClassMetadataBounds bounds;
+ if (storedBounds.tryGet(bounds)) {
+ return bounds;
+ }
+
+ return computeMetadataBoundsFromSuperclass(description, storedBounds);
+}
+
+int32_t
+swift::getResilientImmediateMembersOffset(const ClassDescriptor *description) {
+ assert(description->hasResilientSuperclass());
+ auto &storedBounds = *description->ResilientMetadataBounds.get();
+
+ ptrdiff_t result;
+ if (storedBounds.tryGetImmediateMembersOffset(result)) {
+ return result / sizeof(void*);
+ }
+
+ auto bounds = computeMetadataBoundsFromSuperclass(description, storedBounds);
+ return bounds.ImmediateMembersOffset / sizeof(void*);
+}
+
namespace {
struct GenericCacheEntry;
@@ -94,9 +180,7 @@
size_t getNumArguments() const { return NumArguments; }
- static GenericCacheEntry *getFromMetadata(
- const TypeGenericContextDescriptorHeader &generics,
- Metadata *metadata) {
+ static GenericCacheEntry *getFromMetadata(Metadata *metadata) {
char *bytes = (char*) metadata;
if (auto classType = dyn_cast<ClassMetadata>(metadata)) {
assert(classType->isTypeMetadata());
@@ -142,65 +226,148 @@
return lazyCache->unsafeGetAlreadyInitialized();
}
+#if SWIFT_OBJC_INTEROP
+extern "C" void *_objc_empty_cache;
+#endif
+
+static void
+initializeClassMetadataFromPattern(ClassMetadata *metadata,
+ ClassMetadataBounds bounds,
+ const ClassDescriptor *description,
+ const GenericClassMetadataPattern *pattern) {
+ auto fullMetadata = asFullMetadata(metadata);
+ char *rawMetadata = reinterpret_cast<char*>(metadata);
+
+ // Install the extra-data pattern.
+ void **metadataExtraData =
+ reinterpret_cast<void**>(rawMetadata) + bounds.PositiveSizeInWords;
+ memcpy(metadataExtraData, pattern->getExtraDataPattern(),
+ size_t(pattern->NumExtraDataWords) * sizeof(void*));
+
+ // Install the immediate members pattern:
+ void **immediateMembers =
+ reinterpret_cast<void**>(rawMetadata + bounds.ImmediateMembersOffset);
+
+ // Zero out the entire immediate-members section.
+ // TODO: only memset the parts that aren't covered by the pattern.
+ memset(immediateMembers, 0, description->getImmediateMembersSize());
+
+ // Copy the immediate-members pattern.
+ if (auto immediateSize = pattern->ImmediateMembersPattern_Size) {
+ memcpy(immediateMembers + pattern->ImmediateMembersPattern_TargetOffset,
+ pattern->getImmediateMembersPattern(),
+ size_t(immediateSize) * sizeof(void*));
+ }
+
+ // Initialize the header:
+
+ // Heap destructor.
+ fullMetadata->destroy = pattern->Destroy;
+
+ // Value witness table.
+#if SWIFT_OBJC_INTEROP
+ fullMetadata->ValueWitnesses =
+ (pattern->Flags & ClassFlags::UsesSwiftRefcounting)
+ ? &VALUE_WITNESS_SYM(Bo)
+ : &VALUE_WITNESS_SYM(BO);
+#else
+ fullMetadata->ValueWitnesses = &VALUE_WITNESS_SYM(Bo);
+#endif
+
+#if SWIFT_OBJC_INTEROP
+ // Install the metaclass's RO-data pointer.
+ auto metaclass = reinterpret_cast<AnyClassMetadata *>(
+ metadataExtraData + pattern->MetaclassObjectOffset);
+ auto metaclassRO = metadataExtraData + pattern->MetaclassRODataOffset;
+ metaclass->Data = reinterpret_cast<uintptr_t>(metaclassRO);
+#endif
+
+ // MetadataKind / isa.
+#if SWIFT_OBJC_INTEROP
+ metadata->setClassISA(metaclass);
+#else
+ metadata->setKind(MetadataKind::Class);
+#endif
+
+ // Superclass.
+ metadata->Superclass = nullptr;
+#if SWIFT_OBJC_INTEROP
+ // If the class doesn't have a formal superclass, automatically set
+ // it to SwiftObject.
+ if (!description->hasSuperclass()) {
+ metadata->Superclass = getRootSuperclass();
+ }
+#endif
+
+#if SWIFT_OBJC_INTEROP
+ // Cache data. Install the same initializer that the compiler is
+ // required to use. We don't need to do this in non-ObjC-interop modes.
+ metadata->CacheData[0] = &_objc_empty_cache;
+ metadata->CacheData[1] = nullptr;
+#endif
+
+ // RO-data pointer.
+#if SWIFT_OBJC_INTEROP
+ auto classRO = metadataExtraData + pattern->ClassRODataOffset;
+ metadata->Data =
+ reinterpret_cast<uintptr_t>(classRO) | SWIFT_CLASS_IS_SWIFT_MASK;
+#else
+ metadata->Data = SWIFT_CLASS_IS_SWIFT_MASK;
+#endif
+
+ // Class flags.
+ metadata->Flags = pattern->Flags;
+
+ // Instance layout.
+ metadata->InstanceAddressPoint = 0;
+ metadata->InstanceSize = 0;
+ metadata->InstanceAlignMask = 0;
+
+ // Reserved.
+ metadata->Reserved = 0;
+
+ // Class metadata layout.
+ metadata->ClassSize = bounds.getTotalSizeInBytes();
+ metadata->ClassAddressPoint = bounds.getAddressPointInBytes();
+
+ // Class descriptor.
+ metadata->setDescription(description);
+
+ // I-var destroyer.
+ metadata->IVarDestroyer = pattern->IVarDestroyer;
+}
+
ClassMetadata *
swift::swift_allocateGenericClassMetadata(const ClassDescriptor *description,
- const void *metadataTemplate,
- size_t templateSize,
- size_t templateAddressPoint,
const void *arguments,
- ClassMetadata *superclass,
- size_t numImmediateMembers) {
+ const GenericClassMetadataPattern *pattern){
void * const *argumentsAsArray = reinterpret_cast<void * const *>(arguments);
auto &generics = description->getFullGenericContextHeader();
+ auto &cache = unsafeGetInitializedCache(generics);
+
size_t numGenericArguments = generics.Base.NumKeyArguments;
- size_t metadataSize;
- if (superclass && superclass->isTypeMetadata()) {
- assert(superclass->getClassAddressPoint() <= templateAddressPoint);
+ // Compute the formal bounds of the metadata.
+ auto bounds = description->getMetadataBounds();
- metadataSize = (superclass->getClassSize() -
- superclass->getClassAddressPoint() +
- templateAddressPoint +
- numImmediateMembers * sizeof(void *));
- assert(templateSize <= metadataSize);
- } else {
- metadataSize = (templateSize +
- numImmediateMembers * sizeof(void *));
- }
+ // Augment that with any required extra data from the pattern.
+ auto allocationBounds = bounds;
+ allocationBounds.PositiveSizeInWords += pattern->NumExtraDataWords;
- auto &cache = unsafeGetInitializedCache(generics);
- char *bytes = GenericCacheEntry::allocate(cache.getAllocator(),
- argumentsAsArray,
- numGenericArguments,
- metadataSize)->getData<char>();
+ auto entry = GenericCacheEntry::allocate(cache.getAllocator(),
+ argumentsAsArray,
+ numGenericArguments,
+ allocationBounds.getTotalSizeInBytes());
- // Copy in the metadata template.
- memcpy(bytes, metadataTemplate, templateSize);
+ auto bytes = entry->getData<char>();
+ auto addressPoint = bytes + allocationBounds.getAddressPointInBytes();
+ auto metadata = reinterpret_cast<ClassMetadata *>(addressPoint);
- // Zero out the rest of the metadata.
- memset(bytes + templateSize, 0, metadataSize - templateSize);
+ initializeClassMetadataFromPattern(metadata, bounds, description, pattern);
- // Okay, move to the address point.
- ClassMetadata *metadata =
- reinterpret_cast<ClassMetadata *>(bytes + templateAddressPoint);
- auto patternBytes =
- reinterpret_cast<const char*>(metadataTemplate) +
- templateAddressPoint;
- auto patternMetadata = reinterpret_cast<const ClassMetadata*>(patternBytes);
+ assert(GenericCacheEntry::getFromMetadata(metadata) == entry);
assert(metadata->isTypeMetadata());
- // Overwrite the superclass field.
- metadata->SuperClass = superclass;
- // Adjust the relative reference to the nominal type descriptor.
- if (!metadata->isArtificialSubclass()) {
- metadata->setDescription(patternMetadata->getDescription());
- }
-
- // The pattern might have private prefix matter prior to the start
- // of metadata.
- assert(metadata->getClassAddressPoint() <= templateAddressPoint);
- metadata->setClassSize(metadataSize);
-
return metadata;
}
@@ -241,7 +408,7 @@
[&]() -> GenericCacheEntry* {
// Create new metadata to cache.
auto metadata = generics.InstantiationFunction(description, arguments);
- auto entry = GenericCacheEntry::getFromMetadata(generics, metadata);
+ auto entry = GenericCacheEntry::getFromMetadata(metadata);
entry->Value = metadata;
return entry;
});
@@ -1475,7 +1642,7 @@
_swift_initGenericClassObjCName(theClass);
#endif
- const ClassMetadata *theSuperclass = theClass->SuperClass;
+ const ClassMetadata *theSuperclass = theClass->Superclass;
// Copy the class's immediate methods from the nominal type descriptor
// to the class metadata.
@@ -1509,8 +1676,8 @@
// Copy the generic requirements.
if (description->isGeneric()
&& description->getGenericContextHeader().hasArguments()) {
- memcpy(classWords + description->getGenericArgumentOffset(ancestor),
- superWords + description->getGenericArgumentOffset(ancestor),
+ memcpy(classWords + description->getGenericArgumentOffset(),
+ superWords + description->getGenericArgumentOffset(),
description->getGenericContextHeader().getNumArguments() *
sizeof(uintptr_t));
}
@@ -1531,7 +1698,7 @@
superWords + fieldOffsetVector,
description->NumFields * sizeof(uintptr_t));
}
- ancestor = ancestor->SuperClass;
+ ancestor = ancestor->Superclass;
}
#if SWIFT_OBJC_INTEROP
@@ -1540,7 +1707,7 @@
auto theMetaclass = (ClassMetadata *)object_getClass((id)theClass);
auto theSuperMetaclass
= (const ClassMetadata *)object_getClass(id_const_cast(theSuperclass));
- theMetaclass->SuperClass = theSuperMetaclass;
+ theMetaclass->Superclass = theSuperMetaclass;
#endif
}
@@ -1556,7 +1723,10 @@
swift::swift_relocateClassMetadata(ClassMetadata *self,
size_t templateSize,
size_t numImmediateMembers) {
- const ClassMetadata *superclass = self->SuperClass;
+ // Force the initialization of the metadata layout.
+ (void) self->getDescription()->getMetadataBounds();
+
+ const ClassMetadata *superclass = self->Superclass;
size_t metadataSize;
if (superclass && superclass->isTypeMetadata()) {
@@ -1608,7 +1778,7 @@
// If we have a superclass, start from its size and alignment instead.
if (classHasSuperclass(self)) {
- const ClassMetadata *super = self->SuperClass;
+ const ClassMetadata *super = self->Superclass;
// This is straightforward if the superclass is Swift.
#if SWIFT_OBJC_INTEROP
diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp
index 273877b..9233234 100644
--- a/stdlib/public/runtime/MetadataLookup.cpp
+++ b/stdlib/public/runtime/MetadataLookup.cpp
@@ -657,7 +657,7 @@
LookupDependentMemberFn lookupDependentMember;
/// Ownership information related to the metadata we are trying to lookup.
- TypeOwnership Ownership;
+ TypeReferenceOwnership ReferenceOwnership;
public:
DecodedMetadataBuilder(Demangler &demangler,
@@ -940,17 +940,17 @@
}
BuiltType createUnownedStorageType(BuiltType base) {
- Ownership.setUnowned();
+ ReferenceOwnership.setUnowned();
return base;
}
BuiltType createUnmanagedStorageType(BuiltType base) {
- Ownership.setUnmanaged();
+ ReferenceOwnership.setUnmanaged();
return base;
}
BuiltType createWeakStorageType(BuiltType base) {
- Ownership.setWeak();
+ ReferenceOwnership.setWeak();
return base;
}
@@ -959,7 +959,9 @@
return BuiltType();
}
- TypeOwnership getOwnership() const { return Ownership; }
+ TypeReferenceOwnership getReferenceOwnership() const {
+ return ReferenceOwnership;
+ }
};
}
@@ -1020,7 +1022,7 @@
});
auto type = Demangle::decodeMangledType(builder, node);
- return {type, builder.getOwnership()};
+ return {type, builder.getReferenceOwnership()};
}
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
diff --git a/stdlib/public/runtime/Private.h b/stdlib/public/runtime/Private.h
index 6582683..a6b4995 100644
--- a/stdlib/public/runtime/Private.h
+++ b/stdlib/public/runtime/Private.h
@@ -29,7 +29,7 @@
namespace swift {
-class TypeOwnership {
+class TypeReferenceOwnership {
enum : uint8_t {
Weak = 1 << 0,
Unowned = 1 << 1,
@@ -38,10 +38,10 @@
uint8_t Data;
- constexpr TypeOwnership(uint8_t Data) : Data(Data) {}
+ constexpr TypeReferenceOwnership(uint8_t Data) : Data(Data) {}
public:
- constexpr TypeOwnership() : Data(0) {}
+ constexpr TypeReferenceOwnership() : Data(0) {}
bool isWeak() const { return Data & Weak; }
bool isUnowned() const { return Data & Unowned; }
@@ -60,19 +60,19 @@
/// itself related info has to be bundled with it.
class TypeInfo {
const Metadata *Type;
- const TypeOwnership Ownership;
+ const TypeReferenceOwnership ReferenceOwnership;
public:
- TypeInfo() : Type(nullptr), Ownership() {}
+ TypeInfo() : Type(nullptr), ReferenceOwnership() {}
- TypeInfo(const Metadata *type, TypeOwnership ownership)
- : Type(type), Ownership(ownership) {}
+ TypeInfo(const Metadata *type, TypeReferenceOwnership ownership)
+ : Type(type), ReferenceOwnership(ownership) {}
operator const Metadata *() { return Type; }
- bool isWeak() const { return Ownership.isWeak(); }
- bool isUnowned() const { return Ownership.isUnowned(); }
- bool isUnmanaged() const { return Ownership.isUnmanaged(); }
+ bool isWeak() const { return ReferenceOwnership.isWeak(); }
+ bool isUnowned() const { return ReferenceOwnership.isUnowned(); }
+ bool isUnmanaged() const { return ReferenceOwnership.isUnmanaged(); }
};
#if SWIFT_HAS_ISA_MASKING
@@ -190,7 +190,7 @@
/// Check if a class has a formal superclass in the AST.
static inline
bool classHasSuperclass(const ClassMetadata *c) {
- return (c->SuperClass && c->SuperClass != getRootSuperclass());
+ return (c->Superclass && c->Superclass != getRootSuperclass());
}
/// Replace entries of a freshly-instantiated value witness table with more
diff --git a/stdlib/public/runtime/ProtocolConformance.cpp b/stdlib/public/runtime/ProtocolConformance.cpp
index 80b1bd3..fcca5c5 100644
--- a/stdlib/public/runtime/ProtocolConformance.cpp
+++ b/stdlib/public/runtime/ProtocolConformance.cpp
@@ -470,7 +470,7 @@
// If the type is a class, try its superclass.
if (const ClassMetadata *classType = type->getClassObject()) {
if (classHasSuperclass(classType)) {
- type = getMetadataForClass(classType->SuperClass);
+ type = getMetadataForClass(classType->Superclass);
goto recur;
}
}
@@ -513,7 +513,7 @@
// If the type is a class, try its superclass.
if (const ClassMetadata *classType = type->getClassObject()) {
if (classHasSuperclass(classType)) {
- type = getMetadataForClass(classType->SuperClass);
+ type = getMetadataForClass(classType->Superclass);
continue;
}
}
diff --git a/stdlib/public/runtime/ReflectionMirror.mm b/stdlib/public/runtime/ReflectionMirror.mm
index 2781eb3..7280fdf 100644
--- a/stdlib/public/runtime/ReflectionMirror.mm
+++ b/stdlib/public/runtime/ReflectionMirror.mm
@@ -563,7 +563,7 @@
// Look through artificial subclasses.
while (isa->isTypeMetadata() && isa->isArtificialSubclass()) {
- isa = isa->SuperClass;
+ isa = isa->Superclass;
}
passedType = isa;
}
diff --git a/stdlib/public/runtime/SwiftObject.mm b/stdlib/public/runtime/SwiftObject.mm
index 6b1494d..a7d2f72 100644
--- a/stdlib/public/runtime/SwiftObject.mm
+++ b/stdlib/public/runtime/SwiftObject.mm
@@ -112,7 +112,7 @@
while (classAsMetadata && classAsMetadata->isTypeMetadata()) {
if (!classAsMetadata->isArtificialSubclass())
return classAsMetadata;
- classAsMetadata = classAsMetadata->SuperClass;
+ classAsMetadata = classAsMetadata->Superclass;
}
id objcObject = reinterpret_cast<id>(object);
@@ -195,10 +195,10 @@
return _swift_getObjCClassOfAllocated(self);
}
+ (Class)superclass {
- return (Class)((const ClassMetadata*) self)->SuperClass;
+ return (Class)((const ClassMetadata*) self)->Superclass;
}
- (Class)superclass {
- return (Class)_swift_getClassOfAllocated(self)->SuperClass;
+ return (Class)_swift_getClassOfAllocated(self)->Superclass;
}
+ (BOOL)isMemberOfClass:(Class)cls {
@@ -289,7 +289,7 @@
- (BOOL)isKindOfClass:(Class)someClass {
for (auto cls = _swift_getClassOfAllocated(self); cls != nullptr;
- cls = cls->SuperClass)
+ cls = cls->Superclass)
if (cls == (const ClassMetadata*) someClass)
return YES;
@@ -298,7 +298,7 @@
+ (BOOL)isSubclassOfClass:(Class)someClass {
for (auto cls = (const ClassMetadata*) self; cls != nullptr;
- cls = cls->SuperClass)
+ cls = cls->Superclass)
if (cls == (const ClassMetadata*) someClass)
return YES;
diff --git a/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.asan_ios_dynamic.dylib b/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.asan_ios_dynamic.dylib
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.asan_ios_dynamic.dylib
diff --git a/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.asan_iossim_dynamic.dylib b/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.asan_iossim_dynamic.dylib
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.asan_iossim_dynamic.dylib
diff --git a/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.asan_tvos_dynamic.dylib b/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.asan_tvos_dynamic.dylib
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.asan_tvos_dynamic.dylib
diff --git a/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.asan_tvossim_dynamic.dylib b/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.asan_tvossim_dynamic.dylib
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.asan_tvossim_dynamic.dylib
diff --git a/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.asan_watchos_dynamic.dylib b/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.asan_watchos_dynamic.dylib
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.asan_watchos_dynamic.dylib
diff --git a/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.asan_watchossim_dynamic.dylib b/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.asan_watchossim_dynamic.dylib
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.asan_watchossim_dynamic.dylib
diff --git a/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.fuzzer_osx.a b/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.fuzzer_osx.a
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/darwin/libclang_rt.fuzzer_osx.a
diff --git a/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/linux/libclang_rt.fuzzer-x86_64.a b/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/linux/libclang_rt.fuzzer-x86_64.a
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/Driver/Inputs/fake-resource-dir/lib/swift/clang/lib/linux/libclang_rt.fuzzer-x86_64.a
diff --git a/test/Driver/batch_mode_parseable_output.swift b/test/Driver/batch_mode_parseable_output.swift
new file mode 100644
index 0000000..9930968
--- /dev/null
+++ b/test/Driver/batch_mode_parseable_output.swift
@@ -0,0 +1,125 @@
+// RUN: %empty-directory(%t)
+// RUN: touch %t/file-01.swift %t/file-02.swift %t/file-03.swift
+// RUN: echo 'public func main() {}' >%t/main.swift
+//
+// RUN: %swiftc_driver -enable-batch-mode -parseable-output -c -emit-module -module-name main -j 2 %t/file-01.swift %t/file-02.swift %t/file-03.swift %t/main.swift 2>&1 | %FileCheck %s
+//
+//
+// CHECK: {{[1-9][0-9]*}}
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "began",
+// CHECK-NEXT: "name": "compile",
+// CHECK-NEXT: "command": "{{.*}}/swift{{c?}} -frontend -c -primary-file {{.*}}/file-01.swift -primary-file {{.*}}/file-02.swift {{.*}}/file-03.swift {{.*}}/main.swift {{.*}} -emit-module-doc-path {{.*}}/file-01-[[SWIFTDOC01:[a-z0-9]+]].swiftdoc -emit-module-doc-path {{.*}}/file-02-[[SWIFTDOC02:[a-z0-9]+]].swiftdoc -module-name main -emit-module-path {{.*}}/file-01-[[MODULE01:[a-z0-9]+]].swiftmodule -emit-module-path {{.*}}/file-02-[[MODULE02:[a-z0-9]+]].swiftmodule -o {{.*}}/file-01-[[OBJ01:[a-z0-9]+]].o -o {{.*}}/file-02-[[OBJ02:[a-z0-9]+]].o",
+// CHECK-NEXT: "inputs": [
+// CHECK-NEXT: "{{.*}}/file-01.swift",
+// CHECK-NEXT: "{{.*}}/file-02.swift"
+// CHECK-NEXT: ],
+// CHECK-NEXT: "outputs": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "type": "object",
+// CHECK-NEXT: "path": "{{.*}}/file-01-[[OBJ01]].o"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "type": "object",
+// CHECK-NEXT: "path": "{{.*}}/file-02-[[OBJ02]].o"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "type": "swiftmodule",
+// CHECK-NEXT: "path": "{{.*}}/file-01-[[MODULE01]].swiftmodule"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "type": "swiftmodule",
+// CHECK-NEXT: "path": "{{.*}}/file-02-[[MODULE02]].swiftmodule"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "type": "swiftdoc",
+// CHECK-NEXT: "path": "{{.*}}/file-01-[[SWIFTDOC01]].swiftdoc"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "type": "swiftdoc",
+// CHECK-NEXT: "path": "{{.*}}/file-02-[[SWIFTDOC02]].swiftdoc"
+// CHECK-NEXT: }
+// CHECK-NEXT: ],
+// CHECK-NEXT: "pid": {{[1-9][0-9]*}}
+// CHECK-NEXT: }
+// CHECK-NEXT: {{[1-9][0-9]*}}
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "began",
+// CHECK-NEXT: "name": "compile",
+// CHECK-NEXT: "command": "{{.*}}/swift{{c?}} -frontend -c {{.*}}/file-01.swift {{.*}}/file-02.swift -primary-file {{.*}}/file-03.swift -primary-file {{.*}}/main.swift {{.*}} -emit-module-doc-path {{.*}}/file-03-[[SWIFTDOC03:[a-z0-9]+]].swiftdoc -emit-module-doc-path {{.*}}/main-[[SWIFTDOCMAIN:[a-z0-9]+]].swiftdoc -module-name main -emit-module-path {{.*}}/file-03-[[MODULE03:[a-z0-9]+]].swiftmodule -emit-module-path {{.*}}/main-[[MODULEMAIN:[a-z0-9]+]].swiftmodule -o {{.*}}/file-03-[[OBJ03:[a-z0-9]+]].o -o {{.*}}/main-[[OBJMAIN:[a-z0-9]+]].o",
+// CHECK-NEXT: "inputs": [
+// CHECK-NEXT: "{{.*}}/file-03.swift",
+// CHECK-NEXT: "{{.*}}/main.swift"
+// CHECK-NEXT: ],
+// CHECK-NEXT: "outputs": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "type": "object",
+// CHECK-NEXT: "path": "{{.*}}/file-03-[[OBJ03]].o"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "type": "object",
+// CHECK-NEXT: "path": "{{.*}}/main-[[OBJMAIN]].o"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "type": "swiftmodule",
+// CHECK-NEXT: "path": "{{.*}}/file-03-[[MODULE03]].swiftmodule"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "type": "swiftmodule",
+// CHECK-NEXT: "path": "{{.*}}/main-[[MODULEMAIN]].swiftmodule"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "type": "swiftdoc",
+// CHECK-NEXT: "path": "{{.*}}/file-03-[[SWIFTDOC03]].swiftdoc"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "type": "swiftdoc",
+// CHECK-NEXT: "path": "{{.*}}/main-[[SWIFTDOCMAIN]].swiftdoc"
+// CHECK-NEXT: }
+// CHECK-NEXT: ],
+// CHECK-NEXT: "pid": {{[1-9][0-9]*}}
+// CHECK-NEXT: }
+// CHECK-NEXT: {{[1-9][0-9]*}}
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "finished",
+// CHECK-NEXT: "name": "compile",
+// CHECK-NEXT: "pid": {{[1-9][0-9]*}},
+// CHECK-NEXT: "exit-status": 0
+// CHECK-NEXT: }
+// CHECK-NEXT: {{[1-9][0-9]*}}
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "finished",
+// CHECK-NEXT: "name": "compile",
+// CHECK-NEXT: "pid": {{[1-9][0-9]*}},
+// CHECK-NEXT: "exit-status": 0
+// CHECK-NEXT: }
+// CHECK-NEXT: {{[1-9][0-9]*}}
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "began",
+// CHECK-NEXT: "name": "merge-module",
+// CHECK-NEXT: "command": "{{.*}}/swift{{c?}} -frontend -merge-modules -emit-module {{.*}}/file-01-[[MODULE01]].swiftmodule {{.*}}/file-02-[[MODULE02]].swiftmodule {{.*}}/file-03-[[MODULE03]].swiftmodule {{.*}}/main-[[MODULEMAIN]].swiftmodule {{.*}} -emit-module-doc-path main.swiftdoc -module-name main -o main.swiftmodule",
+// CHECK-NEXT: "inputs": [
+// CHECK-NEXT: "{{.*}}/file-01-[[OBJ01]].o",
+// CHECK-NEXT: "{{.*}}/file-02-[[OBJ02]].o",
+// CHECK-NEXT: "{{.*}}/file-03-[[OBJ03]].o",
+// CHECK-NEXT: "{{.*}}/main-[[OBJMAIN]].o"
+// CHECK-NEXT: ],
+// CHECK-NEXT: "outputs": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "type": "swiftmodule",
+// CHECK-NEXT: "path": "main.swiftmodule"
+// CHECK-NEXT: },
+// CHECK-NEXT: {
+// CHECK-NEXT: "type": "swiftdoc",
+// CHECK-NEXT: "path": "main.swiftdoc"
+// CHECK-NEXT: }
+// CHECK-NEXT: ],
+// CHECK-NEXT: "pid": {{[1-9][0-9]*}}
+// CHECK-NEXT: }
+// CHECK-NEXT: {{[1-9][0-9]*}}
+// CHECK-NEXT: {
+// CHECK-NEXT: "kind": "finished",
+// CHECK-NEXT: "name": "merge-module",
+// CHECK-NEXT: "pid": {{[1-9][0-9]*}},
+// CHECK-NEXT: "exit-status": 0
+// CHECK-NEXT: }
diff --git a/test/Driver/fuzzer.swift b/test/Driver/fuzzer.swift
index 4ab6c2a..937804d 100644
--- a/test/Driver/fuzzer.swift
+++ b/test/Driver/fuzzer.swift
@@ -1,4 +1,4 @@
-// RUN: %swiftc_driver -driver-print-jobs -sanitize=fuzzer,address %s | %FileCheck -check-prefix=LIBFUZZER %s
+// RUN: %swiftc_driver -driver-print-jobs -sanitize=fuzzer,address -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ %s | %FileCheck -check-prefix=LIBFUZZER %s
// LIBFUZZER: libclang_rt.fuzzer
@_cdecl("LLVMFuzzerTestOneInput") public func fuzzOneInput(Data: UnsafePointer<CChar>, Size: CLong) -> CInt {
diff --git a/test/Driver/sanitize_coverage.swift b/test/Driver/sanitize_coverage.swift
index 71f4a0b..d18574c 100644
--- a/test/Driver/sanitize_coverage.swift
+++ b/test/Driver/sanitize_coverage.swift
@@ -2,6 +2,7 @@
// RUN: %swiftc_driver -driver-print-jobs -sanitize-coverage=func -sanitize=address %s | %FileCheck -check-prefix=SANCOV_FUNC %s
// RUN: %swiftc_driver -driver-print-jobs -sanitize-coverage=bb -sanitize=address %s | %FileCheck -check-prefix=SANCOV_BB %s
// RUN: %swiftc_driver -driver-print-jobs -sanitize-coverage=edge -sanitize=address %s | %FileCheck -check-prefix=SANCOV_EDGE %s
+// REQUIRES: asan_runtime
// Try some options
// RUN: %swiftc_driver -driver-print-jobs -sanitize-coverage=edge,indirect-calls,trace-bb,trace-cmp,8bit-counters -sanitize=address %s | %FileCheck -check-prefix=SANCOV_EDGE_WITH_OPTIONS %s
diff --git a/test/Driver/sanitizers.swift b/test/Driver/sanitizers.swift
index 953bfed..d143c70 100644
--- a/test/Driver/sanitizers.swift
+++ b/test/Driver/sanitizers.swift
@@ -1,4 +1,5 @@
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address -target x86_64-apple-macosx10.9 %s | %FileCheck -check-prefix=ASAN -check-prefix=ASAN_OSX %s
+// RUN: not %swiftc_driver -driver-print-jobs -sanitize=fuzzer -target x86_64-apple-macosx10.9 -resource-dir %S/Inputs/nonexistent-resource-dir %s 2>&1 | %FileCheck -check-prefix=FUZZER_NONEXISTENT %s
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address -target x86_64-apple-ios7.1 %s | %FileCheck -check-prefix=ASAN -check-prefix=ASAN_IOSSIM %s
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address -target arm64-apple-ios7.1 %s | %FileCheck -check-prefix=ASAN -check-prefix=ASAN_IOS %s
// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address -target x86_64-apple-tvos9.0 %s | %FileCheck -check-prefix=ASAN -check-prefix=ASAN_tvOS_SIM %s
@@ -54,6 +55,7 @@
// TSAN_tvOS: unsupported option '-sanitize=thread' for target 'arm64-apple-tvos9.0'
// TSAN_watchOS_SIM: unsupported option '-sanitize=thread' for target 'i386-apple-watchos2.0'
// TSAN_watchOS: unsupported option '-sanitize=thread' for target 'armv7k-apple-watchos2.0'
+// FUZZER_NONEXISTENT: unsupported option '-sanitize=fuzzer' for target 'x86_64-apple-macosx10.9'
// TSAN_LINUX: lib/swift/clang/lib/linux/libclang_rt.tsan-x86_64.a
// TSAN: -rpath @executable_path
diff --git a/test/Frontend/batch-mode.swift b/test/Frontend/batch-mode.swift
index 8706761f..d407dad 100644
--- a/test/Frontend/batch-mode.swift
+++ b/test/Frontend/batch-mode.swift
@@ -3,7 +3,7 @@
// RUN: echo 'public func b() { }' >%t/b.swift
// RUN: echo 'public func c() { }' >%t/c.swift
// RUN: echo 'public func main() {a(); b(); c()}' >%t/main.swift
-// RUN: %target-swift-frontend -c -enable-batch-mode -bypass-batch-mode-checks -module-name foo -primary-file %t/a.swift -primary-file %t/b.swift -primary-file %t/c.swift -primary-file %t/main.swift -o %t/a.o -o %t/b.o -o %t/c.o -o %t/main.o
+// RUN: %target-swift-frontend -c -enable-batch-mode -module-name foo -primary-file %t/a.swift -primary-file %t/b.swift -primary-file %t/c.swift -primary-file %t/main.swift -o %t/a.o -o %t/b.o -o %t/c.o -o %t/main.o
//
// RUN: llvm-objdump -t %t/a.o | swift-demangle | %FileCheck -check-prefix=CHECK-A %s
// RUN: llvm-objdump -t %t/b.o | swift-demangle | %FileCheck -check-prefix=CHECK-B %s
diff --git a/test/Frontend/dependencies-selective-supplementaries.swift b/test/Frontend/dependencies-selective-supplementaries.swift
new file mode 100644
index 0000000..c1cd4bc
--- /dev/null
+++ b/test/Frontend/dependencies-selective-supplementaries.swift
@@ -0,0 +1,23 @@
+// This test verifies that, in batch-mode (i.e. >1 primary input),
+// we have fixed a bug that caused every primary input to be a dependent
+// of every ModuleOutputPath, etc.
+
+// RUN: %empty-directory(%t)
+// RUN: echo 'public func a() { }' >%t/a.swift
+// RUN: echo 'public func main() {a()}' >%t/main.swift
+// RUN: %target-swift-frontend -c -enable-batch-mode -module-name foo -primary-file %t/a.swift -primary-file %t/main.swift -emit-dependencies-path %t/a.d -emit-dependencies-path %t/main.d -o %t/a.o -o %t/main.o -emit-module-path %t/a.swiftmodule -emit-module-path %t/main.swiftmodule
+// RUN: %FileCheck -check-prefix=CHECK-MAIN %s <%t/main.d
+// RUN: %FileCheck -check-prefix=NEGATIVE-MAIN %s <%t/main.d
+//
+// CHECK-MAIN-DAG: main.swiftmodule :
+// CHECK-MAIN-DAG: main.o :
+// NEGATIVE-MAIN-NOT: a.swiftmodule
+// NEGATIVE-MAIN-NOT: a.o
+//
+// RUN: %FileCheck -check-prefix=CHECK-A %s <%t/a.d
+// RUN: %FileCheck -check-prefix=NEGATIVE-A %s <%t/a.d
+//
+// CHECK-A-DAG: a.swiftmodule :
+// CHECK-A-DAG: a.o :
+// NEGATIVE-A-NOT: main.swiftmodule
+// NEGATIVE-A-NOT: main.o
diff --git a/test/IRGen/class_metadata.swift b/test/IRGen/class_metadata.swift
index 3f927a3..14ff7fb 100644
--- a/test/IRGen/class_metadata.swift
+++ b/test/IRGen/class_metadata.swift
@@ -63,14 +63,18 @@
// CHECK-SAME: i32 {{.*}} @"$S14class_metadata1CCMa"
// Superclass.
// CHECK-SAME: i32 {{.*}} @"$S14class_metadata1BCMn"
+// Negative size in words.
+// CHECK-SAME: i32 2,
+// Positive size in words.
+// CHECK-32-SAME: i32 15,
+// CHECK-64-SAME: i32 12,
+// Num immediate members.
+// CHECK-32-SAME: i32 1,
// Field count.
// CHECK-SAME: i32 0,
// Field offset vector offset.
// CHECK-32-SAME: i32 15,
// CHECK-64-SAME: i32 12,
-// Argument offset.
-// CHECK-32-SAME: i32 14,
-// CHECK-64-SAME: i32 11,
// Instantiation function.
// CHECK-SAME: i32 {{.*}} @"$S14class_metadata1CCMi"
// Instantiation cache.
diff --git a/test/IRGen/class_resilience.swift b/test/IRGen/class_resilience.swift
index da4709b..68e0063 100644
--- a/test/IRGen/class_resilience.swift
+++ b/test/IRGen/class_resilience.swift
@@ -16,9 +16,11 @@
// CHECK: @"$S16class_resilience14ResilientChildC5fields5Int32VvpWvd" = hidden global [[INT]] {{8|16}}
-// CHECK: @"$S16class_resilience21ResilientGenericChildCMo" = {{(protected )?}}global [[INT]] 0
+// CHECK: @"$S16class_resilience21ResilientGenericChildCMo" = {{(protected )?}}global [[BOUNDS:{ (i32|i64), i32, i32 }]] zeroinitializer
-// CHECK: @"$S16class_resilience26ClassWithResilientPropertyCMo" = {{(protected )?}}constant [[INT]] {{52|80}}
+// CHECK: @"$S16class_resilience26ClassWithResilientPropertyCMo" = {{(protected )?}}constant [[BOUNDS]]
+// CHECK-SAME-32: { [[INT]] 52, i32 2, i32 13 }
+// CHECK-SAME-64: { [[INT]] 80, i32 2, i32 10 }
// CHECK: @"$S16class_resilience28ClassWithMyResilientPropertyC1rAA0eF6StructVvpWvd" = hidden constant [[INT]] {{8|16}}
// CHECK: @"$S16class_resilience28ClassWithMyResilientPropertyC5colors5Int32VvpWvd" = hidden constant [[INT]] {{12|20}}
@@ -28,6 +30,8 @@
// CHECK: [[RESILIENTCHILD_NAME:@.*]] = private constant [15 x i8] c"ResilientChild\00"
+// CHECK: @"$S16class_resilience14ResilientChildCMo" = {{(protected )?}}global [[BOUNDS]] zeroinitializer
+
// CHECK: @"$S16class_resilience14ResilientChildCMn" = {{(protected )?}}constant <{{.*}}> <{
// -- flags: class, unique, reflectable, has vtable, has resilient superclass
// CHECK-SAME: <i32 0xD004_0050>
@@ -39,17 +43,23 @@
// CHECK-SAME: i32 3,
// CHECK-SAME: }>
-// CHECK: @"$S16class_resilience14ResilientChildCMo" = {{(protected )?}}global [[INT]] 0
+// CHECK: @"$S16class_resilience16FixedLayoutChildCMo" = {{(protected )?}}global [[BOUNDS]] zeroinitializer
-// CHECK: @"$S16class_resilience16FixedLayoutChildCMo" = {{(protected )?}}global [[INT]] 0
+// CHECK: @"$S16class_resilience17MyResilientParentCMo" = {{(protected )?}}constant [[BOUNDS]]
+// CHECK-SAME-32: { [[INT]] 52, i32 2, i32 13 }
+// CHECK-SAME-64: { [[INT]] 80, i32 2, i32 10 }
-// CHECK: @"$S16class_resilience17MyResilientParentCMo" = {{(protected )?}}constant [[INT]] {{52|80}}
+// CHECK: @"$S16class_resilience16MyResilientChildCMo" = {{(protected )?}}constant [[BOUNDS]]
+// CHECK-SAME-32: { [[INT]] 60, i32 2, i32 15 }
+// CHECK-SAME-64: { [[INT]] 96, i32 2, i32 12 }
-// CHECK: @"$S16class_resilience16MyResilientChildCMo" = {{(protected )?}}constant [[INT]] {{60|96}}
+// CHECK: @"$S16class_resilience24MyResilientGenericParentCMo" = {{(protected )?}}constant [[BOUNDS]]
+// CHECK-SAME-32: { [[INT]] 52, i32 2, i32 13 }
+// CHECK-SAME-64: { [[INT]] 80, i32 2, i32 10 }
-// CHECK: @"$S16class_resilience24MyResilientGenericParentCMo" = {{(protected )?}}constant [[INT]] {{52|80}}
-
-// CHECK: @"$S16class_resilience24MyResilientConcreteChildCMo" = {{(protected )?}}constant [[INT]] {{64|104}}
+// CHECK: @"$S16class_resilience24MyResilientConcreteChildCMo" = {{(protected )?}}constant [[BOUNDS]]
+// CHECK-SAME-32: { [[INT]] 64, i32 2, i32 16 }
+// CHECK-SAME-64: { [[INT]] 104, i32 2, i32 13 }
import resilient_class
import resilient_struct
@@ -273,7 +283,7 @@
// CHECK-NEXT: [[ADDR:%.*]] = getelementptr inbounds %T16class_resilience21ResilientGenericChildC, %T16class_resilience21ResilientGenericChildC* %0, i32 0, i32 0, i32 0
// CHECK-NEXT: [[ISA:%.*]] = load %swift.type*, %swift.type** [[ADDR]]
-// CHECK-NEXT: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S16class_resilience21ResilientGenericChildCMo"
+// CHECK-NEXT: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S16class_resilience21ResilientGenericChildCMo", i32 0, i32 0)
// CHECK-NEXT: [[METADATA_OFFSET:%.*]] = add [[INT]] [[BASE]], {{16|32}}
// CHECK-NEXT: [[ISA_ADDR:%.*]] = bitcast %swift.type* [[ISA]] to i8*
// CHECK-NEXT: [[FIELD_OFFSET_TMP:%.*]] = getelementptr inbounds i8, i8* [[ISA_ADDR]], [[INT]] [[METADATA_OFFSET]]
@@ -305,7 +315,7 @@
// CHECK-LABEL: define{{( protected)?}} swiftcc %swift.type* @"$S15resilient_class29ResilientGenericOutsideParentC0B11_resilienceE22genericExtensionMethodxmyF"(%T15resilient_class29ResilientGenericOutsideParentC* swiftself) #0 {
// CHECK: [[ISA_ADDR:%.*]] = bitcast %T15resilient_class29ResilientGenericOutsideParentC* %0 to %swift.type**
// CHECK-NEXT: [[ISA:%.*]] = load %swift.type*, %swift.type** [[ISA_ADDR]]
-// CHECK-NEXT: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S15resilient_class29ResilientGenericOutsideParentCMo"
+// CHECK-NEXT: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S15resilient_class29ResilientGenericOutsideParentCMo", i32 0, i32 0)
// CHECK-NEXT: [[GENERIC_PARAM_OFFSET:%.*]] = add [[INT]] [[BASE]], 0
// CHECK-NEXT: [[ISA_TMP:%.*]] = bitcast %swift.type* [[ISA]] to i8*
// CHECK-NEXT: [[GENERIC_PARAM_TMP:%.*]] = getelementptr inbounds i8, i8* [[ISA_TMP]], [[INT]] [[GENERIC_PARAM_OFFSET]]
@@ -352,39 +362,21 @@
// CHECK-LABEL: define private void @initialize_metadata_ResilientChild(i8*)
-// Get the superclass size and address point...
-
-// CHECK: [[SUPER:%.*]] = call %swift.type* @"$S15resilient_class22ResilientOutsideParentCMa"()
-// CHECK: [[SUPER_ADDR:%.*]] = bitcast %swift.type* [[SUPER]] to i8*
-// CHECK: [[SIZE_TMP:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], i32 {{36|56}}
-// CHECK: [[SIZE_ADDR:%.*]] = bitcast i8* [[SIZE_TMP]] to i32*
-// CHECK: [[SIZE:%.*]] = load i32, i32* [[SIZE_ADDR]]
-// CHECK: [[ADDRESS_POINT_TMP:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], i32 {{40|60}}
-// CHECK: [[ADDRESS_POINT_ADDR:%.*]] = bitcast i8* [[ADDRESS_POINT_TMP]] to i32*
-// CHECK: [[ADDRESS_POINT:%.*]] = load i32, i32* [[ADDRESS_POINT_ADDR]]
-
-// CHECK: [[OFFSET:%.*]] = sub i32 [[SIZE]], [[ADDRESS_POINT]]
-
-// Initialize class metadata base offset...
-// CHECK-32: store [[INT]] [[OFFSET]], [[INT]]* @"$S16class_resilience14ResilientChildCMo"
-
-// CHECK-64: [[OFFSET_ZEXT:%.*]] = zext i32 [[OFFSET]] to i64
-// CHECK-64: store [[INT]] [[OFFSET_ZEXT]], [[INT]]* @"$S16class_resilience14ResilientChildCMo"
-
// Initialize the superclass field...
+// CHECK: [[SUPER:%.*]] = call %swift.type* @"$S15resilient_class22ResilientOutsideParentCMa"()
// CHECK: store %swift.type* [[SUPER]], %swift.type** getelementptr inbounds ({{.*}})
// Relocate metadata if necessary...
// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_relocateClassMetadata(%swift.type* {{.*}}, [[INT]] {{60|96}}, [[INT]] 4)
// Initialize field offset vector...
-// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S16class_resilience14ResilientChildCMo"
+// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S16class_resilience14ResilientChildCMo", i32 0, i32 0)
// CHECK: [[OFFSET:%.*]] = add [[INT]] [[BASE]], {{12|24}}
// CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], [[INT]] 1, i8*** {{.*}}, [[INT]]* {{.*}})
// Initialize constructor vtable override...
-// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S15resilient_class22ResilientOutsideParentCMo"
+// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S15resilient_class22ResilientOutsideParentCMo", i32 0, i32 0)
// CHECK: [[OFFSET:%.*]] = add [[INT]] [[BASE]], {{16|32}}
// CHECK: [[METADATA_BYTES:%.*]] = bitcast %swift.type* [[METADATA]] to i8*
// CHECK: [[VTABLE_ENTRY_ADDR:%.*]] = getelementptr inbounds i8, i8* [[METADATA_BYTES]], [[INT]] [[OFFSET]]
@@ -392,7 +384,7 @@
// CHECK: store i8* bitcast (%T16class_resilience14ResilientChildC* (%T16class_resilience14ResilientChildC*)* @"$S16class_resilience14ResilientChildCACycfc" to i8*), i8** [[VTABLE_ENTRY_TMP]]
// Initialize getValue() vtable override...
-// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S15resilient_class22ResilientOutsideParentCMo"
+// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S15resilient_class22ResilientOutsideParentCMo", i32 0, i32 0)
// CHECK: [[OFFSET:%.*]] = add [[INT]] [[BASE]], {{28|56}}
// CHECK: [[METADATA_BYTES:%.*]] = bitcast %swift.type* [[METADATA]] to i8*
// CHECK: [[VTABLE_ENTRY_ADDR:%.*]] = getelementptr inbounds i8, i8* [[METADATA_BYTES]], [[INT]] [[OFFSET]]
@@ -410,7 +402,7 @@
// CHECK-LABEL: define{{( protected)?}} swiftcc i32 @"$S16class_resilience14ResilientChildC5fields5Int32VvgTj"(%T16class_resilience14ResilientChildC* swiftself)
// CHECK: [[ISA_ADDR:%.*]] = getelementptr inbounds %T16class_resilience14ResilientChildC, %T16class_resilience14ResilientChildC* %0, i32 0, i32 0, i32 0
// CHECK-NEXT: [[ISA:%.*]] = load %swift.type*, %swift.type** [[ISA_ADDR]]
-// CHECK-NEXT: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S16class_resilience14ResilientChildCMo"
+// CHECK-NEXT: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S16class_resilience14ResilientChildCMo", i32 0, i32 0)
// CHECK-NEXT: [[METADATA_BYTES:%.*]] = bitcast %swift.type* [[ISA]] to i8*
// CHECK-NEXT: [[VTABLE_OFFSET_TMP:%.*]] = getelementptr inbounds i8, i8* [[METADATA_BYTES]], [[INT]] [[BASE]]
// CHECK-NEXT: [[VTABLE_OFFSET_ADDR:%.*]] = bitcast i8* [[VTABLE_OFFSET_TMP]] to i32 (%T16class_resilience14ResilientChildC*)**
@@ -423,7 +415,7 @@
// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S16class_resilience14ResilientChildC5fields5Int32VvsTj"(i32, %T16class_resilience14ResilientChildC* swiftself)
// CHECK: [[ISA_ADDR:%.*]] = getelementptr inbounds %T16class_resilience14ResilientChildC, %T16class_resilience14ResilientChildC* %1, i32 0, i32 0, i32 0
// CHECK-NEXT: [[ISA:%.*]] = load %swift.type*, %swift.type** [[ISA_ADDR]]
-// CHECK-NEXT: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S16class_resilience14ResilientChildCMo"
+// CHECK-NEXT: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S16class_resilience14ResilientChildCMo", i32 0, i32 0)
// CHECK-NEXT: [[METADATA_OFFSET:%.*]] = add [[INT]] [[BASE]], {{4|8}}
// CHECK-NEXT: [[METADATA_BYTES:%.*]] = bitcast %swift.type* [[ISA]] to i8*
// CHECK-NEXT: [[VTABLE_OFFSET_TMP:%.*]] = getelementptr inbounds i8, i8* [[METADATA_BYTES]], [[INT]] [[METADATA_OFFSET]]
@@ -437,26 +429,8 @@
// CHECK-LABEL: define private void @initialize_metadata_FixedLayoutChild(i8*)
-// Get the superclass size and address point...
-
-// CHECK: [[SUPER:%.*]] = call %swift.type* @"$S15resilient_class22ResilientOutsideParentCMa"()
-// CHECK: [[SUPER_ADDR:%.*]] = bitcast %swift.type* [[SUPER]] to i8*
-// CHECK: [[SIZE_TMP:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], i32 {{36|56}}
-// CHECK: [[SIZE_ADDR:%.*]] = bitcast i8* [[SIZE_TMP]] to i32*
-// CHECK: [[SIZE:%.*]] = load i32, i32* [[SIZE_ADDR]]
-// CHECK: [[ADDRESS_POINT_TMP:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], i32 {{40|60}}
-// CHECK: [[ADDRESS_POINT_ADDR:%.*]] = bitcast i8* [[ADDRESS_POINT_TMP]] to i32*
-// CHECK: [[ADDRESS_POINT:%.*]] = load i32, i32* [[ADDRESS_POINT_ADDR]]
-
-// CHECK: [[OFFSET:%.*]] = sub i32 [[SIZE]], [[ADDRESS_POINT]]
-
-// Initialize class metadata base offset...
-// CHECK-32: store [[INT]] [[OFFSET]], [[INT]]* @"$S16class_resilience16FixedLayoutChildCMo"
-
-// CHECK-64: [[OFFSET_ZEXT:%.*]] = zext i32 [[OFFSET]] to i64
-// CHECK-64: store [[INT]] [[OFFSET_ZEXT]], [[INT]]* @"$S16class_resilience16FixedLayoutChildCMo"
-
// Initialize the superclass field...
+// CHECK: [[SUPER:%.*]] = call %swift.type* @"$S15resilient_class22ResilientOutsideParentCMa"()
// CHECK: store %swift.type* [[SUPER]], %swift.type** getelementptr inbounds ({{.*}})
// Relocate metadata if necessary...
@@ -471,23 +445,14 @@
// Get the superclass size and address point...
+// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** %1, i8** bitcast ({{.*}} @"$S16class_resilience21ResilientGenericChildCMP" to i8**))
+
+// Initialize the superclass pointer...
// CHECK: [[SUPER:%.*]] = call %swift.type* @"$S15resilient_class29ResilientGenericOutsideParentCMa"(%swift.type* %T)
-// CHECK: [[SUPER_TMP:%.*]] = bitcast %swift.type* [[SUPER]] to %objc_class*
-// CHECK: [[SUPER_ADDR:%.*]] = bitcast %objc_class* [[SUPER_TMP]] to i8*
-// CHECK: [[SIZE_TMP:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], i32 {{36|56}}
-// CHECK: [[SIZE_ADDR:%.*]] = bitcast i8* [[SIZE_TMP]] to i32*
-// CHECK: [[SIZE:%.*]] = load i32, i32* [[SIZE_ADDR]]
-// CHECK: [[ADDRESS_POINT_TMP:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], i32 {{40|60}}
-// CHECK: [[ADDRESS_POINT_ADDR:%.*]] = bitcast i8* [[ADDRESS_POINT_TMP]] to i32*
-// CHECK: [[ADDRESS_POINT:%.*]] = load i32, i32* [[ADDRESS_POINT_ADDR]]
+// CHECK: [[T0:%.*]] = bitcast %swift.type* [[METADATA]] to %swift.type**
+// CHECK: [[SUPER_ADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i32 1
+// CHECK: store %swift.type* [[SUPER]], %swift.type** [[SUPER_ADDR]],
-// CHECK: [[OFFSET:%.*]] = sub i32 [[SIZE]], [[ADDRESS_POINT]]
+// CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]],
-// Initialize class metadata base offset...
-// CHECK-32: store [[INT]] [[OFFSET]], [[INT]]* @"$S16class_resilience21ResilientGenericChildCMo"
-
-// CHECK-64: [[OFFSET_ZEXT:%.*]] = zext i32 [[OFFSET]] to i64
-// CHECK-64: store [[INT]] [[OFFSET_ZEXT]], [[INT]]* @"$S16class_resilience21ResilientGenericChildCMo"
-
-// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** bitcast ({{.*}} @"$S16class_resilience21ResilientGenericChildCMP" to i8**), [[INT]] {{[0-9]+}}, [[INT]] {{[0-9]+}}, i8** %1, %objc_class* [[SUPER_TMP]], [[INT]] 5)
// CHECK: ret %swift.type* [[METADATA]]
diff --git a/test/IRGen/enum.sil b/test/IRGen/enum.sil
index 1cbe9d4..9dd72e4 100644
--- a/test/IRGen/enum.sil
+++ b/test/IRGen/enum.sil
@@ -116,8 +116,6 @@
// CHECK-SAME: i32 1,
// -- No empty cases
// CHECK-SAME: i32 0,
-// -- Case type accessor
-// CHECK-SAME: i32 2,
// -- generic instantiation function
// CHECK-SAME: @"$S4enum16DynamicSingletonOMi"
// -- generic parameters, requirements, key, extra
diff --git a/test/IRGen/generic_classes.sil b/test/IRGen/generic_classes.sil
index 3700dc5..4e24036 100644
--- a/test/IRGen/generic_classes.sil
+++ b/test/IRGen/generic_classes.sil
@@ -19,12 +19,16 @@
// CHECK-SAME: <i32 0x8004_00D0>
// -- name
// CHECK-SAME: [12 x i8]* [[ROOTGENERIC_NAME]]
+// -- negative size in words
+// CHECK-SAME: i32 2,
+// -- positive size in words
+// CHECK-SAME: i32 18,
+// -- num immediate members
+// CHECK-SAME: i32 8,
// -- num fields
// CHECK-SAME: i32 3,
// -- field offset vector offset
// CHECK-SAME: i32 15,
-// -- generic parameter vector offset
-// CHECK-SAME: i32 10,
// -- template instantiation function
// CHECK-SAME: %swift.type* (%swift.type_descriptor*, i8**)* @"$S15generic_classes11RootGenericCMi"
// -- template instantiation cache
@@ -38,10 +42,29 @@
// CHECK-SAME: }
// CHECK-LABEL: @"$S15generic_classes11RootGenericCMP" = internal constant
-// -- nominal type descriptor
-// CHECK-SAME: @"$S15generic_classes11RootGenericCMn"
+// CHECK-SAME: <{
+// -- heap destructor
+// CHECK-SAME: @"$S15generic_classes11RootGenericCfD"
// -- ivar destroyer
-// CHECK-SAME: i8* null
+// CHECK-SAME: i8* null,
+// -- flags
+// CHECK_SAME: i32 3,
+// -- immediate pattern size
+// CHECK-SAME: i16 0,
+// -- immediate pattern target offset
+// CHECK-SAME: i16 0,
+// -- extra data size
+// CHECK-SAME-native: i16 0,
+// CHECK-SAME-objc: i16 23,
+// -- class ro-data offset
+// CHECK-SAME-native: i16 0,
+// CHECK-SAME-objc: i16 5,
+// -- metaclass object offset
+// CHECK-SAME-native: i16 0,
+// CHECK-SAME-objc: i16 0,
+// -- class ro-data offset
+// CHECK-SAME-native: i16 0
+// CHECK-SAME-objc: i16 14,
// CHECK-SAME: }>
// -- Check that offset vars are emitted for fixed-layout generics
@@ -87,10 +110,28 @@
// CHECK-SAME: %swift.type* (%swift.type_descriptor*, i8**)* @"$S15generic_classes015GenericInheritsC0CMi"
// CHECK: @"$S15generic_classes015GenericInheritsC0CMP" = internal constant
-// -- nominal type descriptor
-// CHECK-SAME: @"$S15generic_classes015GenericInheritsC0CMn",
+// -- heap destructor
+// CHECK-SAME: @"$S15generic_classes015GenericInheritsC0CfD"
// -- ivar destroyer
-// CHECK-SAME: i8* null
+// CHECK-SAME: i8* null,
+// -- flags
+// CHECK_SAME: i32 3,
+// -- immediate pattern size
+// CHECK-SAME: i16 0,
+// -- immediate pattern target offset
+// CHECK-SAME: i16 0,
+// -- extra data size
+// CHECK-SAME-native: i16 0,
+// CHECK-SAME-objc: i16 23,
+// -- class ro-data offset
+// CHECK-SAME-native: i16 0,
+// CHECK-SAME-objc: i16 5,
+// -- metaclass object offset
+// CHECK-SAME-native: i16 0,
+// CHECK-SAME-objc: i16 0,
+// -- class ro-data offset
+// CHECK-SAME-native: i16 0
+// CHECK-SAME-objc: i16 14,
// CHECK-SAME: }
// CHECK: @"$S15generic_classes018GenericInheritsNonC0CMP"
@@ -292,13 +333,13 @@
*/
// CHECK-LABEL: define{{( protected)?}} internal %swift.type* @"$S15generic_classes11RootGenericCMi"(%swift.type_descriptor*, i8**) {{.*}} {
-// CHECK: [[METADATA:%.*]] ={{( tail)?}} call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, {{.*}}, i64 8)
+// CHECK: [[METADATA:%.*]] ={{( tail)?}} call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** %1, {{.*}} @"$S15generic_classes11RootGenericCMP"{{.*}})
// -- initialize the dependent field offsets
// CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 3, i8*** {{%.*}}, i64* {{%.*}})
// CHECK: }
// CHECK-LABEL: define{{( protected)?}} internal %swift.type* @"$S15generic_classes22RootGenericFixedLayoutCMi"(%swift.type_descriptor*, i8**) {{.*}} {
-// CHECK: [[METADATA:%.*]] ={{( tail)?}} call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, {{.*}}, i64 5)
+// CHECK: [[METADATA:%.*]] ={{( tail)?}} call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** %1, {{.*}} @"$S15generic_classes22RootGenericFixedLayoutCMP"{{.*}})
// CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 3, i8*** {{%.*}}, i64* {{%.*}})
// CHECK: }
@@ -309,10 +350,7 @@
// CHECK: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i32 1
// CHECK: %B = load %swift.type*, %swift.type** [[T1]]
// Construct the superclass.
-// CHECK: [[SUPER:%.*]] = call %swift.type* @"$S15generic_classes11RootGenericCMa"(%swift.type* %A)
-// CHECK: [[T0:%.*]] = bitcast %swift.type* [[SUPER]] to %objc_class*
-// CHECK-native: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** {{.*}}, i64 96, i64 16, i8** %1, %objc_class* [[T0]], i64 6)
-// CHECK-objc: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** {{.*}}, i64 280, i64 200, i8** %1, %objc_class* [[T0]], i64 6)
+// CHECK: [[METADATA:%.*]] ={{( tail)?}} call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** %1, {{.*}} @"$S15generic_classes015GenericInheritsC0CMP"{{.*}})
// CHECK: [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
// Put the generic arguments in their correct positions.
// CHECK: [[A_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY:%.*]], i64 18
@@ -321,26 +359,10 @@
// CHECK: [[B_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY:%.*]], i64 19
// CHECK: [[T0:%.*]] = bitcast %swift.type* %B to i8*
// CHECK: store i8* [[T0]], i8** [[B_ADDR]], align 8
-// Set up the isa.
-// CHECK-objc: [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
-// CHECK-objc: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 0
-// CHECK-objc: [[T1:%.*]] = bitcast i8** [[T0]] to %objc_class**
-// CHECK-objc: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 -25
-// CHECK-objc: [[METACLASS:%.*]] = bitcast i8** [[T0]] to %objc_class*
-// CHECK-objc: store %objc_class* [[METACLASS]], %objc_class** [[T1]], align 8
-// Set up the instance rodata pointer.
-// CHECK-objc: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 4
-// CHECK-objc: [[T1:%.*]] = bitcast i8** [[T0]] to i64*
-// CHECK-objc: [[RODATA:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 -20
-// CHECK-objc: [[T2:%.*]] = ptrtoint i8** [[RODATA]] to i64
-// CHECK-objc: [[T3:%.*]] = or i64 [[T2]], 1
-// CHECK-objc: store i64 [[T3]], i64* [[T1]], align 8
-// Set up the class rodata pointer.
-// CHECK-objc: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 -21
-// CHECK-objc: [[T1:%.*]] = bitcast i8** [[T0]] to i64*
-// CHECK-objc: [[META_RODATA:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 -11
-// CHECK-objc: [[T2:%.*]] = ptrtoint i8** [[META_RODATA]] to i64
-// CHECK-objc: store i64 [[T2]], i64* [[T1]], align 8
+// CHECK: [[SUPER:%.*]] ={{( tail)?}} call %swift.type* @"$S15generic_classes11RootGenericCMa"(%swift.type* %A)
+// CHECK: [[T0:%.*]] = bitcast %swift.type* [[METADATA]] to %swift.type**
+// CHECK: [[T1:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[T0]], i32 1
+// CHECK: store %swift.type* [[SUPER]], %swift.type** [[T1]],
// Initialize our own dependent field offsets.
// CHECK: [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i64*
// CHECK: [[OFFSETS:%.*]] = getelementptr inbounds i64, i64* [[METADATA_ARRAY]], i64 23
diff --git a/test/IRGen/generic_structs.sil b/test/IRGen/generic_structs.sil
index 7af64cd..cfe09bc 100644
--- a/test/IRGen/generic_structs.sil
+++ b/test/IRGen/generic_structs.sil
@@ -29,8 +29,6 @@
// CHECK-SAME: i32 1,
// -- field offset vector offset
// CHECK-SAME: i32 3,
-// -- generic parameter vector offset
-// CHECK-SAME: i32 2,
// -- generic instantiation info
// CHECK-SAME: %swift.type* (%swift.type_descriptor*, i8**)* @"$S15generic_structs13SingleDynamicVMi"
// CHECK-SAME: [{{[0-9]+}} x i8*]* @"$S15generic_structs13SingleDynamicVMI"
@@ -59,8 +57,6 @@
// CHECK-SAME: i32 2,
// -- field offset vector offset
// CHECK-SAME: i32 6,
-// -- generic parameter vector offset
-// CHECK-SAME: i32 2,
// -- generic params, requirements, key args, extra args
// CHECK-SAME: i32 2, i32 2, i32 2, i32 2,
// -- generic parameters
diff --git a/test/IRGen/generic_types.swift b/test/IRGen/generic_types.swift
index a6dc47d..bae4cd4 100644
--- a/test/IRGen/generic_types.swift
+++ b/test/IRGen/generic_types.swift
@@ -11,30 +11,43 @@
// CHECK-LABEL: @"$S13generic_types1ACMI" = internal global [16 x i8*] zeroinitializer, align 8
// CHECK-LABEL: @"$S13generic_types1ACMn" = hidden constant
+// CHECK-SAME: i32 -2147221296,
+// CHECK-SAME: @"$S13generic_typesMXM"
+// <name>
// CHECK-SAME: @"$S13generic_types1ACMa"
+// -- superclass
+// CHECK-SAME: i32 0,
+// -- negative size in words
+// CHECK-SAME: i32 2,
+// -- positive size in words
+// CHECK-SAME: i32 17,
+// -- num immediate members
+// CHECK-SAME: i32 7,
+// -- num fields
+// CHECK-SAME: i32 1,
+// -- field offset vector offset
+// CHECK-SAME: i32 16,
+// -- instantiation function
// CHECK-SAME: @"$S13generic_types1ACMi"
+// -- instantiation cache
// CHECK-SAME: @"$S13generic_types1ACMI"
+// -- num generic params
+// CHECK-SAME: i32 1,
+// -- num generic requirement
+// CHECK-SAME: i32 0,
+// -- num key arguments
+// CHECK-SAME: i32 1,
+// -- num extra arguments
+// CHECK-SAME: i32 0,
+// -- parameter descriptor 1
+// CHECK-SAME: i8 -128,
// CHECK-LABEL: @"$S13generic_types1ACMP" = internal constant
// CHECK-SAME: void ([[A]]*)* @"$S13generic_types1ACfD",
-// CHECK-SAME: i8** @"$SBoWV",
-// CHECK-SAME: i64 0,
-// CHECK-SAME: %swift.type* null,
-// CHECK-native-SAME: %swift.opaque* null,
-// CHECK-objc-SAME: %swift.opaque* @_objc_empty_cache,
-// CHECK-SAME: %swift.opaque* null,
-// CHECK-SAME: i64 {{1|2}},
-// CHECK-SAME: i32 {{3|2}},
-// CHECK-SAME: i32 0,
-// CHECK-SAME: i32 24,
-// CHECK-SAME: i16 7,
-// CHECK-SAME: i16 0,
-// CHECK-SAME: i32 152,
-// CHECK-SAME: i32 16,
-// -- nominal type descriptor
-// CHECK-SAME: @"$S13generic_types1ACMn",
// -- ivar destroyer
-// CHECK-SAME: i8* null
+// CHECK-SAME: i8* null,
+// -- flags
+// CHECK-SAME: i32 {{3|2}},
// CHECK-SAME: }
// CHECK-LABEL: @"$S13generic_types1BCMI" = internal global [16 x i8*] zeroinitializer, align 8
@@ -46,77 +59,29 @@
// CHECK-LABEL: @"$S13generic_types1BCMP" = internal constant
// CHECK-SAME: void ([[B]]*)* @"$S13generic_types1BCfD",
-// CHECK-SAME: i8** @"$SBoWV",
-// CHECK-SAME: i64 0,
-// CHECK-SAME: %swift.type* null,
-// CHECK-native-SAME: %swift.opaque* null,
-// CHECK-objc-SAME: %swift.opaque* @_objc_empty_cache,
-// CHECK-SAME: %swift.opaque* null,
-// CHECK-SAME: i64 {{1|2}},
-// CHECK-SAME: i32 {{3|2}},
-// CHECK-SAME: i32 0,
-// CHECK-SAME: i32 24,
-// CHECK-SAME: i16 7,
-// CHECK-SAME: i16 0,
-// CHECK-SAME: i32 144,
-// CHECK-SAME: i32 16,
-// -- nominal type descriptor
-// CHECK-SAME: @"$S13generic_types1BCMn",
// -- ivar destroyer
// CHECK-SAME: i8* null
+// CHECK-SAME: i32 {{3|2}},
// CHECK-SAME: }
// CHECK-LABEL: @"$S13generic_types1CCMP" = internal constant
// CHECK-SAME: void ([[C]]*)* @"$S13generic_types1CCfD",
-// CHECK-SAME: i8** @"$SBoWV",
-// CHECK-SAME: i64 0,
-// CHECK-SAME: %swift.type* null,
-// CHECK-native-SAME: %swift.opaque* null,
-// CHECK-objc-SAME: %swift.opaque* @_objc_empty_cache,
-// CHECK-SAME: %swift.opaque* null,
-// CHECK-SAME: i64 {{1|2}},
-// CHECK-SAME: i32 {{3|2}},
-// CHECK-SAME: i32 0,
-// CHECK-SAME: i32 24,
-// CHECK-SAME: i16 7,
-// CHECK-SAME: i16 0,
-// CHECK-SAME: i32 160,
-// CHECK-SAME: i32 16,
-// -- nominal type descriptor
-// CHECK-SAME: @"$S13generic_types1CCMn",
// -- ivar destroyer
// CHECK-SAME: i8* null
+// CHECK-SAME: i32 {{3|2}},
// CHECK-SAME: }
// CHECK-LABEL: @"$S13generic_types1DCMP" = internal constant
// CHECK-SAME: void ([[D]]*)* @"$S13generic_types1DCfD",
-// CHECK-SAME: i8** @"$SBoWV",
-// CHECK-SAME: i64 0,
-// CHECK-SAME: %swift.type* null,
-// CHECK-native-SAME: %swift.opaque* null,
-// CHECK-objc-SAME: %swift.opaque* @_objc_empty_cache,
-// CHECK-SAME: %swift.opaque* null,
-// CHECK-SAME: i64 {{1|2}},
-// CHECK-SAME: i32 {{3|2}},
-// CHECK-SAME: i32 0,
-// CHECK-SAME: i32 24,
-// CHECK-SAME: i16 7,
-// CHECK-SAME: i16 0,
-// CHECK-SAME: i32 160,
-// CHECK-SAME: i32 16,
-// -- nominal type descriptor
-// CHECK-SAME: @"$S13generic_types1DCMn",
// -- ivar destroyer
// CHECK-SAME: i8* null
+// CHECK-SAME: i32 {{3|2}},
// CHECK-SAME: }
// CHECK-LABEL: define{{( protected)?}} internal %swift.type* @"$S13generic_types1ACMi"(%swift.type_descriptor*, i8**) {{.*}} {
// CHECK: [[T0:%.*]] = bitcast i8** %1 to %swift.type**
// CHECK: %T = load %swift.type*, %swift.type** [[T0]],
-// CHECK-native: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** bitcast ({{.*}}* @"$S13generic_types1ACMP" to i8**), i64 96, i64 16, i8** %1, %objc_class* null, i64 7)
-// CHECK-objc: [[T0:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$__TtCs12_SwiftObject"
-// CHECK-objc: [[SUPER:%.*]] = call %objc_class* @swift_getInitializedObjCClass(%objc_class* [[T0]])
-// CHECK-objc: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** bitcast ({{.*}}* @"$S13generic_types1ACMP" to i8**), i64 280, i64 200, i8** %1, %objc_class* [[SUPER]], i64 7)
+// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** %1, i8** bitcast ({{.*}}* @"$S13generic_types1ACMP" to i8**))
// CHECK: [[SELF_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i64 10
// CHECK: [[T0:%.*]] = bitcast %swift.type* %T to i8*
@@ -127,10 +92,7 @@
// CHECK-LABEL: define{{( protected)?}} internal %swift.type* @"$S13generic_types1BCMi"(%swift.type_descriptor*, i8**) {{.*}} {
// CHECK: [[T0:%.*]] = bitcast i8** %1 to %swift.type**
// CHECK: %T = load %swift.type*, %swift.type** [[T0]],
-// CHECK-native: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** bitcast ({{.*}}* @"$S13generic_types1BCMP" to i8**), i64 96, i64 16, i8** %1, %objc_class* null, i64 6)
-// CHECK-objc: [[T0:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$__TtCs12_SwiftObject"
-// CHECK-objc: [[SUPER:%.*]] = call %objc_class* @swift_getInitializedObjCClass(%objc_class* [[T0]])
-// CHECK-objc: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** bitcast ({{.*}}* @"$S13generic_types1BCMP" to i8**), i64 280, i64 200, i8** %1, %objc_class* [[SUPER]], i64 6)
+// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** %1, i8** bitcast ({{.*}}* @"$S13generic_types1BCMP" to i8**))
// CHECK: [[SELF_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
// CHECK: [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i64 10
// CHECK: [[T0:%.*]] = bitcast %swift.type* %T to i8*
diff --git a/test/IRGen/generic_vtable.swift b/test/IRGen/generic_vtable.swift
index dd5c8f0..4b972ef 100644
--- a/test/IRGen/generic_vtable.swift
+++ b/test/IRGen/generic_vtable.swift
@@ -63,8 +63,6 @@
//// instantiation time.
// CHECK-LABEL: @"$S14generic_vtable7DerivedCMP" = internal constant <{{.*}}> <{
-// -- nominal type descriptor
-// CHECK-SAME: @"$S14generic_vtable7DerivedCMn",
// -- ivar destroyer
// CHECK-SAME: i8* null
// --
@@ -105,7 +103,7 @@
// - 2 immediate members:
// - type metadata for generic parameter T,
// - and vtable entry for 'm3()'
-// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** bitcast ({{.*}} @"$S14generic_vtable7DerivedCMP" to i8**), i64 {{[0-9]+}}, i64 {{[0-9]+}}, i8** %1, {{.*}}, i64 2)
+// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_descriptor* %0, i8** %1, i8** bitcast ({{.*}} @"$S14generic_vtable7DerivedCMP" to i8**))
// CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 0, {{.*}})
diff --git a/test/IRGen/super.sil b/test/IRGen/super.sil
index 6128570..e236e47 100644
--- a/test/IRGen/super.sil
+++ b/test/IRGen/super.sil
@@ -54,7 +54,7 @@
// ChildToResilientParent is in our resilience domain - can load the superclass's metadata directly.
// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S5super22ChildToResilientParentC6methodyyF"(%T5super22ChildToResilientParentC* swiftself)
// CHECK: [[SUPER_METADATA:%.*]] = call %swift.type* @"$S15resilient_class22ResilientOutsideParentCMa"()
-// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S15resilient_class22ResilientOutsideParentCMo"
+// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS:{.*}]], {{.*}}* @"$S15resilient_class22ResilientOutsideParentCMo", i32 0, i32 0)
// CHECK: [[VTABLE_OFFSET:%.*]] = add [[INT]] [[BASE]], {{20|40}}
// CHECK: [[SUPER_ADDR:%.*]] = bitcast %swift.type* [[SUPER_METADATA]] to i8*
// CHECK: [[VTABLE_ADDR:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], [[INT]] [[VTABLE_OFFSET]]
@@ -76,7 +76,7 @@
// ChildToResilientParent is in our resilience domain - can load the superclass's metadata directly.
// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S5super22ChildToResilientParentC11classMethodyyFZ"(%swift.type* swiftself)
// CHECK: [[SUPER_METADATA:%.*]] = call %swift.type* @"$S15resilient_class22ResilientOutsideParentCMa"()
-// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S15resilient_class22ResilientOutsideParentCMo"
+// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S15resilient_class22ResilientOutsideParentCMo", i32 0, i32 0)
// CHECK: [[VTABLE_OFFSET:%.*]] = add [[INT]] [[BASE]], {{24|48}}
// CHECK: [[SUPER_ADDR:%.*]] = bitcast %swift.type* [[SUPER_METADATA]] to i8*
// CHECK: [[VTABLE_ADDR:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], [[INT]] [[VTABLE_OFFSET]]
@@ -151,7 +151,7 @@
// CHECK: [[OPAQUE_METADATA:%.*]] = bitcast %swift.type* [[METADATA]] to %swift.type**
// CHECK: [[SUPER_METADATA_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[OPAQUE_METADATA]], i32 1
// CHECK: [[SUPER_METADATA:%.*]] = load %swift.type*, %swift.type** [[SUPER_METADATA_PTR]]
-// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S15resilient_class22ResilientOutsideParentCMo"
+// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S15resilient_class22ResilientOutsideParentCMo", i32 0, i32 0)
// CHECK: [[VTABLE_OFFSET:%.*]] = add [[INT]] [[BASE]], {{20|40}}
// CHECK: [[SUPER_ADDR:%.*]] = bitcast %swift.type* [[SUPER_METADATA]] to i8*
// CHECK: [[VTABLE_ADDR:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], [[INT]] [[VTABLE_OFFSET]]
@@ -177,7 +177,7 @@
// CHECK: [[OPAQUE_METADATA:%.*]] = bitcast %swift.type* [[METADATA]] to %swift.type**
// CHECK: [[SUPER_METADATA_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[OPAQUE_METADATA]], i32 1
// CHECK: [[SUPER_METADATA:%.*]] = load %swift.type*, %swift.type** [[SUPER_METADATA_PTR]]
-// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* @"$S15resilient_class22ResilientOutsideParentCMo"
+// CHECK: [[BASE:%.*]] = load [[INT]], [[INT]]* getelementptr inbounds ([[BOUNDS]], [[BOUNDS]]* @"$S15resilient_class22ResilientOutsideParentCMo", i32 0, i32 0)
// CHECK: [[VTABLE_OFFSET:%.*]] = add [[INT]] [[BASE]], {{24|48}}
// CHECK: [[SUPER_ADDR:%.*]] = bitcast %swift.type* [[SUPER_METADATA]] to i8*
// CHECK: [[VTABLE_ADDR:%.*]] = getelementptr inbounds i8, i8* [[SUPER_ADDR]], [[INT]] [[VTABLE_OFFSET]]
diff --git a/test/Inputs/conditional_conformance_basic_conformances.swift b/test/Inputs/conditional_conformance_basic_conformances.swift
index 047a9cb..fdbf82c 100644
--- a/test/Inputs/conditional_conformance_basic_conformances.swift
+++ b/test/Inputs/conditional_conformance_basic_conformances.swift
@@ -323,3 +323,11 @@
func dynamicCastToP1(_ value: Any) -> P1? {
return value as? P1
}
+
+protocol P4 {}
+typealias P4Typealias = P4
+protocol P5 {}
+
+struct SR7101<T> {}
+extension SR7101 : P5 where T == P4Typealias {}
+
diff --git a/test/Misc/Inputs/serialized-diagnostics-batch-mode-helper.swift b/test/Misc/Inputs/serialized-diagnostics-batch-mode-helper.swift
new file mode 100644
index 0000000..d65201b
--- /dev/null
+++ b/test/Misc/Inputs/serialized-diagnostics-batch-mode-helper.swift
@@ -0,0 +1,3 @@
+func testHelper() {
+ nonexistent()
+}
diff --git a/test/Misc/Inputs/serialized-diagnostics-batch-mode-other.swift b/test/Misc/Inputs/serialized-diagnostics-batch-mode-other.swift
new file mode 100644
index 0000000..d0d8ce2
--- /dev/null
+++ b/test/Misc/Inputs/serialized-diagnostics-batch-mode-other.swift
@@ -0,0 +1,6 @@
+func foo() {}
+func foo() {}
+
+func bar() {
+ shouldNotShowUpInOutput()
+}
diff --git a/test/Misc/serialized-diagnostics-batch-mode.swift b/test/Misc/serialized-diagnostics-batch-mode.swift
new file mode 100644
index 0000000..2b25fab
--- /dev/null
+++ b/test/Misc/serialized-diagnostics-batch-mode.swift
@@ -0,0 +1,33 @@
+// RUN: rm -f %t.*
+
+// RUN: not %target-swift-frontend -typecheck -primary-file %s -serialize-diagnostics-path %t.main.dia -primary-file %S/Inputs/serialized-diagnostics-batch-mode-helper.swift -serialize-diagnostics-path %t.helper.dia %S/Inputs/serialized-diagnostics-batch-mode-other.swift 2> %t.stderr.txt
+// RUN: %FileCheck -check-prefix=CHECK-STDERR %s < %t.stderr.txt
+// RUN: %FileCheck -check-prefix=NEGATIVE-STDERR %s < %t.stderr.txt
+
+// RUN: c-index-test -read-diagnostics %t.main.dia 2> %t.main.txt
+// RUN: %FileCheck -check-prefix=CHECK-MAIN %s < %t.main.txt
+// RUN: %FileCheck -check-prefix=NEGATIVE-MAIN %s < %t.main.txt
+
+// RUN: c-index-test -read-diagnostics %t.helper.dia 2> %t.helper.txt
+// RUN: %FileCheck -check-prefix=CHECK-HELPER %s < %t.helper.txt
+// RUN: %FileCheck -check-prefix=NEGATIVE-HELPER %s < %t.helper.txt
+
+// NEGATIVE-MAIN-NOT: shouldNotShowUpInOutput
+// NEGATIVE-HELPER-NOT: shouldNotShowUpInOutput
+// NEGATIVE-STDERR-NOT: shouldNotShowUpInOutput
+
+// NEGATIVE-MAIN-NOT: serialized-diagnostics-batch-mode-helper.swift
+// NEGATIVE-HELPER-NOT: serialized-diagnostics-batch-mode.swift
+
+// CHECK-MAIN-DAG: serialized-diagnostics-batch-mode-other.swift:{{[0-9]+}}:6: error: invalid redeclaration of 'foo()'
+// CHECK-HELPER-DAG: serialized-diagnostics-batch-mode-other.swift:{{[0-9]+}}:6: error: invalid redeclaration of 'foo()'
+// CHECK-STDERR-DAG: serialized-diagnostics-batch-mode-other.swift:{{[0-9]+}}:6: error: invalid redeclaration of 'foo()'
+
+func test() {
+ nonexistent() // CHECK-MAIN-DAG: serialized-diagnostics-batch-mode.swift:[[@LINE]]:3: error: use of unresolved identifier 'nonexistent'
+ // CHECK-STDERR-DAG: serialized-diagnostics-batch-mode.swift:[[@LINE-1]]:3: error: use of unresolved identifier 'nonexistent'
+
+ // The other file has a similar call.
+ // CHECK-HELPER-DAG: serialized-diagnostics-batch-mode-helper.swift:{{[0-9]+}}:3: error: use of unresolved identifier 'nonexistent'
+ // CHECK-STDERR-DAG: serialized-diagnostics-batch-mode-helper.swift:{{[0-9]+}}:3: error: use of unresolved identifier 'nonexistent'
+}
diff --git a/test/Parse/ConditionalCompilation/language_version_explicit.swift b/test/Parse/ConditionalCompilation/language_version_explicit.swift
index 5baef8a..83fd2da 100644
--- a/test/Parse/ConditionalCompilation/language_version_explicit.swift
+++ b/test/Parse/ConditionalCompilation/language_version_explicit.swift
@@ -21,10 +21,19 @@
asdf asdf asdf asdf
#endif
-#if swift(>=4.0.1)
- let z = 1
+// NOTE: Please modify this condition...
+#if swift(>=4.2)
+ let b = 1
#else
// This shouldn't emit any diagnostics.
asdf asdf asdf asdf
#endif
+// NOTE: ...and modify this condition...
+#if swift(>=4.2.1)
+ // This shouldn't emit any diagnostics.
+ asdf asdf asdf asdf
+#else
+ let c = 1
+#endif
+// NOTE: ...the next time the version goes up.
diff --git a/test/SILGen/shared.swift b/test/SILGen/shared.swift
index b0d549a..dd3c974 100644
--- a/test/SILGen/shared.swift
+++ b/test/SILGen/shared.swift
@@ -124,3 +124,58 @@
// CHECK-LABEL: sil hidden @$S6shared0A17_closure_loweringyyySi_AA14ValueAggregateVAA03RefE0CtchF : $@convention(thin) (@guaranteed @callee_guaranteed (Int, @owned ValueAggregate, @owned RefAggregate) -> ()) -> ()
func shared_closure_lowering(_ f : __shared (Int, ValueAggregate, RefAggregate) -> Void) {}
+
+struct Foo {
+ var x: ValueAggregate
+
+ // CHECK-LABEL: sil hidden @$S6shared3FooV21methodSharedArguments7trivial5value3refySih_AA14ValueAggregateVhAA03RefJ0ChtF : $@convention(method) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate, @guaranteed Foo) -> () {
+ func methodSharedArguments(trivial : __shared Int, value : __shared ValueAggregate, ref : __shared RefAggregate) {
+ // CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @guaranteed $ValueAggregate, [[REF_VAL:%[0-9]+]] : @guaranteed $RefAggregate, [[SELF:%[0-9]+]] : @guaranteed $Foo):
+ // CHECK: [[COPY_VALUE_VAL:%[0-9]+]] = copy_value [[VALUE_VAL]] : $ValueAggregate
+ // CHECK: [[COPY_REF_VAL:%[0-9]+]] = copy_value [[REF_VAL]] : $RefAggregate
+ // CHECK: [[OWNED_FUNC:%[0-9]+]] = function_ref @$S6shared3FooV20methodOwnedArguments7trivial5value3refySi_AA14ValueAggregateVAA03RefJ0CtF
+ // CHECK: {{%.*}} = apply [[OWNED_FUNC]]([[TRIVIAL_VAL]], [[COPY_VALUE_VAL]], [[COPY_REF_VAL]], [[SELF]]) : $@convention(method) (Int, @owned ValueAggregate, @owned RefAggregate, @guaranteed Foo) -> ()
+ // CHECK: } // end sil function '$S6shared3FooV21methodSharedArguments7trivial5value3refySih_AA14ValueAggregateVhAA03RefJ0ChtF'
+ return methodOwnedArguments(trivial: trivial, value: value, ref: ref)
+ }
+
+ // CHECK-LABEL: sil hidden @$S6shared3FooV20methodOwnedArguments7trivial5value3refySi_AA14ValueAggregateVAA03RefJ0CtF : $@convention(method) (Int, @owned ValueAggregate, @owned RefAggregate, @guaranteed Foo) -> () {
+ func methodOwnedArguments(trivial : Int, value : ValueAggregate, ref : RefAggregate) {
+ // CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @owned $ValueAggregate, [[REF_VAL:%[0-9]+]] : @owned $RefAggregate, [[SELF:%[0-9]+]] : @guaranteed $Foo):
+ // CHECK: [[BORROW_VALUE_VAL:%[0-9]+]] = begin_borrow [[VALUE_VAL]] : $ValueAggregate
+ // CHECK: [[BORROW_REF_VAL:%[0-9]+]] = begin_borrow [[REF_VAL]] : $RefAggregate
+ // CHECK: [[SHARED_FUNC:%[0-9]+]] = function_ref @$S6shared3FooV21methodSharedArguments7trivial5value3refySih_AA14ValueAggregateVhAA03RefJ0ChtF
+ // CHECK: {{%.*}} = apply [[SHARED_FUNC]]([[TRIVIAL_VAL]], [[BORROW_VALUE_VAL]], [[BORROW_REF_VAL]], [[SELF]])
+ // CHECK: end_borrow [[BORROW_REF_VAL]] from [[REF_VAL]] : $RefAggregate, $RefAggregate
+ // CHECK: end_borrow [[BORROW_VALUE_VAL]] from [[VALUE_VAL]] : $ValueAggregate, $ValueAggregate
+ // CHECK: destroy_value [[REF_VAL]] : $RefAggregate
+ // CHECK: destroy_value [[VALUE_VAL]] : $ValueAggregate
+ // CHECK: } // end sil function '$S6shared3FooV20methodOwnedArguments7trivial5value3refySi_AA14ValueAggregateVAA03RefJ0CtF'
+ return methodSharedArguments(trivial: trivial, value: value, ref: ref)
+ }
+
+ // CHECK-LABEL: sil hidden @$S6shared3FooV21staticSharedArguments7trivial5value3refySih_AA14ValueAggregateVhAA03RefJ0ChtFZ : $@convention(method) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate, @thin Foo.Type) -> () {
+ static func staticSharedArguments(trivial : __shared Int, value : __shared ValueAggregate, ref : __shared RefAggregate) {
+ // CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @guaranteed $ValueAggregate, [[REF_VAL:%[0-9]+]] : @guaranteed $RefAggregate, [[SELF_METATYPE:%[0-9]+]] : @trivial $@thin Foo.Type):
+ // CHECK: [[COPY_VALUE_VAL:%[0-9]+]] = copy_value [[VALUE_VAL]] : $ValueAggregate
+ // CHECK: [[COPY_REF_VAL:%[0-9]+]] = copy_value [[REF_VAL]] : $RefAggregate
+ // CHECK: [[OWNED_FUNC:%[0-9]+]] = function_ref @$S6shared3FooV20staticOwnedArguments7trivial5value3refySi_AA14ValueAggregateVAA03RefJ0CtFZ
+ // CHECK: {{%.*}} = apply [[OWNED_FUNC]]([[TRIVIAL_VAL]], [[COPY_VALUE_VAL]], [[COPY_REF_VAL]], [[SELF_METATYPE]]) : $@convention(method) (Int, @owned ValueAggregate, @owned RefAggregate, @thin Foo.Type) -> ()
+ // CHECK: } // end sil function '$S6shared3FooV21staticSharedArguments7trivial5value3refySih_AA14ValueAggregateVhAA03RefJ0ChtFZ'
+ return staticOwnedArguments(trivial: trivial, value: value, ref: ref)
+ }
+ // CHECK-LABEL: sil hidden @$S6shared3FooV20staticOwnedArguments7trivial5value3refySi_AA14ValueAggregateVAA03RefJ0CtFZ : $@convention(method) (Int, @owned ValueAggregate, @owned RefAggregate, @thin Foo.Type) -> () {
+ static func staticOwnedArguments(trivial : Int, value : ValueAggregate, ref : RefAggregate) {
+ // CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @owned $ValueAggregate, [[REF_VAL:%[0-9]+]] : @owned $RefAggregate, [[SELF_METATYPE:%[0-9]+]] : @trivial $@thin Foo.Type):
+ // CHECK: [[BORROW_VALUE_VAL:%[0-9]+]] = begin_borrow [[VALUE_VAL]] : $ValueAggregate
+ // CHECK: [[BORROW_REF_VAL:%[0-9]+]] = begin_borrow [[REF_VAL]] : $RefAggregate
+ // CHECK: [[SHARED_FUNC:%[0-9]+]] = function_ref @$S6shared3FooV21staticSharedArguments7trivial5value3refySih_AA14ValueAggregateVhAA03RefJ0ChtFZ
+ // CHECK: {{%.*}} = apply [[SHARED_FUNC]]([[TRIVIAL_VAL]], [[BORROW_VALUE_VAL]], [[BORROW_REF_VAL]], [[SELF_METATYPE]])
+ // CHECK: end_borrow [[BORROW_REF_VAL]] from [[REF_VAL]] : $RefAggregate, $RefAggregate
+ // CHECK: end_borrow [[BORROW_VALUE_VAL]] from [[VALUE_VAL]] : $ValueAggregate, $ValueAggregate
+ // CHECK: destroy_value [[REF_VAL]] : $RefAggregate
+ // CHECK: destroy_value [[VALUE_VAL]] : $ValueAggregate
+ // CHECK: } // end sil function '$S6shared3FooV20staticOwnedArguments7trivial5value3refySi_AA14ValueAggregateVAA03RefJ0CtFZ'
+ return staticSharedArguments(trivial: trivial, value: value, ref: ref)
+ }
+}
diff --git a/test/SILOptimizer/access_enforcement_selection.sil b/test/SILOptimizer/access_enforcement_selection.sil
index edc9bab..da682f9 100644
--- a/test/SILOptimizer/access_enforcement_selection.sil
+++ b/test/SILOptimizer/access_enforcement_selection.sil
@@ -228,3 +228,36 @@
%closure = partial_apply %f(%0) : $@convention(thin) (@inout_aliasable Builtin.Int64) -> ()
unreachable
}
+
+sil [canonical] @serializedClosureCapturingByStorageAddress : $@convention(thin) (@inout_aliasable Builtin.Int64) -> () {
+bb0(%0 : @trivial $*Builtin.Int64):
+ %2 = begin_access [read] [unknown] %0 : $*Builtin.Int64
+ %3 = load [trivial] %2 : $*Builtin.Int64
+ end_access %2 : $*Builtin.Int64
+ %10 = tuple ()
+ return %10 : $()
+}
+
+// A begin_access may not be used by a partial_apply or a nested
+// begin_access prior to mandatory inlining. Nonetheless, this does
+// occur in deserialzied SIL. This SIL is only well-formed because the
+// function is marked [canonical].
+sil [canonical] @accessAroundClosure : $@convention(thin) () -> () {
+bb0:
+ %1 = alloc_box ${ var Builtin.Int64 }, var, name "x"
+ %2 = copy_value %1 : ${ var Builtin.Int64 }
+ %3 = project_box %1 : ${ var Builtin.Int64 }, 0
+ // outer access (presumably its uses were mandatory inlined)
+ %4 = begin_access [modify] [static] %3 : $*Builtin.Int64
+ %5 = function_ref @serializedClosureCapturingByStorageAddress : $@convention(thin) (@inout_aliasable Builtin.Int64) -> ()
+ %6 = partial_apply %5(%4) : $@convention(thin) (@inout_aliasable Builtin.Int64) -> ()
+ %7 = begin_access [modify] [static] %4 : $*Builtin.Int64
+ %8 = function_ref @takesInoutAndClosure : $@convention(thin) (@inout Builtin.Int64, @owned @callee_owned () -> ()) -> ()
+ %9 = apply %8(%7, %6) : $@convention(thin) (@inout Builtin.Int64, @owned @callee_owned () -> ()) -> ()
+ end_access %7 : $*Builtin.Int64
+ end_access %4 : $*Builtin.Int64
+ destroy_value %2 : ${ var Builtin.Int64 }
+ destroy_value %1 : ${ var Builtin.Int64 }
+ %10 = tuple ()
+ return %10 : $()
+}
diff --git a/test/Serialization/Recovery/crash-recovery.swift b/test/Serialization/Recovery/crash-recovery.swift
index aecd4d2..e198b5d 100644
--- a/test/Serialization/Recovery/crash-recovery.swift
+++ b/test/Serialization/Recovery/crash-recovery.swift
@@ -14,7 +14,7 @@
// CHECK-CRASH: error: fatal error encountered while reading from module 'Lib'; please file a bug report with your project and the crash log
// CHECK-CRASH-3-NOT: note
-// CHECK-CRASH-4: note: compiling as Swift 4.1, with 'Lib' built as Swift 3.3
+// CHECK-CRASH-4: note: compiling as Swift 4.2, with 'Lib' built as Swift 3.4
// CHECK-CRASH-LABEL: *** DESERIALIZATION FAILURE (please include this section in any bug report) ***
// CHECK-CRASH: could not find 'disappearingMethod()' in parent class
// CHECK-CRASH: While loading members for 'Sub' in module 'Lib'
diff --git a/test/Serialization/Recovery/types-4-to-3.swift b/test/Serialization/Recovery/types-4-to-3.swift
index 380c3d0..f1e216f 100644
--- a/test/Serialization/Recovery/types-4-to-3.swift
+++ b/test/Serialization/Recovery/types-4-to-3.swift
@@ -16,8 +16,8 @@
func requiresConformance(_: B_RequiresConformance<B_ConformsToProto>) {}
func requiresConformance(_: B_RequiresConformance<C_RelyOnConformanceImpl.Assoc>) {}
-class Sub: Base {} // expected-error {{cannot inherit from class 'Base' (compiled with Swift 4.1) because it has overridable members that could not be loaded in Swift 3.3}}
-class Impl: Proto {} // expected-error {{type 'Impl' cannot conform to protocol 'Proto' (compiled with Swift 4.1) because it has requirements that could not be loaded in Swift 3.3}}
+class Sub: Base {} // expected-error {{cannot inherit from class 'Base' (compiled with Swift 4.2) because it has overridable members that could not be loaded in Swift 3.4}}
+class Impl: Proto {} // expected-error {{type 'Impl' cannot conform to protocol 'Proto' (compiled with Swift 4.2) because it has requirements that could not be loaded in Swift 3.4}}
#else // TEST
diff --git a/test/Syntax/round_trip_nul.swift b/test/Syntax/round_trip_nul.swift
new file mode 100644
index 0000000..c53e9b9
--- /dev/null
+++ b/test/Syntax/round_trip_nul.swift
@@ -0,0 +1,5 @@
+// RUN: cat %s | tr '\132' '\0' > %t.tr
+// RUN: cp -f %t.tr %t
+// RUN: %round-trip-syntax-test --swift-syntax-test %swift-syntax-test --file %t
+let a = Z3Z // nul(Z)
+func b() {}
diff --git a/test/Syntax/tokens_nul.swift b/test/Syntax/tokens_nul.swift
new file mode 100644
index 0000000..4dd4efc
--- /dev/null
+++ b/test/Syntax/tokens_nul.swift
@@ -0,0 +1,28 @@
+// RUN: cat %s | tr '\132' '\0' > %t.tmp
+// RUN: cp -f %t.tmp %t
+// RUN: %swift-syntax-test -input-source-filename %t -dump-full-tokens 2>&1 | %FileCheck %t
+let a = Z3Z // nul(Z)
+func b() {}
+
+// CHECK: 4:9: warning: nul character embedded in middle of file
+// CHECK: 4:11: warning: nul character embedded in middle of file
+// CHECK: 4:20: warning: nul character embedded in middle of file
+
+// CHECK-LABEL: 4:7
+// CHECK-NEXT:(Token equal
+// CHECK-NEXT: (text="=")
+// CHECK-NEXT: (trivia space 1)
+// CHECK-NEXT: (trivia garbage_text \000))
+
+// CHECK-LABEL: 4:10
+// CHECK-NEXT:(Token integer_literal
+// CHECK-NEXT: (text="3")
+// CHECK-NEXT: (trivia garbage_text \000)
+// CHECK-NEXT: (trivia space 1))
+
+// CHECK-LABEL: 5:1
+// CHECK-NEXT:(Token kw_func
+// CHECK-NEXT: (trivia line_comment // nul(\000))
+// CHECK-NEXT: (trivia newline 1)
+// CHECK-NEXT: (text="func")
+// CHECK-NEXT: (trivia space 1))
diff --git a/test/api-digester/Outputs/cake.json b/test/api-digester/Outputs/cake.json
index b3e0f75..db252e1 100644
--- a/test/api-digester/Outputs/cake.json
+++ b/test/api-digester/Outputs/cake.json
@@ -425,6 +425,7 @@
"Hashable",
"RawRepresentable"
],
+ "enumRawTypeName": "Int",
"children": [
{
"kind": "Var",
diff --git a/tools/swift-api-digester/swift-api-digester.cpp b/tools/swift-api-digester/swift-api-digester.cpp
index e5576c1..4a21be6 100644
--- a/tools/swift-api-digester/swift-api-digester.cpp
+++ b/tools/swift-api-digester/swift-api-digester.cpp
@@ -328,11 +328,12 @@
bool IsMutating = false;
bool IsStatic = false;
Optional<uint8_t> SelfIndex;
- Ownership Ownership = Ownership::Strong;
+ ReferenceOwnership ReferenceOwnership = ReferenceOwnership::Strong;
std::vector<SDKDeclAttrKind> DeclAttrs;
std::vector<TypeAttrKind> TypeAttrs;
std::vector<StringRef> ConformingProtocols;
StringRef SuperclassUsr;
+ StringRef EnumRawTypeName;
ParentExtensionInfo *ExtInfo = nullptr;
TypeInitInfo TypeInfo;
@@ -402,17 +403,18 @@
StringRef ModuleName;
std::vector<SDKDeclAttrKind> DeclAttributes;
bool IsStatic;
- uint8_t Ownership;
+ uint8_t ReferenceOwnership;
bool hasDeclAttribute(SDKDeclAttrKind DAKind) const;
// Non-null ExtInfo implies this decl is defined in an type extension.
ParentExtensionInfo *ExtInfo;
protected:
- SDKNodeDecl(SDKNodeInitInfo Info, SDKNodeKind Kind) : SDKNode(Info, Kind),
- DKind(Info.DKind), Usr(Info.USR), Location(Info.Location),
- ModuleName(Info.ModuleName), DeclAttributes(Info.DeclAttrs),
- IsStatic(Info.IsStatic), Ownership(uint8_t(Info.Ownership)),
- ExtInfo(Info.ExtInfo) {}
+ SDKNodeDecl(SDKNodeInitInfo Info, SDKNodeKind Kind)
+ : SDKNode(Info, Kind), DKind(Info.DKind), Usr(Info.USR),
+ Location(Info.Location), ModuleName(Info.ModuleName),
+ DeclAttributes(Info.DeclAttrs), IsStatic(Info.IsStatic),
+ ReferenceOwnership(uint8_t(Info.ReferenceOwnership)),
+ ExtInfo(Info.ExtInfo) {}
public:
StringRef getUsr() const { return Usr; }
@@ -421,7 +423,9 @@
StringRef getHeaderName() const;
void addDeclAttribute(SDKDeclAttrKind DAKind);
ArrayRef<SDKDeclAttrKind> getDeclAttributes() const;
- swift::Ownership getOwnership() const { return swift::Ownership(Ownership); }
+ swift::ReferenceOwnership getReferenceOwnership() const {
+ return swift::ReferenceOwnership(ReferenceOwnership);
+ }
bool isObjc() const { return Usr.startswith("c:"); }
static bool classof(const SDKNode *N);
DeclKind getDeclKind() const { return DKind; }
@@ -776,13 +780,26 @@
class SDKNodeTypeDecl : public SDKNodeDecl {
StringRef SuperclassUsr;
std::vector<StringRef> ConformingProtocols;
+ StringRef EnumRawTypeName;
public:
SDKNodeTypeDecl(SDKNodeInitInfo Info) : SDKNodeDecl(Info, SDKNodeKind::TypeDecl),
SuperclassUsr(Info.SuperclassUsr),
- ConformingProtocols(Info.ConformingProtocols){}
+ ConformingProtocols(Info.ConformingProtocols),
+ EnumRawTypeName(Info.EnumRawTypeName) {}
static bool classof(const SDKNode *N);
StringRef getSuperClassUsr() const { return SuperclassUsr; }
ArrayRef<StringRef> getAllProtocols() const { return ConformingProtocols; }
+
+#define NOMINAL_TYPE_DECL(ID, PARENT) \
+ bool is##ID() const { return getDeclKind() == DeclKind::ID; }
+#define DECL(ID, PARENT)
+#include "swift/AST/DeclNodes.def"
+
+ StringRef getEnumRawTypeName() const {
+ assert(isEnum());
+ return EnumRawTypeName;
+ }
+
Optional<SDKNodeTypeDecl*> getSuperclass() const {
if (SuperclassUsr.empty())
return None;
@@ -956,6 +973,11 @@
}
break;
}
+ case KeyKind::KK_enumRawTypeName: {
+ assert(Info.DKind == DeclKind::Enum);
+ Info.EnumRawTypeName = GetScalarString(Pair.getValue());
+ break;
+ }
case KeyKind::KK_printedName:
Info.PrintedName = GetScalarString(Pair.getValue());
break;
@@ -978,8 +1000,9 @@
Info.IsStatic = true;
break;
case KeyKind::KK_ownership:
- Info.Ownership = swift::Ownership(getAsInt(Pair.getValue()));
- assert(Info.Ownership != swift::Ownership::Strong &&
+ Info.ReferenceOwnership =
+ swift::ReferenceOwnership(getAsInt(Pair.getValue()));
+ assert(Info.ReferenceOwnership != swift::ReferenceOwnership::Strong &&
"Strong is implied.");
break;
@@ -1077,7 +1100,7 @@
auto Right = (&Other)->getAs<SDKNodeDecl>();
if (Left->isStatic() ^ Right->isStatic())
return false;
- if (Left->getOwnership() != Right->getOwnership())
+ if (Left->getReferenceOwnership() != Right->getReferenceOwnership())
return false;
LLVM_FALLTHROUGH;
}
@@ -1238,11 +1261,11 @@
return None;
}
-static Ownership getOwnership(ValueDecl *VD) {
- if (auto OA = VD->getAttrs().getAttribute<OwnershipAttr>()) {
+static ReferenceOwnership getReferenceOwnership(ValueDecl *VD) {
+ if (auto OA = VD->getAttrs().getAttribute<ReferenceOwnershipAttr>()) {
return OA->get();
}
- return Ownership::Strong;
+ return ReferenceOwnership::Strong;
}
SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, Type Ty,
@@ -1254,14 +1277,15 @@
TypeAttrs.push_back(TypeAttrKind::TAK_noescape);
}
-SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, ValueDecl *VD) : Ctx(Ctx),
- Name(VD->hasName() ? getEscapedName(VD->getBaseName()) : Ctx.buffer("_")),
- PrintedName(getPrintedName(Ctx, VD)), DKind(VD->getKind()),
- USR(calculateUsr(Ctx, VD)), Location(calculateLocation(Ctx, VD)),
- ModuleName(VD->getModuleContext()->getName().str()),
- IsThrowing(isFuncThrowing(VD)), IsMutating(isFuncMutating(VD)),
- IsStatic(VD->isStatic()), SelfIndex(getSelfIndex(VD)),
- Ownership(getOwnership(VD)), ExtInfo(nullptr) {
+SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, ValueDecl *VD)
+ : Ctx(Ctx),
+ Name(VD->hasName() ? getEscapedName(VD->getBaseName()) : Ctx.buffer("_")),
+ PrintedName(getPrintedName(Ctx, VD)), DKind(VD->getKind()),
+ USR(calculateUsr(Ctx, VD)), Location(calculateLocation(Ctx, VD)),
+ ModuleName(VD->getModuleContext()->getName().str()),
+ IsThrowing(isFuncThrowing(VD)), IsMutating(isFuncMutating(VD)),
+ IsStatic(VD->isStatic()), SelfIndex(getSelfIndex(VD)),
+ ReferenceOwnership(getReferenceOwnership(VD)), ExtInfo(nullptr) {
// Calculate usr for its super class.
if (auto *CD = dyn_cast_or_null<ClassDecl>(VD)) {
@@ -1289,6 +1313,15 @@
ConformingProtocols.push_back(P->getName().str());
}
}
+
+ // Get enum raw type name if this is an enum.
+ if (auto *ED = dyn_cast<EnumDecl>(VD)) {
+ if (auto RT = ED->getRawType()) {
+ if (auto *D = RT->getNominalOrBoundGenericNominal()) {
+ EnumRawTypeName = D->getName().str();
+ }
+ }
+ }
}
SDKNode *SDKNodeInitInfo::createSDKNode(SDKNodeKind Kind) {
@@ -1670,6 +1703,14 @@
KeyKind::KK_conformingProtocols).data(),
Pros);
}
+
+ auto RawTypeName = TD->isEnum() ? TD->getEnumRawTypeName() : StringRef();
+ if (!RawTypeName.empty()) {
+ out.mapRequired(getKeyContent(Ctx,
+ KeyKind::KK_enumRawTypeName).data(),
+ RawTypeName);
+ }
+
}
if (D->isFromExtension()) {
// Even if we don't have any requirements on this parent extension,
@@ -1685,8 +1726,8 @@
out.mapRequired(getKeyContent(Ctx, KeyKind::KK_declAttributes).data(),
Attributes);
// Strong reference is implied, no need for serialization.
- if (D->getOwnership() != Ownership::Strong) {
- uint8_t Raw = uint8_t(D->getOwnership());
+ if (D->getReferenceOwnership() != ReferenceOwnership::Strong) {
+ uint8_t Raw = uint8_t(D->getReferenceOwnership());
out.mapRequired(getKeyContent(Ctx, KeyKind::KK_ownership).data(), Raw);
}
} else if (auto T = dyn_cast<SDKNodeType>(value)) {
@@ -2250,7 +2291,7 @@
auto *RD = R->getAs<SDKNodeDecl>();
if (LD->isStatic() ^ RD->isStatic())
L->annotate(NodeAnnotation::StaticChange);
- if (LD->getOwnership() != RD->getOwnership())
+ if (LD->getReferenceOwnership() != RD->getReferenceOwnership())
L->annotate(NodeAnnotation::OwnershipChange);
detectRename(L, R);
}
@@ -3093,22 +3134,25 @@
return;
}
case NodeAnnotation::OwnershipChange: {
- auto getOwnershipDescription = [&](swift::Ownership O) {
+ auto getOwnershipDescription = [&](swift::ReferenceOwnership O) {
switch (O) {
- case Ownership::Strong: return Ctx.buffer("strong");
- case Ownership::Weak: return Ctx.buffer("weak");
- case Ownership::Unowned: return Ctx.buffer("unowned");
- case Ownership::Unmanaged: return Ctx.buffer("unowned(unsafe)");
+ case ReferenceOwnership::Strong:
+ return Ctx.buffer("strong");
+ case ReferenceOwnership::Weak:
+ return Ctx.buffer("weak");
+ case ReferenceOwnership::Unowned:
+ return Ctx.buffer("unowned");
+ case ReferenceOwnership::Unmanaged:
+ return Ctx.buffer("unowned(unsafe)");
}
llvm_unreachable("Unhandled Ownership in switch.");
};
auto *Count = UpdateMap.findUpdateCounterpart(Node)->getAs<SDKNodeDecl>();
- AttrChangedDecls.Diags.emplace_back(ScreenInfo,
- Node->getDeclKind(),
- Node->getFullyQualifiedName(),
- getOwnershipDescription(Node->getOwnership()),
- getOwnershipDescription(Count->getOwnership()));
+ AttrChangedDecls.Diags.emplace_back(
+ ScreenInfo, Node->getDeclKind(), Node->getFullyQualifiedName(),
+ getOwnershipDescription(Node->getReferenceOwnership()),
+ getOwnershipDescription(Count->getReferenceOwnership()));
return;
}
default:
diff --git a/tools/swift-syntax-test/swift-syntax-test.cpp b/tools/swift-syntax-test/swift-syntax-test.cpp
index f4d00a9..3f4e8b0 100644
--- a/tools/swift-syntax-test/swift-syntax-test.cpp
+++ b/tools/swift-syntax-test/swift-syntax-test.cpp
@@ -112,11 +112,13 @@
int getTokensFromFile(unsigned BufferID,
LangOptions &LangOpts,
SourceManager &SourceMgr,
- DiagnosticEngine &Diags,
+ swift::DiagnosticEngine &Diags,
std::vector<std::pair<RC<syntax::RawSyntax>,
syntax::AbsolutePosition>> &Tokens) {
- Tokens = tokenizeWithTrivia(LangOpts, SourceMgr, BufferID);
- return Diags.hadAnyError() ? EXIT_FAILURE : EXIT_SUCCESS;
+ Tokens = tokenizeWithTrivia(LangOpts, SourceMgr, BufferID,
+ /*Offset=*/0, /*EndOffset=*/0,
+ &Diags);
+ return EXIT_SUCCESS;
}
@@ -191,7 +193,7 @@
TokAndPos.first->print(llvm::outs(), {});
}
- return Diags.hadAnyError() ? EXIT_FAILURE : EXIT_SUCCESS;
+ return EXIT_SUCCESS;
}
int doDumpRawTokenSyntax(const StringRef InputFilename) {
@@ -215,7 +217,7 @@
llvm::outs() << "\n";
}
- return Diags.hadAnyError() ? EXIT_FAILURE : EXIT_SUCCESS;
+ return EXIT_SUCCESS;
}
int doFullParseRoundTrip(const char *MainExecutablePath,
diff --git a/unittests/AST/CMakeLists.txt b/unittests/AST/CMakeLists.txt
index da8699c..5c58c84 100644
--- a/unittests/AST/CMakeLists.txt
+++ b/unittests/AST/CMakeLists.txt
@@ -1,4 +1,5 @@
add_swift_unittest(SwiftASTTests
+ DiagnosticConsumerTests.cpp
SourceLocTests.cpp
TestContext.cpp
TypeMatchTests.cpp
diff --git a/unittests/AST/DiagnosticConsumerTests.cpp b/unittests/AST/DiagnosticConsumerTests.cpp
new file mode 100644
index 0000000..2339395
--- /dev/null
+++ b/unittests/AST/DiagnosticConsumerTests.cpp
@@ -0,0 +1,533 @@
+//===--- DiagnosticConsumerTests.cpp --------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "swift/AST/DiagnosticConsumer.h"
+#include "swift/Basic/SourceManager.h"
+#include "gtest/gtest.h"
+
+using namespace swift;
+
+namespace {
+ using ExpectedDiagnostic = std::pair<SourceLoc, StringRef>;
+
+ class ExpectationDiagnosticConsumer: public DiagnosticConsumer {
+ ExpectationDiagnosticConsumer *previous;
+ SmallVector<ExpectedDiagnostic, 4> expected;
+ bool hasFinished = false;
+
+ public:
+ ExpectationDiagnosticConsumer(ExpectationDiagnosticConsumer *previous,
+ ArrayRef<ExpectedDiagnostic> expected)
+ : previous(previous), expected(expected.begin(), expected.end()) {}
+
+ ~ExpectationDiagnosticConsumer() override {
+ EXPECT_TRUE(hasFinished);
+ EXPECT_TRUE(expected.empty());
+ }
+
+ void handleDiagnostic(SourceManager &SM, SourceLoc loc, DiagnosticKind kind,
+ StringRef formatString,
+ ArrayRef<DiagnosticArgument> formatArgs,
+ const DiagnosticInfo &info) override {
+ ASSERT_FALSE(expected.empty());
+ EXPECT_EQ(std::make_pair(loc, formatString), expected.front());
+ expected.erase(expected.begin());
+ }
+
+ bool finishProcessing() override {
+ EXPECT_FALSE(hasFinished);
+ if (previous)
+ EXPECT_TRUE(previous->hasFinished);
+ hasFinished = true;
+ return false;
+ }
+ };
+} // end anonymous namespace
+
+TEST(FileSpecificDiagnosticConsumer, SubConsumersFinishInOrder) {
+ SourceManager sourceMgr;
+ (void)sourceMgr.addMemBufferCopy("abcde", "A");
+ (void)sourceMgr.addMemBufferCopy("vwxyz", "B");
+
+ auto consumerA = llvm::make_unique<ExpectationDiagnosticConsumer>(
+ nullptr, None);
+ auto consumerUnaffiliated = llvm::make_unique<ExpectationDiagnosticConsumer>(
+ consumerA.get(), None);
+
+ SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 2> consumers;
+ consumers.emplace_back("A", std::move(consumerA));
+ consumers.emplace_back("", std::move(consumerUnaffiliated));
+
+ FileSpecificDiagnosticConsumer topConsumer(consumers);
+ topConsumer.finishProcessing();
+}
+
+TEST(FileSpecificDiagnosticConsumer, InvalidLocDiagsGoToEveryConsumer) {
+ SourceManager sourceMgr;
+ (void)sourceMgr.addMemBufferCopy("abcde", "A");
+ (void)sourceMgr.addMemBufferCopy("vwxyz", "B");
+
+ ExpectedDiagnostic expected[] = { {SourceLoc(), "dummy"} };
+ auto consumerA = llvm::make_unique<ExpectationDiagnosticConsumer>(
+ nullptr, expected);
+ auto consumerUnaffiliated = llvm::make_unique<ExpectationDiagnosticConsumer>(
+ consumerA.get(), expected);
+
+ SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 2> consumers;
+ consumers.emplace_back("A", std::move(consumerA));
+ consumers.emplace_back("", std::move(consumerUnaffiliated));
+
+ FileSpecificDiagnosticConsumer topConsumer(consumers);
+ topConsumer.handleDiagnostic(sourceMgr, SourceLoc(), DiagnosticKind::Error,
+ "dummy", {}, DiagnosticInfo());
+ topConsumer.finishProcessing();
+}
+
+TEST(FileSpecificDiagnosticConsumer, ErrorsWithLocationsGoToExpectedConsumers) {
+ SourceManager sourceMgr;
+ // 01234
+ unsigned bufferA = sourceMgr.addMemBufferCopy("abcde", "A");
+ unsigned bufferB = sourceMgr.addMemBufferCopy("vwxyz", "B");
+
+ SourceLoc frontOfA = sourceMgr.getLocForOffset(bufferA, 0);
+ SourceLoc middleOfA = sourceMgr.getLocForOffset(bufferA, 2);
+ SourceLoc backOfA = sourceMgr.getLocForOffset(bufferA, 4);
+
+ SourceLoc frontOfB = sourceMgr.getLocForOffset(bufferB, 0);
+ SourceLoc middleOfB = sourceMgr.getLocForOffset(bufferB, 2);
+ SourceLoc backOfB = sourceMgr.getLocForOffset(bufferB, 4);
+
+ ExpectedDiagnostic expectedA[] = {
+ {frontOfA, "front"},
+ {middleOfA, "middle"},
+ {backOfA, "back"},
+ };
+ ExpectedDiagnostic expectedB[] = {
+ {frontOfB, "front"},
+ {middleOfB, "middle"},
+ {backOfB, "back"}
+ };
+
+ auto consumerA = llvm::make_unique<ExpectationDiagnosticConsumer>(
+ nullptr, expectedA);
+ auto consumerB = llvm::make_unique<ExpectationDiagnosticConsumer>(
+ consumerA.get(), expectedB);
+
+ SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 2> consumers;
+ consumers.emplace_back("A", std::move(consumerA));
+ consumers.emplace_back("B", std::move(consumerB));
+
+ FileSpecificDiagnosticConsumer topConsumer(consumers);
+ topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
+ "front", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Error,
+ "front", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Error,
+ "middle", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Error,
+ "middle", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Error,
+ "back", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, backOfB, DiagnosticKind::Error,
+ "back", {}, DiagnosticInfo());
+ topConsumer.finishProcessing();
+}
+
+TEST(FileSpecificDiagnosticConsumer,
+ ErrorsInUnaffiliatedFilesGoToEveryConsumer) {
+ SourceManager sourceMgr;
+ // 01234
+ unsigned bufferA = sourceMgr.addMemBufferCopy("abcde", "A");
+ unsigned bufferB = sourceMgr.addMemBufferCopy("vwxyz", "B");
+
+ SourceLoc frontOfA = sourceMgr.getLocForOffset(bufferA, 0);
+ SourceLoc middleOfA = sourceMgr.getLocForOffset(bufferA, 2);
+ SourceLoc backOfA = sourceMgr.getLocForOffset(bufferA, 4);
+
+ SourceLoc frontOfB = sourceMgr.getLocForOffset(bufferB, 0);
+ SourceLoc middleOfB = sourceMgr.getLocForOffset(bufferB, 2);
+ SourceLoc backOfB = sourceMgr.getLocForOffset(bufferB, 4);
+
+ ExpectedDiagnostic expectedA[] = {
+ {frontOfA, "front"},
+ {frontOfB, "front"},
+ {middleOfA, "middle"},
+ {middleOfB, "middle"},
+ {backOfA, "back"},
+ {backOfB, "back"}
+ };
+ ExpectedDiagnostic expectedUnaffiliated[] = {
+ {frontOfB, "front"},
+ {middleOfB, "middle"},
+ {backOfB, "back"}
+ };
+
+ auto consumerA = llvm::make_unique<ExpectationDiagnosticConsumer>(
+ nullptr, expectedA);
+ auto consumerUnaffiliated = llvm::make_unique<ExpectationDiagnosticConsumer>(
+ consumerA.get(), expectedUnaffiliated);
+
+ SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 2> consumers;
+ consumers.emplace_back("A", std::move(consumerA));
+ consumers.emplace_back("", std::move(consumerUnaffiliated));
+
+ FileSpecificDiagnosticConsumer topConsumer(consumers);
+ topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
+ "front", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Error,
+ "front", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Error,
+ "middle", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Error,
+ "middle", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Error,
+ "back", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, backOfB, DiagnosticKind::Error,
+ "back", {}, DiagnosticInfo());
+ topConsumer.finishProcessing();
+}
+
+TEST(FileSpecificDiagnosticConsumer, WarningsAndRemarksAreTreatedLikeErrors) {
+ SourceManager sourceMgr;
+ // 01234
+ unsigned bufferA = sourceMgr.addMemBufferCopy("abcde", "A");
+ unsigned bufferB = sourceMgr.addMemBufferCopy("vwxyz", "B");
+
+ SourceLoc frontOfA = sourceMgr.getLocForBufferStart(bufferA);
+ SourceLoc frontOfB = sourceMgr.getLocForBufferStart(bufferB);
+
+ ExpectedDiagnostic expectedA[] = {
+ {frontOfA, "warning"},
+ {frontOfB, "warning"},
+ {frontOfA, "remark"},
+ {frontOfB, "remark"},
+ };
+ ExpectedDiagnostic expectedUnaffiliated[] = {
+ {frontOfB, "warning"},
+ {frontOfB, "remark"},
+ };
+
+ auto consumerA = llvm::make_unique<ExpectationDiagnosticConsumer>(
+ nullptr, expectedA);
+ auto consumerUnaffiliated = llvm::make_unique<ExpectationDiagnosticConsumer>(
+ consumerA.get(), expectedUnaffiliated);
+
+ SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 2> consumers;
+ consumers.emplace_back("A", std::move(consumerA));
+ consumers.emplace_back("", std::move(consumerUnaffiliated));
+
+ FileSpecificDiagnosticConsumer topConsumer(consumers);
+ topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Warning,
+ "warning", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Warning,
+ "warning", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Remark,
+ "remark", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Remark,
+ "remark", {}, DiagnosticInfo());
+ topConsumer.finishProcessing();
+}
+
+TEST(FileSpecificDiagnosticConsumer, NotesAreAttachedToErrors) {
+ SourceManager sourceMgr;
+ // 01234
+ unsigned bufferA = sourceMgr.addMemBufferCopy("abcde", "A");
+ unsigned bufferB = sourceMgr.addMemBufferCopy("vwxyz", "B");
+
+ SourceLoc frontOfA = sourceMgr.getLocForOffset(bufferA, 0);
+ SourceLoc middleOfA = sourceMgr.getLocForOffset(bufferA, 2);
+ SourceLoc backOfA = sourceMgr.getLocForOffset(bufferA, 4);
+
+ SourceLoc frontOfB = sourceMgr.getLocForOffset(bufferB, 0);
+ SourceLoc middleOfB = sourceMgr.getLocForOffset(bufferB, 2);
+ SourceLoc backOfB = sourceMgr.getLocForOffset(bufferB, 4);
+
+ ExpectedDiagnostic expectedA[] = {
+ {frontOfA, "error"},
+ {middleOfA, "note"},
+ {backOfA, "note"},
+ {frontOfB, "error"},
+ {middleOfB, "note"},
+ {backOfB, "note"},
+ {frontOfA, "error"},
+ {middleOfA, "note"},
+ {backOfA, "note"},
+ };
+ ExpectedDiagnostic expectedUnaffiliated[] = {
+ {frontOfB, "error"},
+ {middleOfB, "note"},
+ {backOfB, "note"},
+ };
+
+ auto consumerA = llvm::make_unique<ExpectationDiagnosticConsumer>(
+ nullptr, expectedA);
+ auto consumerUnaffiliated = llvm::make_unique<ExpectationDiagnosticConsumer>(
+ consumerA.get(), expectedUnaffiliated);
+
+ SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 2> consumers;
+ consumers.emplace_back("A", std::move(consumerA));
+ consumers.emplace_back("", std::move(consumerUnaffiliated));
+
+ FileSpecificDiagnosticConsumer topConsumer(consumers);
+ topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
+ "error", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Error,
+ "error", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, backOfB, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
+ "error", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.finishProcessing();
+}
+
+TEST(FileSpecificDiagnosticConsumer, NotesAreAttachedToWarningsAndRemarks) {
+ SourceManager sourceMgr;
+ // 01234
+ unsigned bufferA = sourceMgr.addMemBufferCopy("abcde", "A");
+ unsigned bufferB = sourceMgr.addMemBufferCopy("vwxyz", "B");
+
+ SourceLoc frontOfA = sourceMgr.getLocForOffset(bufferA, 0);
+ SourceLoc middleOfA = sourceMgr.getLocForOffset(bufferA, 2);
+ SourceLoc backOfA = sourceMgr.getLocForOffset(bufferA, 4);
+
+ SourceLoc frontOfB = sourceMgr.getLocForOffset(bufferB, 0);
+ SourceLoc middleOfB = sourceMgr.getLocForOffset(bufferB, 2);
+ SourceLoc backOfB = sourceMgr.getLocForOffset(bufferB, 4);
+
+ ExpectedDiagnostic expectedA[] = {
+ {frontOfA, "warning"},
+ {middleOfA, "note"},
+ {backOfA, "note"},
+ {frontOfB, "warning"},
+ {middleOfB, "note"},
+ {backOfB, "note"},
+ {frontOfA, "remark"},
+ {middleOfA, "note"},
+ {backOfA, "note"},
+ };
+ ExpectedDiagnostic expectedUnaffiliated[] = {
+ {frontOfB, "warning"},
+ {middleOfB, "note"},
+ {backOfB, "note"},
+ };
+
+ auto consumerA = llvm::make_unique<ExpectationDiagnosticConsumer>(
+ nullptr, expectedA);
+ auto consumerUnaffiliated = llvm::make_unique<ExpectationDiagnosticConsumer>(
+ consumerA.get(), expectedUnaffiliated);
+
+ SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 2> consumers;
+ consumers.emplace_back("A", std::move(consumerA));
+ consumers.emplace_back("", std::move(consumerUnaffiliated));
+
+ FileSpecificDiagnosticConsumer topConsumer(consumers);
+ topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Warning,
+ "warning", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Warning,
+ "warning", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, backOfB, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Remark,
+ "remark", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.finishProcessing();
+}
+
+TEST(FileSpecificDiagnosticConsumer, NotesAreAttachedToErrorsEvenAcrossFiles) {
+ SourceManager sourceMgr;
+ // 01234
+ unsigned bufferA = sourceMgr.addMemBufferCopy("abcde", "A");
+ unsigned bufferB = sourceMgr.addMemBufferCopy("vwxyz", "B");
+
+ SourceLoc frontOfA = sourceMgr.getLocForOffset(bufferA, 0);
+ SourceLoc middleOfA = sourceMgr.getLocForOffset(bufferA, 2);
+ SourceLoc backOfA = sourceMgr.getLocForOffset(bufferA, 4);
+
+ SourceLoc frontOfB = sourceMgr.getLocForOffset(bufferB, 0);
+ SourceLoc middleOfB = sourceMgr.getLocForOffset(bufferB, 2);
+ SourceLoc backOfB = sourceMgr.getLocForOffset(bufferB, 4);
+
+ ExpectedDiagnostic expectedA[] = {
+ {frontOfA, "error"},
+ {middleOfB, "note"},
+ {backOfA, "note"},
+ {frontOfA, "error"},
+ {middleOfB, "note"},
+ {backOfA, "note"},
+ };
+ ExpectedDiagnostic expectedB[] = {
+ {frontOfB, "error"},
+ {middleOfA, "note"},
+ {backOfB, "note"},
+ };
+
+ auto consumerA = llvm::make_unique<ExpectationDiagnosticConsumer>(
+ nullptr, expectedA);
+ auto consumerB = llvm::make_unique<ExpectationDiagnosticConsumer>(
+ consumerA.get(), expectedB);
+
+ SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 2> consumers;
+ consumers.emplace_back("A", std::move(consumerA));
+ consumers.emplace_back("B", std::move(consumerB));
+
+ FileSpecificDiagnosticConsumer topConsumer(consumers);
+ topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
+ "error", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Error,
+ "error", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, backOfB, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
+ "error", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.finishProcessing();
+}
+
+TEST(FileSpecificDiagnosticConsumer,
+ NotesAreAttachedToErrorsEvenAcrossFilesWithUnaffiliatedConsumer) {
+ SourceManager sourceMgr;
+ // 01234
+ unsigned bufferA = sourceMgr.addMemBufferCopy("abcde", "A");
+ unsigned bufferB = sourceMgr.addMemBufferCopy("vwxyz", "B");
+
+ SourceLoc frontOfA = sourceMgr.getLocForOffset(bufferA, 0);
+ SourceLoc middleOfA = sourceMgr.getLocForOffset(bufferA, 2);
+ SourceLoc backOfA = sourceMgr.getLocForOffset(bufferA, 4);
+
+ SourceLoc frontOfB = sourceMgr.getLocForOffset(bufferB, 0);
+ SourceLoc middleOfB = sourceMgr.getLocForOffset(bufferB, 2);
+ SourceLoc backOfB = sourceMgr.getLocForOffset(bufferB, 4);
+
+ ExpectedDiagnostic expectedA[] = {
+ {frontOfA, "error"},
+ {middleOfB, "note"},
+ {backOfA, "note"},
+ {frontOfB, "error"},
+ {middleOfA, "note"},
+ {backOfB, "note"},
+ {frontOfA, "error"},
+ {middleOfB, "note"},
+ {backOfA, "note"},
+ };
+ ExpectedDiagnostic expectedUnaffiliated[] = {
+ {frontOfB, "error"},
+ {middleOfA, "note"},
+ {backOfB, "note"},
+ };
+
+ auto consumerA = llvm::make_unique<ExpectationDiagnosticConsumer>(
+ nullptr, expectedA);
+ auto consumerUnaffiliated = llvm::make_unique<ExpectationDiagnosticConsumer>(
+ consumerA.get(), expectedUnaffiliated);
+
+ SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 2> consumers;
+ consumers.emplace_back("A", std::move(consumerA));
+ consumers.emplace_back("", std::move(consumerUnaffiliated));
+
+ FileSpecificDiagnosticConsumer topConsumer(consumers);
+ topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
+ "error", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Error,
+ "error", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, middleOfA, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, backOfB, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
+ "error", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, middleOfB, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, backOfA, DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.finishProcessing();
+}
+
+
+TEST(FileSpecificDiagnosticConsumer,
+ NotesWithInvalidLocsAreStillAttachedToErrors) {
+ SourceManager sourceMgr;
+ // 01234
+ unsigned bufferA = sourceMgr.addMemBufferCopy("abcde", "A");
+ unsigned bufferB = sourceMgr.addMemBufferCopy("vwxyz", "B");
+
+ SourceLoc frontOfA = sourceMgr.getLocForBufferStart(bufferA);
+ SourceLoc frontOfB = sourceMgr.getLocForBufferStart(bufferB);
+
+ ExpectedDiagnostic expectedA[] = {
+ {frontOfA, "error"},
+ {SourceLoc(), "note"},
+ {frontOfB, "error"},
+ {SourceLoc(), "note"},
+ {frontOfA, "error"},
+ {SourceLoc(), "note"},
+ };
+ ExpectedDiagnostic expectedUnaffiliated[] = {
+ {frontOfB, "error"},
+ {SourceLoc(), "note"},
+ };
+
+ auto consumerA = llvm::make_unique<ExpectationDiagnosticConsumer>(
+ nullptr, expectedA);
+ auto consumerUnaffiliated = llvm::make_unique<ExpectationDiagnosticConsumer>(
+ consumerA.get(), expectedUnaffiliated);
+
+ SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 2> consumers;
+ consumers.emplace_back("A", std::move(consumerA));
+ consumers.emplace_back("", std::move(consumerUnaffiliated));
+
+ FileSpecificDiagnosticConsumer topConsumer(consumers);
+ topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
+ "error", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, SourceLoc(), DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, frontOfB, DiagnosticKind::Error,
+ "error", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, SourceLoc(), DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, frontOfA, DiagnosticKind::Error,
+ "error", {}, DiagnosticInfo());
+ topConsumer.handleDiagnostic(sourceMgr, SourceLoc(), DiagnosticKind::Note,
+ "note", {}, DiagnosticInfo());
+ topConsumer.finishProcessing();
+}
diff --git a/unittests/Parse/LexerTests.cpp b/unittests/Parse/LexerTests.cpp
index 76172d8..c64aa40 100644
--- a/unittests/Parse/LexerTests.cpp
+++ b/unittests/Parse/LexerTests.cpp
@@ -35,7 +35,7 @@
if (KeepEOF)
Toks = tokenizeAndKeepEOF(BufID);
else
- Toks = tokenize(LangOpts, SourceMgr, BufID, 0, 0, KeepComments);
+ Toks = tokenize(LangOpts, SourceMgr, BufID, 0, 0, /*Diags=*/nullptr, KeepComments);
EXPECT_EQ(ExpectedTokens.size(), Toks.size());
for (unsigned i = 0, e = ExpectedTokens.size(); i != e; ++i) {
EXPECT_EQ(ExpectedTokens[i], Toks[i].getKind()) << "i = " << i;
@@ -685,7 +685,7 @@
TEST_F(LexerTest, NoPlaceholder) {
auto checkTok = [&](StringRef Source) {
unsigned BufID = SourceMgr.addMemBufferCopy(Source);
- std::vector<Token> Toks = tokenize(LangOpts, SourceMgr, BufID, 0, 0, false);
+ std::vector<Token> Toks = tokenize(LangOpts, SourceMgr, BufID, 0, 0, /*Diags=*/nullptr, false);
ASSERT_FALSE(Toks.empty());
EXPECT_NE(tok::identifier, Toks[0].getKind());
};
diff --git a/unittests/Parse/TokenizerTests.cpp b/unittests/Parse/TokenizerTests.cpp
index 42b8166..cb9a12f 100644
--- a/unittests/Parse/TokenizerTests.cpp
+++ b/unittests/Parse/TokenizerTests.cpp
@@ -98,6 +98,7 @@
BufID,
/* Offset = */ 0,
/* EndOffset = */ 0,
+ /* Diags = */nullptr,
/* KeepComments = */ true,
/* TokenizeInterpolatedString = */ true,
SplitTokens);
diff --git a/unittests/runtime/Array.cpp b/unittests/runtime/Array.cpp
index 40c8023..eb0d46a 100644
--- a/unittests/runtime/Array.cpp
+++ b/unittests/runtime/Array.cpp
@@ -80,8 +80,7 @@
static const FullMetadata<ClassMetadata> TestClassObjectMetadata = {
{ { &destroyTestObject }, { &VALUE_WITNESS_SYM(Bo) } },
- { { { MetadataKind::Class } }, 0, SWIFT_CLASS_IS_SWIFT_MASK,
- ClassFlags::UsesSwiftRefcounting, 0, 0, 0, 0, 0, 0 }
+ { { nullptr }, ClassFlags::UsesSwiftRefcounting, 0, 0, 0, 0, 0, 0 }
};
/// Create an object that, when deallocated, stores the given value to
diff --git a/unittests/runtime/LongTests/CMakeLists.txt b/unittests/runtime/LongTests/CMakeLists.txt
index ed074a0..665cf5e 100644
--- a/unittests/runtime/LongTests/CMakeLists.txt
+++ b/unittests/runtime/LongTests/CMakeLists.txt
@@ -38,6 +38,14 @@
$<TARGET_OBJECTS:swiftRuntime${SWIFT_PRIMARY_VARIANT_SUFFIX}>
)
+ # The local stdlib implementation provides definitions of the swiftCore
+ # interfaes to avoid pulling in swiftCore itself. Build the
+ # SwiftRuntimeLongTests with swiftCore_EXPORTS to permit exporting the stdlib
+ # interfaces.
+ target_compile_definitions(SwiftRuntimeLongTests
+ PRIVATE
+ swiftCore_EXPORTS)
+
# FIXME: cross-compile for all variants.
target_link_libraries(SwiftRuntimeLongTests
swiftCore${SWIFT_PRIMARY_VARIANT_SUFFIX}
diff --git a/unittests/runtime/LongTests/LongRefcounting.cpp b/unittests/runtime/LongTests/LongRefcounting.cpp
index d954a89..779ec0f 100644
--- a/unittests/runtime/LongTests/LongRefcounting.cpp
+++ b/unittests/runtime/LongTests/LongRefcounting.cpp
@@ -98,8 +98,7 @@
static const FullMetadata<ClassMetadata> TestClassObjectMetadata = {
{ { &deinitTestObject }, { &VALUE_WITNESS_SYM(Bo) } },
- { { { MetadataKind::Class } }, 0, SWIFT_CLASS_IS_SWIFT_MASK,
- ClassFlags::UsesSwiftRefcounting, 0, 0, 0, 0, 0, 0 }
+ { { nullptr }, ClassFlags::UsesSwiftRefcounting, 0, 0, 0, 0, 0, 0 }
};
/// Create an object that, when deinited, stores the given value to
diff --git a/unittests/runtime/Metadata.cpp b/unittests/runtime/Metadata.cpp
index 509ee4f..d57e4fc 100644
--- a/unittests/runtime/Metadata.cpp
+++ b/unittests/runtime/Metadata.cpp
@@ -252,8 +252,7 @@
FullMetadata<ClassMetadata> MetadataTest2 = {
{ { nullptr }, { &VALUE_WITNESS_SYM(Bo) } },
- { { { MetadataKind::Class } }, nullptr, /*rodata*/ 1,
- ClassFlags(), 0, 0, 0, 0, 0, 0 }
+ { { nullptr }, ClassFlags(), 0, 0, 0, 0, 0, 0 }
};
TEST(MetadataTest, getMetatypeMetadata) {
diff --git a/unittests/runtime/Refcounting.cpp b/unittests/runtime/Refcounting.cpp
index e6f60a3..ca66391 100644
--- a/unittests/runtime/Refcounting.cpp
+++ b/unittests/runtime/Refcounting.cpp
@@ -31,8 +31,7 @@
static const FullMetadata<ClassMetadata> TestClassObjectMetadata = {
{ { &destroyTestObject }, { &VALUE_WITNESS_SYM(Bo) } },
- { { { MetadataKind::Class } }, 0, SWIFT_CLASS_IS_SWIFT_MASK,
- ClassFlags::UsesSwiftRefcounting, 0, 0, 0, 0, 0, 0 }
+ { { nullptr }, ClassFlags::UsesSwiftRefcounting, 0, 0, 0, 0, 0, 0 }
};
/// Create an object that, when deallocated, stores the given value to
diff --git a/utils/build-script-impl b/utils/build-script-impl
index 9d1fb48..da3bdb7 100755
--- a/utils/build-script-impl
+++ b/utils/build-script-impl
@@ -2011,10 +2011,10 @@
-DSWIFT_ANDROID_NDK_PATH:STRING="${ANDROID_NDK}"
-DSWIFT_ANDROID_NDK_GCC_VERSION:STRING="${ANDROID_NDK_GCC_VERSION}"
-DSWIFT_ANDROID_SDK_PATH:STRING="${ANDROID_NDK}/platforms/android-${ANDROID_API_LEVEL}/arch-arm"
- -DSWIFT_ANDROID_${HOST}_ICU_UC:STRING="${ANDROID_ICU_UC}"
- -DSWIFT_ANDROID_${HOST}_ICU_UC_INCLUDE:STRING="${ANDROID_ICU_UC_INCLUDE}"
- -DSWIFT_ANDROID_${HOST}_ICU_I18N:STRING="${ANDROID_ICU_I18N}"
- -DSWIFT_ANDROID_${HOST}_ICU_I18N_INCLUDE:STRING="${ANDROID_ICU_I18N_INCLUDE}"
+ -DSWIFT_ANDROID_armv7_ICU_UC:STRING="${ANDROID_ICU_UC}"
+ -DSWIFT_ANDROID_armv7_ICU_UC_INCLUDE:STRING="${ANDROID_ICU_UC_INCLUDE}"
+ -DSWIFT_ANDROID_armv7_ICU_I18N:STRING="${ANDROID_ICU_I18N}"
+ -DSWIFT_ANDROID_armv7_ICU_I18N_INCLUDE:STRING="${ANDROID_ICU_I18N_INCLUDE}"
-DSWIFT_ANDROID_DEPLOY_DEVICE_PATH:STRING="${ANDROID_DEPLOY_DEVICE_PATH}"
)
fi
@@ -2875,6 +2875,7 @@
XCTEST_BUILD_DIR=$(build_directory ${host} xctest)
call "${XCTEST_SOURCE_DIR}"/build_script.py test \
--swiftc="${SWIFTC_BIN}" \
+ --lit="${LLVM_SOURCE_DIR}/utils/lit/lit.py" \
--foundation-build-dir="${FOUNDATION_BUILD_DIR}/Foundation" \
${LIBDISPATCH_BUILD_ARGS} \
$XCTEST_BUILD_ARGS \
diff --git a/utils/build_swift/defaults.py b/utils/build_swift/defaults.py
index bbf5830..51b7441 100644
--- a/utils/build_swift/defaults.py
+++ b/utils/build_swift/defaults.py
@@ -40,7 +40,7 @@
CMAKE_GENERATOR = 'Ninja'
COMPILER_VENDOR = 'none'
-SWIFT_USER_VISIBLE_VERSION = CompilerVersion('4.1')
+SWIFT_USER_VISIBLE_VERSION = CompilerVersion('4.2')
CLANG_USER_VISIBLE_VERSION = CompilerVersion('5.0.0')
SWIFT_ANALYZE_CODE_COVERAGE = 'false'
diff --git a/utils/static-executable-args.lnk b/utils/static-executable-args.lnk
index 0d34ebd..f3da0ed 100644
--- a/utils/static-executable-args.lnk
+++ b/utils/static-executable-args.lnk
@@ -1,5 +1,6 @@
-static
-lswiftCore
+-lswiftImageInspectionShared
-Xlinker
--defsym=__import_pthread_self=pthread_self
-Xlinker
diff --git a/validation-test/stdlib/Arrays.swift.gyb b/validation-test/stdlib/Arrays.swift.gyb
index ea11358..032b4d9 100644
--- a/validation-test/stdlib/Arrays.swift.gyb
+++ b/validation-test/stdlib/Arrays.swift.gyb
@@ -1513,7 +1513,7 @@
expectFalse(a.isEmpty)
}
-% for Kind in ['Array', 'ContiguousArray']:
+% for Kind in ['Array', 'ContiguousArray', 'ArraySlice']:
ArrayTestSuite.test("${Kind}/popLast") {
// Empty
do {