Skip to content

Commit 31f2eec

Browse files
committed
Change type metadata accessors to support incomplete metadata.
This includes global generic and non-generic global access functions, protocol associated type access functions, swift_getGenericMetadata, and generic type completion functions. The main part of this change is that the functions now need to take a MetadataRequest and return a MetadataResponse, which is capable of expressing that the request can fail. The state of the returned metadata is reported as an second, independent return value; this allows the caller to easily check the possibility of failure without having to mask it out from the returned metadata pointer, as well as allowing it to be easily ignored. Also, change metadata access functions to use swiftcc to ensure that this return value is indeed returned in two separate registers. Also, change protocol associated conformance access functions to use swiftcc. This isn't really related, but for some reason it snuck in. Since it's clearly the right thing to do, and since I really didn't want to retroactively tease that back out from all the rest of the test changes, I've left it in. Also, change generic metadata access functions to either pass all the generic arguments directly or pass them all indirectly. I don't know how we ended up with the hybrid approach. I needed to change all the code-generation and calls here anyway in order to pass the request parameter, and I figured I might as well change the ABI to something sensible.
1 parent cb0be34 commit 31f2eec

File tree

98 files changed

+1314
-905
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+1314
-905
lines changed

include/swift/ABI/MetadataValues.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,9 +1363,11 @@ class GenericMetadataPatternFlags : public FlagSet<uint32_t> {
13631363
};
13641364

13651365
/// Kinds of requests for metadata.
1366-
class MetadataRequest : public FlagSet<size_t> {
1366+
template <class IntType>
1367+
class TargetMetadataRequest : public FlagSet<IntType> {
1368+
using super = FlagSet<IntType>;
13671369
public:
1368-
enum BasicKind {
1370+
enum BasicKind : IntType {
13691371
/// A request for fully-completed metadata. The metadata must be
13701372
/// prepared for all supported type operations. This is a superset
13711373
/// of the requirements of LayoutComplete.
@@ -1387,7 +1389,7 @@ class MetadataRequest : public FlagSet<size_t> {
13871389
};
13881390

13891391
private:
1390-
enum {
1392+
enum : IntType {
13911393
BasicKind_bit = 0,
13921394
BasicKind_width = 8,
13931395

@@ -1401,12 +1403,14 @@ class MetadataRequest : public FlagSet<size_t> {
14011403
};
14021404

14031405
public:
1404-
MetadataRequest(BasicKind kind, bool isNonBlocking = false) {
1406+
TargetMetadataRequest(BasicKind kind, bool isNonBlocking = false) {
14051407
setBasicKind(kind);
14061408
setIsNonBlocking(isNonBlocking);
14071409
}
1408-
explicit MetadataRequest(size_t bits) : FlagSet(bits) {}
1409-
constexpr MetadataRequest() {}
1410+
explicit TargetMetadataRequest(IntType bits) : super(bits) {}
1411+
constexpr TargetMetadataRequest() {}
1412+
1413+
FLAGSET_DEFINE_EQUALITY(TargetMetadataRequest)
14101414

14111415
FLAGSET_DEFINE_FIELD_ACCESSORS(BasicKind_bit,
14121416
BasicKind_width,
@@ -1418,6 +1422,8 @@ class MetadataRequest : public FlagSet<size_t> {
14181422
isNonBlocking,
14191423
setIsNonBlocking)
14201424
};
1425+
using MetadataRequest =
1426+
TargetMetadataRequest<size_t>;
14211427

14221428
} // end namespace swift
14231429

include/swift/Basic/FlagSet.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,20 +83,32 @@ class FlagSet {
8383
// Intended to be used in the body of a subclass of FlagSet.
8484
#define FLAGSET_DEFINE_FLAG_ACCESSORS(BIT, GETTER, SETTER) \
8585
bool GETTER() const { \
86-
return getFlag<BIT>(); \
86+
return this->template getFlag<BIT>(); \
8787
} \
8888
void SETTER(bool value) { \
89-
setFlag<BIT>(value); \
89+
this->template setFlag<BIT>(value); \
9090
}
9191

9292
// A convenient macro for defining a getter and setter for a field.
9393
// Intended to be used in the body of a subclass of FlagSet.
9494
#define FLAGSET_DEFINE_FIELD_ACCESSORS(BIT, WIDTH, TYPE, GETTER, SETTER) \
9595
TYPE GETTER() const { \
96-
return getField<BIT, WIDTH, TYPE>(); \
96+
return this->template getField<BIT, WIDTH, TYPE>(); \
9797
} \
9898
void SETTER(TYPE value) { \
99-
setField<BIT, WIDTH, TYPE>(value); \
99+
this->template setField<BIT, WIDTH, TYPE>(value); \
100+
}
101+
102+
// A convenient macro to expose equality operators.
103+
// These can't be provided directly by FlagSet because that would allow
104+
// different flag sets to be compared if they happen to have the same
105+
// underlying type.
106+
#define FLAGSET_DEFINE_EQUALITY(TYPENAME) \
107+
friend bool operator==(TYPENAME lhs, TYPENAME rhs) { \
108+
return lhs.getOpaqueValue() == rhs.getOpaqueValue(); \
109+
} \
110+
friend bool operator!=(TYPENAME lhs, TYPENAME rhs) { \
111+
return lhs.getOpaqueValue() != rhs.getOpaqueValue(); \
100112
}
101113

102114
public:

include/swift/Runtime/Metadata.h

Lines changed: 107 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,31 @@ class WeakReference;
189189
template <typename Runtime> struct TargetMetadata;
190190
using Metadata = TargetMetadata<InProcess>;
191191

192+
/// The result of requesting type metadata. Generally the return value of
193+
/// a function.
194+
///
195+
/// For performance, functions returning this type should use SWIFT_CC so
196+
/// that the components are returned as separate values.
197+
struct MetadataResponse {
198+
/// For metadata access functions, this is the requested metadata.
199+
///
200+
/// For metadata initialization functions, this is either null,
201+
/// indicating that initialization was successful, or a metadata on
202+
/// which initialization depends for further progress.
203+
const Metadata *Value;
204+
205+
/// For metadata access functions, this is the current state of the
206+
/// metadata returned. Always use this instead of trying to inspect
207+
/// the metadata directly; an incomplete metadata may be getting
208+
/// initialized concurrently. This can generally be ignored if the
209+
/// metadata request was for abstract metadata or if the request is
210+
/// blocking.
211+
///
212+
/// For metadata initialization functions, this is the state that the
213+
/// given metadata needs to be in before initialization can continue.
214+
MetadataRequest::BasicKind State;
215+
};
216+
192217
template <typename Runtime> struct TargetProtocolConformanceDescriptor;
193218

194219
/// Storage for an arbitrary value. In C/C++ terms, this is an
@@ -1983,6 +2008,16 @@ using TargetWitnessTablePointer =
19832008

19842009
using WitnessTablePointer = TargetWitnessTablePointer<InProcess>;
19852010

2011+
using AssociatedTypeAccessFunction =
2012+
SWIFT_CC(swift) MetadataResponse(MetadataRequest request,
2013+
const Metadata *self,
2014+
const WitnessTable *selfConformance);
2015+
2016+
using AssociatedWitnessTableAccessFunction =
2017+
SWIFT_CC(swift) WitnessTable *(const Metadata *associatedType,
2018+
const Metadata *self,
2019+
const WitnessTable *selfConformance);
2020+
19862021
/// The possible physical representations of existential types.
19872022
enum class ExistentialTypeRepresentation {
19882023
/// The type uses an opaque existential representation.
@@ -3008,9 +3043,10 @@ struct MetadataCompletionContext {
30083043
/// pointer to indicate that completion is blocked on the completion of
30093044
/// some other type
30103045
using MetadataCompleter =
3011-
Metadata *(const Metadata *type,
3012-
MetadataCompletionContext *context,
3013-
const TargetGenericMetadataPattern<InProcess> *pattern);
3046+
SWIFT_CC(swift)
3047+
MetadataResponse(const Metadata *type,
3048+
MetadataCompletionContext *context,
3049+
const TargetGenericMetadataPattern<InProcess> *pattern);
30143050

30153051
/// An instantiation pattern for type metadata.
30163052
template <typename Runtime>
@@ -3229,98 +3265,92 @@ using TypeGenericContextDescriptorHeader =
32293265
/// Wrapper class for the pointer to a metadata access function that provides
32303266
/// operator() overloads to call it with the right calling convention.
32313267
class MetadataAccessFunction {
3232-
const Metadata * (*Function)(...);
3268+
MetadataResponse (*Function)(...);
32333269

32343270
static_assert(NumDirectGenericTypeMetadataAccessFunctionArgs == 3,
32353271
"Need to account for change in number of direct arguments");
32363272

3237-
template<typename T>
3238-
const Metadata *applyN(const void *arg0,
3239-
const void *arg1,
3240-
const void *arg2,
3241-
llvm::ArrayRef<T *> argRest) const {
3242-
using FnN = const Metadata *(const void *,
3243-
const void *,
3244-
const void *,
3245-
const void *);
3246-
return reinterpret_cast<FnN*>(Function)(arg0, arg1, arg2, argRest.data());
3247-
}
3248-
3249-
template<typename...Args>
3250-
const Metadata *variadic_apply(const void *arg0,
3251-
const void *arg1,
3252-
const void *arg2,
3253-
llvm::MutableArrayRef<const void *> argRest,
3254-
unsigned n,
3255-
const void *arg3,
3256-
Args...argN) const {
3257-
argRest[n] = arg3;
3258-
return variadic_apply(arg0, arg1, arg2, argRest, n+1, argN...);
3259-
}
3260-
3261-
const Metadata *variadic_apply(const void *arg0,
3262-
const void *arg1,
3263-
const void *arg2,
3264-
llvm::MutableArrayRef<const void *> argRest,
3265-
unsigned n) const {
3266-
return applyN(arg0, arg1, arg2, argRest);
3267-
}
3268-
32693273
public:
3270-
explicit MetadataAccessFunction(const Metadata * (*Function)(...))
3274+
explicit MetadataAccessFunction(MetadataResponse (*Function)(...))
32713275
: Function(Function)
32723276
{}
32733277

32743278
explicit operator bool() const {
32753279
return Function != nullptr;
32763280
}
32773281

3278-
// Invoke with an array of arguments.
3279-
template<typename T>
3280-
const Metadata *operator()(llvm::ArrayRef<T *> args) const {
3282+
/// Invoke with an array of arguments of dynamic size.
3283+
MetadataResponse operator()(MetadataRequest request,
3284+
llvm::ArrayRef<const void *> args) const {
32813285
switch (args.size()) {
32823286
case 0:
3283-
return (*this)();
3287+
return operator()(request);
32843288
case 1:
3285-
return (*this)(args[0]);
3289+
return operator()(request, args[0]);
32863290
case 2:
3287-
return (*this)(args[0], args[1]);
3291+
return operator()(request, args[0], args[1]);
32883292
case 3:
3289-
return (*this)(args[0], args[1], args[2]);
3293+
return operator()(request, args[0], args[1], args[2]);
32903294
default:
3291-
return applyN(args[0], args[1], args[2], args);
3295+
return applyMany(request, args.data());
32923296
}
32933297
}
32943298

3295-
// Invoke with n arguments.
3296-
const Metadata *operator()() const {
3297-
using Fn0 = const Metadata *();
3298-
return reinterpret_cast<Fn0*>(Function)();
3299-
}
3300-
const Metadata *operator()(const void *arg0) const {
3301-
using Fn1 = const Metadata *(const void *);
3302-
return reinterpret_cast<Fn1*>(Function)(arg0);
3303-
3304-
}
3305-
const Metadata *operator()(const void *arg0,
3306-
const void *arg1) const {
3307-
using Fn2 = const Metadata *(const void *, const void *);
3308-
return reinterpret_cast<Fn2*>(Function)(arg0, arg1);
3309-
}
3310-
const Metadata *operator()(const void *arg0,
3311-
const void *arg1,
3312-
const void *arg2) const {
3313-
using Fn3 = const Metadata *(const void *, const void *, const void *);
3314-
return reinterpret_cast<Fn3*>(Function)(arg0, arg1, arg2);
3299+
/// Invoke with exactly 0 arguments.
3300+
MetadataResponse operator()(MetadataRequest request) const {
3301+
using Fn0 = SWIFT_CC(swift) MetadataResponse(MetadataRequest request);
3302+
return reinterpret_cast<Fn0*>(Function)(request);
3303+
}
3304+
3305+
/// Invoke with exactly 1 argument.
3306+
MetadataResponse operator()(MetadataRequest request,
3307+
const void *arg0) const {
3308+
using Fn1 = SWIFT_CC(swift) MetadataResponse(MetadataRequest request,
3309+
const void *arg0);
3310+
return reinterpret_cast<Fn1*>(Function)(request, arg0);
3311+
3312+
}
3313+
3314+
/// Invoke with exactly 2 arguments.
3315+
MetadataResponse operator()(MetadataRequest request,
3316+
const void *arg0,
3317+
const void *arg1) const {
3318+
using Fn2 = SWIFT_CC(swift) MetadataResponse(MetadataRequest request,
3319+
const void *arg0,
3320+
const void *arg1);
3321+
return reinterpret_cast<Fn2*>(Function)(request, arg0, arg1);
3322+
}
3323+
3324+
/// Invoke with exactly 3 arguments.
3325+
MetadataResponse operator()(MetadataRequest request,
3326+
const void *arg0,
3327+
const void *arg1,
3328+
const void *arg2) const {
3329+
using Fn3 = SWIFT_CC(swift) MetadataResponse(MetadataRequest request,
3330+
const void *arg0,
3331+
const void *arg1,
3332+
const void *arg2);
3333+
return reinterpret_cast<Fn3*>(Function)(request, arg0, arg1, arg2);
33153334
}
33163335

3336+
/// Invoke with more than 3 arguments.
33173337
template<typename...Args>
3318-
const Metadata *operator()(const void *arg0,
3319-
const void *arg1,
3320-
const void *arg2,
3321-
Args...argN) const {
3322-
const void *args[3 + sizeof...(Args)];
3323-
return variadic_apply(arg0, arg1, arg2, args, 3, argN...);
3338+
MetadataResponse operator()(MetadataRequest request,
3339+
const void *arg0,
3340+
const void *arg1,
3341+
const void *arg2,
3342+
Args... argN) const {
3343+
const void *args[] = { arg0, arg1, arg2, argN... };
3344+
return applyMany(request, args);
3345+
}
3346+
3347+
private:
3348+
/// In the more-then-max case, just pass all the arguments as an array.
3349+
MetadataResponse applyMany(MetadataRequest request,
3350+
const void * const *args) const {
3351+
using FnN = SWIFT_CC(swift) MetadataResponse(MetadataRequest request,
3352+
const void * const *args);
3353+
return reinterpret_cast<FnN*>(Function)(request, args);
33243354
}
33253355
};
33263356

@@ -3336,7 +3366,7 @@ class TargetTypeContextDescriptor
33363366
/// The function type here is a stand-in. You should use getAccessFunction()
33373367
/// to wrap the function pointer in an accessor that uses the proper calling
33383368
/// convention for a given number of arguments.
3339-
TargetRelativeDirectPointer<Runtime, const Metadata *(...),
3369+
TargetRelativeDirectPointer<Runtime, MetadataResponse(...),
33403370
/*Nullable*/ true> AccessFunctionPtr;
33413371

33423372
MetadataAccessFunction getAccessFunction() const {
@@ -3855,27 +3885,11 @@ TargetTypeContextDescriptor<Runtime>::getFullGenericContextHeader() const {
38553885
}
38563886

38573887
/// \brief Fetch a uniqued metadata object for a generic nominal type.
3858-
///
3859-
/// The basic algorithm for fetching a metadata object is:
3860-
/// func swift_getGenericMetadata(header, arguments) {
3861-
/// if (metadata = getExistingMetadata(&header.PrivateData,
3862-
/// arguments[0..header.NumArguments]))
3863-
/// return metadata
3864-
/// metadata = malloc(superclass.MetadataSize +
3865-
/// numImmediateMembers * sizeof(void *))
3866-
/// memcpy(metadata, header.MetadataTemplate, header.TemplateSize)
3867-
/// for (i in 0..header.NumFillInstructions)
3868-
/// metadata[header.FillInstructions[i].ToIndex]
3869-
/// = arguments[header.FillInstructions[i].FromIndex]
3870-
/// setExistingMetadata(&header.PrivateData,
3871-
/// arguments[0..header.NumArguments],
3872-
/// metadata)
3873-
/// return metadata
3874-
/// }
3875-
SWIFT_RUNTIME_EXPORT
3876-
const Metadata *
3877-
swift_getGenericMetadata(const TypeContextDescriptor *description,
3878-
const void *arguments);
3888+
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
3889+
MetadataResponse
3890+
swift_getGenericMetadata(MetadataRequest request,
3891+
const void * const *arguments,
3892+
const TypeContextDescriptor *description);
38793893

38803894
/// Allocate a generic class metadata object. This is intended to be
38813895
/// called by the metadata instantiation function of a generic class.

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -801,11 +801,12 @@ FUNCTION(GetForeignTypeMetadata, swift_getForeignTypeMetadata, C_CC,
801801
ARGS(TypeMetadataPtrTy),
802802
ATTRS(NoUnwind, ReadNone)) // only writes to runtime-private fields
803803

804-
// Metadata *swift_getGenericMetadata(TypeContextDescriptor *type,
805-
// const void *arguments);
806-
FUNCTION(GetGenericMetadata, swift_getGenericMetadata, C_CC,
807-
RETURNS(TypeMetadataPtrTy),
808-
ARGS(TypeContextDescriptorPtrTy, Int8PtrTy),
804+
// MetadataResponse swift_getGenericMetadata(MetadataRequest request,
805+
// const void * const *arguments,
806+
// TypeContextDescriptor *type);
807+
FUNCTION(GetGenericMetadata, swift_getGenericMetadata, SwiftCC,
808+
RETURNS(TypeMetadataResponseTy),
809+
ARGS(SizeTy, Int8PtrTy, TypeContextDescriptorPtrTy),
809810
ATTRS(NoUnwind, ReadOnly))
810811

811812
// Metadata *swift_allocateGenericClassMetadata(ClassDescriptor *type,

lib/IRGen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ add_swift_library(swiftIRGen STATIC
4242
LoadableByAddress.cpp
4343
LocalTypeData.cpp
4444
MetadataLayout.cpp
45+
MetadataRequest.cpp
4546
StructLayout.cpp
4647
SwiftTargetInfo.cpp
4748
TypeLayoutVerifier.cpp

0 commit comments

Comments
 (0)