mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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:
@@ -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>;
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(
|
||||
|
||||
38
test/IRGen/typed_throws.swift
Normal file
38
test/IRGen/typed_throws.swift
Normal 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
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user