[Typed throws] IR generation and runtime support for function type metadata

Extend function type metadata with an entry for the thrown error type,
so that thrown error types are represented at runtime as well. Note
that this required the introduction of "extended" function type
flags into function type metadata, because we would have used the last
bit. Do so, and define one extended flag bit as representing typed
throws.

Add `swift_getExtendedFunctionTypeMetadata` to the runtime to build
function types that have the extended flags and a thrown error type.
Teach IR generation to call this function to form the metadata, when
appropriate.

Introduce all of the runtime mangling/demangling support needed for
thrown error types.
This commit is contained in:
Doug Gregor
2023-10-29 07:33:04 -07:00
parent e82854d860
commit 40e07cf900
18 changed files with 369 additions and 49 deletions

View File

@@ -1463,6 +1463,13 @@ template <typename Runtime>
struct TargetFunctionGlobalActorMetadata {
ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> GlobalActorType;
};
using FunctionGlobalActorMetadata = TargetFunctionGlobalActorMetadata<InProcess>;
template <typename Runtime>
struct TargetFunctionThrownErrorMetadata {
ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> ThrownErrorType;
};
using FunctionThrownErrorMetadata = TargetFunctionThrownErrorMetadata<InProcess>;
/// The structure of function type metadata.
template <typename Runtime>
@@ -1472,7 +1479,9 @@ struct TargetFunctionTypeMetadata : public TargetMetadata<Runtime>,
ConstTargetMetadataPointer<Runtime, swift::TargetMetadata>,
ParameterFlags,
TargetFunctionMetadataDifferentiabilityKind<typename Runtime::StoredSize>,
TargetFunctionGlobalActorMetadata<Runtime>> {
TargetFunctionGlobalActorMetadata<Runtime>,
ExtendedFunctionTypeFlags,
TargetFunctionThrownErrorMetadata<Runtime>> {
using StoredSize = typename Runtime::StoredSize;
using Parameter = ConstTargetMetadataPointer<Runtime, swift::TargetMetadata>;
@@ -1483,7 +1492,9 @@ private:
Parameter,
ParameterFlags,
TargetFunctionMetadataDifferentiabilityKind<StoredSize>,
TargetFunctionGlobalActorMetadata<Runtime>>;
TargetFunctionGlobalActorMetadata<Runtime>,
ExtendedFunctionTypeFlags,
TargetFunctionThrownErrorMetadata<Runtime>>;
friend TrailingObjects;
template<typename T>
@@ -1516,6 +1527,16 @@ private:
return hasGlobalActor() ? 1 : 0;
}
size_t numTrailingObjects(OverloadToken<ExtendedFunctionTypeFlags>) const {
return hasExtendedFlags() ? 1 : 0;
}
size_t numTrailingObjects(
OverloadToken<TargetFunctionThrownErrorMetadata<Runtime>>
) const {
return hasThrownError() ? 1 : 0;
}
public:
Parameter *getParameters() {
return this->template getTrailingObjects<Parameter>();
@@ -1548,6 +1569,13 @@ public:
bool hasParameterFlags() const { return Flags.hasParameterFlags(); }
bool isEscaping() const { return Flags.isEscaping(); }
bool hasGlobalActor() const { return Flags.hasGlobalActor(); }
bool hasExtendedFlags() const { return Flags.hasExtendedFlags(); }
bool hasThrownError() const {
if (!Flags.hasExtendedFlags())
return false;
return getExtendedFlags().isTypedThrows();
}
static constexpr StoredSize OffsetToFlags = sizeof(TargetMetadata<Runtime>);
@@ -1594,6 +1622,35 @@ public:
this->template getTrailingObjects<TargetFunctionGlobalActorMetadata<Runtime>>();
return globalActorAddr->GlobalActorType;
}
ExtendedFunctionTypeFlags *getExtendedFlagsAddr() {
assert(hasExtendedFlags());
return this->template getTrailingObjects<ExtendedFunctionTypeFlags>();
}
ExtendedFunctionTypeFlags getExtendedFlags() const {
if (!hasExtendedFlags())
return ExtendedFunctionTypeFlags();
return this->template getTrailingObjects<ExtendedFunctionTypeFlags>()[0];
}
ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> *
getThrownErrorAddr() {
assert(hasThrownError());
auto thrownErrorAddr =
this->template getTrailingObjects<TargetFunctionThrownErrorMetadata<Runtime>>();
return &thrownErrorAddr->ThrownErrorType;
}
ConstTargetMetadataPointer<Runtime, swift::TargetMetadata>
getThrownError() const {
if (!hasThrownError())
return ConstTargetMetadataPointer<Runtime, swift::TargetMetadata>();
auto thrownErrorAddr =
this->template getTrailingObjects<TargetFunctionThrownErrorMetadata<Runtime>>();
return thrownErrorAddr->ThrownErrorType;
}
};
using FunctionTypeMetadata = TargetFunctionTypeMetadata<InProcess>;

View File

@@ -1037,7 +1037,8 @@ class TargetFunctionTypeFlags {
GlobalActorMask = 0x10000000U,
AsyncMask = 0x20000000U,
SendableMask = 0x40000000U,
// NOTE: The next bit will need to introduce a separate flags word.
ExtendedFlagsMask = 0x80000000U,
// NOTE: No more room for flags here. Use TargetExtendedFunctionTypeFlags.
};
int_type Data;
@@ -1099,6 +1100,12 @@ public:
(Data & ~GlobalActorMask) | (globalActor ? GlobalActorMask : 0));
}
constexpr TargetFunctionTypeFlags<int_type>
withExtendedFlags(bool extendedFlags) const {
return TargetFunctionTypeFlags<int_type>(
(Data & ~ExtendedFlagsMask) | (extendedFlags ? ExtendedFlagsMask : 0));
}
unsigned getNumParameters() const { return Data & NumParametersMask; }
FunctionMetadataConvention getConvention() const {
@@ -1127,6 +1134,10 @@ public:
return bool (Data & GlobalActorMask);
}
bool hasExtendedFlags() const {
return bool (Data & ExtendedFlagsMask);
}
int_type getIntValue() const {
return Data;
}
@@ -1144,6 +1155,43 @@ public:
};
using FunctionTypeFlags = TargetFunctionTypeFlags<size_t>;
/// Extended flags in a function type metadata record.
template <typename int_type>
class TargetExtendedFunctionTypeFlags {
enum : int_type {
TypedThrowsMask = 0x00000001U,
};
int_type Data;
constexpr TargetExtendedFunctionTypeFlags(int_type Data) : Data(Data) {}
public:
constexpr TargetExtendedFunctionTypeFlags() : Data(0) {}
constexpr TargetExtendedFunctionTypeFlags<int_type>
withTypedThrows(bool typedThrows) const {
return TargetExtendedFunctionTypeFlags<int_type>(
(Data & ~TypedThrowsMask) | (typedThrows ? TypedThrowsMask : 0));
}
bool isTypedThrows() const { return bool(Data & TypedThrowsMask); }
int_type getIntValue() const {
return Data;
}
static TargetExtendedFunctionTypeFlags<int_type> fromIntValue(int_type Data) {
return TargetExtendedFunctionTypeFlags(Data);
}
bool operator==(TargetExtendedFunctionTypeFlags<int_type> other) const {
return Data == other.Data;
}
bool operator!=(TargetExtendedFunctionTypeFlags<int_type> other) const {
return Data != other.Data;
}
};
using ExtendedFunctionTypeFlags = TargetExtendedFunctionTypeFlags<uint32_t>;
template <typename int_type>
class TargetParameterTypeFlags {
enum : int_type {

View File

@@ -914,6 +914,9 @@ public:
/// Get the runtime availability of support for differentiation.
AvailabilityContext getDifferentiationAvailability();
/// Get the runtime availability of support for typed throws.
AvailabilityContext getTypedThrowsAvailability();
/// Get the runtime availability of getters and setters of multi payload enum
/// tag single payloads.
AvailabilityContext getMultiPayloadEnumTagSinglePayload();
@@ -982,6 +985,10 @@ public:
/// compiler for the target platform.
AvailabilityContext getSwift59Availability();
/// Get the runtime availability of features introduced in the Swift 5.9
/// compiler for the target platform.
AvailabilityContext getSwift511Availability();
// Note: Update this function if you add a new getSwiftXYAvailability above.
/// Get the runtime availability for a particular version of Swift (5.0+).
AvailabilityContext

View File

@@ -1002,7 +1002,10 @@ public:
}
BuiltType thrownError = BuiltType();
// FIXME: Read from metadata.
if (Function->hasThrownError()) {
thrownError = readTypeFromMetadata(Function->getThrownError(), false,
recursion_limit);
}
auto BuiltFunction = Builder.createFunctionType(
Parameters, Result, flags, diffKind, globalActor, thrownError);

View File

@@ -504,6 +504,14 @@ swift_getFunctionTypeMetadataGlobalActor(
const Metadata *const *parameters, const uint32_t *parameterFlags,
const Metadata *result, const Metadata *globalActor);
SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *
swift_getExtendedFunctionTypeMetadata(
FunctionTypeFlags flags, FunctionMetadataDifferentiabilityKind diffKind,
const Metadata *const *parameters, const uint32_t *parameterFlags,
const Metadata *result, const Metadata *globalActor,
ExtendedFunctionTypeFlags extFlags, const Metadata *thrownError);
SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *
swift_getFunctionTypeMetadata0(FunctionTypeFlags flags,

View File

@@ -786,6 +786,31 @@ FUNCTION(GetFunctionMetadataDifferentiable,
EFFECT(MetaData),
MEMEFFECTS(ReadOnly))
// Metadata *
// swift_getExtendedFunctionTypeMetadata(unsigned long flags,
// unsigned long diffKind,
// const Metadata **parameters,
// const uint32_t *parameterFlags,
// const Metadata *result,
// const Metadata *globalActor,
// uint32_t extendedflags,
// const Metadata *thrownError);
FUNCTION(GetFunctionMetadataExtended,
swift_getExtendedFunctionTypeMetadata,
C_CC, TypedThrowsAvailability,
RETURNS(TypeMetadataPtrTy),
ARGS(SizeTy,
SizeTy,
TypeMetadataPtrTy->getPointerTo(0),
Int32Ty->getPointerTo(0),
TypeMetadataPtrTy,
TypeMetadataPtrTy,
Int32Ty,
TypeMetadataPtrTy),
ATTRS(NoUnwind),
EFFECT(MetaData),
MEMEFFECTS(ReadOnly))
// Metadata *
// swift_getFunctionTypeMetadataGlobalActor(unsigned long flags,
// unsigned long diffKind,

View File

@@ -545,6 +545,10 @@ AvailabilityContext ASTContext::getDifferentiationAvailability() {
return getSwiftFutureAvailability();
}
AvailabilityContext ASTContext::getTypedThrowsAvailability() {
return getSwift511Availability();
}
AvailabilityContext ASTContext::getMultiPayloadEnumTagSinglePayload() {
return getSwift56Availability();
}
@@ -752,6 +756,11 @@ AvailabilityContext ASTContext::getSwift59Availability() {
}
}
AvailabilityContext ASTContext::getSwift511Availability() {
// Placeholder
return getSwiftFutureAvailability();
}
AvailabilityContext ASTContext::getSwiftFutureAvailability() {
auto target = LangOpts.Target;

View File

@@ -378,6 +378,8 @@ toolchains::Darwin::addArgsToLinkStdlib(ArgStringList &Arguments,
runtimeCompatibilityVersion = llvm::VersionTuple(5, 6);
} else if (value.equals("5.8")) {
runtimeCompatibilityVersion = llvm::VersionTuple(5, 8);
} else if (value.equals("5.11")) {
runtimeCompatibilityVersion = llvm::VersionTuple(5, 11);
} else if (value.equals("none")) {
runtimeCompatibilityVersion = llvm::None;
} else {

View File

@@ -2811,6 +2811,8 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
runtimeCompatibilityVersion = llvm::VersionTuple(5, 6);
} else if (version.equals("5.8")) {
runtimeCompatibilityVersion = llvm::VersionTuple(5, 8);
} else if (version.equals("5.11")) {
runtimeCompatibilityVersion = llvm::VersionTuple(5, 11);
} else {
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
versionArg->getAsString(Args), version);

View File

@@ -176,6 +176,20 @@ public:
llvm::Optional<llvm::VersionTuple>
getRuntimeVersionThatSupportsDemanglingType(CanType type) {
// The Swift 5.11 runtime is the first version able to demangle types
// that involve typed throws.
bool usesTypedThrows = type.findIf([](CanType t) -> bool {
if (auto fn = dyn_cast<AnyFunctionType>(t)) {
if (!fn.getThrownError().isNull())
return true;
}
return false;
});
if (usesTypedThrows) {
return llvm::VersionTuple(5, 11);
}
// The Swift 5.5 runtime is the first version able to demangle types
// related to concurrency.
bool needsConcurrency = type.findIf([](CanType t) -> bool {

View File

@@ -883,6 +883,14 @@ namespace RuntimeConstants {
return RuntimeAvailability::AlwaysAvailable;
}
RuntimeAvailability TypedThrowsAvailability(ASTContext &Context) {
auto featureAvailability = Context.getTypedThrowsAvailability();
if (!isDeploymentAvailabilityContainedIn(Context, featureAvailability)) {
return RuntimeAvailability::ConditionallyAvailable;
}
return RuntimeAvailability::AlwaysAvailable;
}
RuntimeAvailability
MultiPayloadEnumTagSinglePayloadAvailability(ASTContext &context) {
auto featureAvailability = context.getMultiPayloadEnumTagSinglePayload();

View File

@@ -1397,7 +1397,8 @@ ParameterFlags irgen::getABIParameterFlags(ParameterTypeFlags flags) {
.withIsolated(flags.isIsolated());
}
static FunctionTypeFlags getFunctionTypeFlags(CanFunctionType type) {
static std::pair<FunctionTypeFlags, ExtendedFunctionTypeFlags>
getFunctionTypeFlags(CanFunctionType type) {
bool hasParameterFlags = false;
for (auto param : type.getParams()) {
if (!getABIParameterFlags(param.getParameterFlags()).isNone()) {
@@ -1425,7 +1426,10 @@ static FunctionTypeFlags getFunctionTypeFlags(CanFunctionType type) {
break;
}
return FunctionTypeFlags()
auto extFlags = ExtendedFunctionTypeFlags()
.withTypedThrows(!type->getThrownError().isNull());
auto flags = FunctionTypeFlags()
.withConvention(metadataConvention)
.withAsync(type->isAsync())
.withConcurrent(type->isSendable())
@@ -1433,7 +1437,10 @@ static FunctionTypeFlags getFunctionTypeFlags(CanFunctionType type) {
.withParameterFlags(hasParameterFlags)
.withEscaping(isEscaping)
.withDifferentiable(type->isDifferentiable())
.withGlobalActor(!type->getGlobalActor().isNull());
.withGlobalActor(!type->getGlobalActor().isNull())
.withExtendedFlags(extFlags.getIntValue() != 0);
return std::make_pair(flags, extFlags);
}
namespace {
@@ -1559,7 +1566,10 @@ static MetadataResponse emitFunctionTypeMetadataRef(IRGenFunction &IGF,
auto params = type.getParams();
bool hasPackExpansion = type->containsPackExpansionParam();
auto flags = getFunctionTypeFlags(type);
FunctionTypeFlags flags;
ExtendedFunctionTypeFlags extFlags;
std::tie(flags, extFlags) = getFunctionTypeFlags(type);
llvm::Value *flagsVal = nullptr;
llvm::Value *shapeExpression = nullptr;
CanPackType packType;
@@ -1615,7 +1625,8 @@ static MetadataResponse emitFunctionTypeMetadataRef(IRGenFunction &IGF,
case 2:
case 3: {
if (!flags.hasParameterFlags() && !type->isDifferentiable() &&
!type->getGlobalActor() && !hasPackExpansion) {
!type->getGlobalActor() && !hasPackExpansion &&
!flags.hasExtendedFlags()) {
llvm::SmallVector<llvm::Value *, 8> arguments;
auto metadataFn = constructSimpleCall(arguments);
auto *call = IGF.Builder.CreateCall(metadataFn, arguments);
@@ -1669,7 +1680,7 @@ static MetadataResponse emitFunctionTypeMetadataRef(IRGenFunction &IGF,
assert(metadataDifferentiabilityKind.isDifferentiable());
diffKindVal = llvm::ConstantInt::get(
IGF.IGM.SizeTy, metadataDifferentiabilityKind.getIntValue());
} else if (type->getGlobalActor()) {
} else if (type->getGlobalActor() || flags.hasExtendedFlags()) {
diffKindVal = llvm::ConstantInt::get(
IGF.IGM.SizeTy,
FunctionMetadataDifferentiabilityKind::NonDifferentiable);
@@ -1695,10 +1706,27 @@ static MetadataResponse emitFunctionTypeMetadataRef(IRGenFunction &IGF,
if (Type globalActor = type->getGlobalActor()) {
arguments.push_back(
IGF.emitAbstractTypeMetadataRef(globalActor->getCanonicalType()));
} else if (flags.hasExtendedFlags()) {
arguments.push_back(llvm::ConstantPointerNull::get(IGF.IGM.TypeMetadataPtrTy));
}
if (flags.hasExtendedFlags()) {
auto extFlagsVal = llvm::ConstantInt::get(IGF.IGM.Int32Ty,
extFlags.getIntValue());
arguments.push_back(extFlagsVal);
}
if (Type thrownError = type->getThrownError()) {
arguments.push_back(
IGF.emitAbstractTypeMetadataRef(thrownError->getCanonicalType()));
} else if (flags.hasExtendedFlags()) {
arguments.push_back(llvm::ConstantPointerNull::get(IGF.IGM.TypeMetadataPtrTy));
}
auto getMetadataFn =
type->getGlobalActor()
flags.hasExtendedFlags()
? IGF.IGM.getGetFunctionMetadataExtendedFunctionPointer()
: type->getGlobalActor()
? (IGF.IGM.isConcurrencyAvailable()
? IGF.IGM
.getGetFunctionMetadataGlobalActorFunctionPointer()

View File

@@ -779,9 +779,17 @@ public:
Dem);
}
if (F->getFlags().isThrowing())
if (F->getFlags().isThrowing()) {
if (auto thrownError = F->getThrownError()) {
auto node = Dem.createNode(Node::Kind::TypedThrowsAnnotation);
auto thrownErrorNode = visit(thrownError);
node->addChild(thrownErrorNode, Dem);
funcNode->addChild(node, Dem);
} else {
funcNode->addChild(Dem.createNode(Node::Kind::ThrowsAnnotation), Dem);
// FIXME: TypedThrowsAnnotation
}
}
if (F->getFlags().isSendable()) {
funcNode->addChild(
Dem.createNode(Node::Kind::ConcurrentFunctionType), Dem);

View File

@@ -805,9 +805,18 @@ swift::_swift_buildDemanglingForMetadata(const Metadata *type,
(Node::IndexType)MangledDifferentiabilityKind::Linear), Dem);
break;
}
if (func->isThrowing())
if (func->isThrowing()) {
if (auto thrownError = func->getThrownError()) {
auto thrownErrorTypeNode =
_swift_buildDemanglingForMetadata(thrownError, Dem);
NodePointer thrownErrorNode =
Dem.createNode(Node::Kind::TypedThrowsAnnotation);
thrownErrorNode->addChild(thrownErrorTypeNode, Dem);
funcNode->addChild(thrownErrorNode, Dem);
} else {
funcNode->addChild(Dem.createNode(Node::Kind::ThrowsAnnotation), Dem);
// FIXME: TypedThrowsAnnotation
}
}
if (func->isSendable()) {
funcNode->addChild(
Dem.createNode(Node::Kind::ConcurrentFunctionType), Dem);

View File

@@ -1357,8 +1357,11 @@ public:
const ::ParameterFlags *ParameterFlags;
const Metadata *Result;
const Metadata *GlobalActor;
const ExtendedFunctionTypeFlags ExtFlags;
const Metadata *ThrownError;
FunctionTypeFlags getFlags() const { return Flags; }
ExtendedFunctionTypeFlags getExtFlags() const { return ExtFlags; }
FunctionMetadataDifferentiabilityKind getDifferentiabilityKind() const {
return DifferentiabilityKind;
@@ -1380,12 +1383,14 @@ public:
}
const Metadata *getGlobalActor() const { return GlobalActor; }
const Metadata *getThrownError() const { return ThrownError; }
friend llvm::hash_code hash_value(const Key &key) {
auto hash = llvm::hash_combine(
key.Flags.getIntValue(),
key.DifferentiabilityKind.getIntValue(),
key.Result, key.GlobalActor);
key.Result, key.GlobalActor,
key.ExtFlags.getIntValue(), key.ThrownError);
for (unsigned i = 0, e = key.getFlags().getNumParameters(); i != e; ++i) {
hash = llvm::hash_combine(hash, key.getParameter(i));
hash = llvm::hash_combine(hash, key.getParameterFlags(i).getIntValue());
@@ -1410,6 +1415,10 @@ public:
return false;
if (key.getGlobalActor() != Data.getGlobalActor())
return false;
if (key.getExtFlags().getIntValue() != Data.getExtendedFlags().getIntValue())
return false;
if (key.getThrownError() != Data.getThrownError())
return false;
for (unsigned i = 0, e = key.getFlags().getNumParameters(); i != e; ++i) {
if (key.getParameter(i) != Data.getParameter(i))
return false;
@@ -1423,29 +1432,31 @@ public:
friend llvm::hash_code hash_value(const FunctionCacheEntry &value) {
Key key = {value.Data.Flags, value.Data.getDifferentiabilityKind(),
value.Data.getParameters(), value.Data.getParameterFlags(),
value.Data.ResultType, value.Data.getGlobalActor()};
value.Data.ResultType, value.Data.getGlobalActor(),
value.Data.getExtendedFlags(), value.Data.getThrownError()};
return hash_value(key);
}
static size_t getExtraAllocationSize(const Key &key) {
return getExtraAllocationSize(key.Flags);
return getExtraAllocationSize(key.Flags, key.ExtFlags);
}
size_t getExtraAllocationSize() const {
return getExtraAllocationSize(Data.Flags);
return getExtraAllocationSize(Data.Flags, Data.getExtendedFlags());
}
static size_t getExtraAllocationSize(const FunctionTypeFlags &flags) {
static size_t getExtraAllocationSize(const FunctionTypeFlags &flags,
const ExtendedFunctionTypeFlags &extFlags) {
const auto numParams = flags.getNumParameters();
auto size = numParams * sizeof(FunctionTypeMetadata::Parameter);
if (flags.hasParameterFlags())
size += numParams * sizeof(uint32_t);
if (flags.isDifferentiable())
size = roundUpToAlignment(size, sizeof(void *)) +
sizeof(FunctionMetadataDifferentiabilityKind);
if (flags.hasGlobalActor())
size = roundUpToAlignment(size, sizeof(void *)) + sizeof(Metadata *);
return roundUpToAlignment(size, sizeof(void *));
return FunctionTypeMetadata::additionalSizeToAlloc<
const Metadata *, ParameterFlags, FunctionMetadataDifferentiabilityKind,
FunctionGlobalActorMetadata, ExtendedFunctionTypeFlags,
FunctionThrownErrorMetadata>(numParams,
flags.hasParameterFlags() ? numParams : 0,
flags.isDifferentiable() ? 1 : 0,
flags.hasGlobalActor() ? 1 : 0,
flags.hasExtendedFlags() ? 1 : 0,
extFlags.isTypedThrows() ? 1 : 0);
}
};
@@ -1506,9 +1517,13 @@ swift::swift_getFunctionTypeMetadata(FunctionTypeFlags flags,
assert(!flags.hasGlobalActor()
&& "Global actor function type metadata should be obtained using "
"'swift_getFunctionTypeMetadataGlobalActor'");
assert(!flags.hasExtendedFlags()
&& "Extended flags function type metadata should be obtained using "
"'swift_getExtendedFunctionTypeMetadata'");
FunctionCacheEntry::Key key = {
flags, FunctionMetadataDifferentiabilityKind::NonDifferentiable, parameters,
reinterpret_cast<const ParameterFlags *>(parameterFlags), result, nullptr
reinterpret_cast<const ParameterFlags *>(parameterFlags), result, nullptr,
ExtendedFunctionTypeFlags(), nullptr
};
return &FunctionTypes.getOrInsert(key).first->Data;
}
@@ -1521,11 +1536,15 @@ swift::swift_getFunctionTypeMetadataDifferentiable(
assert(!flags.hasGlobalActor()
&& "Global actor function type metadata should be obtained using "
"'swift_getFunctionTypeMetadataGlobalActor'");
assert(!flags.hasExtendedFlags()
&& "Extended flags function type metadata should be obtained using "
"'swift_getExtendedFunctionTypeMetadata'");
assert(flags.isDifferentiable());
assert(diffKind.isDifferentiable());
FunctionCacheEntry::Key key = {
flags, diffKind, parameters,
reinterpret_cast<const ParameterFlags *>(parameterFlags), result, nullptr
reinterpret_cast<const ParameterFlags *>(parameterFlags), result, nullptr,
ExtendedFunctionTypeFlags(), nullptr
};
return &FunctionTypes.getOrInsert(key).first->Data;
}
@@ -1535,10 +1554,29 @@ swift::swift_getFunctionTypeMetadataGlobalActor(
FunctionTypeFlags flags, FunctionMetadataDifferentiabilityKind diffKind,
const Metadata *const *parameters, const uint32_t *parameterFlags,
const Metadata *result, const Metadata *globalActor) {
assert(flags.hasGlobalActor());
assert(!flags.hasExtendedFlags()
&& "Extended flags function type metadata should be obtained using "
"'swift_getExtendedFunctionTypeMetadata'");
FunctionCacheEntry::Key key = {
flags, diffKind, parameters,
reinterpret_cast<const ParameterFlags *>(parameterFlags), result, globalActor
reinterpret_cast<const ParameterFlags *>(parameterFlags), result,
globalActor, ExtendedFunctionTypeFlags(), nullptr
};
return &FunctionTypes.getOrInsert(key).first->Data;
}
const FunctionTypeMetadata *
swift::swift_getExtendedFunctionTypeMetadata(
FunctionTypeFlags flags, FunctionMetadataDifferentiabilityKind diffKind,
const Metadata *const *parameters, const uint32_t *parameterFlags,
const Metadata *result, const Metadata *globalActor,
ExtendedFunctionTypeFlags extFlags, const Metadata *thrownError) {
assert(flags.hasExtendedFlags() || extFlags.getIntValue() == 0);
assert(flags.hasExtendedFlags() || thrownError == nullptr);
FunctionCacheEntry::Key key = {
flags, diffKind, parameters,
reinterpret_cast<const ParameterFlags *>(parameterFlags), result,
globalActor, extFlags, thrownError
};
return &FunctionTypes.getOrInsert(key).first->Data;
}
@@ -1592,6 +1630,13 @@ FunctionCacheEntry::FunctionCacheEntry(const Key &key) {
*Data.getGlobalActorAddr() = key.getGlobalActor();
if (flags.isDifferentiable())
*Data.getDifferentiabilityKindAddress() = key.getDifferentiabilityKind();
if (flags.hasExtendedFlags()) {
auto extFlags = key.getExtFlags();
*Data.getExtendedFlagsAddr() = extFlags;
if (extFlags.isTypedThrows())
*Data.getThrownErrorAddr() = key.getThrownError();
}
for (unsigned i = 0; i < numParameters; ++i) {
Data.getParameters()[i] = key.getParameter(i);

View File

@@ -1969,22 +1969,18 @@ public:
flags = flags.withGlobalActor(true);
}
// FIXME: thrownError
ExtendedFunctionTypeFlags extFlags;
if (thrownError) {
flags = flags.withExtendedFlags(true);
extFlags = extFlags.withTypedThrows(true);
}
return BuiltType(
flags.hasGlobalActor()
? swift_getFunctionTypeMetadataGlobalActor(flags, diffKind, paramTypes.data(),
flags.hasParameterFlags() ? paramFlags.data() : nullptr,
result.getMetadata(), globalActorType.getMetadata())
: flags.isDifferentiable()
? swift_getFunctionTypeMetadataDifferentiable(
swift_getExtendedFunctionTypeMetadata(
flags, diffKind, paramTypes.data(),
flags.hasParameterFlags() ? paramFlags.data() : nullptr,
result.getMetadata())
: swift_getFunctionTypeMetadata(
flags, paramTypes.data(),
flags.hasParameterFlags() ? paramFlags.data() : nullptr,
result.getMetadata()));
result.getMetadata(), globalActorType.getMetadataOrNull(), extFlags,
thrownError.getMetadataOrNull()));
}
TypeLookupErrorOr<BuiltType> createImplFunctionType(

View File

@@ -0,0 +1,38 @@
// RUN: %target-swift-frontend -primary-file %s -emit-ir -enable-experimental-feature TypedThrows -disable-availability-checking -runtime-compatibility-version none -target %module-target-future | %FileCheck %s --check-prefix=CHECK-MANGLE
// RUN: %target-swift-frontend -primary-file %s -emit-ir -enable-experimental-feature TypedThrows -disable-availability-checking -runtime-compatibility-version 5.8 -disable-concrete-type-metadata-mangled-name-accessors | %FileCheck %s --check-prefix=CHECK-NOMANGLE
enum MyBigError: Error {
case epicFail
}
// CHECK-MANGLE: @"$s12typed_throws1XVAA1PAAWP" = hidden global [2 x ptr] [ptr @"$s12typed_throws1XVAA1PAAMc", ptr getelementptr inbounds (i8, ptr @"symbolic ySi_____YKc 12typed_throws10MyBigErrorO", {{i32|i64}} 1)]
struct X: P {
typealias A = (Int) throws(MyBigError) -> Void
}
func requiresP<T: P>(_: T.Type) { }
func createsP() {
requiresP(X.self)
}
// CHECK-LABEL: define {{.*}}hidden swiftcc ptr @"$s12typed_throws13buildMetatypeypXpyF"()
func buildMetatype() -> Any.Type {
typealias Fn = (Int) throws(MyBigError) -> Void
// CHECK-MANGLE: __swift_instantiateConcreteTypeFromMangledName(ptr @"$sySi12typed_throws10MyBigErrorOYKcMD
// CHECK-NOMANGLE: call swiftcc %swift.metadata_response @"$sySi12typed_throws10MyBigErrorOYKcMa"
return Fn.self
}
// CHECK-NOMANGLE: define linkonce_odr hidden swiftcc %swift.metadata_response @"$sySi12typed_throws10MyBigErrorOYKcMa"
// CHECK: call ptr @swift_getExtendedFunctionTypeMetadata({{i32|i64}} 2231369729, {{i32|i64}} 0, ptr [[PARAMS:%.*]], ptr null, ptr getelementptr inbounds (%swift.full_existential_type, ptr @"$sytN", i32 0, i32 1), ptr null, i32 1, ptr getelementptr inbounds (<{ ptr, ptr, i64, ptr }>, ptr {{.*}}@"$s12typed_throws10MyBigErrorOMf"
// CHECK-NOMANGLE: declare extern_weak ptr @swift_getExtendedFunctionTypeMetadata
protocol P {
associatedtype A
}

View File

@@ -1,5 +1,5 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift -Xfrontend -disable-availability-checking -parse-stdlib %s -module-name main -o %t/a.out
// RUN: %target-build-swift -Xfrontend -disable-availability-checking -parse-stdlib -enable-experimental-feature TypedThrows %s -module-name main -o %t/a.out
// RUN: %target-codesign %t/a.out
// RUN: %target-run %t/a.out
// REQUIRES: executable_test
@@ -522,5 +522,18 @@ if #available(SwiftStdlib 5.1, *) {
}
}
enum MyBigError: Error {
case epicFail
}
if #available(SwiftStdlib 5.11, *) {
DemangleToMetadataTests.test("typed throws") {
typealias Fn = (Int) throws(MyBigError) -> Void
expectEqual("ySi4main10MyBigErrorOYKc", _mangledTypeName(Fn.self)!)
print("Looking up the typed throws... \(_typeByName("ySi4main10MyBigErrorOYKc"))")
expectEqual(Fn.self, _typeByName("ySi4main10MyBigErrorOYKc")!)
}
}
runAllTests()