Merge pull request #12789 from rjmccall/sil-coroutines
diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h
index 0259ba7..8edd152 100644
--- a/include/swift/ABI/MetadataValues.h
+++ b/include/swift/ABI/MetadataValues.h
@@ -550,10 +550,11 @@
template <typename int_type>
class TargetFunctionTypeFlags {
enum : int_type {
- NumArgumentsMask = 0x00FFFFFFU,
- ConventionMask = 0x0F000000U,
- ConventionShift = 24U,
- ThrowsMask = 0x10000000U,
+ NumParametersMask = 0x00FFFFFFU,
+ ConventionMask = 0x0F000000U,
+ ConventionShift = 25U,
+ ThrowsMask = 0x10000000U,
+ ParamFlagsMask = 0x01000000U,
};
int_type Data;
@@ -561,8 +562,9 @@
public:
constexpr TargetFunctionTypeFlags() : Data(0) {}
- constexpr TargetFunctionTypeFlags withNumArguments(unsigned numArguments) const {
- return TargetFunctionTypeFlags((Data & ~NumArgumentsMask) | numArguments);
+ constexpr TargetFunctionTypeFlags
+ withNumParameters(unsigned numParams) const {
+ return TargetFunctionTypeFlags((Data & ~NumParametersMask) | numParams);
}
constexpr TargetFunctionTypeFlags<int_type>
@@ -576,11 +578,15 @@
return TargetFunctionTypeFlags<int_type>((Data & ~ThrowsMask) |
(throws ? ThrowsMask : 0));
}
-
- unsigned getNumArguments() const {
- return Data & NumArgumentsMask;
+
+ constexpr TargetFunctionTypeFlags<int_type>
+ withParameterFlags(bool hasFlags) const {
+ return TargetFunctionTypeFlags<int_type>((Data & ~ParamFlagsMask) |
+ (hasFlags ? ParamFlagsMask : 0));
}
-
+
+ unsigned getNumParameters() const { return Data & NumParametersMask; }
+
FunctionMetadataConvention getConvention() const {
return FunctionMetadataConvention((Data&ConventionMask) >> ConventionShift);
}
@@ -588,7 +594,9 @@
bool throws() const {
return bool(Data & ThrowsMask);
}
-
+
+ bool hasParameterFlags() const { return bool(Data & ParamFlagsMask); }
+
int_type getIntValue() const {
return Data;
}
@@ -606,6 +614,56 @@
};
using FunctionTypeFlags = TargetFunctionTypeFlags<size_t>;
+template <typename int_type>
+class TargetParameterTypeFlags {
+ enum : int_type {
+ InOutMask = 1 << 0,
+ SharedMask = 1 << 1,
+ VariadicMask = 1 << 2,
+ };
+ int_type Data;
+
+ constexpr TargetParameterTypeFlags(int_type Data) : Data(Data) {}
+
+public:
+ constexpr TargetParameterTypeFlags() : Data(0) {}
+
+ constexpr TargetParameterTypeFlags<int_type> withInOut(bool isInOut) const {
+ return TargetParameterTypeFlags<int_type>((Data & ~InOutMask) |
+ (isInOut ? InOutMask : 0));
+ }
+
+ constexpr TargetParameterTypeFlags<int_type> withShared(bool isShared) const {
+ return TargetParameterTypeFlags<int_type>((Data & ~SharedMask) |
+ (isShared ? SharedMask : 0));
+ }
+
+ constexpr TargetParameterTypeFlags<int_type>
+ withVariadic(bool isVariadic) const {
+ return TargetParameterTypeFlags<int_type>((Data & ~VariadicMask) |
+ (isVariadic ? VariadicMask : 0));
+ }
+
+ bool isNone() const { return Data == 0; }
+ bool isInOut() const { return Data & InOutMask; }
+ bool isShared() const { return Data & SharedMask; }
+ bool isVariadic() const { return Data & VariadicMask; }
+
+ int_type getIntValue() const { return Data; }
+
+ static TargetParameterTypeFlags<int_type> fromIntValue(int_type Data) {
+ return TargetParameterTypeFlags(Data);
+ }
+
+ bool operator==(TargetParameterTypeFlags<int_type> other) const {
+ return Data == other.Data;
+ }
+ bool operator!=(TargetParameterTypeFlags<int_type> other) const {
+ return Data != other.Data;
+ }
+};
+using ParameterFlags = TargetParameterTypeFlags<uint32_t>;
+
/// Field types and flags as represented in a nominal type's field/case type
/// vector.
class FieldType {
diff --git a/include/swift/AST/PrettyStackTrace.h b/include/swift/AST/PrettyStackTrace.h
index 96894b1..9715dd32 100644
--- a/include/swift/AST/PrettyStackTrace.h
+++ b/include/swift/AST/PrettyStackTrace.h
@@ -26,6 +26,7 @@
class ASTContext;
class Decl;
class Expr;
+ class GenericSignature;
class Pattern;
class Stmt;
class TypeRepr;
@@ -129,6 +130,24 @@
virtual void print(llvm::raw_ostream &OS) const;
};
+class PrettyStackTraceGenericSignature : public llvm::PrettyStackTraceEntry {
+ const char *Action;
+ GenericSignature *GenericSig;
+ Optional<unsigned> Requirement;
+
+public:
+ PrettyStackTraceGenericSignature(const char *action,
+ GenericSignature *genericSig,
+ Optional<unsigned> requirement = None)
+ : Action(action), GenericSig(genericSig), Requirement(requirement) { }
+
+ void setRequirement(Optional<unsigned> requirement) {
+ Requirement = requirement;
+ }
+
+ void print(llvm::raw_ostream &out) const override;
+};
+
} // end namespace swift
#endif
diff --git a/include/swift/Reflection/TypeRef.h b/include/swift/Reflection/TypeRef.h
index d96fc9e..e88adeb 100644
--- a/include/swift/Reflection/TypeRef.h
+++ b/include/swift/Reflection/TypeRef.h
@@ -344,7 +344,7 @@
for (const auto &Param : Parameters) {
ID.addString(Param.getLabel().str());
ID.addPointer(Param.getType());
- ID.addInteger(static_cast<uint32_t>(Param.getFlags().toRaw()));
+ ID.addInteger(static_cast<uint32_t>(Param.getFlags().getIntValue()));
}
ID.addPointer(Result);
ID.addInteger(static_cast<uint64_t>(Flags.getIntValue()));
diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h
index d8ac5a3..502b13d 100644
--- a/include/swift/Remote/MetadataReader.h
+++ b/include/swift/Remote/MetadataReader.h
@@ -17,7 +17,6 @@
#ifndef SWIFT_REMOTE_METADATAREADER_H
#define SWIFT_REMOTE_METADATAREADER_H
-#include "swift/AST/Types.h"
#include "swift/Runtime/Metadata.h"
#include "swift/Remote/MemoryReader.h"
#include "swift/Demangling/Demangler.h"
@@ -33,9 +32,9 @@
template <typename BuiltType> class FunctionParam {
StringRef Label;
BuiltType Type;
- ParameterTypeFlags Flags;
+ ParameterFlags Flags;
- FunctionParam(StringRef label, BuiltType type, ParameterTypeFlags flags)
+ FunctionParam(StringRef label, BuiltType type, ParameterFlags flags)
: Label(label), Type(type), Flags(flags) {}
public:
@@ -45,7 +44,7 @@
StringRef getLabel() const { return Label; }
BuiltType getType() const { return Type; }
- ParameterTypeFlags getFlags() const { return Flags; }
+ ParameterFlags getFlags() const { return Flags; }
void setLabel(StringRef label) { Label = label; }
void setType(BuiltType type) { Type = type; }
@@ -53,6 +52,7 @@
void setVariadic() { Flags = Flags.withVariadic(true); }
void setShared() { Flags = Flags.withShared(true); }
void setInOut() { Flags = Flags.withInOut(true); }
+ void setFlags(ParameterFlags flags) { Flags = flags; };
FunctionParam withLabel(StringRef label) const {
return FunctionParam(label, Type, Flags);
@@ -62,7 +62,7 @@
return FunctionParam(Label, type, Flags);
}
- FunctionParam withFlags(ParameterTypeFlags flags) const {
+ FunctionParam withFlags(ParameterFlags flags) const {
return FunctionParam(Label, Type, flags);
}
};
@@ -798,40 +798,32 @@
}
case MetadataKind::Function: {
auto Function = cast<TargetFunctionTypeMetadata<Runtime>>(Meta);
+ auto *const parameters = Function->getParameters();
std::vector<FunctionParam<BuiltType>> Parameters;
- StoredPointer ArgumentAddress = MetadataAddress +
- sizeof(TargetFunctionTypeMetadata<Runtime>);
- for (StoredPointer i = 0; i < Function->getNumArguments(); ++i,
- ArgumentAddress += sizeof(StoredPointer)) {
- StoredPointer FlaggedArgumentAddress;
- if (!Reader->readInteger(RemoteAddress(ArgumentAddress),
- &FlaggedArgumentAddress))
+ for (unsigned i = 0, n = Function->getNumParameters(); i != n; ++i) {
+ StoredPointer ParamMetadata;
+ if (!Reader->readInteger(RemoteAddress(parameters + i), &ParamMetadata))
+ return BuiltType();
+
+ auto ParamTypeRef = readTypeFromMetadata(ParamMetadata);
+ if (!ParamTypeRef)
return BuiltType();
FunctionParam<BuiltType> Param;
-
- // TODO: Use target-agnostic FlaggedPointer to mask this!
- const auto InOutMask = (StoredPointer) 1;
- // FIXME: Add import parameter related flags from metadata
- if ((FlaggedArgumentAddress & InOutMask) != 0)
- Param.setInOut();
-
- FlaggedArgumentAddress &= ~InOutMask;
- if (auto ParamTypeRef = readTypeFromMetadata(FlaggedArgumentAddress)) {
- Param.setType(ParamTypeRef);
- Parameters.push_back(std::move(Param));
- } else {
- return BuiltType();
- }
+ Param.setType(ParamTypeRef);
+ Param.setFlags(Function->getParameterFlags(i));
+ Parameters.push_back(std::move(Param));
}
auto Result = readTypeFromMetadata(Function->ResultType);
if (!Result)
return BuiltType();
- auto flags = FunctionTypeFlags().withConvention(Function->getConvention())
- .withThrows(Function->throws());
+ auto flags = FunctionTypeFlags()
+ .withConvention(Function->getConvention())
+ .withThrows(Function->throws())
+ .withParameterFlags(Function->hasParameterFlags());
auto BuiltFunction =
Builder.createFunctionType(Parameters, Result, flags);
TypeCache[MetadataAddress] = BuiltFunction;
@@ -1195,8 +1187,24 @@
return _readMetadata<TargetExistentialMetatypeMetadata>(address);
case MetadataKind::ForeignClass:
return _readMetadata<TargetForeignClassMetadata>(address);
- case MetadataKind::Function:
- return _readMetadata<TargetFunctionTypeMetadata>(address);
+ case MetadataKind::Function: {
+ StoredSize flagsValue;
+ auto flagsAddr =
+ address + TargetFunctionTypeMetadata<Runtime>::OffsetToFlags;
+ if (!Reader->readInteger(RemoteAddress(flagsAddr), &flagsValue))
+ return nullptr;
+
+ auto flags =
+ TargetFunctionTypeFlags<StoredSize>::fromIntValue(flagsValue);
+
+ auto totalSize = sizeof(TargetFunctionTypeMetadata<Runtime>) +
+ flags.getNumParameters() * sizeof(StoredPointer);
+
+ if (flags.hasParameterFlags())
+ totalSize += flags.getNumParameters() * sizeof(uint32_t);
+
+ return _readMetadata(address, totalSize);
+ }
case MetadataKind::HeapGenericLocalVariable:
return _readMetadata<TargetGenericBoxHeapMetadata>(address);
case MetadataKind::HeapLocalVariable:
diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h
index 7d24fc5..3681ab1 100644
--- a/include/swift/Runtime/Metadata.h
+++ b/include/swift/Runtime/Metadata.h
@@ -1745,36 +1745,48 @@
template <typename Runtime>
struct TargetFunctionTypeMetadata : public TargetMetadata<Runtime> {
using StoredSize = typename Runtime::StoredSize;
-
- // TODO: Make this target agnostic
- using Argument = FlaggedPointer<const TargetMetadata<Runtime> *, 0>;
+ using Parameter = const TargetMetadata<Runtime> *;
TargetFunctionTypeFlags<StoredSize> Flags;
/// The type metadata for the result type.
ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> ResultType;
- TargetPointer<Runtime, Argument> getArguments() {
- return reinterpret_cast<TargetPointer<Runtime, Argument>>(this + 1);
+ Parameter *getParameters() { return reinterpret_cast<Parameter *>(this + 1); }
+
+ const Parameter *getParameters() const {
+ return reinterpret_cast<const Parameter *>(this + 1);
}
- TargetPointer<Runtime, const Argument> getArguments() const {
- return reinterpret_cast<TargetPointer<Runtime, const Argument>>(this + 1);
+ ParameterFlags getParameterFlags(unsigned index) const {
+ assert(index < getNumParameters());
+ auto flags = hasParameterFlags() ? getParameterFlags()[index] : 0;
+ return ParameterFlags::fromIntValue(flags);
}
-
- StoredSize getNumArguments() const {
- return Flags.getNumArguments();
+
+ StoredSize getNumParameters() const {
+ return Flags.getNumParameters();
}
FunctionMetadataConvention getConvention() const {
return Flags.getConvention();
}
bool throws() const { return Flags.throws(); }
+ bool hasParameterFlags() const { return Flags.hasParameterFlags(); }
static constexpr StoredSize OffsetToFlags = sizeof(TargetMetadata<Runtime>);
static bool classof(const TargetMetadata<Runtime> *metadata) {
return metadata->getKind() == MetadataKind::Function;
}
+
+ uint32_t *getParameterFlags() {
+ return reinterpret_cast<uint32_t *>(getParameters() + getNumParameters());
+ }
+
+ const uint32_t *getParameterFlags() const {
+ return reinterpret_cast<const uint32_t *>(getParameters() +
+ getNumParameters());
+ }
};
using FunctionTypeMetadata = TargetFunctionTypeMetadata<InProcess>;
@@ -2639,28 +2651,58 @@
/// \brief Fetch a uniqued metadata for a function type.
SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *
-swift_getFunctionTypeMetadata(const void *flagsArgsAndResult[]);
+swift_getFunctionTypeMetadata(FunctionTypeFlags flags,
+ const Metadata *const *parameters,
+ const uint32_t *parameterFlags,
+ const Metadata *result);
SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *
swift_getFunctionTypeMetadata1(FunctionTypeFlags flags,
- const void *arg0,
- const Metadata *resultMetadata);
+ const Metadata *arg0,
+ const Metadata *result);
+
+SWIFT_RUNTIME_EXPORT
+const FunctionTypeMetadata *
+swift_getFunctionTypeMetadata1WithFlags(FunctionTypeFlags flags,
+ const Metadata *arg0,
+ ParameterFlags flags0,
+ const Metadata *result);
SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *
swift_getFunctionTypeMetadata2(FunctionTypeFlags flags,
- const void *arg0,
- const void *arg1,
- const Metadata *resultMetadata);
+ const Metadata *arg0,
+ const Metadata *arg1,
+ const Metadata *result);
SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *
-swift_getFunctionTypeMetadata3(FunctionTypeFlags flags,
- const void *arg0,
- const void *arg1,
- const void *arg2,
- const Metadata *resultMetadata);
+swift_getFunctionTypeMetadata2WithFlags(FunctionTypeFlags flags,
+ const Metadata *arg0,
+ ParameterFlags flags0,
+ const Metadata *arg1,
+ ParameterFlags flags1,
+ const Metadata *result);
+
+SWIFT_RUNTIME_EXPORT
+const FunctionTypeMetadata *swift_getFunctionTypeMetadata3(
+ FunctionTypeFlags flags,
+ const Metadata *arg0,
+ const Metadata *arg1,
+ const Metadata *arg2,
+ const Metadata *result);
+
+SWIFT_RUNTIME_EXPORT
+const FunctionTypeMetadata *swift_getFunctionTypeMetadata3WithFlags(
+ FunctionTypeFlags flags,
+ const Metadata *arg0,
+ ParameterFlags flags0,
+ const Metadata *arg1,
+ ParameterFlags flags1,
+ const Metadata *arg2,
+ ParameterFlags flags2,
+ const Metadata *result);
/// \brief Fetch a uniqued metadata for a thin function type.
SWIFT_RUNTIME_EXPORT
diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def
index 072ebe8..a07686e 100644
--- a/include/swift/Runtime/RuntimeFunctions.def
+++ b/include/swift/Runtime/RuntimeFunctions.def
@@ -759,28 +759,84 @@
ARGS(OpaquePtrTy, SizeTy, TypeMetadataPtrTy),
ATTRS(NoUnwind))
-// Metadata *swift_getFunctionTypeMetadata(const void **args);
+// Metadata *swift_getFunctionTypeMetadata(unsigned long flags,
+// const Metadata **parameters,
+// const uint32_t *parameterFlags,
+// const Metadata *result);
FUNCTION(GetFunctionMetadata, swift_getFunctionTypeMetadata, DefaultCC,
RETURNS(TypeMetadataPtrTy),
- ARGS(Int8PtrTy->getPointerTo(0)),
+ ARGS(SizeTy,
+ TypeMetadataPtrTy->getPointerTo(0),
+ Int32Ty->getPointerTo(0),
+ TypeMetadataPtrTy),
ATTRS(NoUnwind, ReadNone))
-// Metadata *swift_getFunctionTypeMetadata1(unsigned long flags, const void *arg0, const Metadata *resultMetadata);
+// Metadata *swift_getFunctionTypeMetadata1(unsigned long flags,
+// const Metadata *arg0,
+// const Metadata *resultMetadata);
FUNCTION(GetFunctionMetadata1, swift_getFunctionTypeMetadata1, DefaultCC,
+ RETURNS(TypeMetadataPtrTy),
+ ARGS(SizeTy, TypeMetadataPtrTy, TypeMetadataPtrTy),
+ ATTRS(NoUnwind, ReadNone))
+
+// Metadata *swift_getFunctionTypeMetadata1WithFlags(unsigned long flags,
+// const Metadata *arg0,
+// const uint32_t paramFlags,
+// const Metadata *resultMetadata);
+FUNCTION(GetFunctionMetadata1WithFlags, swift_getFunctionTypeMetadata1WithFlags,
+ DefaultCC,
RETURNS(TypeMetadataPtrTy),
- ARGS(SizeTy, Int8PtrTy, TypeMetadataPtrTy),
+ ARGS(SizeTy, TypeMetadataPtrTy, Int32Ty, TypeMetadataPtrTy),
ATTRS(NoUnwind, ReadNone))
-// Metadata *swift_getFunctionTypeMetadata2(unsigned long flags, const void *arg0, const void *arg1, const Metadata *resultMetadata);
-FUNCTION(GetFunctionMetadata2, swift_getFunctionTypeMetadata2, DefaultCC,
+// Metadata *swift_getFunctionTypeMetadata2(unsigned long flags,
+// const Metadata *arg0,
+// const Metadata *arg1,
+// const Metadata *resultMetadata);
+FUNCTION(GetFunctionMetadata2, swift_getFunctionTypeMetadata2,
+ DefaultCC,
+ RETURNS(TypeMetadataPtrTy),
+ ARGS(SizeTy, TypeMetadataPtrTy, TypeMetadataPtrTy, TypeMetadataPtrTy),
+ ATTRS(NoUnwind, ReadNone))
+
+// Metadata *swift_getFunctionTypeMetadata2WithFlags(unsigned long flags,
+// const Metadata *arg0,
+// const uint32_t flags0,
+// const Metadata *arg1,
+// const uint32_t flags1,
+// const Metadata *resultMetadata);
+FUNCTION(GetFunctionMetadata2WithFlags, swift_getFunctionTypeMetadata2WithFlags,
+ DefaultCC,
RETURNS(TypeMetadataPtrTy),
- ARGS(SizeTy, Int8PtrTy, Int8PtrTy, TypeMetadataPtrTy),
+ ARGS(SizeTy, TypeMetadataPtrTy, Int32Ty, TypeMetadataPtrTy, Int32Ty,
+ TypeMetadataPtrTy),
ATTRS(NoUnwind, ReadNone))
-// Metadata *swift_getFunctionTypeMetadata3(unsigned long flags, const void *arg0, const void *arg1, const void *arg2, const Metadata *resultMetadata);
-FUNCTION(GetFunctionMetadata3, swift_getFunctionTypeMetadata3, DefaultCC,
+// Metadata *swift_getFunctionTypeMetadata3(unsigned long flags,
+// const Metadata *arg0,
+// const Metadata *arg1,
+// const Metadata *arg2,
+// const Metadata *resultMetadata);
+FUNCTION(GetFunctionMetadata3, swift_getFunctionTypeMetadata3,
+ DefaultCC,
+ RETURNS(TypeMetadataPtrTy),
+ ARGS(SizeTy, TypeMetadataPtrTy, TypeMetadataPtrTy, TypeMetadataPtrTy,
+ TypeMetadataPtrTy),
+ ATTRS(NoUnwind, ReadNone))
+
+// Metadata *swift_getFunctionTypeMetadata3WithFlags(unsigned long flags,
+// const Metadata *arg0,
+// const uint32_t flags0,
+// const Metadata *arg1,
+// const uint32_t flags1,
+// const Metadata *arg2,
+// const uint32_t flags2,
+// const Metadata *resultMetadata);
+FUNCTION(GetFunctionMetadata3WithFlags, swift_getFunctionTypeMetadata3WithFlags,
+ DefaultCC,
RETURNS(TypeMetadataPtrTy),
- ARGS(SizeTy, Int8PtrTy, Int8PtrTy, Int8PtrTy, TypeMetadataPtrTy),
+ ARGS(SizeTy, TypeMetadataPtrTy, Int32Ty, TypeMetadataPtrTy, Int32Ty,
+ TypeMetadataPtrTy, Int32Ty, TypeMetadataPtrTy),
ATTRS(NoUnwind, ReadNone))
// Metadata *swift_getForeignTypeMetadata(Metadata *nonUnique);
diff --git a/include/swift/SIL/SILDeclRef.h b/include/swift/SIL/SILDeclRef.h
index 4f95c8a..b1bc7be 100644
--- a/include/swift/SIL/SILDeclRef.h
+++ b/include/swift/SIL/SILDeclRef.h
@@ -66,8 +66,6 @@
/// True if the entry point is natively foreign.
bool requiresForeignToNativeThunk(ValueDecl *vd);
-unsigned getNaturalUncurryLevel(ValueDecl *vd);
-
enum ForDefinition_t : bool {
NotForDefinition = false,
ForDefinition = true
@@ -304,7 +302,7 @@
void print(llvm::raw_ostream &os) const;
void dump() const;
- unsigned getUncurryLevel() const;
+ unsigned getParameterListCount() const;
ResilienceExpansion getResilienceExpansion() const {
return ResilienceExpansion(Expansion);
diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp
index 2b31ca1..4279839 100644
--- a/lib/AST/GenericSignature.cpp
+++ b/lib/AST/GenericSignature.cpp
@@ -20,6 +20,7 @@
#include "swift/AST/Decl.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Module.h"
+#include "swift/AST/PrettyStackTrace.h"
#include "swift/AST/Types.h"
#include "swift/Basic/STLExtras.h"
#include <functional>
@@ -174,6 +175,18 @@
return getCanonicalSignature() == this;
}
+#ifndef NDEBUG
+/// Determine the canonical ordering of requirements.
+static unsigned getRequirementKindOrder(RequirementKind kind) {
+ switch (kind) {
+ case RequirementKind::Conformance: return 2;
+ case RequirementKind::Superclass: return 0;
+ case RequirementKind::SameType: return 3;
+ case RequirementKind::Layout: return 1;
+ }
+}
+#endif
+
CanGenericSignature GenericSignature::getCanonical(
ArrayRef<GenericTypeParamType *> params,
ArrayRef<Requirement> requirements) {
@@ -197,8 +210,105 @@
Requirement(reqt.getKind(), reqt.getFirstType()->getCanonicalType(),
reqt.getLayoutConstraint()));
}
+
auto canSig = get(canonicalParams, canonicalRequirements,
/*isKnownCanonical=*/true);
+
+#ifndef NDEBUG
+ PrettyStackTraceGenericSignature debugStack("canonicalizing", canSig);
+
+ // Check that the signature is canonical.
+ for (unsigned idx : indices(canonicalRequirements)) {
+ debugStack.setRequirement(idx);
+
+ const auto &reqt = canonicalRequirements[idx];
+
+ // Left-hand side must be canonical in its context.
+ // Check canonicalization of requirement itself.
+ switch (reqt.getKind()) {
+ case RequirementKind::Superclass:
+ assert(canSig->isCanonicalTypeInContext(reqt.getFirstType()) &&
+ "Left-hand side is not canonical");
+ assert(canSig->isCanonicalTypeInContext(reqt.getSecondType()) &&
+ "Superclass type isn't canonical in its own context");
+ break;
+
+ case RequirementKind::Layout:
+ assert(canSig->isCanonicalTypeInContext(reqt.getFirstType()) &&
+ "Left-hand side is not canonical");
+ break;
+
+ case RequirementKind::SameType:
+ assert(reqt.getFirstType()->isTypeParameter() &&
+ "Left-hand side must be a type parameter");
+ if (reqt.getSecondType()->isTypeParameter()) {
+ assert(compareDependentTypes(reqt.getFirstType(), reqt.getSecondType())
+ < 0 &&
+ "Out-of-order type parameters in same-type constraint");
+ } else {
+ assert(canSig->isCanonicalTypeInContext(reqt.getSecondType()) &&
+ "Concrete same-type isn't canonical in its own context");
+ }
+ break;
+
+ case RequirementKind::Conformance:
+ assert(reqt.getFirstType()->isTypeParameter() &&
+ "Left-hand side must be a type parameter");
+ assert(isa<ProtocolType>(reqt.getSecondType().getPointer()) &&
+ "Right-hand side of conformance isn't a protocol type");
+ break;
+ }
+
+ // From here on, we're only interested in requirements beyond the first.
+ if (idx == 0) continue;
+
+ // Make sure that the left-hand sides are in nondecreasing order.
+ const auto &prevReqt = canonicalRequirements[idx-1];
+ int compareLHS =
+ compareDependentTypes(prevReqt.getFirstType(), reqt.getFirstType());
+ assert(compareLHS <= 0 && "Out-of-order left-hand sides");
+
+ // If we have two same-type requirements where the left-hand sides differ
+ // but fall into the same equivalence class, we can check the form.
+ if (compareLHS < 0 && reqt.getKind() == RequirementKind::SameType &&
+ prevReqt.getKind() == RequirementKind::SameType &&
+ canSig->areSameTypeParameterInContext(prevReqt.getFirstType(),
+ reqt.getFirstType())) {
+ // If it's a it's a type parameter, make sure the equivalence class is
+ // wired together sanely.
+ if (prevReqt.getSecondType()->isTypeParameter()) {
+ assert(prevReqt.getSecondType()->isEqual(reqt.getFirstType()) &&
+ "same-type constraints within an equiv. class are out-of-order");
+ } else {
+ // Otherwise, the concrete types must match up.
+ assert(prevReqt.getSecondType()->isEqual(reqt.getSecondType()) &&
+ "inconsistent concrete same-type constraints in equiv. class");
+ }
+ }
+
+ // From here on, we only care about cases where the previous and current
+ // requirements have the same left-hand side.
+ if (compareLHS != 0) continue;
+
+ // Check ordering of requirement kinds.
+ assert((getRequirementKindOrder(prevReqt.getKind()) <=
+ getRequirementKindOrder(reqt.getKind())) &&
+ "Requirements for a given kind are out-of-order");
+
+ // From here on, we only care about the same requirement kind.
+ if (prevReqt.getKind() != reqt.getKind()) continue;
+
+ assert(reqt.getKind() == RequirementKind::Conformance &&
+ "Only conformance requirements can have multiples");
+
+ auto prevProto =
+ prevReqt.getSecondType()->castTo<ProtocolType>()->getDecl();
+ auto proto = reqt.getSecondType()->castTo<ProtocolType>()->getDecl();
+ assert(ProtocolType::compareProtocols(&prevProto, &proto) < 0 &&
+ "Out-of-order conformance requirements");
+ }
+#endif
+
return CanGenericSignature(canSig);
}
@@ -621,14 +731,12 @@
type1,
ArchetypeResolutionKind::CompleteWellFormed);
assert(equivClass1 && "not a valid dependent type of this signature?");
- assert(!equivClass1->concreteType);
auto equivClass2 =
builder.resolveEquivalenceClass(
type2,
ArchetypeResolutionKind::CompleteWellFormed);
assert(equivClass2 && "not a valid dependent type of this signature?");
- assert(!equivClass2->concreteType);
return equivClass1 == equivClass2;
}
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index 4aada77..860600c 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -2954,36 +2954,30 @@
/// Resolve any unresolved dependent member types using the given builder.
static Type resolveDependentMemberTypes(GenericSignatureBuilder &builder,
- Type type,
- ArchetypeResolutionKind kind) {
+ Type type) {
if (!type->hasTypeParameter()) return type;
- return type.transformRec([&builder,kind](TypeBase *type) -> Optional<Type> {
- if (auto depTy = dyn_cast<DependentMemberType>(type)) {
- if (depTy->getAssocType()) return None;
+ return type.transformRec([&builder](TypeBase *type) -> Optional<Type> {
+ if (!type->isTypeParameter())
+ return None;
- Type newBase =
- resolveDependentMemberTypes(builder, depTy->getBase(), kind);
- if (newBase->is<ErrorType>())
- return ErrorType::get(depTy);
+ // Map the type parameter to an equivalence class.
+ auto equivClass =
+ builder.resolveEquivalenceClass(Type(type),
+ ArchetypeResolutionKind::WellFormed);
+ if (!equivClass)
+ return ErrorType::get(Type(type));
- auto parentEquivClass = builder.resolveEquivalenceClass(newBase, kind);
- if (!parentEquivClass)
- return ErrorType::get(depTy);
+ // If there is a concrete type in this equivalence class, use that.
+ if (equivClass->concreteType) {
+ // .. unless it's recursive.
+ if (equivClass->recursiveConcreteType)
+ return ErrorType::get(Type(type));
- auto memberType =
- parentEquivClass->lookupNestedType(builder, depTy->getName());
- if (!memberType)
- return ErrorType::get(depTy);
-
- if (auto assocType = dyn_cast<AssociatedTypeDecl>(memberType))
- return Type(DependentMemberType::get(newBase, assocType));
-
- // FIXME: Need to substitute here.
- return Type(type);
+ return resolveDependentMemberTypes(builder, equivClass->concreteType);
}
- return None;
+ return equivClass->getAnchor(builder, builder.getGenericParams());
});
}
@@ -3094,9 +3088,7 @@
// FIXME: Generic typealiases contradict the assumption above.
// If there is a type parameter somewhere in this type, resolve it.
if (type->hasTypeParameter()) {
- Type resolved =
- resolveDependentMemberTypes(*this, type,
- ArchetypeResolutionKind::WellFormed);
+ Type resolved = resolveDependentMemberTypes(*this, type);
if (resolved->hasError() && !type->hasError())
return ResolvedType::forUnresolved(nullptr);
@@ -5951,10 +5943,9 @@
diag::redundant_same_type_to_concrete,
diag::same_type_redundancy_here);
- // Resolve any this-far-unresolved dependent types.
+ // Resolve any thus-far-unresolved dependent types.
equivClass->concreteType =
- resolveDependentMemberTypes(*this, equivClass->concreteType,
- ArchetypeResolutionKind::CompleteWellFormed);
+ resolveDependentMemberTypes(*this, equivClass->concreteType);
}
void GenericSignatureBuilder::checkSuperclassConstraints(
@@ -5996,8 +5987,7 @@
// Resolve any this-far-unresolved dependent types.
equivClass->superclass =
- resolveDependentMemberTypes(*this, equivClass->superclass,
- ArchetypeResolutionKind::CompleteWellFormed);
+ resolveDependentMemberTypes(*this, equivClass->superclass);
// If we have a concrete type, check it.
// FIXME: Substitute into the concrete type.
diff --git a/lib/AST/PrettyStackTrace.cpp b/lib/AST/PrettyStackTrace.cpp
index 26a1fb5..649baea 100644
--- a/lib/AST/PrettyStackTrace.cpp
+++ b/lib/AST/PrettyStackTrace.cpp
@@ -18,6 +18,7 @@
#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Expr.h"
+#include "swift/AST/GenericSignature.h"
#include "swift/AST/Module.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/Stmt.h"
@@ -214,3 +215,12 @@
out << "While " << Action << " starting at ";
printSourceLocDescription(out, Loc, Context);
}
+
+void PrettyStackTraceGenericSignature::print(llvm::raw_ostream &out) const {
+ out << "While " << Action << " generic signature ";
+ GenericSig->print(out);
+ if (Requirement) {
+ out << " in requirement #" << *Requirement;
+ }
+ out << '\n';
+}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 1e6b61a..1a15a3f 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -18,6 +18,7 @@
#include "ForeignRepresentationInfo.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ExistentialLayout.h"
+#include "swift/AST/GenericSignatureBuilder.h"
#include "swift/AST/TypeVisitor.h"
#include "swift/AST/TypeWalker.h"
#include "swift/AST/Decl.h"
@@ -3089,15 +3090,110 @@
getAssocType(), getName(), None);
}
+static Type substGenericFunctionType(GenericFunctionType *genericFnType,
+ TypeSubstitutionFn substitutions,
+ LookupConformanceFn lookupConformances,
+ SubstOptions options) {
+ // Substitute into the function type (without generic signature).
+ auto *bareFnType = FunctionType::get(genericFnType->getInput(),
+ genericFnType->getResult(),
+ genericFnType->getExtInfo());
+ Type result =
+ Type(bareFnType).subst(substitutions, lookupConformances, options);
+ if (!result || result->is<ErrorType>()) return result;
+
+ auto *fnType = result->castTo<FunctionType>();
+ // Substitute generic parameters.
+ bool anySemanticChanges = false;
+ SmallVector<GenericTypeParamType *, 4> genericParams;
+ for (auto param : genericFnType->getGenericParams()) {
+ Type paramTy =
+ Type(param).subst(substitutions, lookupConformances, options);
+ if (!paramTy)
+ return Type();
+
+ if (auto newParam = paramTy->getAs<GenericTypeParamType>()) {
+ if (!newParam->isEqual(param))
+ anySemanticChanges = true;
+
+ genericParams.push_back(newParam);
+ } else {
+ anySemanticChanges = true;
+ }
+ }
+
+ // If no generic parameters remain, this is a non-generic function type.
+ if (genericParams.empty())
+ return result;
+
+ // Transform requirements.
+ SmallVector<Requirement, 4> requirements;
+ for (const auto &req : genericFnType->getRequirements()) {
+ // Substitute into the requirement.
+ auto substReqt = req.subst(substitutions, lookupConformances, options);
+ if (!substReqt) {
+ anySemanticChanges = true;
+ continue;
+ }
+
+ // Did anything change?
+ if (!anySemanticChanges &&
+ (!req.getFirstType()->isEqual(substReqt->getFirstType()) ||
+ (req.getKind() != RequirementKind::Layout &&
+ !req.getSecondType()->isEqual(substReqt->getSecondType())))) {
+ anySemanticChanges = true;
+ }
+
+ // Skip any erroneous requirements.
+ if (substReqt->getFirstType()->hasError() ||
+ (substReqt->getKind() != RequirementKind::Layout &&
+ substReqt->getSecondType()->hasError()))
+ continue;
+
+ requirements.push_back(*substReqt);
+ }
+
+ GenericSignature *genericSig = nullptr;
+ if (anySemanticChanges) {
+ // If there were semantic changes, we need to build a new generic
+ // signature.
+ GenericSignatureBuilder builder(genericFnType->getASTContext());
+
+ // Add the generic parameters to the builder.
+ for (auto gp : genericParams)
+ builder.addGenericParameter(gp);
+
+ // Add the requirements to the builder.
+ auto source =
+ GenericSignatureBuilder::FloatingRequirementSource::forAbstract();
+ for (const auto &req : requirements)
+ builder.addRequirement(req, source, /*inferForModule=*/nullptr);
+
+ // Form the generic signature.
+ genericSig = std::move(builder).computeGenericSignature(SourceLoc());
+ } else {
+ // Use the mapped generic signature.
+ genericSig = GenericSignature::get(genericParams, requirements);
+ }
+
+ // Produce the new generic function type.
+ return GenericFunctionType::get(genericSig, fnType->getInput(),
+ fnType->getResult(), fnType->getExtInfo());
+}
+
static Type substType(Type derivedType,
TypeSubstitutionFn substitutions,
LookupConformanceFn lookupConformances,
SubstOptions options) {
+ // Handle substitutions into generic function types.
+ if (auto genericFnType = derivedType->getAs<GenericFunctionType>()) {
+ return substGenericFunctionType(genericFnType, substitutions,
+ lookupConformances, options);
+ }
// FIXME: Change getTypeOfMember() to not pass GenericFunctionType here
if (!derivedType->hasArchetype() &&
- !derivedType->hasTypeParameter() &&
- !derivedType->is<GenericFunctionType>())
+ !derivedType->hasTypeParameter())
return derivedType;
return derivedType.transformRec([&](TypeBase *type) -> Optional<Type> {
@@ -3409,6 +3505,7 @@
assert(memberType);
+ // Perform the substitution.
auto substitutions = getMemberSubstitutionMap(module, member);
return memberType.subst(substitutions, SubstFlags::UseErrorType);
}
@@ -3802,6 +3899,7 @@
return DependentMemberType::get(dependentBase, dependent->getName());
}
+ case TypeKind::GenericFunction:
case TypeKind::Function: {
auto function = cast<AnyFunctionType>(base);
auto inputTy = function->getInput().transformRec(fn);
@@ -3811,131 +3909,33 @@
if (!resultTy)
return Type();
- if (inputTy.getPointer() == function->getInput().getPointer() &&
- resultTy.getPointer() == function->getResult().getPointer())
- return *this;
+ bool isUnchanged =
+ inputTy.getPointer() == function->getInput().getPointer() &&
+ resultTy.getPointer() == function->getResult().getPointer();
+
+ if (auto genericFnType = dyn_cast<GenericFunctionType>(base)) {
+
+#ifndef NDEBUG
+ // Check that generic parameters won't be trasnformed.
+ // Transform generic parameters.
+ for (auto param : genericFnType->getGenericParams()) {
+ assert(Type(param).transformRec(fn).getPointer() == param &&
+ "GenericFunctionType transform() changes type parameter");
+ }
+#endif
+ if (isUnchanged) return *this;
+
+ auto genericSig = genericFnType->getGenericSignature();
+ return GenericFunctionType::get(genericSig, inputTy, resultTy,
+ function->getExtInfo());
+ }
+
+ if (isUnchanged) return *this;
return FunctionType::get(inputTy, resultTy,
function->getExtInfo());
}
- case TypeKind::GenericFunction: {
- GenericFunctionType *function = cast<GenericFunctionType>(base);
- bool anyChanges = false;
-
- // Transform generic parameters.
- SmallVector<GenericTypeParamType *, 4> genericParams;
- for (auto param : function->getGenericParams()) {
- Type paramTy = Type(param).transformRec(fn);
- if (!paramTy)
- return Type();
-
- if (auto newParam = paramTy->getAs<GenericTypeParamType>()) {
- if (newParam != param)
- anyChanges = true;
-
- genericParams.push_back(newParam);
- } else {
- anyChanges = true;
- }
- }
-
- // Transform requirements.
- SmallVector<Requirement, 4> requirements;
- for (const auto &req : function->getRequirements()) {
- auto firstType = req.getFirstType().transformRec(fn);
- if (!firstType)
- return Type();
-
- if (firstType.getPointer() != req.getFirstType().getPointer())
- anyChanges = true;
-
- if (req.getKind() == RequirementKind::Layout) {
- if (!firstType->isTypeParameter())
- continue;
-
- requirements.push_back(Requirement(req.getKind(), firstType,
- req.getLayoutConstraint()));
- continue;
- }
-
- Type secondType = req.getSecondType();
- if (secondType) {
- secondType = secondType.transformRec(fn);
- if (!secondType)
- return Type();
-
- if (secondType.getPointer() != req.getSecondType().getPointer())
- anyChanges = true;
- }
-
- if (!firstType->isTypeParameter()) {
- if (!secondType || !secondType->isTypeParameter())
- continue;
- std::swap(firstType, secondType);
- }
-
- requirements.push_back(Requirement(req.getKind(), firstType,
- secondType));
- }
-
- // Transform input type.
- auto inputTy = function->getInput().transformRec(fn);
- if (!inputTy)
- return Type();
-
- // Transform result type.
- auto resultTy = function->getResult().transformRec(fn);
- if (!resultTy)
- return Type();
-
- // Check whether anything changed.
- if (!anyChanges &&
- inputTy.getPointer() == function->getInput().getPointer() &&
- resultTy.getPointer() == function->getResult().getPointer())
- return *this;
-
- // If no generic parameters remain, this is a non-generic function type.
- if (genericParams.empty()) {
- return FunctionType::get(inputTy, resultTy, function->getExtInfo());
- }
-
- // Sort/unique the generic parameters by depth/index.
- using llvm::array_pod_sort;
- array_pod_sort(genericParams.begin(), genericParams.end(),
- [](GenericTypeParamType * const * gpp1,
- GenericTypeParamType * const * gpp2) {
- auto gp1 = *gpp1;
- auto gp2 = *gpp2;
-
- if (gp1->getDepth() < gp2->getDepth())
- return -1;
-
- if (gp1->getDepth() > gp2->getDepth())
- return 1;
-
- if (gp1->getIndex() < gp2->getIndex())
- return -1;
-
- if (gp1->getIndex() > gp2->getIndex())
- return 1;
-
- return 0;
- });
- genericParams.erase(std::unique(genericParams.begin(), genericParams.end(),
- [](GenericTypeParamType *gp1,
- GenericTypeParamType *gp2) {
- return gp1->getDepth() == gp2->getDepth()
- && gp1->getIndex() == gp2->getIndex();
- }),
- genericParams.end());
-
- // Produce the new generic function type.
- auto sig = GenericSignature::get(genericParams, requirements);
- return GenericFunctionType::get(sig, inputTy, resultTy,
- function->getExtInfo());
- }
-
case TypeKind::ArraySlice: {
auto slice = cast<ArraySliceType>(base);
auto baseTy = slice->getBaseType().transformRec(fn);
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index 69bb2c9..8b3ffed 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -705,43 +705,32 @@
"metadata ref for generic function type");
return llvm::UndefValue::get(IGF.IGM.TypeMetadataPtrTy);
}
-
- llvm::Value *extractAndMarkResultType(CanFunctionType type) {
- // If the function type throws, set the lower bit of the return type
- // address, so that we can carry this information over to the function
- // type metadata.
- auto metadata = IGF.emitTypeMetadataRef(type->getResult()->
- getCanonicalType());
- return metadata;
- }
- llvm::Value *extractAndMarkInOut(AnyFunctionType::CanParam param) {
- // If the type is inout, get the metadata for its inner object type
- // instead, and then set the lowest bit to help the runtime unique
- // the metadata type for this function.
+ llvm::Value *getFunctionParameterRef(AnyFunctionType::CanParam param) {
auto type = param.getType();
- if (param.getParameterFlags().isInOut()) {
- auto objectType = type->getInOutObjectType()->getCanonicalType();
- auto metadata = IGF.emitTypeMetadataRef(objectType);
- auto metadataInt = IGF.Builder.CreatePtrToInt(metadata, IGF.IGM.SizeTy);
- auto inoutFlag = llvm::ConstantInt::get(IGF.IGM.SizeTy, 1);
- auto marked = IGF.Builder.CreateOr(metadataInt, inoutFlag);
- return IGF.Builder.CreateIntToPtr(marked, IGF.IGM.Int8PtrTy);
- }
-
- auto metadata = IGF.emitTypeMetadataRef(type);
- return IGF.Builder.CreateBitCast(metadata, IGF.IGM.Int8PtrTy);
+ if (param.getParameterFlags().isInOut())
+ type = type->getInOutObjectType()->getCanonicalType();
+ return IGF.emitTypeMetadataRef(type);
}
llvm::Value *visitFunctionType(CanFunctionType type) {
if (auto metatype = tryGetLocal(type))
return metatype;
- auto resultMetadata = extractAndMarkResultType(type);
+ auto result =
+ IGF.emitTypeMetadataRef(type->getResult()->getCanonicalType());
auto params = type.getParams();
auto numParams = params.size();
+ bool hasFlags = false;
+ for (auto param : params) {
+ if (!param.getParameterFlags().isNone()) {
+ hasFlags = true;
+ break;
+ }
+ }
+
// Map the convention to a runtime metadata value.
FunctionMetadataConvention metadataConvention;
switch (type->getRepresentation()) {
@@ -760,78 +749,136 @@
}
auto flagsVal = FunctionTypeFlags()
- .withNumArguments(numParams)
+ .withNumParameters(numParams)
.withConvention(metadataConvention)
- .withThrows(type->throws());
+ .withThrows(type->throws())
+ .withParameterFlags(hasFlags);
auto flags = llvm::ConstantInt::get(IGF.IGM.SizeTy,
flagsVal.getIntValue());
- switch (numParams) {
- case 1: {
- auto arg0 = extractAndMarkInOut(params[0]);
- auto call = IGF.Builder.CreateCall(IGF.IGM.getGetFunctionMetadata1Fn(),
- {flags, arg0, resultMetadata});
- call->setDoesNotThrow();
- return setLocal(CanType(type), call);
- }
+ auto collectParameters =
+ [&](llvm::function_ref<void(unsigned, llvm::Value *,
+ ParameterFlags flags)>
+ processor) {
+ for (auto index : indices(params)) {
+ auto param = params[index];
+ auto flags = param.getParameterFlags();
- case 2: {
- auto arg0 = extractAndMarkInOut(params[0]);
- auto arg1 = extractAndMarkInOut(params[1]);
- auto call = IGF.Builder.CreateCall(
- IGF.IGM.getGetFunctionMetadata2Fn(),
- {flags, arg0, arg1, resultMetadata});
- call->setDoesNotThrow();
- return setLocal(CanType(type), call);
- }
+ auto parameterFlags = ParameterFlags()
+ .withInOut(flags.isInOut())
+ .withShared(flags.isShared())
+ .withVariadic(flags.isVariadic());
- case 3: {
- auto arg0 = extractAndMarkInOut(params[0]);
- auto arg1 = extractAndMarkInOut(params[1]);
- auto arg2 = extractAndMarkInOut(params[2]);
- auto call = IGF.Builder.CreateCall(
- IGF.IGM.getGetFunctionMetadata3Fn(),
- {flags, arg0, arg1, arg2,
- resultMetadata});
- call->setDoesNotThrow();
- return setLocal(CanType(type), call);
- }
+ processor(index, getFunctionParameterRef(param), parameterFlags);
+ }
+ };
+
+ auto constructSimpleCall =
+ [&](llvm::SmallVectorImpl<llvm::Value *> &arguments)
+ -> llvm::Constant * {
+ arguments.push_back(flags);
+
+ collectParameters([&](unsigned i, llvm::Value *typeRef,
+ ParameterFlags flags) {
+ arguments.push_back(typeRef);
+ if (hasFlags)
+ arguments.push_back(
+ llvm::ConstantInt::get(IGF.IGM.Int32Ty, flags.getIntValue()));
+ });
+
+ arguments.push_back(result);
+
+ switch (params.size()) {
+ case 1:
+ return hasFlags ? IGF.IGM.getGetFunctionMetadata1WithFlagsFn()
+ : IGF.IGM.getGetFunctionMetadata1Fn();
+
+ case 2:
+ return hasFlags ? IGF.IGM.getGetFunctionMetadata2WithFlagsFn()
+ : IGF.IGM.getGetFunctionMetadata2Fn();
+
+ case 3:
+ return hasFlags ? IGF.IGM.getGetFunctionMetadata3WithFlagsFn()
+ : IGF.IGM.getGetFunctionMetadata3Fn();
default:
- auto arrayTy = llvm::ArrayType::get(IGF.IGM.Int8PtrTy, numParams + 2);
- Address buffer = IGF.createAlloca(arrayTy,
- IGF.IGM.getPointerAlignment(),
- "function-arguments");
- IGF.Builder.CreateLifetimeStart(buffer,
+ llvm_unreachable("supports only 1/2/3 parameter functions");
+ }
+ };
+
+ auto getArrayFor = [&](llvm::Type *elementType, unsigned size,
+ const llvm::Twine &name) -> Address {
+ auto arrayTy = llvm::ArrayType::get(elementType, size);
+ return IGF.createAlloca(arrayTy, IGF.IGM.getPointerAlignment(), name);
+ };
+
+ switch (numParams) {
+ case 1:
+ case 2:
+ case 3: {
+ llvm::SmallVector<llvm::Value *, 8> arguments;
+ auto *metadataFn = constructSimpleCall(arguments);
+ auto *call = IGF.Builder.CreateCall(metadataFn, arguments);
+ call->setDoesNotThrow();
+ return setLocal(CanType(type), call);
+ }
+
+ default:
+ auto *const Int32Ptr = IGF.IGM.Int32Ty->getPointerTo();
+
+ llvm::SmallVector<llvm::Value *, 8> arguments;
+ arguments.push_back(flags);
+
+ Address parameters;
+ if (!params.empty()) {
+ parameters = getArrayFor(IGF.IGM.TypeMetadataPtrTy, numParams,
+ "function-parameters");
+
+ IGF.Builder.CreateLifetimeStart(parameters,
IGF.IGM.getPointerSize() * numParams);
- Address pointerToFirstArg = IGF.Builder.CreateStructGEP(buffer, 0,
- Size(0));
- Address flagsPtr = IGF.Builder.CreateBitCast(pointerToFirstArg,
- IGF.IGM.SizeTy->getPointerTo());
- IGF.Builder.CreateStore(flags, flagsPtr);
- for (auto i : indices(params)) {
- auto argMetadata = extractAndMarkInOut(params[i]);
- Address argPtr = IGF.Builder.CreateStructGEP(buffer, i + 1,
+ ConstantInitBuilder paramFlags(IGF.IGM);
+ auto flagsArr = paramFlags.beginArray();
+ collectParameters([&](unsigned i, llvm::Value *typeRef,
+ ParameterFlags flags) {
+ auto argPtr = IGF.Builder.CreateStructGEP(parameters, i,
IGF.IGM.getPointerSize());
- IGF.Builder.CreateStore(argMetadata, argPtr);
+ IGF.Builder.CreateStore(typeRef, argPtr);
+ if (hasFlags)
+ flagsArr.addInt32(flags.getIntValue());
+ });
+
+ auto parametersPtr =
+ IGF.Builder.CreateStructGEP(parameters, 0, Size(0));
+ arguments.push_back(parametersPtr.getAddress());
+
+ if (hasFlags) {
+ auto *flagsVar = flagsArr.finishAndCreateGlobal(
+ "parameter-flags", IGF.IGM.getPointerAlignment(),
+ /* constant */ true);
+ arguments.push_back(IGF.Builder.CreateBitCast(flagsVar, Int32Ptr));
+ } else {
+ flagsArr.abandon();
+ arguments.push_back(llvm::ConstantPointerNull::get(Int32Ptr));
}
+ } else {
+ arguments.push_back(llvm::ConstantPointerNull::get(
+ IGF.IGM.TypeMetadataPtrTy->getPointerTo()));
+ arguments.push_back(llvm::ConstantPointerNull::get(Int32Ptr));
+ }
- Address resultPtr = IGF.Builder.CreateStructGEP(
- buffer, numParams + 1, IGF.IGM.getPointerSize());
- resultPtr = IGF.Builder.CreateBitCast(resultPtr,
- IGF.IGM.TypeMetadataPtrTy->getPointerTo());
- IGF.Builder.CreateStore(resultMetadata, resultPtr);
+ arguments.push_back(result);
- auto call = IGF.Builder.CreateCall(IGF.IGM.getGetFunctionMetadataFn(),
- pointerToFirstArg.getAddress());
- call->setDoesNotThrow();
+ auto call = IGF.Builder.CreateCall(IGF.IGM.getGetFunctionMetadataFn(),
+ arguments);
+ call->setDoesNotThrow();
- IGF.Builder.CreateLifetimeEnd(buffer,
+ if (parameters.isValid())
+ IGF.Builder.CreateLifetimeEnd(parameters,
IGF.IGM.getPointerSize() * numParams);
- return setLocal(type, call);
+ return setLocal(type, call);
}
}
diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp
index aa2ab44..2ba989d 100644
--- a/lib/ParseSIL/ParseSIL.cpp
+++ b/lib/ParseSIL/ParseSIL.cpp
@@ -1236,7 +1236,7 @@
if (!P.consumeIf(tok::sil_exclamation)) {
// Construct SILDeclRef.
Result = SILDeclRef(VD, Kind, expansion, /*isCurried=*/false, IsObjC);
- if (uncurryLevel < Result.getUncurryLevel())
+ if (uncurryLevel < Result.getParameterListCount() - 1)
Result = Result.asCurried();
return false;
}
@@ -1327,7 +1327,7 @@
// Construct SILDeclRef.
Result = SILDeclRef(VD, Kind, expansion, /*isCurried=*/false, IsObjC);
- if (uncurryLevel < Result.getUncurryLevel())
+ if (uncurryLevel < Result.getParameterListCount() - 1)
Result = Result.asCurried();
return false;
}
diff --git a/lib/RemoteAST/RemoteAST.cpp b/lib/RemoteAST/RemoteAST.cpp
index 064af07..5dcf23e 100644
--- a/lib/RemoteAST/RemoteAST.cpp
+++ b/lib/RemoteAST/RemoteAST.cpp
@@ -334,7 +334,12 @@
auto label = Ctx.getIdentifier(param.getLabel());
auto flags = param.getFlags();
- funcParams.push_back(AnyFunctionType::Param(type, label, flags));
+ auto parameterFlags = ParameterTypeFlags()
+ .withInOut(flags.isInOut())
+ .withShared(flags.isShared())
+ .withVariadic(flags.isVariadic());
+
+ funcParams.push_back(AnyFunctionType::Param(type, label, parameterFlags));
}
return FunctionType::get(funcParams, output, einfo);
diff --git a/lib/SIL/SILDeclRef.cpp b/lib/SIL/SILDeclRef.cpp
index 1acb152..65dda5d 100644
--- a/lib/SIL/SILDeclRef.cpp
+++ b/lib/SIL/SILDeclRef.cpp
@@ -227,29 +227,6 @@
return false;
}
-static unsigned getFuncNaturalUncurryLevel(AnyFunctionRef AFR) {
- assert(AFR.getParameterLists().size() >= 1 && "no arguments for func?!");
- return AFR.getParameterLists().size() - 1;
-}
-
-unsigned swift::getNaturalUncurryLevel(ValueDecl *vd) {
- if (auto *func = dyn_cast<FuncDecl>(vd)) {
- return getFuncNaturalUncurryLevel(func);
- } else if (isa<ConstructorDecl>(vd)) {
- return 1;
- } else if (auto *ed = dyn_cast<EnumElementDecl>(vd)) {
- return ed->hasAssociatedValues() ? 1 : 0;
- } else if (isa<DestructorDecl>(vd)) {
- return 0;
- } else if (isa<ClassDecl>(vd)) {
- return 1;
- } else if (isa<VarDecl>(vd)) {
- return 0;
- } else {
- llvm_unreachable("Unhandled ValueDecl for SILDeclRef");
- }
-}
-
SILDeclRef::SILDeclRef(ValueDecl *vd, SILDeclRef::Kind kind,
ResilienceExpansion expansion,
bool isCurried, bool isForeign)
@@ -888,12 +865,23 @@
llvm_unreachable("Unhandled access level in switch.");
}
-unsigned SILDeclRef::getUncurryLevel() const {
- if (isCurried)
- return 0;
- if (!hasDecl())
- return getFuncNaturalUncurryLevel(*getAnyFunctionRef());
- if (kind == Kind::DefaultArgGenerator)
- return 0;
- return getNaturalUncurryLevel(getDecl());
+unsigned SILDeclRef::getParameterListCount() const {
+ if (isCurried || !hasDecl() || kind == Kind::DefaultArgGenerator)
+ return 1;
+
+ auto *vd = getDecl();
+
+ if (auto *func = dyn_cast<AbstractFunctionDecl>(vd)) {
+ return func->getParameterLists().size();
+ } else if (auto *ed = dyn_cast<EnumElementDecl>(vd)) {
+ return ed->hasAssociatedValues() ? 2 : 1;
+ } else if (isa<DestructorDecl>(vd)) {
+ return 1;
+ } else if (isa<ClassDecl>(vd)) {
+ return 2;
+ } else if (isa<VarDecl>(vd)) {
+ return 1;
+ } else {
+ llvm_unreachable("Unhandled ValueDecl for SILDeclRef");
+ }
}
diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp
index b25e10a..81f745e 100644
--- a/lib/SIL/SILFunctionType.cpp
+++ b/lib/SIL/SILFunctionType.cpp
@@ -1781,7 +1781,7 @@
return false;
// Must be a type member.
- if (constant.getUncurryLevel() != 1)
+ if (constant.getParameterListCount() != 2)
return false;
// Must be imported from a function.
@@ -2501,7 +2501,7 @@
TypeConverter::LoweredFormalTypes
TypeConverter::getLoweredFormalTypes(SILDeclRef constant,
CanAnyFunctionType fnType) {
- unsigned uncurryLevel = constant.getUncurryLevel();
+ unsigned uncurryLevel = constant.getParameterListCount() - 1;
auto extInfo = fnType->getExtInfo();
// Form an abstraction pattern for bridging purposes.
diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp
index 36ae99d..541c479 100644
--- a/lib/SIL/SILPrinter.cpp
+++ b/lib/SIL/SILPrinter.cpp
@@ -351,7 +351,7 @@
break;
}
- auto uncurryLevel = getUncurryLevel();
+ auto uncurryLevel = getParameterListCount() - 1;
if (uncurryLevel != 0)
OS << (isDot ? '.' : '!') << uncurryLevel;
diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp
index 1349372..1813f86 100644
--- a/lib/SILGen/SILGenApply.cpp
+++ b/lib/SILGen/SILGenApply.cpp
@@ -459,10 +459,10 @@
return SubstFormalInterfaceType;
}
- unsigned getNaturalUncurryLevel() const {
+ unsigned getParameterListCount() const {
switch (kind) {
case Kind::IndirectValue:
- return 0;
+ return 1;
case Kind::StandaloneFunction:
case Kind::EnumElement:
@@ -470,7 +470,7 @@
case Kind::SuperMethod:
case Kind::WitnessMethod:
case Kind::DynamicMethod:
- return Constant.getUncurryLevel();
+ return Constant.getParameterListCount();
}
llvm_unreachable("Unhandled Kind in switch.");
@@ -500,21 +500,57 @@
return result;
}
- ManagedValue getFnValueAtUncurryLevel(SILGenFunction &SGF,
- unsigned level) const & {
+ SILDeclRef getCurriedConstant(bool isCurried) const {
+ if (isCurried) {
+ auto constant = Constant.asCurried();
+
+ // If we're currying a direct reference to a class-dispatched method,
+ // make sure we emit the right set of thunks.
+ if (kind == Kind::StandaloneFunction) {
+ if (auto func = Constant.getAbstractFunctionDecl()) {
+ if (getMethodDispatch(func) == MethodDispatch::Class) {
+ return constant.asDirectReference(true);
+ }
+ }
+ }
+
+ return constant;
+ }
+
+ return Constant;
+ }
+
+ SILType getDynamicMethodType(SILGenFunction &SGF) const {
+ // Lower the substituted type from the AST, which should have any generic
+ // parameters in the original signature erased to their upper bounds.
+ auto substFormalType = getSubstFormalType();
+ auto objcFormalType = substFormalType.withExtInfo(
+ substFormalType->getExtInfo().withSILRepresentation(
+ SILFunctionTypeRepresentation::ObjCMethod));
+ auto fnType = SGF.SGM.M.Types.getUncachedSILFunctionTypeForConstant(
+ Constant, objcFormalType);
+
+ auto closureType = replaceSelfTypeForDynamicLookup(
+ SGF.getASTContext(), fnType,
+ SelfValue.getValue().getSILSubstType(SGF).getSwiftRValueType(),
+ Constant);
+
+ return SILType::getPrimitiveObjectType(closureType);
+ }
+
+ ManagedValue getFnValue(SILGenFunction &SGF, bool isCurried) const & {
Optional<SILDeclRef> constant = None;
if (!Constant) {
- assert(level == 0 && "can't curry indirect function");
+ assert(!isCurried && "can't curry indirect function");
} else {
- unsigned uncurryLevel = Constant.getUncurryLevel();
- assert(level <= uncurryLevel &&
- "uncurrying past natural uncurry level of standalone function");
- if (level < uncurryLevel) {
- assert(level == 0);
- constant = Constant.asCurried();
- } else {
- constant = Constant;
+ constant = getCurriedConstant(isCurried);
+
+ // If the call is curried, emit a direct call to the curry thunk.
+ if (constant->isCurried) {
+ auto constantInfo = SGF.getConstantInfo(*constant);
+ SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
+ return ManagedValue::forUnmanaged(ref);
}
}
@@ -524,36 +560,13 @@
return IndirectValue;
case Kind::StandaloneFunction: {
- // If we're currying a direct reference to a class-dispatched method,
- // make sure we emit the right set of thunks.
- if (constant->isCurried && Constant.hasDecl())
- if (auto func = Constant.getAbstractFunctionDecl())
- if (getMethodDispatch(func) == MethodDispatch::Class)
- constant = constant->asDirectReference(true);
-
auto constantInfo = SGF.getConstantInfo(*constant);
SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
return ManagedValue::forUnmanaged(ref);
}
- case Kind::EnumElement: {
- auto constantInfo = SGF.getConstantInfo(*constant);
-
- // We should not end up here if the enum constructor call is fully
- // applied.
- assert(constant->isCurried);
-
- SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
- return ManagedValue::forUnmanaged(ref);
- }
+ case Kind::EnumElement:
+ llvm_unreachable("Should have been curried");
case Kind::ClassMethod: {
- auto constantInfo = SGF.getConstantInfo(*constant);
-
- // If the call is curried, emit a direct call to the curry thunk.
- if (constant->isCurried) {
- SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
- return ManagedValue::forUnmanaged(ref);
- }
-
auto methodTy = SGF.SGM.Types.getConstantOverrideType(*constant);
// Otherwise, do the dynamic dispatch inline.
@@ -596,15 +609,8 @@
case Kind::WitnessMethod: {
auto constantInfo = SGF.getConstantInfo(*constant);
- // If the call is curried, emit a direct call to the curry thunk.
- if (constant->isCurried) {
- SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
- return ManagedValue::forUnmanaged(ref);
- }
-
- auto proto = Constant.getDecl()
- ->getDeclContext()
- ->getAsProtocolOrProtocolExtensionContext();
+ auto proto = cast<ProtocolDecl>(
+ Constant.getDecl()->getDeclContext());
auto lookupType = getSubstFormalType()
.getInput()
->getRValueInstanceType()
@@ -614,52 +620,34 @@
Loc, lookupType, ProtocolConformanceRef(proto), *constant,
constantInfo.getSILType(), constant->isForeign);
return ManagedValue::forUnmanaged(fn);
- ;
}
case Kind::DynamicMethod: {
- assert(!constant->isCurried);
assert(constant->isForeign);
-
- // Lower the substituted type from the AST, which should have any generic
- // parameters in the original signature erased to their upper bounds.
- auto substFormalType = getSubstFormalType();
- auto objcFormalType = substFormalType.withExtInfo(
- substFormalType->getExtInfo().withSILRepresentation(
- SILFunctionTypeRepresentation::ObjCMethod));
- auto fnType = SGF.SGM.M.Types.getUncachedSILFunctionTypeForConstant(
- *constant, objcFormalType);
-
- auto closureType = replaceSelfTypeForDynamicLookup(
- SGF.getASTContext(), fnType,
- SelfValue.getValue().getSILSubstType(SGF).getSwiftRValueType(),
- Constant);
+ auto closureType = getDynamicMethodType(SGF);
Scope S(SGF, Loc);
ManagedValue self =
SelfValue.getValue().borrow(SGF).getAsSingleValue(SGF);
SILValue fn = SGF.B.createObjCMethod(
Loc, self.getValue(), *constant,
- SILType::getPrimitiveObjectType(closureType));
+ closureType);
return ManagedValue::forUnmanaged(fn);
}
}
}
- CalleeTypeInfo getTypeInfoAtUncurryLevel(SILGenFunction &SGF,
- unsigned level) const & {
+ CalleeTypeInfo getTypeInfo(SILGenFunction &SGF, bool isCurried) const & {
Optional<SILDeclRef> constant = None;
if (!Constant) {
- assert(level == 0 && "can't curry indirect function");
+ assert(!isCurried && "can't curry indirect function");
} else {
- unsigned uncurryLevel = Constant.getUncurryLevel();
- assert(level <= uncurryLevel &&
- "uncurrying past natural uncurry level of standalone function");
- if (level < uncurryLevel) {
- assert(level == 0);
- constant = Constant.asCurried();
- } else {
- constant = Constant;
+ constant = getCurriedConstant(isCurried);
+
+ // If the call is curried, emit a direct call to the curry thunk.
+ if (constant->isCurried) {
+ auto constantInfo = SGF.getConstantInfo(*constant);
+ return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
}
}
@@ -669,38 +657,16 @@
return createCalleeTypeInfo(SGF, constant, IndirectValue.getType());
case Kind::StandaloneFunction: {
- // If we're currying a direct reference to a class-dispatched method,
- // make sure we emit the right set of thunks.
- if (constant->isCurried && Constant.hasDecl())
- if (auto func = Constant.getAbstractFunctionDecl())
- if (getMethodDispatch(func) == MethodDispatch::Class)
- constant = constant->asDirectReference(true);
-
auto constantInfo = SGF.getConstantInfo(*constant);
return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
- ;
}
- case Kind::EnumElement: {
- auto constantInfo = SGF.getConstantInfo(*constant);
-
- // We should not end up here if the enum constructor call is fully
- // applied.
- assert(constant->isCurried);
- return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
- }
+ case Kind::EnumElement:
+ llvm_unreachable("Should have been curried");
case Kind::ClassMethod: {
- // If the call is curried, emit a direct call to the curry thunk.
- if (constant->isCurried) {
- auto constantInfo = SGF.getConstantInfo(*constant);
- return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
- }
-
- // Otherwise, grab the override info.
auto constantInfo = SGF.SGM.Types.getConstantOverrideInfo(*constant);
return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
}
case Kind::SuperMethod: {
- assert(!constant->isCurried);
auto base = SGF.SGM.Types.getOverriddenVTableEntry(*constant);
auto constantInfo =
SGF.SGM.Types.getConstantOverrideInfo(*constant, base);
@@ -711,23 +677,7 @@
return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
}
case Kind::DynamicMethod: {
- assert(!constant->isCurried);
-
- // Lower the substituted type from the AST, which should have any generic
- // parameters in the original signature erased to their upper bounds.
- auto substFormalType = getSubstFormalType();
- auto objcFormalType = substFormalType.withExtInfo(
- substFormalType->getExtInfo().withSILRepresentation(
- SILFunctionTypeRepresentation::ObjCMethod));
- auto fnType = SGF.SGM.M.Types.getUncachedSILFunctionTypeForConstant(
- *constant, objcFormalType);
-
- auto closureType = replaceSelfTypeForDynamicLookup(
- SGF.getASTContext(), fnType,
- SelfValue.getValue().getSILSubstType(SGF).getSwiftRValueType(),
- Constant);
-
- SILType formalType = SILType::getPrimitiveObjectType(closureType);
+ auto formalType = getDynamicMethodType(SGF);
return createCalleeTypeInfo(SGF, constant, formalType);
}
}
@@ -745,11 +695,7 @@
/// lowering, such as a builtin, or return null if there is no specialized
/// emitter.
Optional<SpecializedEmitter>
- getSpecializedEmitter(SILGenModule &SGM, unsigned uncurryLevel) const {
- // Currently we have no curried known functions.
- if (uncurryLevel != 0)
- return None;
-
+ getSpecializedEmitter(SILGenModule &SGM) const {
switch (kind) {
case Kind::StandaloneFunction: {
return SpecializedEmitter::forDecl(SGM, Constant);
@@ -3959,8 +3905,7 @@
std::vector<CallSite> extraSites;
Callee callee;
FormalEvaluationScope initialWritebackScope;
- unsigned uncurries;
- bool applied;
+ unsigned expectedSiteCount;
bool assumedPlusZeroSelf;
public:
@@ -3970,17 +3915,14 @@
bool assumedPlusZeroSelf = false)
: SGF(SGF), callee(std::move(callee)),
initialWritebackScope(std::move(writebackScope)),
- uncurries(callee.getNaturalUncurryLevel() + 1), applied(false),
+ expectedSiteCount(callee.getParameterListCount()),
assumedPlusZeroSelf(assumedPlusZeroSelf) {}
/// Add a level of function application by passing in its possibly
/// unevaluated arguments and their formal type.
void addCallSite(CallSite &&site) {
- assert(!applied && "already applied!");
-
// Append to the main argument list if we have uncurry levels remaining.
- if (uncurries > 0) {
- --uncurries;
+ if (uncurriedSites.size() < expectedSiteCount) {
uncurriedSites.push_back(std::move(site));
return;
}
@@ -4011,30 +3953,21 @@
/// Is this a fully-applied enum element constructor call?
bool isEnumElementConstructor() {
- return (callee.kind == Callee::Kind::EnumElement && uncurries == 0);
+ return (callee.kind == Callee::Kind::EnumElement &&
+ uncurriedSites.size() == expectedSiteCount);
}
/// True if this is a completely unapplied super method call
- bool isPartiallyAppliedSuperMethod(unsigned uncurryLevel) {
+ bool isPartiallyAppliedSuperMethod() {
return (callee.kind == Callee::Kind::SuperMethod &&
- uncurryLevel == 0);
+ uncurriedSites.size() == 1);
}
RValue apply(SGFContext C = SGFContext()) {
initialWritebackScope.verify();
- assert(!applied && "already applied!");
-
- applied = true;
-
- // Get the callee value at the needed uncurry level, uncurrying as
- // much as possible. If the number of calls is less than the natural
- // uncurry level, the callee emission might create a curry thunk.
- unsigned uncurryLevel = callee.getNaturalUncurryLevel() - uncurries;
-
// Emit the first level of call.
- FirstLevelApplicationResult firstLevelResult =
- applyFirstLevelCallee(uncurryLevel, C);
+ auto firstLevelResult = applyFirstLevelCallee(C);
// End of the initial writeback scope.
initialWritebackScope.verify();
@@ -4063,17 +3996,8 @@
firstLevelResult.foreignSelf, C, formalTypeThrows);
}
- ~CallEmission() { assert(applied && "never applied!"); }
-
// Movable, but not copyable.
- CallEmission(CallEmission &&e)
- : SGF(e.SGF), uncurriedSites(std::move(e.uncurriedSites)),
- extraSites(std::move(e.extraSites)), callee(std::move(e.callee)),
- initialWritebackScope(std::move(e.initialWritebackScope)),
- uncurries(e.uncurries), applied(e.applied),
- assumedPlusZeroSelf(e.assumedPlusZeroSelf) {
- e.applied = true;
- }
+ CallEmission(CallEmission &&e) = default;
private:
CallEmission(const CallEmission &) = delete;
@@ -4132,19 +4056,17 @@
FirstLevelApplicationResult
applySpecializedEmitter(SpecializedEmitter &specializedEmitter,
- unsigned uncurryLevel, SGFContext C);
+ SGFContext C);
FirstLevelApplicationResult
- applyPartiallyAppliedSuperMethod(unsigned uncurryLevel, SGFContext C);
+ applyPartiallyAppliedSuperMethod(SGFContext C);
FirstLevelApplicationResult
- applyEnumElementConstructor(unsigned uncurryLevel, SGFContext C);
+ applyEnumElementConstructor(SGFContext C);
- FirstLevelApplicationResult applyNormalCall(unsigned uncurryLevel,
- SGFContext C);
+ FirstLevelApplicationResult applyNormalCall(SGFContext C);
- FirstLevelApplicationResult applyFirstLevelCallee(unsigned uncurryLevel,
- SGFContext C);
+ FirstLevelApplicationResult applyFirstLevelCallee(SGFContext C);
RValue applyRemainingCallSites(RValue &&result,
AbstractionPattern origFormalType,
@@ -4167,25 +4089,27 @@
}
CallEmission::FirstLevelApplicationResult
-CallEmission::applyFirstLevelCallee(unsigned uncurryLevel, SGFContext C) {
+CallEmission::applyFirstLevelCallee(SGFContext C) {
// Check for a specialized emitter.
- if (auto emitter = callee.getSpecializedEmitter(SGF.SGM, uncurryLevel)) {
- return applySpecializedEmitter(emitter.getValue(), uncurryLevel, C);
+ if (uncurriedSites.size() == expectedSiteCount) {
+ if (auto emitter = callee.getSpecializedEmitter(SGF.SGM)) {
+ return applySpecializedEmitter(emitter.getValue(), C);
+ }
}
- if (isPartiallyAppliedSuperMethod(uncurryLevel)) {
- return applyPartiallyAppliedSuperMethod(uncurryLevel, C);
+ if (isPartiallyAppliedSuperMethod()) {
+ return applyPartiallyAppliedSuperMethod(C);
}
if (isEnumElementConstructor()) {
- return applyEnumElementConstructor(uncurryLevel, C);
+ return applyEnumElementConstructor(C);
}
- return applyNormalCall(uncurryLevel, C);
+ return applyNormalCall(C);
}
CallEmission::FirstLevelApplicationResult
-CallEmission::applyNormalCall(unsigned uncurryLevel, SGFContext C) {
+CallEmission::applyNormalCall(SGFContext C) {
FirstLevelApplicationResult firstLevelResult;
// We use the context emit-into initialization only for the
@@ -4195,10 +4119,11 @@
firstLevelResult.formalType = callee.getSubstFormalType();
auto origFormalType = callee.getOrigFormalType();
+ bool isCurried = (uncurriedSites.size() < callee.getParameterListCount());
+
// Get the callee type information.
- CalleeTypeInfo calleeTypeInfo =
- callee.getTypeInfoAtUncurryLevel(SGF, uncurryLevel);
- ManagedValue mv = callee.getFnValueAtUncurryLevel(SGF, uncurryLevel);
+ auto calleeTypeInfo = callee.getTypeInfo(SGF, isCurried);
+ auto mv = callee.getFnValue(SGF, isCurried);
// In C language modes, substitute the type of the AbstractionPattern
// so that we won't see type parameters down when we try to form bridging
@@ -4257,7 +4182,7 @@
}
CallEmission::FirstLevelApplicationResult
-CallEmission::applyEnumElementConstructor(unsigned uncurryLevel, SGFContext C) {
+CallEmission::applyEnumElementConstructor(SGFContext C) {
FirstLevelApplicationResult firstLevelResult;
assert(!assumedPlusZeroSelf);
SGFContext uncurriedContext = (extraSites.empty() ? C : SGFContext());
@@ -4312,10 +4237,8 @@
}
CallEmission::FirstLevelApplicationResult
-CallEmission::applyPartiallyAppliedSuperMethod(unsigned uncurryLevel,
- SGFContext C) {
+CallEmission::applyPartiallyAppliedSuperMethod(SGFContext C) {
FirstLevelApplicationResult firstLevelResult;
- assert(uncurryLevel == 0);
// We want to emit the arguments as fully-substituted values
// because that's what the partially applied super method expects;
@@ -4395,7 +4318,7 @@
CallEmission::FirstLevelApplicationResult
CallEmission::applySpecializedEmitter(SpecializedEmitter &specializedEmitter,
- unsigned uncurryLevel, SGFContext C) {
+ SGFContext C) {
FirstLevelApplicationResult firstLevelResult;
// We use the context emit-into initialization only for the
@@ -4404,8 +4327,6 @@
ManagedValue mv;
- assert(uncurryLevel == 0);
-
// Get the callee type information. We want to emit the arguments as
// fully-substituted values because that's what the specialized emitters
// expect.
@@ -4688,8 +4609,8 @@
auto origFormalType = callee.getOrigFormalType();
auto substFormalType = callee.getSubstFormalType();
- CalleeTypeInfo calleeTypeInfo = callee.getTypeInfoAtUncurryLevel(*this, 0);
- ManagedValue mv = callee.getFnValueAtUncurryLevel(*this, 0);
+ auto calleeTypeInfo = callee.getTypeInfo(*this, /*isCurried=*/false);
+ auto mv = callee.getFnValue(*this, /*isCurried=*/false);
assert(!calleeTypeInfo.foreignError);
assert(!calleeTypeInfo.foreignSelf.isImportAsMember());
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index 0df0b79..a0f3f0e 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -1042,8 +1042,11 @@
// If the referenced decl isn't a VarDecl, it should be a constant of some
// sort.
SILDeclRef silDeclRef(decl);
- if (silDeclRef.getUncurryLevel() > 0)
+ if (silDeclRef.getParameterListCount() == 2) {
+ // Unqualified reference to an instance method from a static context,
+ // without applying 'self'.
silDeclRef = silDeclRef.asCurried();
+ }
ManagedValue result = emitClosureValue(loc, silDeclRef, refType,
declRef.getSubstitutions());
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index f53508b..ff6e2b4 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -2348,25 +2348,14 @@
// Replace generic type parameters and associated types with their
// witnesses, when we have them.
auto selfTy = conformance->getProtocol()->getSelfInterfaceType();
- type = type.transform([&](Type type) -> Type {
- // If a dependent member refers to an associated type, replace it.
- if (auto member = type->getAs<DependentMemberType>()) {
- if (member->getBase()->isEqual(selfTy)) {
- // FIXME: Could handle inherited conformances here.
- if (conformance->hasTypeWitness(member->getAssocType()))
- return conformance->getTypeWitness(member->getAssocType(), nullptr);
- }
- }
+ return type.subst([&](SubstitutableType *dependentType) {
+ if (dependentType->isEqual(selfTy))
+ return conformance->getType();
- // Replace 'Self' with the conforming type.
- if (type->isEqual(selfTy))
- return conformance->getType();
-
- return type;
- });
-
- //
- return type;
+ return Type(dependentType);
+ },
+ LookUpConformanceInModule(module),
+ SubstFlags::UseErrorType);
}
/// \brief Retrieve the kind of requirement described by the given declaration,
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 97db81d..9aa42f8 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -2273,6 +2273,11 @@
options -= TR_ImmediateFunctionInput;
options -= TR_FunctionInput;
options -= TR_TypeAliasUnderlyingType;
+ // FIXME: Until we remove the IUO type from the type system, we
+ // need to continue to parse IUOs in SIL tests so that we can
+ // match the types we generate from the importer.
+ if (!options.contains(TR_SILMode))
+ options -= TR_AllowIUO;
Type inputTy = resolveType(repr->getArgsTypeRepr(),
options | TR_ImmediateFunctionInput);
diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp
index f02cac1..b1e78e8 100644
--- a/lib/Serialization/DeserializeSIL.cpp
+++ b/lib/Serialization/DeserializeSIL.cpp
@@ -710,7 +710,7 @@
(SILDeclRef::Kind)ListOfValues[NextIdx+1],
(swift::ResilienceExpansion)ListOfValues[NextIdx+2],
/*isCurried=*/false, ListOfValues[NextIdx+4] > 0);
- if (ListOfValues[NextIdx+3] < DRef.getUncurryLevel())
+ if (ListOfValues[NextIdx+3] < DRef.getParameterListCount() - 1)
DRef = DRef.asCurried();
NextIdx += 5;
return DRef;
diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp
index ade1175..02317e9 100644
--- a/lib/Serialization/SerializeSIL.cpp
+++ b/lib/Serialization/SerializeSIL.cpp
@@ -482,7 +482,7 @@
ListOfValues.push_back(S.addDeclRef(Ref.getDecl()));
ListOfValues.push_back((unsigned)Ref.kind);
ListOfValues.push_back((unsigned)Ref.getResilienceExpansion());
- ListOfValues.push_back(Ref.getUncurryLevel());
+ ListOfValues.push_back(Ref.getParameterListCount() - 1);
ListOfValues.push_back(Ref.isForeign);
}
diff --git a/stdlib/public/Reflection/TypeRef.cpp b/stdlib/public/Reflection/TypeRef.cpp
index 18a0d5a..c782c71 100644
--- a/stdlib/public/Reflection/TypeRef.cpp
+++ b/stdlib/public/Reflection/TypeRef.cpp
@@ -147,9 +147,6 @@
if (flags.isShared())
printHeader("shared");
- if (flags.isEscaping())
- printHeader("escaping");
-
printRec(param.getType());
if (!flags.isNone()) {
diff --git a/stdlib/public/core/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb
index 567c036..3861ca5 100644
--- a/stdlib/public/core/FloatingPointTypes.swift.gyb
+++ b/stdlib/public/core/FloatingPointTypes.swift.gyb
@@ -1503,8 +1503,9 @@
public init?(exactly value: ${That}) {
_value = Builtin.${sign}itofp_${ThatBuiltinName}_FPIEEE${bits}(value._value)
-% if srcBits < SignificandBitCount:
- if ${That}(self) != value {
+% if srcBits >= SignificandBitCount:
+ guard let roundTrip = ${That}(exactly: self),
+ roundTrip == value else {
return nil
}
% end
diff --git a/stdlib/public/runtime/Casting.cpp b/stdlib/public/runtime/Casting.cpp
index 585e8c9..67f01c5 100644
--- a/stdlib/public/runtime/Casting.cpp
+++ b/stdlib/public/runtime/Casting.cpp
@@ -1920,12 +1920,18 @@
// The result and argument types must match.
if (srcFn->ResultType != targetFn->ResultType)
return _fail(src, srcType, targetType, flags);
- if (srcFn->getNumArguments() != targetFn->getNumArguments())
+ if (srcFn->getNumParameters() != targetFn->getNumParameters())
return _fail(src, srcType, targetType, flags);
- for (unsigned i = 0, e = srcFn->getNumArguments(); i < e; ++i)
- if (srcFn->getArguments()[i] != targetFn->getArguments()[i])
+
+ if (srcFn->hasParameterFlags() != targetFn->hasParameterFlags())
+ return _fail(src, srcType, targetType, flags);
+
+ for (unsigned i = 0, e = srcFn->getNumParameters(); i < e; ++i) {
+ if (srcFn->getParameters()[i] != targetFn->getParameters()[i] ||
+ srcFn->getParameterFlags(i) != targetFn->getParameterFlags(i))
return _fail(src, srcType, targetType, flags);
-
+ }
+
return _succeed(dest, src, srcType, flags);
}
diff --git a/stdlib/public/runtime/Demangle.cpp b/stdlib/public/runtime/Demangle.cpp
index 3f2aaa1..62c2597 100644
--- a/stdlib/public/runtime/Demangle.cpp
+++ b/stdlib/public/runtime/Demangle.cpp
@@ -319,13 +319,19 @@
}
std::vector<NodePointer> inputs;
- for (unsigned i = 0, e = func->getNumArguments(); i < e; ++i) {
- auto arg = func->getArguments()[i];
- auto input = _swift_buildDemanglingForMetadata(arg.getPointer(), Dem);
- if (arg.getFlag()) {
+ for (unsigned i = 0, e = func->getNumParameters(); i < e; ++i) {
+ auto param = func->getParameters()[i];
+ auto flags = func->getParameterFlags(i);
+ auto input = _swift_buildDemanglingForMetadata(param, Dem);
+
+ if (flags.isInOut()) {
NodePointer inout = Dem.createNode(Node::Kind::InOut);
inout->addChild(input, Dem);
input = inout;
+ } else if (flags.isShared()) {
+ NodePointer shared = Dem.createNode(Node::Kind::Shared);
+ shared->addChild(input, Dem);
+ input = shared;
}
inputs.push_back(input);
}
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index 8266a0f..8ed371c 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -14,22 +14,23 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Support/MathExtras.h"
-#include "swift/Demangling/Demangler.h"
+#include "swift/Runtime/Metadata.h"
+#include "MetadataCache.h"
#include "swift/Basic/LLVM.h"
-#include "swift/Basic/Range.h"
#include "swift/Basic/Lazy.h"
+#include "swift/Basic/Range.h"
+#include "swift/Demangling/Demangler.h"
#include "swift/Runtime/Casting.h"
#include "swift/Runtime/HeapObject.h"
-#include "swift/Runtime/Metadata.h"
#include "swift/Runtime/Mutex.h"
#include "swift/Strings.h"
-#include "MetadataCache.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
#include <algorithm>
-#include <condition_variable>
-#include <new>
#include <cctype>
+#include <condition_variable>
#include <iostream>
+#include <new>
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
// Avoid defining macro max(), min() which conflict with std::max(), std::min()
@@ -322,20 +323,31 @@
FullMetadata<FunctionTypeMetadata> Data;
struct Key {
- const void * const *FlagsArgsAndResult;
+ const FunctionTypeFlags Flags;
- FunctionTypeFlags getFlags() const {
- return FunctionTypeFlags::fromIntValue(size_t(FlagsArgsAndResult[0]));
+ const Metadata *const *Parameters;
+ const uint32_t *ParameterFlags;
+ const Metadata *Result;
+
+ Key(FunctionTypeFlags flags,
+ const Metadata *const *params,
+ const uint32_t *paramFlags,
+ const Metadata *result)
+ : Flags(flags), Parameters(params), ParameterFlags(paramFlags),
+ Result(result) {}
+
+ FunctionTypeFlags getFlags() const { return Flags; }
+ const Metadata *const *getParameters() const { return Parameters; }
+ const Metadata *getResult() const { return Result; }
+
+ const uint32_t *getParameterFlags() const {
+ return ParameterFlags;
}
- const Metadata *getResult() const {
- auto opaqueResult = FlagsArgsAndResult[getFlags().getNumArguments() + 1];
- return reinterpret_cast<const Metadata *>(opaqueResult);
- }
-
- const void * const *getArguments() const {
- return getFlags().getNumArguments() == 0
- ? nullptr : &FlagsArgsAndResult[1];
+ ::ParameterFlags getParameterFlags(unsigned index) const {
+ assert(index < Flags.getNumParameters());
+ auto flags = Flags.hasParameterFlags() ? ParameterFlags[index] : 0;
+ return ParameterFlags::fromIntValue(flags);
}
};
@@ -354,23 +366,35 @@
if (auto result = comparePointers(key.getResult(), Data.ResultType))
return result;
- for (unsigned i = 0, e = keyFlags.getNumArguments(); i != e; ++i) {
+ for (unsigned i = 0, e = keyFlags.getNumParameters(); i != e; ++i) {
+ if (auto result = comparePointers(key.getParameters()[i],
+ Data.getParameters()[i]))
+ return result;
+
if (auto result =
- comparePointers(key.getArguments()[i],
- Data.getArguments()[i].getOpaqueValue()))
+ compareIntegers(key.getParameterFlags(i).getIntValue(),
+ Data.getParameterFlags(i).getIntValue()))
return result;
}
return 0;
}
-
static size_t getExtraAllocationSize(Key key) {
- return key.getFlags().getNumArguments()
- * sizeof(FunctionTypeMetadata::Argument);
+ return getExtraAllocationSize(key.Flags);
}
+
size_t getExtraAllocationSize() const {
- return Data.Flags.getNumArguments()
- * sizeof(FunctionTypeMetadata::Argument);
+ return getExtraAllocationSize(Data.Flags);
+ }
+
+ static size_t getExtraAllocationSize(const FunctionTypeFlags flags) {
+ const auto numParams = flags.getNumParameters();
+ auto size = numParams * sizeof(FunctionTypeMetadata::Parameter);
+ if (flags.hasParameterFlags())
+ size += numParams * sizeof(uint32_t);
+
+ const auto alignment = sizeof(void *);
+ return (size + alignment - 1) & ~(alignment - 1);
}
};
@@ -381,53 +405,101 @@
const FunctionTypeMetadata *
swift::swift_getFunctionTypeMetadata1(FunctionTypeFlags flags,
- const void *arg0,
+ const Metadata *arg0,
const Metadata *result) {
- assert(flags.getNumArguments() == 1
+ assert(flags.getNumParameters() == 1
&& "wrong number of arguments in function metadata flags?!");
- const void *flagsArgsAndResult[] = {
- reinterpret_cast<const void*>(flags.getIntValue()),
- arg0,
- static_cast<const void *>(result)
- };
- return swift_getFunctionTypeMetadata(flagsArgsAndResult);
-}
-const FunctionTypeMetadata *
-swift::swift_getFunctionTypeMetadata2(FunctionTypeFlags flags,
- const void *arg0,
- const void *arg1,
- const Metadata *result) {
- assert(flags.getNumArguments() == 2
- && "wrong number of arguments in function metadata flags?!");
- const void *flagsArgsAndResult[] = {
- reinterpret_cast<const void*>(flags.getIntValue()),
- arg0,
- arg1,
- static_cast<const void *>(result)
- };
- return swift_getFunctionTypeMetadata(flagsArgsAndResult);
-}
-const FunctionTypeMetadata *
-swift::swift_getFunctionTypeMetadata3(FunctionTypeFlags flags,
- const void *arg0,
- const void *arg1,
- const void *arg2,
- const Metadata *result) {
- assert(flags.getNumArguments() == 3
- && "wrong number of arguments in function metadata flags?!");
- const void *flagsArgsAndResult[] = {
- reinterpret_cast<const void*>(flags.getIntValue()),
- arg0,
- arg1,
- arg2,
- static_cast<const void *>(result)
- };
- return swift_getFunctionTypeMetadata(flagsArgsAndResult);
+ const Metadata *parameters[] = { arg0 };
+ return swift_getFunctionTypeMetadata(flags, parameters, nullptr, result);
}
const FunctionTypeMetadata *
-swift::swift_getFunctionTypeMetadata(const void *flagsArgsAndResult[]) {
- FunctionCacheEntry::Key key = { flagsArgsAndResult };
+swift::swift_getFunctionTypeMetadata1WithFlags(FunctionTypeFlags flags,
+ const Metadata *arg0,
+ ParameterFlags flags0,
+ const Metadata *result) {
+ assert(flags.getNumParameters() == 1
+ && "wrong number of arguments in function metadata flags?!");
+ const Metadata *parameters[] = { arg0 };
+ const uint32_t parameterFlags[] = { flags0.getIntValue() };
+ return swift_getFunctionTypeMetadata(flags,
+ parameters,
+ parameterFlags,
+ result);
+}
+
+const FunctionTypeMetadata *
+swift::swift_getFunctionTypeMetadata2(FunctionTypeFlags flags,
+ const Metadata *arg0,
+ const Metadata *arg1,
+ const Metadata *result) {
+ assert(flags.getNumParameters() == 2
+ && "wrong number of arguments in function metadata flags?!");
+ const Metadata *parameters[] = { arg0, arg1 };
+ return swift_getFunctionTypeMetadata(flags, parameters, nullptr, result);
+}
+
+const FunctionTypeMetadata *
+swift::swift_getFunctionTypeMetadata2WithFlags(FunctionTypeFlags flags,
+ const Metadata *arg0,
+ ParameterFlags flags0,
+ const Metadata *arg1,
+ ParameterFlags flags1,
+ const Metadata *result) {
+ assert(flags.getNumParameters() == 2
+ && "wrong number of arguments in function metadata flags?!");
+ const Metadata *parameters[] = { arg0, arg1 };
+ const uint32_t parameterFlags[] = {
+ flags0.getIntValue(),
+ flags1.getIntValue()
+ };
+ return swift_getFunctionTypeMetadata(flags,
+ parameters,
+ parameterFlags,
+ result);
+}
+
+const FunctionTypeMetadata *
+swift::swift_getFunctionTypeMetadata3(FunctionTypeFlags flags,
+ const Metadata *arg0,
+ const Metadata *arg1,
+ const Metadata *arg2,
+ const Metadata *result) {
+ assert(flags.getNumParameters() == 3
+ && "wrong number of arguments in function metadata flags?!");
+ const Metadata *parameters[] = { arg0, arg1, arg2 };
+ return swift_getFunctionTypeMetadata(flags, parameters, nullptr, result);
+}
+
+const FunctionTypeMetadata *
+swift::swift_getFunctionTypeMetadata3WithFlags(FunctionTypeFlags flags,
+ const Metadata *arg0,
+ ParameterFlags flags0,
+ const Metadata *arg1,
+ ParameterFlags flags1,
+ const Metadata *arg2,
+ ParameterFlags flags2,
+ const Metadata *result) {
+ assert(flags.getNumParameters() == 3
+ && "wrong number of arguments in function metadata flags?!");
+ const Metadata *parameters[] = { arg0, arg1, arg2 };
+ const uint32_t parameterFlags[] = {
+ flags0.getIntValue(),
+ flags1.getIntValue(),
+ flags2.getIntValue()
+ };
+ return swift_getFunctionTypeMetadata(flags,
+ parameters,
+ parameterFlags,
+ result);
+}
+
+const FunctionTypeMetadata *
+swift::swift_getFunctionTypeMetadata(FunctionTypeFlags flags,
+ const Metadata *const *parameters,
+ const uint32_t *parameterFlags,
+ const Metadata *result) {
+ FunctionCacheEntry::Key key = { flags, parameters, parameterFlags, result };
return &FunctionTypes.getOrInsert(key).first->Data;
}
@@ -458,16 +530,16 @@
break;
}
- unsigned numArguments = flags.getNumArguments();
+ unsigned numParameters = flags.getNumParameters();
Data.setKind(MetadataKind::Function);
Data.Flags = flags;
Data.ResultType = key.getResult();
- for (size_t i = 0; i < numArguments; ++i) {
- auto opaqueArg = key.getArguments()[i];
- auto arg = FunctionTypeMetadata::Argument::getFromOpaqueValue(opaqueArg);
- Data.getArguments()[i] = arg;
+ for (unsigned i = 0; i < numParameters; ++i) {
+ Data.getParameters()[i] = key.getParameters()[i];
+ if (flags.hasParameterFlags())
+ Data.getParameterFlags()[i] = key.getParameterFlags(i).getIntValue();
}
}
diff --git a/test/IRGen/c_function_pointer.sil b/test/IRGen/c_function_pointer.sil
index 760918c..f6e7886 100644
--- a/test/IRGen/c_function_pointer.sil
+++ b/test/IRGen/c_function_pointer.sil
@@ -27,5 +27,4 @@
// CHECK-LABEL: define linkonce_odr hidden %swift.type* @_T0yyXCMa()
// -- 0x3000001 -- C convention, 1 argument
-// CHECK: call %swift.type* @swift_getFunctionTypeMetadata(i8** %3)
-
+// CHECK: call %swift.type* @swift_getFunctionTypeMetadata([[WORD:i(32|64)]] 100663296, %swift.type** null, i32* null, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
diff --git a/test/IRGen/dynamic_cast_functions.swift b/test/IRGen/dynamic_cast_functions.swift
index a6dc73e..16f6141 100644
--- a/test/IRGen/dynamic_cast_functions.swift
+++ b/test/IRGen/dynamic_cast_functions.swift
@@ -48,3 +48,72 @@
// CHECK: ok
print((t1 == t2) ? "fail" : "ok")
+
+let i: (inout Int) -> Void = { _ in }
+let j: (__shared Int) -> Void = { _ in }
+let k: (Int, inout Int) -> Void = { _,_ in }
+let l: (inout Int, Float, inout String) -> Void = { _,_,_ in }
+let m: (__shared Int, String, inout Float, Double) -> Void = { _,_,_,_ in }
+
+let i_any: Any = i
+let j_any: Any = j
+let k_any: Any = k
+let l_any: Any = l
+let m_any: Any = m
+
+// CHECK: ok
+print((i_any as? (Int) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((i_any as? (__shared Int) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((i_any as? (inout Int) -> Void) != nil ? "ok" : "fail")
+
+// CHECK: ok
+print((j_any as? (Int) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((j_any as? (inout Int) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((j_any as? (__shared Int) -> Void) != nil ? "ok" : "fail")
+
+// CHECK: ok
+print((k_any as? (Int, Int) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((k_any as? (Int, inout Int) -> Void) != nil ? "ok" : "fail")
+// CHECK: ok
+print((k_any as? (inout Int, Int) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((k_any as? (inout Int, __shared Int) -> Void) != nil ? "fail" : "ok")
+
+// CHECK: ok
+print((l_any as? (Int, Float, String) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((l_any as? (Int, Float, inout String) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((l_any as? (Int, inout Float, String) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((l_any as? (inout Int, Float, String) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((l_any as? (inout Int, inout Float, String) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((l_any as? (inout Int, Float, __shared String) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((l_any as? (inout Int, Float, inout String) -> Void) != nil ? "ok" : "fail")
+
+// CHECK: ok
+print((m_any as? (Int, String, Float, Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (Int, String, Float, inout Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (Int, String, Float, __shared Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (Int, String, inout Float, Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (Int, __shared String, Float, Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (inout Int, String, __shared Float, Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (__shared Int, String, Float, inout Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (Int, __shared String, inout Float, Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (__shared Int, String, inout Float, Double) -> Void) != nil ? "ok" : "fail")
diff --git a/test/IRGen/function_metadata.swift b/test/IRGen/function_metadata.swift
index 5dec8d0..f38c450 100644
--- a/test/IRGen/function_metadata.swift
+++ b/test/IRGen/function_metadata.swift
@@ -4,45 +4,42 @@
// CHECK: define hidden swiftcc void @_T017function_metadata9test_archyyF()
func test_arch() {
- // CHECK: call %swift.type* @swift_getFunctionTypeMetadata(i8** %3) {{#[0-9]+}}
+ // CHECK: call %swift.type* @swift_getFunctionTypeMetadata([[WORD:i(32|64)]] 0, %swift.type** null, i32* null, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
arch( {() -> () in } )
- // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD:i(32|64)]] 1, i8* bitcast (%swift.type* @_T0SiN to i8*), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1)) {{#[0-9]+}}
+ // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD:i(32|64)]] 1, %swift.type* @_T0SiN, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1)) {{#[0-9]+}}
arch({(x: Int) -> () in })
- // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD]] 1, i8* bitcast (%swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1) to i8*), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
+ // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD]] 1, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
arch({(_: ()) -> () in })
- // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD]] 1, i8* inttoptr ([[WORD]] or ([[WORD]] ptrtoint (%swift.type* @_T0SiN to [[WORD]]), [[WORD]] 1) to i8*), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
+ // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1WithFlags([[WORD]] 16777217, %swift.type* @_T0SiN, i32 1, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
arch({(x: inout Int) -> () in })
- // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD]] 1, i8* %3, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
+ // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD]] 1, %swift.type* %2, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
arch({(x: (Int, Float)) -> () in })
- // CHECK: call %swift.type* @swift_getFunctionTypeMetadata2([[WORD]] 2, i8* inttoptr ([[WORD]] or ([[WORD]] ptrtoint (%swift.type* @_T0SiN to [[WORD]]), [[WORD]] 1) to i8*), i8* bitcast (%swift.type* @_T0SiN to i8*), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
+ // CHECK: call %swift.type* @swift_getFunctionTypeMetadata2WithFlags([[WORD]] 16777218, %swift.type* @_T0SiN, i32 1, %swift.type* @_T0SiN, i32 0, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
arch({(x: inout Int, y: Int) -> () in })
- // CHECK: call %swift.type* @swift_getFunctionTypeMetadata2([[WORD]] 2, i8* bitcast (%swift.type* @_T0SfN to i8*), i8* bitcast (%swift.type* @_T0SiN to i8*), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
+ // CHECK: call %swift.type* @swift_getFunctionTypeMetadata2([[WORD]] 2, %swift.type* @_T0SfN, %swift.type* @_T0SiN, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
arch({(a: Float, b: Int) -> () in })
- // CHECK: call %swift.type* @swift_getFunctionTypeMetadata3([[WORD]] 3, i8* inttoptr ([[WORD]] or ([[WORD]] ptrtoint (%swift.type* @_T0SiN to [[WORD]]), [[WORD]] 1) to i8*), i8* bitcast (%swift.type* @_T0SfN to i8*), i8* bitcast (%swift.type* @_T0SSN to i8*), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
+ // CHECK: call %swift.type* @swift_getFunctionTypeMetadata3WithFlags([[WORD]] 16777219, %swift.type* @_T0SiN, i32 1, %swift.type* @_T0SfN, i32 0, %swift.type* @_T0SSN, i32 0, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
arch({(x: inout Int, y: Float, z: String) -> () in })
- // CHECK: call %swift.type* @swift_getFunctionTypeMetadata3([[WORD]] 3, i8* bitcast (%swift.type* @_T0SfN to i8*), i8* bitcast (%swift.type* @_T0SfN to i8*), i8* bitcast (%swift.type* @_T0SiN to i8*), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
+ // CHECK: call %swift.type* @swift_getFunctionTypeMetadata3([[WORD]] 3, %swift.type* @_T0SfN, %swift.type* @_T0SfN, %swift.type* @_T0SiN, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
arch({(a: Float, b: Float, c: Int) -> () in })
- // CHECK: [[T0:%.*]] = getelementptr inbounds [6 x i8*], [6 x i8*]* %function-arguments, i32 0, i32 0
- // CHECK: store [[WORD]] 4
- // CHECK: getelementptr inbounds [6 x i8*], [6 x i8*]* %function-arguments, i32 0, i32 1
- // CHECK: store i8* inttoptr ([[WORD]] or ([[WORD]] ptrtoint (%swift.type* @_T0SiN to [[WORD]]), [[WORD]] 1) to i8*)
- // CHECK: getelementptr inbounds [6 x i8*], [6 x i8*]* %function-arguments, i32 0, i32 2
- // CHECK: store i8* bitcast (%swift.type* @_T0SdN to i8*)
- // CHECK: getelementptr inbounds [6 x i8*], [6 x i8*]* %function-arguments, i32 0, i32 3
- // CHECK: store i8* bitcast (%swift.type* @_T0SSN to i8*)
- // CHECK: getelementptr inbounds [6 x i8*], [6 x i8*]* %function-arguments, i32 0, i32 4
- // CHECK: store i8* bitcast (%swift.type* @_T0s4Int8VN to i8*)
- // CHECK: getelementptr inbounds [6 x i8*], [6 x i8*]* %function-arguments, i32 0, i32 5
- // CHECK: store %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1)
- // CHECK: call %swift.type* @swift_getFunctionTypeMetadata(i8** [[T0]]) {{#[0-9]+}}
+ // CHECK: getelementptr inbounds [4 x %swift.type*], [4 x %swift.type*]* %function-parameters, i32 0, i32 0
+ // CHECK: store %swift.type* @_T0SiN, %swift.type** [[T:%.*]], align [[ALIGN:(4|8)]]
+ // CHECK: getelementptr inbounds [4 x %swift.type*], [4 x %swift.type*]* %function-parameters, i32 0, i32 1
+ // CHECK: store %swift.type* @_T0SdN, %swift.type** [[T:%.*]], align [[ALIGN:(4|8)]]
+ // CHECK: getelementptr inbounds [4 x %swift.type*], [4 x %swift.type*]* %function-parameters, i32 0, i32 2
+ // CHECK: store %swift.type* @_T0SSN, %swift.type** [[T:%.*]], align [[ALIGN:(4|8)]]
+ // CHECK: getelementptr inbounds [4 x %swift.type*], [4 x %swift.type*]* %function-parameters, i32 0, i32 3
+ // CHECK: store %swift.type* @_T0s4Int8VN, %swift.type** [[T:%.*]], align [[ALIGN:(4|8)]]
+ // CHECK: [[T:%.*]] = getelementptr inbounds [4 x %swift.type*], [4 x %swift.type*]* %function-parameters, i32 0, i32 0
+ // CHECK: call %swift.type* @swift_getFunctionTypeMetadata([[WORD]] 16777220, %swift.type** %7, i32* getelementptr inbounds ([4 x i32], [4 x i32]* @parameter-flags, i32 0, i32 0), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
arch({(x: inout Int, y: Double, z: String, w: Int8) -> () in })
}
diff --git a/test/IRGen/objc_block.sil b/test/IRGen/objc_block.sil
index ce8a344..808f47d 100644
--- a/test/IRGen/objc_block.sil
+++ b/test/IRGen/objc_block.sil
@@ -38,5 +38,4 @@
// CHECK-LABEL: define{{( protected)?}} swiftcc void @generic_with_block(%objc_block** noalias nocapture dereferenceable({{.*}}))
// -- 0x100_0001 = block convention, 1 arg
-// CHECK: call %swift.type* @swift_getFunctionTypeMetadata(i8** %3)
-
+// CHECK: call %swift.type* @swift_getFunctionTypeMetadata([[WORD:i(32|64)]] 33554432, %swift.type** null, i32* null, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
diff --git a/test/Sema/diag_erroneous_iuo.swift b/test/Sema/diag_erroneous_iuo.swift
index 2e51057..d938be6 100644
--- a/test/Sema/diag_erroneous_iuo.swift
+++ b/test/Sema/diag_erroneous_iuo.swift
@@ -81,6 +81,8 @@
var x: V
var y: W
+ var fn1: (Int!) -> Int // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ var fn2: (Int) -> Int! // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
subscript (
index: ImplicitlyUnwrappedOptional<Int> // expected-error {{the spelling 'ImplicitlyUnwrappedOptional' is unsupported; use '!' after the type name}}{{12-40=}}{{43-43=!}}{{43-44=}}
@@ -138,18 +140,53 @@
func vararg(_ first: Int, more: Int!...) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
}
+func varargIdentifier(_ first: Int, more: ImplicitlyUnwrappedOptional<Int>...) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+}
+
func iuoInTuple() -> (Int!) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
return 1
}
-func iuoInTuple2() -> (Float, Int!) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+func iuoInTupleIdentifier() -> (ImplicitlyUnwrappedOptional<Int>) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
return 1
}
+func iuoInTuple2() -> (Float, Int!) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return (1.0, 1)
+}
+
+func iuoInTuple2Identifier() -> (Float, ImplicitlyUnwrappedOptional<Int>) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return (1.0, 1)
+}
+
func takesFunc(_ fn: (Int!) -> Int) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
return fn(0)
}
+func takesFuncIdentifier(_ fn: (ImplicitlyUnwrappedOptional<Int>) -> Int) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return fn(0)
+}
+
+func takesFunc2(_ fn: (Int) -> Int!) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return fn(0)
+}
+
+func takesFunc2Identifier(_ fn: (Int) -> ImplicitlyUnwrappedOptional<Int>) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return fn(0)
+}
+
func returnsFunc() -> (Int!) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
return { $0 }
}
+
+func returnsFuncIdentifier() -> (ImplicitlyUnwrappedOptional<Int>) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return { $0 }
+}
+
+func returnsFunc2() -> (Int) -> Int! { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return { $0 }
+}
+
+func returnsFunc2Identifier() -> (Int) -> ImplicitlyUnwrappedOptional<Int> { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return { $0 }
+}
diff --git a/test/stdlib/TestNSNumberBridging.swift b/test/stdlib/TestNSNumberBridging.swift
index f5c4685..1638226 100644
--- a/test/stdlib/TestNSNumberBridging.swift
+++ b/test/stdlib/TestNSNumberBridging.swift
@@ -658,16 +658,16 @@
let uint = (number!) as? UInt
expectEqual(UInt(exactly: interestingValue), uint)
- // these are disabled because of https://bugs.swift.org/browse/SR-4634
- if uint! != UInt(UInt32.max) && uint! != UInt(UInt32.max - 1) {
- let float = (number!) as? Float
- let expectedFloat = Float(uint!)
- testFloat(expectedFloat, float)
+ let float = (number!) as? Float
+ let expectedFloat = Float(exactly: uint!)
+ if UInt.bitWidth == 32 && uint! >= UInt.max - 1 {
+ expectNil(expectedFloat)
+ } else {
+ testFloat(expectedFloat, float)
}
-
-
+
let double = (number!) as? Double
- let expectedDouble = Double(uint!)
+ let expectedDouble = Double(exactly: uint!)
testDouble(expectedDouble, double)
}
let bridged = interestingValue as NSNumber
diff --git a/unittests/Reflection/TypeRef.cpp b/unittests/Reflection/TypeRef.cpp
index 29d943f..c736ce5 100644
--- a/unittests/Reflection/TypeRef.cpp
+++ b/unittests/Reflection/TypeRef.cpp
@@ -147,7 +147,7 @@
EXPECT_NE(F4, F1);
// Test parameter with and without inout/shared/variadic and/or label.
- ParameterTypeFlags paramFlags;
+ ParameterFlags paramFlags;
auto inoutFlags = paramFlags.withInOut(true);
auto variadicFlags = paramFlags.withVariadic(true);
auto sharedFlags = paramFlags.withShared(true);
diff --git a/validation-test/stdlib/FloatingPointConversion.swift.gyb b/validation-test/stdlib/FloatingPointConversion.swift.gyb
index 9882102..3a96da7 100644
--- a/validation-test/stdlib/FloatingPointConversion.swift.gyb
+++ b/validation-test/stdlib/FloatingPointConversion.swift.gyb
@@ -115,75 +115,59 @@
% end # for in all_floating_point_types (Other)
-%{
-
-float_to_int_conversion_template = gyb.parse_template("float_to_int_conversion",
-"""
-% for int_ty in all_integer_types(word_bits):
-% OtherInt = int_ty.stdlib_name
-% OtherMin = int_ty.min
-% OtherMax = int_ty.max
-% (FloatMin, FloatMax) = getFtoIBounds(self_type.bits, int_ty.bits, int_ty.is_signed)
-
-% for testValue in [0, FloatMin, FloatMax, FloatMin - 1, FloatMax + 1, OtherMin, OtherMax]:
-
-% if testValue < OtherMin or testValue > OtherMax:
-% # Can't construct `other` value, do nothing and continue.
-
-% elif testValue >= FloatMin and testValue <= FloatMax:
-
-FixedPointConversionTruncations.test("${OtherInt}to${Self}Conversion/${testValue}") {
- expectEqual(${Self}(${testValue} as ${OtherInt}), ${testValue})
-}
-
-FixedPointConversionFailures.test("${OtherInt}to${Self}FailableConversion/${testValue}") {
- expectEqual(${Self}(exactly: ${testValue} as ${OtherInt}), ${testValue})
-}
-
-% else:
-
-FixedPointConversionTruncations.test("${OtherInt}to${Self}Truncation/${testValue}") {
- let value: ${OtherInt} = ${testValue}
- let result = ${Self}(value)
- expectNotEqual(${OtherInt}(result), value)
-}
-
-FixedPointConversionFailures.test("${OtherInt}to${Self}Failure/${testValue}") {
- let value: ${OtherInt} = ${testValue}
- let result = ${Self}(exactly: value)
- expectEqual(result, ${OtherMin} as ${Self})
- expectEqual(${OtherInt}(result!), value)
-}
-
-% end
-
-% end # testValue in testValues
-% end # for in all_integer_types (Other)
-""")
-}%
-
#if arch(i386) || arch(arm)
-
- ${gyb.execute_template(
- float_to_int_conversion_template,
- word_bits=32,
- **locals()
- )}
-
+% int_types = all_integer_types(32)
#elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x)
-
- ${gyb.execute_template(
- float_to_int_conversion_template,
- word_bits=64,
- **locals()
- )}
-
+% int_types = all_integer_types(64)
#else
-
_UnimplementedError()
-
#endif
+% for int_ty in int_types:
+% OtherInt = int_ty.stdlib_name
+
+extension ${OtherInt} {
+ static var _test${Self}Conversion: [(${OtherInt}, ${OtherInt}, ${OtherInt}?)] {
+ if bitWidth > ${Self}.significandBitCount + 1 {
+ let bitOffset = ${Self}.significandBitCount + 1
+ let limit: ${OtherInt} = ~(~0 << bitOffset)
+ let over: ${OtherInt} = 1 + limit << 1
+ return [
+ (0, 0, 0),
+ (limit, limit, limit),
+ (over, over + 1, nil),
+% if int_ty.is_signed:
+ (-limit, -limit, -limit),
+ (-over, -(over + 1), nil),
+% end
+ ]
+ } else {
+ return [
+ (0, 0, 0),
+ (.min, .min, .min),
+ (.max, .max, .max),
+ ]
+ }
+ }
+}
+
+FixedPointConversionTruncations.test("${OtherInt}to${Self}")
+ .forEach(in: ${OtherInt}._test${Self}Conversion) {
+ value, roundedExpectation, exactExpectation in
+
+ let roundedResult = ${Self}(value)
+ expectEqual(roundedResult, ${Self}(roundedExpectation))
+
+ let exactResult = ${Self}(exactly: value)
+ if let expectation = exactExpectation {
+ expectEqual(exactResult!, ${Self}(expectation))
+ } else {
+ expectNil(exactResult)
+ }
+}
+
+% end # for in int_types
+
% if Self == 'Float80':
#endif
% end
diff --git a/validation-test/stdlib/ValidationNSNumberBridging.swift b/validation-test/stdlib/ValidationNSNumberBridging.swift
index 3e99a47..61255c4 100644
--- a/validation-test/stdlib/ValidationNSNumberBridging.swift
+++ b/validation-test/stdlib/ValidationNSNumberBridging.swift
@@ -652,16 +652,16 @@
let uint = (number!) as? UInt
expectEqual(UInt(exactly: interestingValue), uint)
- // these are disabled because of https://bugs.swift.org/browse/SR-4634
- if uint! != UInt(UInt32.max) && uint! != UInt(UInt32.max - 1) {
- let float = (number!) as? Float
- let expectedFloat = Float(uint!)
- testFloat(expectedFloat, float)
+ let float = (number!) as? Float
+ let expectedFloat = Float(exactly: uint!)
+ if UInt.bitWidth == 32 && uint! >= UInt.max - 1 {
+ expectNil(expectedFloat)
+ } else {
+ testFloat(expectedFloat, float)
}
-
-
+
let double = (number!) as? Double
- let expectedDouble = Double(uint!)
+ let expectedDouble = Double(exactly: uint!)
testDouble(expectedDouble, double)
}
let bridged = interestingValue as NSNumber