Skip to content

Commit b04155b

Browse files
authored
Merge pull request #15330 from rjmccall/incomplete-metadata-accessors
Change type metadata accessors to support incomplete metadata
2 parents cb0be34 + 31f2eec commit b04155b

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)