mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Template metadata structures
- Add RuntimeTarget template This will allow for converting between metadata structures for native host and remote target architectures. - Create InProcess and External templates for stored pointers Add a few more types to abstract pointer access in the runtime structures but keep native in-process pointer access the same as that with a plain old pointer type. There is now a notion of a "stored pointer", which is just the raw value of the pointer, and the actual pointer type, which is used for loads. Decoupling these allows us to fork the behavior when looking at metadata in an external process, but keep things the same for the in-process case. There are two basic "runtime targets" that you can use to work with metadata: InProcess: Defines the pointer to be trivially a T* and stored as a uintptr_t. A Metadata * is exactly as it was before, but defined via AbstractMetadata<InProcess>. External: A template that requires a target to specify its pointer size. ExternalPointer: An opaque pointer in another address space that can't (and shouldn't) be indirected with operator* or operator->. The memory reader will fetch the data explicitly.
This commit is contained in:
@@ -26,11 +26,13 @@
|
|||||||
|
|
||||||
namespace swift {
|
namespace swift {
|
||||||
|
|
||||||
struct Metadata;
|
struct InProcess;
|
||||||
|
template <typename Runtime> struct TargetMetadata;
|
||||||
|
using Metadata = TargetMetadata<InProcess>;
|
||||||
|
|
||||||
/// Kinds of Swift metadata records. Some of these are types, some
|
/// Kinds of Swift metadata records. Some of these are types, some
|
||||||
/// aren't.
|
/// aren't.
|
||||||
enum class MetadataKind : uintptr_t {
|
enum class MetadataKind : uint32_t {
|
||||||
#define METADATAKIND(name, value) name = value,
|
#define METADATAKIND(name, value) name = value,
|
||||||
#define ABSTRACTMETADATAKIND(name, start, end) \
|
#define ABSTRACTMETADATAKIND(name, start, end) \
|
||||||
name##_Start = start, name##_End = end,
|
name##_Start = start, name##_End = end,
|
||||||
@@ -38,7 +40,7 @@ enum class MetadataKind : uintptr_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Kinds of Swift nominal type descriptor records.
|
/// Kinds of Swift nominal type descriptor records.
|
||||||
enum class NominalTypeKind : uintptr_t {
|
enum class NominalTypeKind : uint32_t {
|
||||||
#define NOMINALTYPEMETADATAKIND(name, value) name = value,
|
#define NOMINALTYPEMETADATAKIND(name, value) name = value,
|
||||||
#include "MetadataKind.def"
|
#include "MetadataKind.def"
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -83,15 +83,18 @@ static inline void crash(const char *message) {
|
|||||||
LLVM_ATTRIBUTE_NORETURN
|
LLVM_ATTRIBUTE_NORETURN
|
||||||
extern void
|
extern void
|
||||||
fatalError(uint32_t flags, const char *format, ...);
|
fatalError(uint32_t flags, const char *format, ...);
|
||||||
|
|
||||||
|
struct InProcess;
|
||||||
|
|
||||||
struct Metadata;
|
template <typename Runtime> struct TargetMetadata;
|
||||||
|
using Metadata = TargetMetadata<InProcess>;
|
||||||
|
|
||||||
// swift_dynamicCastFailure halts using fatalError()
|
// swift_dynamicCastFailure halts using fatalError()
|
||||||
// with a description of a failed cast's types.
|
// with a description of a failed cast's types.
|
||||||
LLVM_ATTRIBUTE_NORETURN
|
LLVM_ATTRIBUTE_NORETURN
|
||||||
void
|
void
|
||||||
swift_dynamicCastFailure(const swift::Metadata *sourceType,
|
swift_dynamicCastFailure(const Metadata *sourceType,
|
||||||
const swift::Metadata *targetType,
|
const Metadata *targetType,
|
||||||
const char *message = nullptr);
|
const char *message = nullptr);
|
||||||
|
|
||||||
// swift_dynamicCastFailure halts using fatalError()
|
// swift_dynamicCastFailure halts using fatalError()
|
||||||
|
|||||||
@@ -23,8 +23,14 @@ namespace swift {
|
|||||||
|
|
||||||
struct OpaqueValue;
|
struct OpaqueValue;
|
||||||
struct ValueWitnessTable;
|
struct ValueWitnessTable;
|
||||||
struct Metadata;
|
|
||||||
struct EnumMetadata;
|
struct InProcess;
|
||||||
|
|
||||||
|
template <typename Runtime> struct TargetMetadata;
|
||||||
|
using Metadata = TargetMetadata<InProcess>;
|
||||||
|
|
||||||
|
template <typename Runtime> struct TargetEnumMetadata;
|
||||||
|
using EnumMetadata = TargetEnumMetadata<InProcess>;
|
||||||
struct TypeLayout;
|
struct TypeLayout;
|
||||||
|
|
||||||
/// \brief Initialize the value witness table for a generic, single-payload
|
/// \brief Initialize the value witness table for a generic, single-payload
|
||||||
|
|||||||
@@ -29,9 +29,15 @@
|
|||||||
#include "../../../stdlib/public/SwiftShims/HeapObject.h"
|
#include "../../../stdlib/public/SwiftShims/HeapObject.h"
|
||||||
|
|
||||||
namespace swift {
|
namespace swift {
|
||||||
|
|
||||||
|
struct InProcess;
|
||||||
|
|
||||||
|
template <typename Runtime> struct TargetMetadata;
|
||||||
|
using Metadata = TargetMetadata<InProcess>;
|
||||||
|
|
||||||
|
template <typename Runtime> struct TargetHeapMetadata;
|
||||||
|
using HeapMetadata = TargetHeapMetadata<InProcess>;
|
||||||
|
|
||||||
struct Metadata;
|
|
||||||
struct HeapMetadata;
|
|
||||||
struct OpaqueValue;
|
struct OpaqueValue;
|
||||||
|
|
||||||
/// Allocates a new heap object. The returned memory is
|
/// Allocates a new heap object. The returned memory is
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -24,7 +24,9 @@ struct objc_class;
|
|||||||
|
|
||||||
namespace swift {
|
namespace swift {
|
||||||
|
|
||||||
struct Metadata;
|
template <typename Runtime> struct TargetMetadata;
|
||||||
|
using Metadata = TargetMetadata<InProcess>;
|
||||||
|
|
||||||
struct HeapObject;
|
struct HeapObject;
|
||||||
|
|
||||||
} // end namespace swift
|
} // end namespace swift
|
||||||
|
|||||||
@@ -19,9 +19,14 @@
|
|||||||
#include "swift/Basic/type_traits.h"
|
#include "swift/Basic/type_traits.h"
|
||||||
|
|
||||||
namespace swift {
|
namespace swift {
|
||||||
#endif
|
|
||||||
|
|
||||||
struct HeapMetadata;
|
struct InProcess;
|
||||||
|
|
||||||
|
template <typename Target> struct TargetHeapMetadata;
|
||||||
|
using HeapMetadata = TargetHeapMetadata<InProcess>;
|
||||||
|
#else
|
||||||
|
typedef struct HeapMetadata HeapMetadata;
|
||||||
|
#endif
|
||||||
|
|
||||||
// The members of the HeapObject header that are not shared by a
|
// The members of the HeapObject header that are not shared by a
|
||||||
// standard Objective-C instance
|
// standard Objective-C instance
|
||||||
@@ -32,7 +37,7 @@ struct HeapMetadata;
|
|||||||
/// The Swift heap-object header.
|
/// The Swift heap-object header.
|
||||||
struct HeapObject {
|
struct HeapObject {
|
||||||
/// This is always a valid pointer to a metadata object.
|
/// This is always a valid pointer to a metadata object.
|
||||||
struct HeapMetadata const *metadata;
|
HeapMetadata const *metadata;
|
||||||
|
|
||||||
SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;
|
SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;
|
||||||
// FIXME: allocate two words of metadata on 32-bit platforms
|
// FIXME: allocate two words of metadata on 32-bit platforms
|
||||||
|
|||||||
@@ -23,8 +23,17 @@
|
|||||||
#include "Visibility.h"
|
#include "Visibility.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
namespace swift { extern "C" {
|
namespace swift {
|
||||||
|
|
||||||
|
template <unsigned PointerSize> struct RuntimeTarget;
|
||||||
|
using HostTarget = RuntimeTarget<sizeof(uintptr_t)>;
|
||||||
|
|
||||||
|
template <typename Target> struct TargetMetadata;
|
||||||
|
using Metadata = TargetMetadata<InProcess>;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
#else
|
#else
|
||||||
|
typedef struct Metadata Metadata;
|
||||||
#define bool _Bool
|
#define bool _Bool
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -49,14 +58,11 @@ const char *_swift_stdlib_strtod_clocale(const char *nptr, double *outResult);
|
|||||||
/// overflow.
|
/// overflow.
|
||||||
SWIFT_RUNTIME_STDLIB_INTERFACE
|
SWIFT_RUNTIME_STDLIB_INTERFACE
|
||||||
const char *_swift_stdlib_strtof_clocale(const char *nptr, float *outResult);
|
const char *_swift_stdlib_strtof_clocale(const char *nptr, float *outResult);
|
||||||
|
|
||||||
struct Metadata;
|
|
||||||
|
|
||||||
/// Return the superclass, if any. The result is nullptr for root
|
/// Return the superclass, if any. The result is nullptr for root
|
||||||
/// classes and class protocol types.
|
/// classes and class protocol types.
|
||||||
SWIFT_RUNTIME_EXPORT
|
SWIFT_RUNTIME_EXPORT
|
||||||
const struct Metadata *swift_class_getSuperclass(
|
const Metadata *swift_class_getSuperclass(const Metadata *);
|
||||||
const struct Metadata *);
|
|
||||||
|
|
||||||
SWIFT_RUNTIME_STDLIB_INTERFACE
|
SWIFT_RUNTIME_STDLIB_INTERFACE
|
||||||
void _swift_stdlib_flockfile_stdout(void);
|
void _swift_stdlib_flockfile_stdout(void);
|
||||||
|
|||||||
@@ -2071,7 +2071,7 @@ getExistentialValueWitnesses(ExistentialTypeState &E,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ExistentialTypeRepresentation
|
template<> ExistentialTypeRepresentation
|
||||||
ExistentialTypeMetadata::getRepresentation() const {
|
ExistentialTypeMetadata::getRepresentation() const {
|
||||||
// Some existentials use special containers.
|
// Some existentials use special containers.
|
||||||
switch (Flags.getSpecialProtocol()) {
|
switch (Flags.getSpecialProtocol()) {
|
||||||
@@ -2088,7 +2088,7 @@ ExistentialTypeMetadata::getRepresentation() const {
|
|||||||
return ExistentialTypeRepresentation::Opaque;
|
return ExistentialTypeRepresentation::Opaque;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
template<> bool
|
||||||
ExistentialTypeMetadata::mayTakeValue(const OpaqueValue *container) const {
|
ExistentialTypeMetadata::mayTakeValue(const OpaqueValue *container) const {
|
||||||
switch (getRepresentation()) {
|
switch (getRepresentation()) {
|
||||||
// Owning a reference to a class existential is equivalent to owning a
|
// Owning a reference to a class existential is equivalent to owning a
|
||||||
@@ -2112,7 +2112,7 @@ ExistentialTypeMetadata::mayTakeValue(const OpaqueValue *container) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
template<> void
|
||||||
ExistentialTypeMetadata::deinitExistentialContainer(OpaqueValue *container)
|
ExistentialTypeMetadata::deinitExistentialContainer(OpaqueValue *container)
|
||||||
const {
|
const {
|
||||||
switch (getRepresentation()) {
|
switch (getRepresentation()) {
|
||||||
@@ -2135,7 +2135,7 @@ const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const OpaqueValue *
|
template<> const OpaqueValue *
|
||||||
ExistentialTypeMetadata::projectValue(const OpaqueValue *container) const {
|
ExistentialTypeMetadata::projectValue(const OpaqueValue *container) const {
|
||||||
switch (getRepresentation()) {
|
switch (getRepresentation()) {
|
||||||
case ExistentialTypeRepresentation::Class: {
|
case ExistentialTypeRepresentation::Class: {
|
||||||
@@ -2161,7 +2161,7 @@ ExistentialTypeMetadata::projectValue(const OpaqueValue *container) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Metadata *
|
template<> const Metadata *
|
||||||
ExistentialTypeMetadata::getDynamicType(const OpaqueValue *container) const {
|
ExistentialTypeMetadata::getDynamicType(const OpaqueValue *container) const {
|
||||||
switch (getRepresentation()) {
|
switch (getRepresentation()) {
|
||||||
case ExistentialTypeRepresentation::Class: {
|
case ExistentialTypeRepresentation::Class: {
|
||||||
@@ -2183,7 +2183,7 @@ ExistentialTypeMetadata::getDynamicType(const OpaqueValue *container) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const WitnessTable *
|
template<> const WitnessTable *
|
||||||
ExistentialTypeMetadata::getWitnessTable(const OpaqueValue *container,
|
ExistentialTypeMetadata::getWitnessTable(const OpaqueValue *container,
|
||||||
unsigned i) const {
|
unsigned i) const {
|
||||||
assert(i < Flags.getNumWitnessTables());
|
assert(i < Flags.getNumWitnessTables());
|
||||||
@@ -2388,37 +2388,7 @@ swift::swift_getForeignTypeMetadata(ForeignTypeMetadata *nonUnique) {
|
|||||||
|
|
||||||
/*** Other metadata routines ***********************************************/
|
/*** Other metadata routines ***********************************************/
|
||||||
|
|
||||||
const NominalTypeDescriptor *
|
template<> const GenericMetadata *
|
||||||
Metadata::getNominalTypeDescriptor() const {
|
|
||||||
switch (getKind()) {
|
|
||||||
case MetadataKind::Class: {
|
|
||||||
const ClassMetadata *cls = static_cast<const ClassMetadata *>(this);
|
|
||||||
if (!cls->isTypeMetadata())
|
|
||||||
return nullptr;
|
|
||||||
if (cls->isArtificialSubclass())
|
|
||||||
return nullptr;
|
|
||||||
return cls->getDescription();
|
|
||||||
}
|
|
||||||
case MetadataKind::Struct:
|
|
||||||
case MetadataKind::Enum:
|
|
||||||
case MetadataKind::Optional:
|
|
||||||
return static_cast<const StructMetadata *>(this)->Description;
|
|
||||||
case MetadataKind::ForeignClass:
|
|
||||||
case MetadataKind::Opaque:
|
|
||||||
case MetadataKind::Tuple:
|
|
||||||
case MetadataKind::Function:
|
|
||||||
case MetadataKind::Existential:
|
|
||||||
case MetadataKind::ExistentialMetatype:
|
|
||||||
case MetadataKind::Metatype:
|
|
||||||
case MetadataKind::ObjCClassWrapper:
|
|
||||||
case MetadataKind::HeapLocalVariable:
|
|
||||||
case MetadataKind::HeapGenericLocalVariable:
|
|
||||||
case MetadataKind::ErrorObject:
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const GenericMetadata *
|
|
||||||
Metadata::getGenericPattern() const {
|
Metadata::getGenericPattern() const {
|
||||||
auto ntd = getNominalTypeDescriptor();
|
auto ntd = getNominalTypeDescriptor();
|
||||||
if (!ntd)
|
if (!ntd)
|
||||||
@@ -2426,7 +2396,7 @@ Metadata::getGenericPattern() const {
|
|||||||
return ntd->getGenericMetadataPattern();
|
return ntd->getGenericMetadataPattern();
|
||||||
}
|
}
|
||||||
|
|
||||||
const ClassMetadata *
|
template<> const ClassMetadata *
|
||||||
Metadata::getClassObject() const {
|
Metadata::getClassObject() const {
|
||||||
switch (getKind()) {
|
switch (getKind()) {
|
||||||
case MetadataKind::Class: {
|
case MetadataKind::Class: {
|
||||||
|
|||||||
@@ -73,10 +73,10 @@ namespace {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
TypeMetadataCacheEntry(const llvm::StringRef name,
|
TypeMetadataCacheEntry(const llvm::StringRef name,
|
||||||
const struct Metadata *metadata)
|
const ::Metadata *metadata)
|
||||||
: Name(name.str()), Metadata(metadata) {}
|
: Name(name.str()), Metadata(metadata) {}
|
||||||
|
|
||||||
const struct Metadata *getMetadata(void) {
|
const ::Metadata *getMetadata(void) {
|
||||||
return Metadata;
|
return Metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,6 +230,7 @@ swift::swift_registerTypeMetadataRecords(const TypeMetadataRecord *begin,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// copied from ProtocolConformanceRecord::getCanonicalTypeMetadata()
|
// copied from ProtocolConformanceRecord::getCanonicalTypeMetadata()
|
||||||
|
template<>
|
||||||
const Metadata *TypeMetadataRecord::getCanonicalTypeMetadata() const {
|
const Metadata *TypeMetadataRecord::getCanonicalTypeMetadata() const {
|
||||||
switch (getTypeKind()) {
|
switch (getTypeKind()) {
|
||||||
case TypeMetadataRecordKind::UniqueDirectType:
|
case TypeMetadataRecordKind::UniqueDirectType:
|
||||||
@@ -238,7 +239,7 @@ const Metadata *TypeMetadataRecord::getCanonicalTypeMetadata() const {
|
|||||||
return swift_getForeignTypeMetadata((ForeignTypeMetadata *)getDirectType());
|
return swift_getForeignTypeMetadata((ForeignTypeMetadata *)getDirectType());
|
||||||
case TypeMetadataRecordKind::UniqueDirectClass:
|
case TypeMetadataRecordKind::UniqueDirectClass:
|
||||||
if (auto *ClassMetadata =
|
if (auto *ClassMetadata =
|
||||||
static_cast<const struct ClassMetadata *>(getDirectType()))
|
static_cast<const ::ClassMetadata *>(getDirectType()))
|
||||||
return swift_getObjCClassMetadata(ClassMetadata);
|
return swift_getObjCClassMetadata(ClassMetadata);
|
||||||
else
|
else
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
#include "llvm/Support/Compiler.h"
|
#include "llvm/Support/Compiler.h"
|
||||||
|
|
||||||
namespace swift {
|
namespace swift {
|
||||||
struct ProtocolDescriptor;
|
|
||||||
|
|
||||||
#if SWIFT_HAS_ISA_MASKING
|
#if SWIFT_HAS_ISA_MASKING
|
||||||
SWIFT_RUNTIME_EXPORT
|
SWIFT_RUNTIME_EXPORT
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ static const char *class_getName(const ClassMetadata* type) {
|
|||||||
reinterpret_cast<Class>(const_cast<ClassMetadata*>(type)));
|
reinterpret_cast<Class>(const_cast<ClassMetadata*>(type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtocolConformanceRecord::dump() const {
|
template<> void ProtocolConformanceRecord::dump() const {
|
||||||
auto symbolName = [&](const void *addr) -> const char * {
|
auto symbolName = [&](const void *addr) -> const char * {
|
||||||
Dl_info info;
|
Dl_info info;
|
||||||
int ok = dladdr(addr, &info);
|
int ok = dladdr(addr, &info);
|
||||||
@@ -96,7 +96,7 @@ void ProtocolConformanceRecord::dump() const {
|
|||||||
/// Take the type reference inside a protocol conformance record and fetch the
|
/// Take the type reference inside a protocol conformance record and fetch the
|
||||||
/// canonical metadata pointer for the type it refers to.
|
/// canonical metadata pointer for the type it refers to.
|
||||||
/// Returns nil for universal or generic type references.
|
/// Returns nil for universal or generic type references.
|
||||||
const Metadata *ProtocolConformanceRecord::getCanonicalTypeMetadata()
|
template<> const Metadata *ProtocolConformanceRecord::getCanonicalTypeMetadata()
|
||||||
const {
|
const {
|
||||||
switch (getTypeKind()) {
|
switch (getTypeKind()) {
|
||||||
case TypeMetadataRecordKind::UniqueDirectType:
|
case TypeMetadataRecordKind::UniqueDirectType:
|
||||||
@@ -127,7 +127,9 @@ const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const WitnessTable *ProtocolConformanceRecord::getWitnessTable(const Metadata *type)
|
template<>
|
||||||
|
const WitnessTable *
|
||||||
|
ProtocolConformanceRecord::getWitnessTable(const Metadata *type)
|
||||||
const {
|
const {
|
||||||
switch (getConformanceKind()) {
|
switch (getConformanceKind()) {
|
||||||
case ProtocolConformanceReferenceKind::WitnessTable:
|
case ProtocolConformanceReferenceKind::WitnessTable:
|
||||||
@@ -441,7 +443,7 @@ recur_inside_cache_lock:
|
|||||||
// For generic and resilient types, nondependent conformances
|
// For generic and resilient types, nondependent conformances
|
||||||
// are keyed by the nominal type descriptor rather than the
|
// are keyed by the nominal type descriptor rather than the
|
||||||
// metadata, so try that.
|
// metadata, so try that.
|
||||||
auto *description = type->getNominalTypeDescriptor();
|
auto *description = type->getNominalTypeDescriptor().get();
|
||||||
|
|
||||||
// Hash and lookup the type-protocol pair in the cache.
|
// Hash and lookup the type-protocol pair in the cache.
|
||||||
if (auto *Value = C.findCached(description, protocol)) {
|
if (auto *Value = C.findCached(description, protocol)) {
|
||||||
@@ -483,7 +485,7 @@ bool isRelatedType(const Metadata *type, const void *candidate,
|
|||||||
|
|
||||||
// If the type is resilient or generic, see if there's a witness table
|
// If the type is resilient or generic, see if there's a witness table
|
||||||
// keyed off the nominal type descriptor.
|
// keyed off the nominal type descriptor.
|
||||||
auto *description = type->getNominalTypeDescriptor();
|
auto *description = type->getNominalTypeDescriptor().get();
|
||||||
if (description == candidate && !candidateIsMetadata)
|
if (description == candidate && !candidateIsMetadata)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user