[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

@@ -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);